usawa

Unnamed repository; edit this file 'description' to name the repository.
Info | Log | Files | Refs | Submodules | LICENSE

commit 452035fba633b71198cb3c1529704345a9275c04
parent 01f614ede0eb194c85ace7d1adce97f9aba63cd2
Author: lash <dev@holbrook.no>
Date:   Sun, 15 Feb 2026 00:12:59 +0000

Add docs for resolver

Diffstat:
Mdummy/usawa/resolve/base.py | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mdummy/usawa/resolve/fs.py | 28+++++++++++++++++++++++++---
2 files changed, 88 insertions(+), 7 deletions(-)

diff --git a/dummy/usawa/resolve/base.py b/dummy/usawa/resolve/base.py @@ -5,11 +5,22 @@ import hexathon from usawa.error import VerifyError +"""Verifies a key as a sha512 digest, optionally against the given value. + +:param k: Key to check. +:type k: bytes or hex string +:param v: Value to check against key. +:type v: bytes +:raises ValueError: Invalid key (not 512 bits) +:raises VerifyError: Value digest does not match key. +:return: Key as hex string +:rtype: str +""" def sha512_verify(k, v=None): if isinstance(k, str): k = bytes.fromhex(k) if len(k) != 64: - raise ValueError('expect 512 bit key') + raise ValueError('expect 512 bit key') khx = hexathon.uniform(k.hex()) if v != None: h = hashlib.sha512() @@ -21,13 +32,61 @@ def sha512_verify(k, v=None): class BaseResolver: - def get(self, k, v, verifier=None): + """A resolver abstracts an immutable store used for storing asset data. + + Key/value pairs put to the store are checked by the verifier function before submission. Similarly, the value retrieved is checked by the verifier against the key used to get it. + + :raises IOError: Resolver backend unavailable, temporarily or permanently. + :param verifier: Verifier function for checking keys and key/value relation. + :type verifier: function, by default usawa.resolve.sha512_verify + """ + def __init__(self, verifier=sha512_verify): + self.verifier = verifier + + + """Get value for key. + + :param k: Key + :type k: bytes or hex string + :raises FileNotFoundError: Key does not exist. + :raises PermissionError: No access to data. + :raises IOError: Any other read problem. + :return: Value + :rtype: bytes + """ + def get(self, k): raise NotImplementedError() + """Put value under key. - def put(self, k): + Value may not be available immediately after method returns, since the implementation may store asynchronously. + + :param k: Key + :type k: bytes or hex string + :param v: Value + :type v: bytes + :raises FileExistsError: Key exists. + :raises PermissionError: No access to data. + :raises IOError: Any other read problem. + :return: A textual representation of the key + :rtype: str + """ + def put(self, k, v): raise NotImplementedError() - def delete(self, k): + """Check availability of data without invoking a full get call. + + If -1 is returned, the key does not exist. + + If 0 is returned, the key has been added but may not yet be available for a get() call. + + If a value greater than 0 is returned, get() can safely be called. + + :param k: Key to check state for + :type k: bytes or hex string + :return: storage state + :rtype: int + """ + def state(self, k): raise NotImplementedError() diff --git a/dummy/usawa/resolve/fs.py b/dummy/usawa/resolve/fs.py @@ -4,7 +4,7 @@ import logging from .base import BaseResolver, sha512_verify from usawa.error import VerifyError -logg = logging.getLogger('usawa.fsresolver') +logg = logging.getLogger('usawa.resolve.fs') def normalize_keyname(k): @@ -17,12 +17,23 @@ def normalize_keyname(k): class FSResolver(BaseResolver): + """Resolver implementation for a filesystem directory. + + If directory does not exist it will be created, along with any necessary ascendants. + + :param path: Path to directory to store under. + :type path: str + :raises PermissionError: Insufficient access to create directory. + :seealso: usawa.resolve.BaseResolver + """ def __init__(self, path, verifier=sha512_verify): + super(FSResolver, self).__init__(verifier=verifier) self.path = os.path.realpath(path) - self.verifier = verifier os.makedirs(self.path, exist_ok=True) + """Implements usawa.resolve.BaseResolver + """ def get(self, k): khx = self.verifier(k) fp = os.path.join(self.path, khx) @@ -34,6 +45,8 @@ class FSResolver(BaseResolver): return v + """Implements usawa.resolve.BaseResolver + """ def put(self, k, v): khx = self.verifier(k, v=v) fp = os.path.join(self.path, khx) @@ -41,4 +54,13 @@ class FSResolver(BaseResolver): c = f.write(v) logg.debug('{} bytes written for key {}'.format(c, k)) f.close() - return v + return k + + + """Implements usawa.resolve.BaseResolver + """ + def have(self, k): + r = -1 + if os.path.is_file(): + r = 1 + return r