From cc48280e006967b1ab97ab04c74b9c181352fcf8 Mon Sep 17 00:00:00 2001 From: mehtank <mehtank> Date: Thu, 29 Apr 2021 00:51:18 -0700 Subject: [PATCH] Generate component compositional hierarchy tree --- rocolib/__init__.py | 2 +- rocolib/library/__init__.py | 119 +++++++++++++----------------------- rocolib/utils/filter.py | 39 ------------ 3 files changed, 43 insertions(+), 117 deletions(-) delete mode 100644 rocolib/utils/filter.py diff --git a/rocolib/__init__.py b/rocolib/__init__.py index a54d298..db495d5 100644 --- a/rocolib/__init__.py +++ b/rocolib/__init__.py @@ -9,7 +9,7 @@ from os.path import realpath from os.path import relpath -__version__ = "0.2.1" +__version__ = "0.2.2" __author__ = 'UCLA LEMUR' __credits__ = 'The Laboratory for Embedded Machines and Ubiquitous Robots' diff --git a/rocolib/library/__init__.py b/rocolib/library/__init__.py index 5e3fbc3..73f6613 100644 --- a/rocolib/library/__init__.py +++ b/rocolib/library/__init__.py @@ -14,32 +14,51 @@ ROCOLIB_LIBRARY = dirname(realpath(__file__)) pyComponents = [ basename(f)[:-3] for f in glob(ROCOLIB_LIBRARY + "/[!_]*.py")] yamlComponents = [ basename(f)[:-5] for f in glob(ROCOLIB_LIBRARY + "/*.yaml")] -allComponents = list(set(pyComponents + yamlComponents)) +allComponents = set(pyComponents + yamlComponents) + +def getSubcomponents(c): + try: + return set((x['classname'] for x in load_yaml(c).get('subcomponents', dict()).values())) + except FileNotFoundError: + return set() + +def getComponentTree(): + tree = [] + ac = set(allComponents) + while ac: + leaves = [] + for c in ac: + subcomponents = getSubcomponents(c) + if not subcomponents.intersection(ac): + leaves.append(c) + tree.append(sorted(leaves)) + ac -= set(leaves) + return tree def getComponent(c, **kwargs): - ''' - Here we are doing Dynamic instantiation from string name of a class in dynamically imported module - Parameter c (str): component name e.g. 'Stool' - ''' - if c in pyComponents: - # Load "module.submodule.MyClass" - obj = getattr(importlib.import_module("rocolib.library." + c), c) - # Instantiate the class (pass arguments to the constructor, if needed) - my_obj = obj() - elif c in yamlComponents: - my_obj = Component(f"{ROCOLIB_LIBRARY}/{c}.yaml") - else: - raise ValueError(f"Component {c} not found in library") - - for k, v in kwargs.items(): - if k == 'name': - my_obj.setName(v) + ''' + Here we are doing Dynamic instantiation from string name of a class in dynamically imported module + Parameter c (str): component name e.g. 'Stool' + ''' + if c in pyComponents: + # Load "module.submodule.MyClass" + obj = getattr(importlib.import_module("rocolib.library." + c), c) + # Instantiate the class (pass arguments to the constructor, if needed) + my_obj = obj() + elif c in yamlComponents: + my_obj = Component(f"{ROCOLIB_LIBRARY}/{c}.yaml") else: - my_obj.setParameter(k, v) - if 'name' not in kwargs: - my_obj.setName(c) + raise ValueError(f"Component {c} not found in library") + + for k, v in kwargs.items(): + if k == 'name': + my_obj.setName(v) + else: + my_obj.setParameter(k, v) + if 'name' not in kwargs: + my_obj.setName(c) - return my_obj + return my_obj def rebuild(built=None): if built is None: @@ -71,7 +90,7 @@ def rebuildComponent(c, built=None, throw=True): for sc in subcomponents: rebuildComponent(sc, built) - # XXX TOOD: Test to make sure we don't call this script and then infinitely recurse! + # XXX TODO: Test to make sure we don't call this script and then infinitely recurse! log.debug(f"Calling os.system: % python {ROCOLIB_LIBRARY}/{src}") if system(f"python {ROCOLIB_LIBRARY}/{src}"): success = False @@ -94,57 +113,3 @@ def getComponentPaths(c): if src: paths["builder"] = rocopath(join(ROCOLIB_LIBRARY, src)) return paths - - -# tag : [[required ports], [forbidden ports]] -tagDefinitions = { - 'sensor': [["DataOutputPort"],[]], - 'actuator': [["DataInputPort"],[]], - 'mechanical': [["EdgePort"],[]], - 'device': [["MountPort"],[]], - 'UI': [[],["MountPort", "EdgePort"]] -} - -def tag(ports): - tags = {} - portset = set(ports.keys()) - for tag, (must, cant) in tagDefinitions.items(): - if set(must).issubset(portset) and not len(set(cant).intersection(portset)): - tags[tag] = [port for ptype in must for port in ports[ptype] ] - return tags - -_taggedComponents = {} -def getTags(x): - if x in _taggedComponents: - return _taggedComponents[x] - - try: - c = getComponent(x) - except: - return None - - if isinstance(c, Component): - interfaces = list(c.interfaces.keys()) - ports = {} - for iname in interfaces: - i = c.getInterface(iname) - iclass = i.__class__.__name__ - try: - ports[iclass].append(iname) - except KeyError: - ports[iclass] = [iname] - _taggedComponents[x] = tag(ports) - return tag(ports) - return None - -def taggedComponents(components = None): - if components == None: - components = allComponents - for x in components: - if getTags(x): - yield x, getTags(x) - -def filterComponents(tagList, components = None): - for x, tags in taggedComponents(components): - if set(tagList).issubset(set(tags.keys())): - yield x, [port for tag in tagList for port in tags[tag] ] diff --git a/rocolib/utils/filter.py b/rocolib/utils/filter.py deleted file mode 100644 index bfc90ea..0000000 --- a/rocolib/utils/filter.py +++ /dev/null @@ -1,39 +0,0 @@ -from rocolib.library import filterComponents - -print("~~~") -print("Actuators") -print("~~~") -''' -print "All:" -for c in filterComponents(["actuator"]): - print "-", c -''' -print("Mechanical actuators:") -for c in filterComponents(["actuator", "mechanical"]): - print("-", c) -print("Physical interface devices:") -for c in filterComponents(["actuator", "device"]): - print("-", c) -print("Virtual UI widgets:") -for c in filterComponents(["actuator", "UI"]): - print("-", c) - -print() - -print("~~~") -print("Sensors") -print("~~~") -''' -print "All:" -for c in filterComponents(["sensor"]): - print "-", c -print "Mechanical feedback sensors:" -for c in filterComponents(["sensor", "mechanical"]): - print "-", c -''' -print("Environmental sensing devices:") -for c in filterComponents(["sensor", "device"]): - print("-", c) -print("Virtual UI widgets:") -for c in filterComponents(["sensor", "UI"]): - print("-", c) -- GitLab