def compute_param_updates(subscribers, param_key, param_value): """ Compute subscribers that should be notified based on the parameter update @param subscribers: parameter subscribers @type subscribers: Registrations @param param_key: parameter key @type param_key: str @param param_value: parameter value @type param_value: str """ # logic correct for both updates and deletions if not subscribers: return [] # end with a trailing slash to optimize startswith check from # needing an extra equals check if param_key != SEP: param_key = canonicalize_name(param_key) + SEP # compute all the updated keys if type(param_value) == dict: all_keys = _compute_all_keys(param_key, param_value) else: all_keys = None updates = [] # subscriber gets update if anything in the subscribed namespace is updated or if its deleted for sub_key in subscribers.iterkeys(): ns_key = sub_key if ns_key[-1] != SEP: ns_key = sub_key + SEP if param_key.startswith(ns_key): node_apis = subscribers[sub_key] updates.append((node_apis, param_key, param_value)) elif all_keys is not None and ns_key.startswith(param_key) \ and not sub_key in all_keys: # parameter was deleted node_apis = subscribers[sub_key] updates.append((node_apis, sub_key, {})) # add updates for exact matches within tree if all_keys is not None: # #586: iterate over parameter tree for notification for key in all_keys: if key in subscribers: # compute actual update value sub_key = key[len(param_key):] namespaces = [x for x in sub_key.split(SEP) if x] val = param_value for ns in namespaces: val = val[ns] updates.append((subscribers[key], key, val)) return updates
def unsubscribe_param(self, key, unregistration_args): """ @param key str: parameter key @type key: str @param unregistration_args: additional args to pass to subscribers.unregister. i.e. unregister will be called with (key, *unregistration_args) @type unregistration_args: tuple @return: return value of subscribers.unregister() """ if key != SEP: key = canonicalize_name(key) + SEP return self.reg_manager.unregister_param_subscriber(key, *unregistration_args)
def add_remap(self, remap): """ Add a new remap setting to the context. if a remap already exists with the same from key, it will be removed @param remap: remap setting @type remap: (str, str) """ remap = [canonicalize_name(x) for x in remap] if not remap[0] or not remap[1]: raise RLException("remap from/to attributes cannot be empty") if not is_legal_name(remap[0]): raise RLException("remap from [%s] is not a valid ROS name"%remap[0]) if not is_legal_name(remap[1]): raise RLException("remap to [%s] is not a valid ROS name"%remap[1]) matches = [r for r in self._remap_args if r[0] == remap[0]] for m in matches: self._remap_args.remove(m) self._remap_args.append(remap)
def test_canonicalize_name(): from rosgraph.names import canonicalize_name tests = [ ('', ''), ('/', '/'), ('foo', 'foo'), ('/foo', '/foo'), ('/foo/', '/foo'), ('/foo/bar', '/foo/bar'), ('/foo/bar/', '/foo/bar'), ('/foo/bar//', '/foo/bar'), ('/foo//bar', '/foo/bar'), ('//foo/bar', '/foo/bar'), ('foo/bar', 'foo/bar'), ('foo//bar', 'foo/bar'), ('foo/bar/', 'foo/bar'), ('/foo/bar', '/foo/bar'), ] for t, v in tests: assert v == canonicalize_name(t)
def subscribe_param(self, key, registration_args): """ @param key: parameter key @type key: str @param registration_args: additional args to pass to subscribers.register. First parameter is always the parameter key. @type registration_args: tuple """ if key != SEP: key = canonicalize_name(key) + SEP try: self.lock.acquire() # fetch parameter value try: val = self.get_param(key) except KeyError: # parameter not set yet val = {} self.reg_manager.register_param_subscriber(key, *registration_args) return val finally: self.lock.release()