shep

Multi-state key stores using bit masks for python3
git clone git://git.defalsify.org/shep.git
Log | Files | Refs | LICENSE

commit 8ccc89b4a538bc351fe25edea74158ed06fc0149
parent 57a9ea44ff34fc5a58aecfff1f8e86e7415748ca
Author: lash <dev@holbrook.no>
Date:   Thu, 17 Mar 2022 19:16:33 +0000

Binary content option, sync all option

Diffstat:
MCHANGELOG | 2++
Mshep/persist.py | 24++++++++++++++++--------
Mshep/state.py | 2+-
Mshep/store/file.py | 21+++++++++++++--------
Mtests/test_file.py | 21++++++++++++++++++++-
Mtests/test_store.py | 1+
6 files changed, 53 insertions(+), 18 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG @@ -3,6 +3,8 @@ * Change method for atomic simultaneous set and unset * Optionally allow undefined composite states * Dynamic bits + * Optional binary contents + * Sync all if no state passed as argument - 0.1.0 * Release version bump - 0.0.19: diff --git a/shep/persist.py b/shep/persist.py @@ -129,7 +129,7 @@ class PersistedState(State): return to_state - def sync(self, state): + def sync(self, state=None): """Reload resources for a single state in memory from the persisted state store. :param state: State to load @@ -137,16 +137,24 @@ class PersistedState(State): :raises StateItemExists: A content key is already recorded with a different state in memory than in persisted store. # :todo: if sync state is none, sync all """ - k = self.name(state) + states = [] + if state == None: + states = list(self.all()) + else: + states = [self.name(state)] - self.__ensure_store(k) + ks = [] + for k in states: + ks.append(k) - for o in self.__stores[k].list(): + for k in ks: self.__ensure_store(k) - try: - super(PersistedState, self).put(o[0], state=state, contents=o[1]) - except StateItemExists: - pass + for o in self.__stores[k].list(): + state = self.from_name(k) + try: + super(PersistedState, self).put(o[0], state=state, contents=o[1]) + except StateItemExists as e: + pass def list(self, state): diff --git a/shep/state.py b/shep/state.py @@ -317,7 +317,7 @@ class State: """ if state == None: state = getattr(self, self.base_state_name) - elif self.__reverse.get(state) == None: + elif self.__reverse.get(state) == None and self.check_alias: raise StateInvalid(state) self.__check_key(key) self.__add_state_list(state, key) diff --git a/shep/store/file.py b/shep/store/file.py @@ -8,10 +8,14 @@ class SimpleFileStore: :param path: Filesystem base path for all state directory :type path: str """ - def __init__(self, path): + def __init__(self, path, binary=False): self.__path = path os.makedirs(self.__path, exist_ok=True) - + if binary: + self.__m = ['rb', 'wb'] + else: + self.__m = ['r', 'w'] + def add(self, k, contents=None): """Add a new key and optional contents @@ -25,7 +29,7 @@ class SimpleFileStore: if contents == None: contents = '' - f = open(fp, 'w') + f = open(fp, self.__m[1]) f.write(contents) f.close() @@ -51,7 +55,7 @@ class SimpleFileStore: :return: Contents """ fp = os.path.join(self.__path, k) - f = open(fp, 'r') + f = open(fp, self.__m[0]) r = f.read() f.close() return r @@ -66,7 +70,7 @@ class SimpleFileStore: files = [] for p in os.listdir(self.__path): fp = os.path.join(self.__path, p) - f = open(fp, 'r') + f = open(fp, self.__m[0]) r = f.read() f.close() if len(r) == 0: @@ -98,7 +102,7 @@ class SimpleFileStore: """ fp = os.path.join(self.__path, k) os.stat(fp) - f = open(fp, 'w') + f = open(fp, self.__m[1]) r = f.write(contents) f.close() @@ -119,8 +123,9 @@ class SimpleFileStoreFactory: :param path: Filesystem path as base path for states :type path: str """ - def __init__(self, path): + def __init__(self, path, binary=False): self.__path = path + self.__binary = binary def add(self, k): @@ -133,4 +138,4 @@ class SimpleFileStoreFactory: """ k = str(k) store_path = os.path.join(self.__path, k) - return SimpleFileStore(store_path) + return SimpleFileStore(store_path, binary=self.__binary) diff --git a/tests/test_file.py b/tests/test_file.py @@ -142,7 +142,7 @@ class TestStateReport(unittest.TestCase): os.stat(fp) - def test_sync(self): + def test_sync_one(self): self.states.put('abcd', state=self.states.FOO, contents='foo') self.states.put('xxx', state=self.states.FOO) self.states.put('yyy', state=self.states.FOO) @@ -162,6 +162,25 @@ class TestStateReport(unittest.TestCase): self.assertEqual(self.states.get('zzzz'), 'xyzzy') + def test_sync_all(self): + self.states.put('abcd', state=self.states.FOO) + self.states.put('xxx', state=self.states.BAR) + + fp = os.path.join(self.d, 'FOO', 'abcd') + f = open(fp, 'w') + f.write('foofoo') + f.close() + + fp = os.path.join(self.d, 'BAR', 'zzzz') + f = open(fp, 'w') + f.write('barbar') + f.close() + + self.states.sync() + self.assertEqual(self.states.get('abcd'), None) + self.assertEqual(self.states.get('zzzz'), 'barbar') + + def test_path(self): self.states.put('yyy', state=self.states.FOO) diff --git a/tests/test_store.py b/tests/test_store.py @@ -80,5 +80,6 @@ class TestStateItems(unittest.TestCase): self.assertIsNone(self.mockstore.v.get(item)) + if __name__ == '__main__': unittest.main()