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:
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