def template_for(node): """Returns the template uri for node. :param node: Something on the controller tree. (method, class, instance, etc) :type node: object :rtype: list""" global _template_for_cache return _cached_path_to(callable_cache_key(node), node, _template_for_cache, True)
def path_to(node): """Returns the canonical path to node. :param node: Something on the controller tree. (method, class, instance, etc) :type node: object :rtype: list""" global _path_to_cache return _cached_path_to(callable_cache_key(node), node, _path_to_cache, False)
def callable_info(cls, f): '''Info about a callable. The results are cached for efficiency. :param f: :type f: callable :rtype: frozendict ''' if not callable(f): return None if isinstance(f, FunctionType): # in case of ensure_va_kwa try: f = f.wrapped_func except AttributeError: pass cache_key = callable_cache_key(f) try: return cls._info_cache[cache_key] except KeyError: pass is_method, args, varargs, varkw, defaults = cls.getargspec(f) _args = [] args_len = len(args) defaults_len = 0 if defaults is not None: defaults_len = len(defaults) for i,n in enumerate(args): default_index = i-(args_len-defaults_len) v = Undefined if default_index > -1: v = defaults[default_index] _args.append((n, v)) info = frozendict({ 'name':f.func_name, 'args':tuple(_args), 'varargs':bool(varargs), 'varkw':bool(varkw), 'method':is_method }) cls._info_cache[cache_key] = info return info
def uri_for(node): """Returns the canonical exposed URI of a node. If node is a controller or a __call__, the uri always ends in a slash. Otherwise it never ends in a slash. :param node: :type node: callable :rtype: string """ cache_key = callable_cache_key(node) try: return _uri_for_cache[cache_key] except KeyError: path = path_to(node) if path is None: uri = None else: uri = "/" + "/".join(path) if len(path) > 0 and (not isinstance(node, (MethodType, FunctionType)) or node.__name__ == "__call__"): uri += "/" _uri_for_cache[cache_key] = uri return uri
def ensure_va_kwa(cls, f, parent=None): '''Ensures `f` accepts both ``*varargs`` and ``**kwargs``. If `f` does not support ``*args``, it will be wrapped with a function which cuts away extra arguments in ``*args``. If `f` does not support ``*args``, it will be wrapped with a function which discards the ``**kwargs``. :param f: :type f: callable :param parent: The parent on which `f` is defined. If specified, we will perform ``parent.<name of f> = wrapper`` in the case we needed to wrap `f`. :type parent: object :returns: A callable which is guaranteed to accept both ``*args`` and ``**kwargs``. :rtype: callable ''' is_method, args, varargs, varkw, defaults = cls.getargspec(f) va_kwa_wrapper = None if varargs is None and varkw is None: if args: def va_kwa_wrapper(*va, **kw): kws = kw.copy() for k in kw: if k not in args: del kws[k] return f(*va[:len(args)], **kws) else: def va_kwa_wrapper(*va, **kw): return f() elif varargs is None: if args: def va_kwa_wrapper(*va, **kw): return f(*va[:len(args)], **kw) else: def va_kwa_wrapper(*va, **kw): return f(**kw) elif varkw is None: if args: def va_kwa_wrapper(*va, **kw): kws = kw.copy() for k in kw: if k not in args: del kws[k] return f(*va, **kw) else: def va_kwa_wrapper(*va, **kw): return f(*va) if va_kwa_wrapper: va_kwa_wrapper.info = frozendict(cls.callable_info(f).update({ 'varargs': True, 'varkw': True })) cls._info_cache[callable_cache_key(f)] = va_kwa_wrapper.info va_kwa_wrapper.wrapped_func = f va_kwa_wrapper.im_func = f va_kwa_wrapper.__name__ = f.__name__ try: va_kwa_wrapper.im_class = f.im_class except AttributeError: pass for k in dir(f): if k[0] != '_' or k in ('__name__'): setattr(va_kwa_wrapper, k, getattr(f, k)) if parent is not None: setattr(parent, info['name'], va_kwa_wrapper) return va_kwa_wrapper return f