usawa

Signed, immutable accounting.
Log | Files | Refs | Submodules | LICENSE

commit beabc49b77a26cfaf8263d34392d02ff44f9605c
parent 01df1e54806b09d5aad99fc9d8d020cddd0db97d
Author: lash <dev@holbrook.no>
Date:   Sun, 22 Mar 2026 21:56:14 -0600

Add test for indexed asset store

Diffstat:
Adummy/tests/base.py | 26++++++++++++++++++++++++++
Mdummy/tests/store.py | 22++++++++++++++++++++--
Mdummy/usawa/store.py | 109+++++++++++++++++++++++++++++++++++++++++++------------------------------------
3 files changed, 106 insertions(+), 51 deletions(-)

diff --git a/dummy/tests/base.py b/dummy/tests/base.py @@ -0,0 +1,26 @@ +import unittest +import logging + +from usawa.base import UsawaElement + +logging.basicConfig(level=logging.DEBUG) +logg = logging.getLogger() + + +class TestElement(unittest.TestCase): + + def test_element_serialize(self): + o = UsawaElement() + o.add_tag('foo') + o.add_tag('bar') + o.add_tag('baz') + o.add_pair('inky', 'pinky') + o.add_pair('blinky', 'clyde') + + v = o.serialize() + o = UsawaElement() + o.deserialize(v) + + +if __name__ == '__main__': + unittest.main() diff --git a/dummy/tests/store.py b/dummy/tests/store.py @@ -9,7 +9,7 @@ import lxml.etree from whee.mem import MemStore from usawa import Ledger, UnitIndex, EntryPart, Entry, DemoWallet, Asset -from usawa.store import LedgerStore +from usawa.store import LedgerStore, AssetStore from usawa.crypto import ACL logging.basicConfig(level=logging.DEBUG) @@ -17,6 +17,9 @@ logg = logging.getLogger() testdir = os.path.realpath(os.path.dirname(__file__)) +hash_of_foo = bytes.fromhex('f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7') +uuid_for_foo = uuid.UUID('9ce0268e-4add-4874-9a00-322dd0157c97') + class TestStore(unittest.TestCase): @@ -173,7 +176,22 @@ class TestStore(unittest.TestCase): store.put_draft(o) o = store.get_draft(o) - + + + def test_store_asset_index(self): + store = AssetStore(self.store) + asset = Asset(digest=hash_of_foo, ref=str(uuid_for_foo)) + store.add_asset(asset) + + asset = Asset(digest=hash_of_foo) + o = store.get_asset(asset) + self.assertEqual(o.get_digest(binary=True), hash_of_foo) + self.assertEqual(o.get_ref(binary=True), uuid_for_foo.bytes) + + asset = Asset(ref=str(uuid_for_foo)) + o = store.get_asset_indexed(asset) + self.assertEqual(o.get_digest(binary=True), hash_of_foo) + self.assertEqual(o.get_ref(binary=True), uuid_for_foo.bytes) if __name__ == '__main__': unittest.main() diff --git a/dummy/usawa/store.py b/dummy/usawa/store.py @@ -208,55 +208,6 @@ class EntryStore(BaseStore): i += 1 return entry -class LedgerStore(EntryStore, KeyStore): - """Wrapper for an implementation of the whee store that handles encoding of ledgers and entries. - - :param implementation: Store implementation. - :type implementation: whee.Interface (implementation) - :param ledger: The ledger for which to execute store operations. - :type ledger: usawa.Ledger - """ - def __init__(self, implementation, ledger): - super(LedgerStore, self).__init__(implementation) - if not isinstance(ledger, Ledger): - raise ValueError('invalid ledger') - self.ledger = ledger - - - """Implements whee.Interface.start - """ - def start(self): - serial = 0 - k = pfx_ledger_topic(self.ledger.topic) - try: - b = self.db.get(k) - serial = int.from_bytes(8, byteorder='big') - except FileNotFoundError: - v = serial.to_bytes(8, byteorder='big') - self.db.put(k, v) - self.ledger.serial = serial - - - """Implements whee.Interface.lock - """ - def lock(self): - k = pfx_ledger_lock(self.ledger.topic) - v = None - # TODO: needs to be an atomic routine - try: - v = self.db.get(k) - except KeyError: - raise PermissionError() - self.db.put(k, 0x01, exist_ok) - # atomic until here - - - """Implements whee.Interface.unlock - """ - def unlock(self): - k = pfx_ledger_lock(self.ledger.topic) - v = self.db.delete(k) - """Add an entry to the store. @@ -303,6 +254,8 @@ class LedgerStore(EntryStore, KeyStore): return entry +class AssetStore(BaseStore): + """Add an entry attachment asset to the store. :param asset: Asset containing digest to restore. @@ -327,6 +280,64 @@ class LedgerStore(EntryStore, KeyStore): return Asset.deserialize(v, digest) + """Restore an entry attachment asset from the store using the reference index. + """ + def get_asset_indexed(self, asset): + k = pfx_asset_index(asset) + k = self.db.get(k) + v = self.db.get(k) + return Asset.deserialize(v, k[1:]) + + +class LedgerStore(EntryStore, AssetStore, KeyStore): + """Wrapper for an implementation of the whee store that handles encoding of ledgers and entries. + + :param implementation: Store implementation. + :type implementation: whee.Interface (implementation) + :param ledger: The ledger for which to execute store operations. + :type ledger: usawa.Ledger + """ + def __init__(self, implementation, ledger): + super(LedgerStore, self).__init__(implementation) + if not isinstance(ledger, Ledger): + raise ValueError('invalid ledger') + self.ledger = ledger + + + """Implements whee.Interface.start + """ + def start(self): + serial = 0 + k = pfx_ledger_topic(self.ledger.topic) + try: + b = self.db.get(k) + serial = int.from_bytes(8, byteorder='big') + except FileNotFoundError: + v = serial.to_bytes(8, byteorder='big') + self.db.put(k, v) + self.ledger.serial = serial + + + """Implements whee.Interface.lock + """ + def lock(self): + k = pfx_ledger_lock(self.ledger.topic) + v = None + # TODO: needs to be an atomic routine + try: + v = self.db.get(k) + except KeyError: + raise PermissionError() + self.db.put(k, 0x01, exist_ok) + # atomic until here + + + """Implements whee.Interface.unlock + """ + def unlock(self): + k = pfx_ledger_lock(self.ledger.topic) + v = self.db.delete(k) + """Load all entries from store, oldest to newest. Must be called on an unused ledger instance. Using with a ledger that contains or has contains entries is undefined.