Source code for potpy.context

import inspect


[docs]class Context(dict): """ A dict class that can call callables with arguments from itself. Best explained with an example: >>> def answer(question, foo): ... return 'The answer to the %s question is: %d' % (question, foo) ... >>> ctx = Context(foo=42, question='ultimate') >>> ctx.inject(answer) 'The answer to the ultimate question is: 42' Callable items are called before being passed to the callable: >>> ctx = Context(foo=lambda bar: bar.upper(), bar='qux') >>> ctx.inject(lambda foo: foo) 'QUX' .. note:: Callable items are called during :meth:`__getitem__`: >>> Context(foo=lambda: 42)['foo'] 42 Contexts have ``'context'`` as an implicit a member, so callables can refer to the context itself: >>> ctx = Context(foo='foo') >>> ctx.inject(lambda context: dict(context)) {'foo': 'foo'} When injecting a call, you may override context items (or provide missing items) with keyword arguments: >>> ctx.inject(lambda foo, bar: (foo, bar), bar='bar') ('foo', 'bar') .. note:: ``*args``- and ``**kwargs``-style arguments cannot be injected at this time. .. note:: Due to limitations of the :mod:`inspect` module, builtin and extension functions cannot be injected. You may work around this by wrapping the function in Python: >>> ctx = Context(n='42') >>> ctx.inject(lambda n: int(n)) 42 """ def _get_argspec(self, obj): if not callable(obj): raise TypeError('%r is not callable' % (obj,)) if inspect.isfunction(obj): return inspect.getargspec(obj) if hasattr(obj, 'im_func'): spec = self._get_argspec(obj.im_func) del spec[0][0] return spec if inspect.isclass(obj): if '__init__' not in obj.__dict__: return [], [], None, None return self._get_argspec(obj.__init__) return self._get_argspec(obj.__call__) def __getitem__(self, key): if key == 'context': value = dict.get(self, key, self) else: value = dict.__getitem__(self, key) if callable(value): return self.inject(value) return value def get(self, key, default=None): try: return self[key] except KeyError: return default
[docs] def inject(self, func, **kwargs): """Inject arguments from context into a callable. :param func: The callable to inject arguments into. :param \*\*kwargs: Specify values to override context items. """ args, varargs, keywords, defaults = self._get_argspec(func) if defaults: required_args = args[:-len(defaults)] optional_args = args[len(required_args):] else: required_args = args optional_args = [] values = [ kwargs[arg] if arg in kwargs else self[arg] for arg in required_args ] if defaults: values.extend( kwargs[arg] if arg in kwargs else self.get(arg, default) for arg, default in zip(optional_args, defaults) ) return func(*values)

Project Versions

This Page