def _setup_vars(self, cname, component): self.logger.debug("Injecting magic variables into %s", cname) component_type = type(component) # Iterate over variables with type annotations for n, inject_type in get_class_annotations(component_type).items(): # If the variable is private ignore it if n.startswith('_'): continue if hasattr(component_type, n): attr = getattr(component_type, n) # If the value given to the variable is an instance of a type and isn't a property # raise an error. No double declaring types, e.g foo: type = type if isinstance(attr, type) and not isinstance(attr, property): raise ValueError("%s.%s has two type declarations" % (component_type.__name__, n)) # Otherwise, skip this set class variable continue # If the variable has been assigned in __init__, skip it if hasattr(component, n): continue # If the type is not actually a type, give a meaningful error if not isinstance(inject_type, type): raise TypeError( 'Component %s has a non-type annotation on %s (%r); lone non-injection variable annotations are disallowed, did you want to assign a static variable?' % (cname, n, inject_type)) self._inject(n, inject_type, cname, component) # Iterate over static variables for n in dir(component): # If the variable is private or a proprty, don't inject if n.startswith('_') or isinstance( getattr(component_type, n, True), property): continue inject_type = getattr(component, n) # If the value assigned isn't a type, don't inject if not isinstance(inject_type, type): continue self._inject(n, inject_type, cname, component) for (name, method) in inspect.getmembers(component, predicate=inspect.ismethod): if getattr(method, '__feedback__', False): self._feedbacks.append((component, cname, name))
def _setup_vars(self, cname, component): self.logger.debug("Injecting magic variables into %s", cname) component_type = type(component) # Iterate over variables with type annotations for n, inject_type in get_class_annotations(component_type).items(): # If the variable is private ignore it if n.startswith('_'): continue if hasattr(component_type, n): attr = getattr(component_type, n) # If the value given to the variable is an instance of a type and isn't a property # raise an error. No double declaring types, e.g foo: type = type if isinstance(attr, type) and not isinstance(attr, property): raise ValueError("%s.%s has two type declarations" % (component_type.__name__, n)) # Otherwise, skip this set class variable continue # If the variable has been assigned in __init__, skip it if hasattr(component, n): continue # If the type is not actually a type, give a meaningful error if not isinstance(inject_type, type): raise TypeError('Component %s has a non-type annotation on %s (%r); lone non-injection variable annotations are disallowed, did you want to assign a static variable?' % (cname, n, inject_type)) self._inject(n, inject_type, cname, component) # Iterate over static variables for n in dir(component): # If the variable is private or a proprty, don't inject if n.startswith('_') or isinstance(getattr(component_type, n, True), property): continue inject_type = getattr(component, n) # If the value assigned isn't a type, don't inject if not isinstance(inject_type, type): continue self._inject(n, inject_type, cname, component) for (name, method) in inspect.getmembers(component, predicate=inspect.ismethod): if getattr(method, '__feedback__', False): self._feedbacks.append((component, cname, name))
def _create_components(self): # # TODO: Will need to inject into any autonomous mode component # too, as they're a bit different # # TODO: Will need to order state machine components before # other components just in case components = [] self.logger.info("Creating magic components") # Identify all of the types, and create them cls = self.__class__ # - Iterate over class variables with type annotations for m, ctyp in get_class_annotations(cls).items(): # Ignore private variables if m.startswith('_'): continue if hasattr(cls, m): attr = getattr(cls, m) # If the value given to the variable is an instance of a type and isn't a property # raise an error. No double declaring types, e.g foo: type = type if isinstance(attr, type) and not isinstance(attr, property): raise ValueError("%s.%s has two type declarations" % (cls.__name__, m)) # Otherwise, skip this set class variable continue # If the variable has been assigned in __init__ or createObjects, skip it if hasattr(self, m): continue # If the type is not actually a type, give a meaningful error if not isinstance(ctyp, type): raise TypeError('%s has a non-type annotation on %s (%r); lone non-injection variable annotations are disallowed, did you want to assign a static variable?' % (cls.__name__, m, ctyp)) component = self._create_component(m, ctyp) # Store for later components.append((m, component)) # - Iterate over set class variables for m in self.members: if m.startswith('_') or isinstance(getattr(cls, m, None), _TunableProperty): continue ctyp = getattr(self, m) if not isinstance(ctyp, type): continue component = self._create_component(m, ctyp) # Store for later components.append((m, component)) # Collect attributes of this robot that are injectable self._injectables = {} for n in dir(self): if n.startswith('_') or n in self._exclude_from_injection or \ isinstance(getattr(cls, n, None), _TunableProperty): continue o = getattr(self, n) # Don't inject methods # TODO: This could actually be a cool capability.. if inspect.ismethod(o): continue self._injectables[n] = o # For each new component, perform magic injection for cname, component in components: self._components.append(component) setup_tunables(component, cname, 'components') self._setup_vars(cname, component) self._setup_reset_vars(component) # Do it for autonomous modes too for mode in self._automodes.modes.values(): mode.logger = logging.getLogger(mode.MODE_NAME) setup_tunables(mode, mode.MODE_NAME, 'autonomous') self._setup_vars(mode.MODE_NAME, mode) # And for self too setup_tunables(self, 'robot', None) # Call setup functions for components for cname, component in components: if hasattr(component, 'setup'): component.setup()
def _create_components(self): # # TODO: Will need to inject into any autonomous mode component # too, as they're a bit different # # TODO: Will need to order state machine components before # other components just in case components = [] self.logger.info("Creating magic components") # Identify all of the types, and create them cls = self.__class__ # - Iterate over class variables with type annotations for m, ctyp in get_class_annotations(cls).items(): # Ignore private variables if m.startswith("_"): continue if hasattr(cls, m): attr = getattr(cls, m) # If the value given to the variable is an instance of a type and isn't a property # raise an error. No double declaring types, e.g foo: type = type if isinstance(attr, type) and not isinstance(attr, property): raise ValueError( "%s.%s has two type declarations" % (cls.__name__, m) ) # Otherwise, skip this set class variable continue # If the variable has been assigned in __init__ or createObjects, skip it if hasattr(self, m): continue # If the type is not actually a type, give a meaningful error if not isinstance(ctyp, type): raise TypeError( "%s has a non-type annotation on %s (%r); lone non-injection variable annotations are disallowed, did you want to assign a static variable?" % (cls.__name__, m, ctyp) ) component = self._create_component(m, ctyp) # Store for later components.append((m, component)) # - Iterate over set class variables for m in self.members: if m.startswith("_") or isinstance(getattr(cls, m, None), tunable): continue ctyp = getattr(self, m) if not isinstance(ctyp, type): continue component = self._create_component(m, ctyp) # Store for later components.append((m, component)) # Collect attributes of this robot that are injectable self._injectables = {} for n in dir(self): if ( n.startswith("_") or n in self._exclude_from_injection or isinstance(getattr(cls, n, None), tunable) ): continue o = getattr(self, n) # Don't inject methods # TODO: This could actually be a cool capability.. if inspect.ismethod(o): continue self._injectables[n] = o # For each new component, perform magic injection for cname, component in components: setup_tunables(component, cname, "components") self._setup_vars(cname, component) self._setup_reset_vars(component) # Do it for autonomous modes too for mode in self._automodes.modes.values(): mode.logger = logging.getLogger(mode.MODE_NAME) setup_tunables(mode, mode.MODE_NAME, "autonomous") self._setup_vars(mode.MODE_NAME, mode) # And for self too setup_tunables(self, "robot", None) self._feedbacks += collect_feedbacks(self, "robot", None) # Call setup functions for components for cname, component in components: setup = getattr(component, "setup", None) if setup is not None: setup() # ... and grab all the feedback methods self._feedbacks += collect_feedbacks(component, cname, "components") # Call setup functions for autonomous modes for mode in self._automodes.modes.values(): if hasattr(mode, "setup"): mode.setup() self._components = components