chainlib

Generic blockchain access library and tooling
Log | Files | Refs | README | LICENSE

commit 63f2694494cf61a423a80b7570ecfbca7658f89e
parent 24a56194291f94ccd35f87ad4f4b9c8f1b11b093
Author: lash <dev@holbrook.no>
Date:   Tue, 14 Feb 2023 05:28:33 +0000

Rename find to gen, enable contract context arg returns for gen

Diffstat:
MCHANGELOG | 7+++++++
Dchainlib/cli/find.py | 45---------------------------------------------
Achainlib/cli/gen.py | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Dchainlib/runnable/find.py | 49-------------------------------------------------
Achainlib/runnable/gen.py | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msetup.cfg | 2+-
6 files changed, 140 insertions(+), 95 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG @@ -1,3 +1,10 @@ +- 0.4.8 + * Introduce scheme to detect chainlib 'capable' modules. + * Add chainlib-gen tool to generate contract bytecode, constructor bytecode and other contract context data from chainlib modules. +- 0.4.7 + * Enable setting of unsigned sender from cli arguments +- 0.4.6 + * Load dialect module in settings - 0.4.5 * Add unsafe flag to base read field - 0.4.4 diff --git a/chainlib/cli/find.py b/chainlib/cli/find.py @@ -1,45 +0,0 @@ -# standard imports -import sys -import os -import logging -from importlib import import_module - -logg = logging.getLogger(__name__) - - -__mf = {} - -def execute_for_path(d, fltr=None, cmd=None, args=None, handler=None): - logg.debug('scanning package directory {}'.format(d)) - fp = os.path.join(d, 'data', '.chainlib') - if not os.path.exists(fp): - return None - s = os.path.basename(d) - if fltr != None and s not in fltr: - logg.info('skipped chainlib module "{}" not matching search filter'.format(s)) - return None - pm = __mf.get(s) - if pm != None: - logg.info('skipped chainlib module "{}" already exxcuted from {}'.format(s, pm)) - return None - __mf[s] = d - logg.info('found chainlib module {} in {}'.format(s, d)) - m = import_module(s) - handler(m, cmd, args) - - -def find_chainlib_modules(fltr=None, cmd=None, args=None, handler=None): - m = [] - for p in sys.path: - logg.debug('scanning path is {}'.format(p)) - (n, x) = os.path.splitext(p) - if x: - continue - for d in os.listdir(p): - dp = os.path.join(p, d) - if not os.path.isdir(dp): - continue - r = execute_for_path(dp, fltr=fltr, cmd=cmd, args=args, handler=handler) - if r != None: - m.append(r) - return m diff --git a/chainlib/cli/gen.py b/chainlib/cli/gen.py @@ -0,0 +1,49 @@ +# standard imports +import sys +import os +import logging +from importlib import import_module + +logg = logging.getLogger(__name__) + + +__mf = {} + +# to fulfill this protocol, the module MUST: +# * include a file MODULE/data/.chainlib +# * must export the method args(v) in the root module namespace. It must return the argument keys recognized by the command v, two arrays in a tuple, where the first array includes required argument keys and the second includes optional keys. If the command recognizes no arguments, an empty tuple should be returned. + +def execute_for_path(d, fltr=None, cmd=None, args=None, handler=None, is_key_query=False): + logg.debug('scanning package directory {}'.format(d)) + fp = os.path.join(d, 'data', '.chainlib') + if not os.path.exists(fp): + return None + s = os.path.basename(d) + if fltr != None and s not in fltr: + logg.info('skipped chainlib module "{}" not matching search filter'.format(s)) + return None + pm = __mf.get(s) + if pm != None: + logg.info('skipped chainlib module "{}" already exxcuted from {}'.format(s, pm)) + return None + __mf[s] = d + logg.info('found chainlib module {} in {}'.format(s, d)) + m = import_module(s) + handler(m, cmd, args, is_key_query=is_key_query) + + +def find_chainlib_modules(fltr=None, cmd=None, args=None, handler=None, is_key_query=False): + m = [] + for p in sys.path: + logg.debug('scanning path is {}'.format(p)) + (n, x) = os.path.splitext(p) + if x: + continue + for d in os.listdir(p): + dp = os.path.join(p, d) + if not os.path.isdir(dp): + continue + r = execute_for_path(dp, fltr=fltr, cmd=cmd, args=args, handler=handler, is_key_query=is_key_query) + if r != None: + m.append(r) + return m diff --git a/chainlib/runnable/find.py b/chainlib/runnable/find.py @@ -1,49 +0,0 @@ -# standard imports -import argparse -import sys -import os -import logging - -# local imports -from chainlib.cli.find import find_chainlib_modules - -logging.basicConfig(level=logging.WARNING) -logg = logging.getLogger() - - -ap = argparse.ArgumentParser() -ap.add_argument('--cmd', type=str, help='command to execute on module. default command will be executed if not specified') -ap.add_argument('--arg', type=str, action='append', help='argument for command to execute') -ap.add_argument('-v', action='store_true', help='verbose logging') -ap.add_argument('-vv', action='store_true', help='very verbose logging') -ap.add_argument('module', type=str, help='module to locate and execute') -args = ap.parse_args(sys.argv[1:]) - -if args.vv: - logg.setLevel(logging.DEBUG) -elif args.v: - logg.setLevel(logging.INFO) - - -def default_handler(m, cmd, args): - r = None - if cmd == None: - if args == None: - r = m.default() - else: - r = m.default(*args) - else: - fn = getattr(m, cmd) - if args == None: - r = fn() - else: - r = fn(*args) - print(r) - - -def main(): - find_chainlib_modules(fltr=[args.module], cmd=args.cmd, args=args.arg, handler=default_handler) - - -if __name__ == '__main__': - main() diff --git a/chainlib/runnable/gen.py b/chainlib/runnable/gen.py @@ -0,0 +1,83 @@ +# standard imports +import argparse +import sys +import os +import logging + +# local imports +from chainlib.cli.gen import find_chainlib_modules + +logging.basicConfig(level=logging.WARNING) +logg = logging.getLogger() + + +ap = argparse.ArgumentParser() +ap.add_argument('-v', action='store_true', help='verbose logging') +ap.add_argument('-vv', action='store_true', help='very verbose logging') +ap.add_argument('-k', action='store_true', help='return keys for command') +ap.add_argument('module', type=str, help='module to locate and execute') +ap.add_argument('command', type=str, nargs='?', help='command to execute on module. default command will be executed if not specified') +ap.add_argument('arg', type=str, nargs=argparse.REMAINDER) +args = ap.parse_args() + +if args.vv: + logg.setLevel(logging.DEBUG) +elif args.v: + logg.setLevel(logging.INFO) + +def parse_remaining(rargs): + rargsr = [] + for v in rargs: + if v == '-vv': + logg.setLevel(logging.DEBUG) + elif v == '-v': + logg.setLevel(logging.INFO) + elif v == '-k': + return None + else: + rargsr.append(v) + r = {} + logg.debug('parsing rargs {}'.format(rargsr)) + while True: + try: + pfx = rargsr.pop(0) + except IndexError: + break + if len(pfx) < 3 or pfx[:2] != '--': + raise ValueError('unexpected arg element: {}'.format(pfx)) + k = pfx[2:] + try: + v = rargsr.pop(0) + except IndexError: + raise ValueError('missing value for attribute: {}'.format(pfx)) + r[k] = v + return r + + +def default_handler(m, cmd, args, is_key_query=False): + r = None + + if is_key_query: + r = m.args(cmd) + print('required: ' + ', '.join(r[0])) + print('optional: ' + ', '.join(r[1])) + return + + fn = getattr(m, cmd) + if args == None: + r = fn() + else: + r = fn(**args) + print(r) + + +def main(): + arg = parse_remaining(args.arg) + is_key_query = False + if arg == None: + is_key_query = True + find_chainlib_modules(fltr=[args.module], cmd=args.command, args=arg, handler=default_handler, is_key_query=is_key_query) + + +if __name__ == '__main__': + main() diff --git a/setup.cfg b/setup.cfg @@ -23,4 +23,4 @@ classifiers = [options.entry_points] console_scripts = - chainlib-find = chainlib.runnable.find:main + chainlib-gen = chainlib.runnable.gen:main