Skip to content

Commit

Permalink
Merge pull request #2 from labteral/develop
Browse files Browse the repository at this point in the history
v2
  • Loading branch information
brunneis authored Apr 12, 2021
2 parents 5387109 + 02a0022 commit c0e2f94
Show file tree
Hide file tree
Showing 13 changed files with 442 additions and 228 deletions.
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# synced
Work with disk-synced objects in Python (dict, list & primitive types).


> By default, data is stored under `./synced-data`. You can change this behaviour by setting the `path` parameter in the constructor. Note that this path can be shared by all the defined variables if their id is unique.
## Primitive types
```python
from synced import svalue

svar = svalue('id1')
svar.set(1)
svar.get()
```

## List
```python
from synced import slist

svar = slist('id2')
svar.append(1)
svar.extend([2, 3])

len(svar)

for value in svar:
print(value)
```

## Dict
```python
from synced import sdict

svar = sdict('id2')
svar['1'] = 'one'
svar.update({'2': 'two', '3': 'three'})

len(svar)

for key, value in svar.items():
print(key, value)
```

## Common methods
```python
svar.clear() # void content
svar.reload() # reinstantiate from disk
svar.begin() # begin an atomic transaction
svar.commit() # commit an atomic transaction
```
2 changes: 2 additions & 0 deletions run-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
python3 setup.py install && for test in tests/*.py; do python3 "$test"; done
2 changes: 1 addition & 1 deletion synced/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
from .slist import slist
from .svalue import svalue

__version__ = '0.0.14a'
__version__ = '2.214.0'
96 changes: 57 additions & 39 deletions synced/sdict.py
Original file line number Diff line number Diff line change
@@ -1,87 +1,105 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from .synced import DiskStore
import logging
from .synced import DictStore
from collections.abc import Mapping, Iterable


class sdict(dict):

COLL_TYPE = 'dict'

def __init__(self, name, collection=None, path=None, **kwargs):
if len(name) > DiskStore.MAX_KEY_LENGTH:
raise ValueError
self._memory_store = dict()
self._disk_store = DiskStore(path)
self._name = name
if path is None:
path = './synced-data'

for key, value in self._disk_store.get_coll(self._name, sdict.COLL_TYPE):
self._memory_store[key] = value
self._disk_store = DictStore(name, path)
self._load_memory_store()

if collection is not None:
if not self._memory_store:
self.update(collection)
else:
logging.warn('already initialized, collection discarded')
raise ValueError('already initialized, collection discarded')

def __eq__(self, other):
return self._memory_store.__eq__(other)
@property
def dict(self):
return dict(self._memory_store)

def __str__(self):
return self._memory_store.__str__()
def begin(self):
self._disk_store.begin()

def __repr__(self):
return self._memory_store.__repr__()
def commit(self):
self._disk_store.commit()

def get_dict(self):
return dict(self._memory_store)
def reload(self):
self._disk_store.reload()
self._load_memory_store()

def update(self, collection):
if isinstance(collection, Mapping):
for key, value in collection.items():
self.__setitem__(key, value)
return
if isinstance(collection, Iterable):
for item in collection:
self.__setitem__(item[0], item[1])
return
try:
if isinstance(collection, Mapping):
self._disk_store.begin()
for key, value in collection.items():
self.__setitem__(key, value)
self._disk_store.commit()
return
if isinstance(collection, Iterable):
self._disk_store.begin()
for item in collection:
self.__setitem__(item[0], item[1])
self._disk_store.commit()
return
except Exception as error:
self.reload()
raise error

raise TypeError

def clear(self):
self._disk_store.delete_coll(self._name, sdict.COLL_TYPE)
self._disk_store.clear()
self._memory_store = dict()

def items(self):
return self._memory_store.items()

def pop(self, key, default=None):
self._disk_store.delete(key, self._name, sdict.COLL_TYPE)
self._disk_store.delete(key)
return self._memory_store.pop(key)

def setdefault(self, key, default=None):
self.__setitem__(key, default)

def copy(self):
raise NotImplementedError

def popitem(self):
raise NotImplementedError

def _load_memory_store(self):
self._memory_store = dict()
for key, value in self._disk_store.get():
self._memory_store[key] = value

def __len__(self):
return self._memory_store.__len__()

def __setitem__(self, key, value):
self._disk_store.put_dict(key, value, self._name)
self._disk_store.put(key, value)
self._memory_store[key] = value

def __getitem__(self, key):
return self._memory_store[key]

def __delitem__(self, key):
self._disk_store.delete(key, self._name, sdict.COLL_TYPE)
self._disk_store.delete(key)
del self._memory_store[key]

def __contains__(self, value):
return self._memory_store.__contains__(value)

def copy(self):
raise NotImplementedError
def __eq__(self, other):
return self._memory_store.__eq__(other)

def popitem(self):
raise NotImplementedError
def __str__(self):
return self._memory_store.__str__()

def items(self):
return self._memory_store.items()
def __repr__(self):
return self._memory_store.__repr__()
107 changes: 62 additions & 45 deletions synced/slist.py
Original file line number Diff line number Diff line change
@@ -1,77 +1,63 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from .synced import DiskStore
from .synced import ListStore
import logging
from collections.abc import Iterable


class slist(list):

COLL_TYPE = 'list'

def __init__(self, name, collection=None, path=None, **kwargs):
if len(name) > DiskStore.MAX_KEY_LENGTH:
raise ValueError
self._memory_store = list()
self._disk_store = DiskStore(path)
self._name = name
if path is None:
path = './synced-data'

for value in self._disk_store.get_coll(self._name, slist.COLL_TYPE):
self._memory_store.append(value)
self._disk_store = ListStore(name, path)
self._load_memory_store()

if collection is not None:
if not self._memory_store:
self.update(collection)
else:
logging.warn('already initialized, collection discarded')

def __eq__(self, other):
return self._memory_store.__eq__(other)
@property
def list(self):
return list(self._memory_store)

def __str__(self):
return self._memory_store.__str__()
def begin(self):
self._disk_store.begin()

def __repr__(self):
return self._memory_store.__repr__()
def commit(self):
self._disk_store.commit()

def reload(self):
self._disk_store.reload()
self._load_memory_store()

def update(self, collection):
if not isinstance(collection, str) and isinstance(collection, Iterable):
for item in collection:
self.append(item)
self.extend(collection)
return
raise TypeError

def append(self, value):
self._disk_store.append_list(value, self._name)
self._memory_store.append(value)
try:
self._disk_store.append(value)
self._memory_store.append(value)
except Exception as error:
self.reload()
raise error

def extend(self, iterable):
for item in iterable:
self.append(item)

def get_list(self):
return list(self._memory_store)

def __len__(self):
return self._memory_store.__len__()

def __iter__(self):
return self._memory_store.__iter__()

def __getitem__(self, index):
return self._memory_store.__getitem__(index)

def __delitem__(self, index):
self._disk_store.delete(str(index), self._name, slist.COLL_TYPE)
del self._memory_store[index]

def __setitem__(self, index, item):
self._disk_store.put(str(index), item, self._name, slist.COLL_TYPE)
self._memory_store[index] = item
try:
self._disk_store.extend(iterable)
self._memory_store.extend(iterable)
except Exception as error:
self.reload()
raise error

def clear(self):
self._disk_store.delete_coll(self._name, slist.COLL_TYPE)
self._disk_store.clear()
self._memory_store = list()

def count(self, value):
Expand All @@ -90,4 +76,35 @@ def sort(self, key=None, reverse=False):
raise NotImplementedError

def copy(self):
raise NotImplementedError
raise NotImplementedError

def _load_memory_store(self):
self._memory_store = list()
for value in self._disk_store.get():
self._memory_store.append(value)

def __eq__(self, other):
return self._memory_store.__eq__(other)

def __str__(self):
return self._memory_store.__str__()

def __repr__(self):
return self._memory_store.__repr__()

def __len__(self):
return self._memory_store.__len__()

def __iter__(self):
return self._memory_store.__iter__()

def __getitem__(self, index):
return self._memory_store.__getitem__(index)

def __delitem__(self, index):
self._disk_store.delete(index)
del self._memory_store[index]

def __setitem__(self, index, item):
self._disk_store.put(index, item)
self._memory_store[index] = item
Loading

0 comments on commit c0e2f94

Please sign in to comment.