2022-01-31 16:53:33 +01:00
|
|
|
# standard imports
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
|
|
class SimpleFileStore:
|
2022-02-09 18:30:41 +01:00
|
|
|
"""Filesystem store of contents for state, with one directory per state.
|
2022-01-31 16:53:33 +01:00
|
|
|
|
2022-02-09 18:30:41 +01:00
|
|
|
:param path: Filesystem base path for all state directory
|
|
|
|
:type path: str
|
|
|
|
"""
|
2022-01-31 16:53:33 +01:00
|
|
|
def __init__(self, path):
|
2022-02-02 08:24:43 +01:00
|
|
|
self.__path = path
|
|
|
|
os.makedirs(self.__path, exist_ok=True)
|
2022-01-31 16:53:33 +01:00
|
|
|
|
|
|
|
|
2022-02-04 23:15:51 +01:00
|
|
|
def add(self, k, contents=None):
|
2022-02-09 18:30:41 +01:00
|
|
|
"""Add a new key and optional contents
|
|
|
|
|
|
|
|
:param k: Content key to add
|
|
|
|
:type k: str
|
|
|
|
:param contents: Optional contents to assign for content key
|
|
|
|
:type contents: any
|
|
|
|
"""
|
2022-02-02 08:24:43 +01:00
|
|
|
fp = os.path.join(self.__path, k)
|
2022-02-02 10:27:57 +01:00
|
|
|
if contents == None:
|
2022-02-01 10:34:36 +01:00
|
|
|
contents = ''
|
|
|
|
|
2022-01-31 16:53:33 +01:00
|
|
|
f = open(fp, 'w')
|
|
|
|
f.write(contents)
|
|
|
|
f.close()
|
|
|
|
|
|
|
|
|
2022-02-01 14:54:27 +01:00
|
|
|
def remove(self, k):
|
2022-02-09 18:30:41 +01:00
|
|
|
"""Remove a content key from a state.
|
|
|
|
|
|
|
|
:param k: Content key to remove from the state
|
|
|
|
:type k: str
|
|
|
|
:raises FileNotFoundError: Content key does not exist in the state
|
|
|
|
"""
|
2022-02-02 08:24:43 +01:00
|
|
|
fp = os.path.join(self.__path, k)
|
2022-02-01 14:54:27 +01:00
|
|
|
os.unlink(fp)
|
|
|
|
|
2022-02-09 18:30:41 +01:00
|
|
|
|
2022-02-01 10:34:36 +01:00
|
|
|
def get(self, k):
|
2022-02-09 18:30:41 +01:00
|
|
|
"""Retrieve the content for the given content key.
|
|
|
|
|
|
|
|
:param k: Content key to retrieve content for
|
|
|
|
:type k: str
|
|
|
|
:raises FileNotFoundError: Content key does not exist for the state
|
|
|
|
:rtype: any
|
|
|
|
:return: Contents
|
|
|
|
"""
|
2022-02-02 08:24:43 +01:00
|
|
|
fp = os.path.join(self.__path, k)
|
2022-02-01 10:34:36 +01:00
|
|
|
f = open(fp, 'r')
|
|
|
|
r = f.read()
|
|
|
|
f.close()
|
|
|
|
return r
|
|
|
|
|
|
|
|
|
2022-02-01 15:38:24 +01:00
|
|
|
def list(self):
|
2022-02-09 18:30:41 +01:00
|
|
|
"""List all content keys persisted for the state.
|
|
|
|
|
|
|
|
:rtype: list of str
|
|
|
|
:return: Content keys in state
|
|
|
|
"""
|
2022-02-01 15:38:24 +01:00
|
|
|
files = []
|
2022-02-02 08:24:43 +01:00
|
|
|
for p in os.listdir(self.__path):
|
|
|
|
fp = os.path.join(self.__path, p)
|
2022-02-01 15:38:24 +01:00
|
|
|
f = open(fp, 'r')
|
|
|
|
r = f.read()
|
|
|
|
f.close()
|
|
|
|
if len(r) == 0:
|
|
|
|
r = None
|
|
|
|
files.append((p, r,))
|
|
|
|
return files
|
|
|
|
|
|
|
|
|
2022-02-09 18:30:41 +01:00
|
|
|
def path(self, k=None):
|
|
|
|
"""Return filesystem path for persisted state or state item.
|
|
|
|
|
|
|
|
:param k: If given, will return filesystem path to specified content key
|
|
|
|
:type k: str
|
|
|
|
:rtype: str
|
|
|
|
:return: File path
|
|
|
|
"""
|
|
|
|
if k == None:
|
2022-02-02 08:24:43 +01:00
|
|
|
return self.__path
|
2022-02-09 18:30:41 +01:00
|
|
|
return os.path.join(self.__path, k)
|
|
|
|
|
2022-02-02 08:24:43 +01:00
|
|
|
|
2022-02-09 18:30:41 +01:00
|
|
|
def replace(self, k, contents):
|
|
|
|
"""Replace persisted content for persisted content key.
|
2022-02-02 08:24:43 +01:00
|
|
|
|
2022-02-09 18:30:41 +01:00
|
|
|
:param k: Content key to replace contents for
|
|
|
|
:type k: str
|
|
|
|
:param contents: Contents
|
|
|
|
:type contents: any
|
|
|
|
"""
|
|
|
|
fp = os.path.join(self.__path, k)
|
2022-02-04 23:15:51 +01:00
|
|
|
os.stat(fp)
|
|
|
|
f = open(fp, 'w')
|
|
|
|
r = f.write(contents)
|
|
|
|
f.close()
|
|
|
|
|
|
|
|
|
2022-03-13 17:36:17 +01:00
|
|
|
def modified(self, k):
|
|
|
|
path = self.path(k)
|
|
|
|
st = os.stat(path)
|
|
|
|
return float(st.st_ctime())
|
|
|
|
|
|
|
|
|
|
|
|
def register_modify(self, k):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2022-01-31 16:53:33 +01:00
|
|
|
class SimpleFileStoreFactory:
|
2022-02-09 18:30:41 +01:00
|
|
|
"""Provide a method to instantiate SimpleFileStore instances that provide persistence for individual states.
|
2022-01-31 16:53:33 +01:00
|
|
|
|
2022-02-09 18:30:41 +01:00
|
|
|
:param path: Filesystem path as base path for states
|
|
|
|
:type path: str
|
|
|
|
"""
|
2022-01-31 16:53:33 +01:00
|
|
|
def __init__(self, path):
|
2022-02-02 08:24:43 +01:00
|
|
|
self.__path = path
|
2022-01-31 16:53:33 +01:00
|
|
|
|
|
|
|
|
|
|
|
def add(self, k):
|
2022-02-09 18:30:41 +01:00
|
|
|
"""Create a new SimpleFileStore for a state.
|
|
|
|
|
|
|
|
:param k: Identifier for the state
|
|
|
|
:type k: str
|
|
|
|
:rtype: SimpleFileStore
|
|
|
|
:return: A filesystem persistence instance with the given identifier as subdirectory
|
|
|
|
"""
|
2022-01-31 16:53:33 +01:00
|
|
|
k = str(k)
|
2022-02-02 08:24:43 +01:00
|
|
|
store_path = os.path.join(self.__path, k)
|
2022-01-31 16:53:33 +01:00
|
|
|
return SimpleFileStore(store_path)
|