diff --git a/rocolib/__main__.py b/rocolib/__main__.py index 32c397df2f6e1e1c86ab2d47226055a938769d74..fc980a6f6d0ecd89ee182bfcf05298ad8d551d08 100644 --- a/rocolib/__main__.py +++ b/rocolib/__main__.py @@ -4,6 +4,7 @@ import yaml import sys import logging import argparse +from os.path import basename from pprint import pprint from textwrap import shorten from dash import Dash @@ -11,7 +12,7 @@ from rocolib.library import getComponent, getComponentTree from rocolib.api.composables.graph.Joint import FingerJoint -def test(component, params, thickness, outdir=None, display=False): +def test(component, params, thickness, outdir=None, display=False, outputs=None): f = getComponent(component) if params is not None: for p in params: @@ -32,11 +33,16 @@ def test(component, params, thickness, outdir=None, display=False): if outdir: filedir = f"{outdir}/{component}" - ret = f.makeOutput(outputs = True, filedir=filedir, thickness=t, joint=j, remake=False) + outputs = outputs or True + else: + filedir = None + outputs = outputs or () + ret = f.makeOutput(outputs = outputs, filedir=filedir, thickness=t, joint=j, remake=False) for composable, outs in ret.items(): - print(f"Composable: {composable}") - pprint({k: shorten(str(v), 60) for k, v in outs.items()}) + if outs: + print(f"Composable: {composable}") + pprint({k: shorten(str(v), 60) for k, v in outs.items()}) if display: app = Dash(__name__) @@ -48,6 +54,8 @@ def cli_argparse(): LOG_LEVELS = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] DEFAULT_LOG_LEVEL = "WARNING" + rocoview = (basename(sys.argv[0]) == "rocoview") + parser = argparse.ArgumentParser() parser.add_argument("component", nargs='?', @@ -66,7 +74,11 @@ def cli_argparse(): parser.add_argument("-P", help="List component parameters (use multiple times for more detail)", dest="param_list", action="append_const", const=1) parser.add_argument("-t", type=float, help="Thickness (i.e. making with wood)") - parser.add_argument("-d", action='store_true', help="Display visualizations") + if not rocoview: + parser.add_argument("-d", action='store_true', help="Display visualizations") + parser.add_argument("-s", type=str, action='append', help="Select specific outputs to save") + parser.add_argument("-S", help="List composable outputs (use multiple times for more detail)", + dest="output_list", action="append_const", const=1) parser.add_argument("-p", nargs=2, action='append', metavar=("NAME", "VALUE"), help="Set component parameter NAME to value VALUE") @@ -76,6 +88,8 @@ def cli_argparse(): sys.exit(1) args = parser.parse_args() + if rocoview: + args.d = True log_level = LOG_LEVELS.index(DEFAULT_LOG_LEVEL) # For each "-q" and "-v" flag, adjust the logging verbosity accordingly @@ -108,34 +122,41 @@ def cli_argparse(): else: outdir = args.output else: - outdir = "output" + outdir = not rocoview and "output" or None if args.component: - if args.interface_list: + def printList(arg, lsfn, make=False): + if not arg: + return f = getComponent(args.component) - info = f.getInterfaceInfo(len(args.interface_list)) - if len(args.interface_list) == 1: - print("\n".join(info)) - else: - pprint(info) - + if make: + f.make() + ls = lsfn(f) + ind = min(len(arg), len(ls)) - 1 + pprint(ls[ind]) if not args.p or args.t or args.d: exit(0) - if args.param_list: - f = getComponent(args.component) - info = f.getParameterInfo() - if len(args.param_list) == 1: - print("\n".join(info.keys())) - elif len(args.param_list) == 2: - pprint({k: v['defaultValue'] for k,v in info.items()}) - elif len(args.param_list) == 3: - pprint({k: {x: v[x] for x in ('defaultValue', 'spec')} for k,v in info.items()}) - else: - pprint(info) - if not args.p or args.t or args.d: - exit(0) - test(args.component, args.p, thickness=args.t, outdir=outdir, display=args.d) + printList(args.interface_list, lambda c : (lambda info : ( + list(info.keys()), + {k: v["port"] for k, v in info.items()}, + info, + ))(c.getInterfaceInfo())) + + printList(args.param_list, lambda c : (lambda info : ( + list(info.keys()), + {k: v["defaultValue"] for k, v in info.items()}, + {k: {x: v[x] for x in ('defaultValue', 'spec')} for k,v in info.items()}, + info, + ))(c.getParameterInfo())) + + printList(args.output_list, lambda c : (lambda info : ( + {composable: list(outputs.keys()) for composable, outputs in info.items()}, + {composable: {k: {x: v[x] for x in ('stub', 'widget')} for k, v in outputs.items()} for composable, outputs in info.items()}, + info, + ))(c.listOutputs()), make=True) + + test(args.component, args.p, thickness=args.t, outdir=outdir, display=args.d, outputs=args.s) acted = True if not acted: diff --git a/rocolib/api/components/Component.py b/rocolib/api/components/Component.py index b94d56c7e8bfc6364b717c53ddbc7f00aa895b74..e2546838d0269377abce29d96b96c95c467292de 100644 --- a/rocolib/api/components/Component.py +++ b/rocolib/api/components/Component.py @@ -121,12 +121,6 @@ class Component(Parameterized): pass def getInterfaceInfo(self, detail=1): - if detail == 1: - return list(self.interfaces.keys()) - - if detail == 2: - return {x: self.getInterface(x, transient=True).__class__.__name__ for x in self.interfaces} - i = {x: dict(port = self.getInterface(x, transient=True).__class__.__name__) for x in self.interfaces} for k, v in self.interfaces.items(): if isinstance(v, dict): @@ -549,6 +543,13 @@ class Component(Parameterized): elts.append(html.Div(dcc.Tabs(tabs))) return html.Div(elts) + def listOutputs(self): + rets = {} + for (name, composable) in self.composables.items(): + ss = composable.listOutputs(None) + rets[name] = ss + return rets + def makeOutput(self, outputs=(), filedir=None, widgets=False, **ka): if filedir: log.info(f"Compiling robot designs to directory {filedir} ...") @@ -569,7 +570,6 @@ class Component(Parameterized): pass rets = {} - for (name, composable) in self.composables.items(): ss = composable.makeOutput(name, outputs, filedir, widgets, **ka) rets[name] = ss diff --git a/rocolib/api/composables/Composable.py b/rocolib/api/composables/Composable.py index 8b51fec41e414970542ae286d74fb4fb7953dbaf..35d4e501a2f27ad00289aeaeca12f4b8b37faec2 100644 --- a/rocolib/api/composables/Composable.py +++ b/rocolib/api/composables/Composable.py @@ -32,7 +32,7 @@ class Composable: if hasattr(method, 'output'): out = method.output keyword = out['stub'].split('.')[0] - if out['widget'] == widgets: + if out['widget'] == widgets or widgets is None: outputs[keyword] = out return outputs diff --git a/setup.py b/setup.py index c17117ffeb993ef68fb85d51ff2441a0b73e8dbb..beedf6f39189b618d91a41884bcb41e46b2cf51f 100644 --- a/setup.py +++ b/setup.py @@ -55,6 +55,7 @@ setup( entry_points={ 'console_scripts': [ 'roco = rocolib.__main__:cli_argparse', + 'rocoview = rocolib.__main__:cli_argparse', ] }, )