usawa

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

commit ad861a4e91d1a290498d9172383ed3adee61ba14
parent 7f2dadcfc9d407e16559f4f36b36023c6ee10cc4
Author: lash <dev@holbrook.no>
Date:   Mon, 18 May 2026 18:03:57 -0600

Add linker cli

Diffstat:
Mdummy/usawa/link.py | 2+-
Adummy/usawa/runnable/link.py | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/dummy/usawa/link.py b/dummy/usawa/link.py @@ -30,7 +30,7 @@ class EntryLink: self.idx[entry.serial] = s if self.idx_ref != None: self.idx_ref[entry.ref] = s - logg.debug('link {} added entry {}'.format(link_uuid, entry)) + logg.info('link {} added entry {}'.format(link_uuid, entry)) def link_to(self, anchor, entry): diff --git a/dummy/usawa/runnable/link.py b/dummy/usawa/runnable/link.py @@ -0,0 +1,79 @@ +import os +import sys +import logging +import urllib.parse +import argparse +import uuid +import datetime +#import getpass + +import usawa.config +from usawa.context import UsawaContext +from usawa import Ledger, Entry, EntryPart, DemoWallet, UnitIndex, load, ACL +from usawa.link import EntryLink +from usawa.constant import CATEGORIES +from usawa.store import LedgerStore +from whee.valkey import ValkeyStore +from whee.fs import FsStore +from xdg_base_dirs import xdg_data_home + +logging.basicConfig(level=logging.WARNING) +logg = logging.getLogger() + + +def main(): + argp = argparse.ArgumentParser() + argp.add_argument('-o', type=str, dest='output', help='output file for resulting XML document') + #argp.add_argument('-p', action='store_true', help='prompt for password to open wallet') + argp.add_argument('-c', type=str, help='override config dir') + argp.add_argument('-v', type=str, choices=['info','debug','warning','error'], help='be verbose') + argp.add_argument('-i', type=str, help='input ledger state') + argp.add_argument('--link-id', type=str, help='link uuid') + argp.add_argument('entries', nargs='+', type=str, help='entries to link') + arg = argp.parse_args() + + if arg.v: + logg.setLevel(getattr(logging, arg.v.upper())) + + cfg = usawa.config.load_config(config_dir=arg.c) + ctx = UsawaContext(cfg, signing=False) + ctx.init(arg) + + linker = EntryLink(ctx.ledger) + #ctx.store.load(entry_callback_post, linker=linker) + ctx.store.load(linker=linker) + + entries = [] + for v in arg.entries: + o = None + try: + o = Entry.empty(serial=int(v)) + except ValueError: + o = Entry.empty(ref=uuid.UUID(v)) + entry = ctx.store.get_entry(o, linker=linker) + logg.info('entry {}'.format(entry)) + entries.append(entry) + + anchor = None + link_id = None + for o in entries: + r = linker.get(o) + if r == None: + if anchor == None: + anchor = o + link_id = anchor.ref + elif link_id == None: + link_id = r + elif link_id != r: + raise AttributeError('link {} does not match link {} for entry {}'.format(r, link_id, o)) + + + for o in entries: + try: + linker.link(o, link_uuid=link_id) + except FileExistsError: + logg.debug('link {} exists for entry {}'.format(link_id, o)) + + +if __name__ == '__main__': + main()