Source code for helpers

import sys
import json

[docs]class Struct: """This class describes structures with arbitrary fields. It is used, e.g. for the communication between the supervisor and the UI. Example:: p = Struct() p.goal = Struct() p.goal.x = 0.0 p.goal.y = 0.5 p.velocity = Struct() p.velocity.v = 0.2 p.gains = Struct() p.gains.kp = 10.0 p.gains.ki = 2.0 p.gains.kd = 0.0 Alternatives:: p = Struct({'goal':{'x':0.0, 'y':0.5}, 'velocity':{'v':0.2}, 'gains':{'kp':10.0, 'ki':2.0, 'kd':0.0}}) p = Struct("{'goal':{'x':0.0, 'y':0.5}, 'velocity':{'v':0.2}, 'gains':{'kp':10.0, 'ki':2.0, 'kd':0.0}}") In the second case, the string has to be a valid JSON object. It is also impossible to use dictionaries as values in the Struct in these cases. """ def __init__(self,desc = None): if desc is not None: try: dct = dict(desc) except Exception: try: dct = dict(json.loads(desc)) except Exception: raise ValueError("Invalid Struct description {}".format(repr(desc))) for k,v in dct.items(): if isinstance(v,dict): self.__dict__[k] = Struct(v) else: self.__dict__[k] = v def __str__(self): def str_field(key,value): indent = " "*(len(str(key)) + 3) str_value = str(value) if isinstance(value,Struct): # create indent str_value = str_value.replace('\n','\n'+indent) return "{}: {}".format(key,str_value) return "Struct\n {}".format("\n ".join((str_field(k,v) for k,v in self.__dict__.items()))) def __repr__(self): return json.dumps(self.__dict__) # This might be the same as repr(dict), but it's safer. def __eq__(self,other): if not isinstance(other,Struct): return NotImplemented return len(self.__dict__) == len(other.__dict__) and all(k in other.__dict__ and other.__dict__[k] == v for k,v in self.__dict__.items() )
__loaded_modules = set()
[docs]def unload_user_modules(): """Unload all modules loaded so far with :func:`~helpers.load_by_name`""" global __loaded_modules if 'helpers' in __loaded_modules: __loaded_modules.remove('helpers') while __loaded_modules: module = __loaded_modules.pop() if module in sys.modules: del sys.modules[module] for module in list(sys.modules): if sys.modules[module] is None: del sys.modules[module]
[docs]def load_by_name(module_string, path = None): """Load a class from a module, specified by *module_string*. The *path* is an additional path that is prepended to the module string. E.g. ``C = load_by_name('mymodule.MyClass','path.to.module')`` is equivalent to ``from path.to.module.mymodule import MyClass as C``. """ global __loaded_modules pieces = module_string.split('.') if len(pieces) == 1: # No dot filename = module_string.lower() class_name = module_string else: filename = pieces[-2] class_name = pieces[-1] if len(pieces) > 2: # Many dots if path is None: path = ".".join(pieces[:-2]) else: path = ".".join([path] + pieces[:-2]) try: # Cache already loaded modules old_modules = set(sys.modules) try: # Load module if path is not None: module = __import__(path, globals(), locals(), [filename]).__dict__[filename] else: module = __import__(filename) except Exception: raise finally: # Store the difference __loaded_modules = __loaded_modules.union(set(sys.modules) - old_modules) return module.__dict__[class_name] except ImportError: print("Module {} failed to load".format(filename)) raise except KeyError: print("No class {} in module {}".format(class_name,filename)) raise