def _lookup(self, namespace_id, follow_symrefs=True): """ Description: Get an object in the namespace by its namespace id Input: namespace_id: id of the object to retrieve follow_symrefs: whether or not to try to perform a deep lookup deep lookups can contain other NSIDs which will be looked up in turn until a final value is found and returned. For this feature to be enabled, this node's ._nsroot attribute must also be a valid NamespaceNode-like object that supports a lookup() method that will be passed an NSID. Output: item if found, else NamespaceLookupError raised """ log = LoggerAdapter(logger, {'name_ext': 'NamespaceNode._lookup'}) log.debug('[{}] lookup([{}])'.format(self._nsid, namespace_id)) obj = None if follow_symrefs and is_nsid_ref(namespace_id): value = self._lookup_symbolic_ref(namespace_id) return value else: #- split the NSID by path seperator (normally a dot) path = self._name_to_path(namespace_id) #- fully qualified NSID or not? if self._nsroot and path[0] == self._nsroot._nsid: #- lookup fully qualified NSIDs using the root node next_nsid = '.'.join(path[1:]) return self._nsroot.lookup(next_nsid, follow_symrefs=follow_symrefs) else: #- lookup relative NSIDs iteratively from current obj = self for name in path: try: obj = getattr(obj, name) if follow_symrefs and is_nsid_ref(obj): return self._lookup_symbolic_ref(obj) except AttributeError as err: log.error( 'thewired Failed to find value for [{}] in [{}]'. format(namespace_id, self._nsid)) raise NamespaceLookupError("{}.{}".format( self._nsid, namespace_id)) from err return obj
def _lookup_symbolic_ref(self, ref, follow_symrefs=True): """ Description: lookup a value in starting from NSROOT, instead of a value in this namespace node. (if nsroot is not set, we lookup from this node.) Input: ref: the symbolic reference to lookup follow: whether to follow links that lead to links or not """ log = LoggerAdapter(logger, {'name_ext': 'NamspaceNode._lookup_symbolic_ref'}) if self._nsroot is None: nsroot = self else: nsroot = self._nsroot log.debug("nsid ref: {}".format(ref)) #- strip the prefix nsid = get_nsid_from_ref(ref) ref = nsroot._lookup(nsid) if follow_symrefs: while is_nsid_ref(ref): log.debug("nsid ref: {}".format(ref)) nsid = get_nsid_from_ref(ref) ref = nsroot._lookup(nsid) #- ref no longer an nsid ref return ref
def get_addendum(self, nsid=None, implementor=None, *args, **kwargs): """ Description: addendums can be callables or strings this wraps the differences up Input: nsid: nsid of the implementor to get the addendum for implementor: implementor object to get the addendum for *args: ignored **kwargs: passed to the ParametizedCall object if this is a dynamic addendum type """ log = LoggerAdapter(logger, {'name_ext': 'AddendumFormatter.get_addendum'}) log.debug("Entering") log.debug("args: {}".format(args)) log.debug("kwargs: {}".format(kwargs)) if implementor and self.key: log.debug("Getting key function") key_func = self.get_key_func() key = key_func(implementor) else: key = None log.debug("key: {}".format(key)) log.debug("_addendums: {}".format(self._addendums)) addendums = list() for addendum in self._addendums: if is_nsid_ref(addendum): log.debug("Dereferencing addendum: {}".format(addendum)) addendum = self.nsroot._lookup(addendum) if isinstance(addendum, collections.Mapping): log.debug("Found mapping addendum") if ParametizedCall.is_param_call_map(addendum): log.debug("Found Parametized Call addendum") method_name, params = ParametizedCall.get_params( addendum, **kwargs) addendum = ParametizedCall(self.nsroot, method_name, params) log.debug("Instantiated ParametizedCall") if callable(addendum): log.debug("Calling addendum w/ key: {}".format(key)) addendums.append( addendum(nsid=nsid, implementor=implementor, key=key)) else: log.debug("Using bare addendum text: {}".format(addendum)) addendums.append(addendum) final_addendum = ''.join(addendums) log.debug("final addendum: {}".format(final_addendum)) log.debug("Exiting") return final_addendum
def get_key_func(self): """ Description: key methods are possibly NSIDs, so we may have to look them up at run time. """ if self.key: if is_nsid_ref(self.key): key_func = self.nsroot._lookup(self.key) return key_func else: return None
def deref_sequence_items(self, seq): """ Description: dereference everything in a sequence """ dref_seq = list() for item in seq: if is_nsid_ref(item): item = self.nsroot._lookup_symbolic_ref(item, follow_symrefs=True) dref_seq.append(item) return dref_seq
def make_addendum(self, nsid=None, implementor=None, key=None, need_key=True): """ Description: create the addendum dynamically from the parameter map Inter-namespace symbolic references are all deferenced Input: nsid: ignored; implementor: ignored; key: sub key to use in the parameterized dict generally per-implementor object specific need_key: boolean to control raising KeyError if provided key does not exist in the addendum param map Output: a string suitable for use in an Addendum provider """ log = LoggerAdapter(logger, {'name_ext': 'ParametizedCall.make_addendum'}) unpack_str = '' for k, v in self.params.items(): #- dereference symbolic ref values if is_nsid_ref(v): log.debug("Dereferencing symbolic ref: {}".format(v)) v = self.nsroot._lookup_symbolic_ref(v, follow_symrefs=True) log.debug("deref: {}".format(v)) #- dereference sequence items if isinstance(v, collections.Sequence) and not isinstance(v, str): v = self.stringify_sequence(v, key=key) unpack_str += '{} = {}, '.format(k, v) continue if isinstance(v, collections.Mapping) and key is not None: try: v = v[key] #unpack_str += '{} = {}, '.format(k,v[key]) except KeyError as err: #- subkey not present msg = "Subkey '{}' not present; not using".format(key) log.debug(msg) if need_key: raise if isinstance(v, str): unpack_str += '{} = \'{}\', '.format(k, v) else: #- immediate non-string value unpack_str += '{} = {}, '.format(k, v) #- chop off last ", " unpack_str = unpack_str[0:-2] addendum = '.' + self.method_name + '(' + unpack_str + ')' log.debug("returning addendum: {}".format(addendum)) return addendum