python-dependency-injector/dependency_injector/providers/callable.py
2016-05-18 01:17:15 +03:00

116 lines
3.2 KiB
Python

"""Dependency injector callable providers."""
import six
from dependency_injector.providers.base import Provider
from dependency_injector.injections import Arg, KwArg
from dependency_injector.utils import represent_provider
from dependency_injector.errors import Error
@six.python_2_unicode_compatible
class Callable(Provider):
r""":py:class:`Callable` provider calls wrapped callable on every call.
:py:class:`Callable` provider provides callable that is called on every
provider call with some predefined dependency injections.
:py:class:`Callable` supports positional and keyword argument injections:
.. code-block:: python
some_function = Callable(some_function) \
.args('arg1', 'arg2') \
.kwargs(arg3=3, arg4=4)
"""
__slots__ = ('_provides', '_args', '_kwargs')
def __init__(self, provides):
"""Initializer.
:param provides: Wrapped callable.
:type provides: callable
"""
if not callable(provides):
raise Error('Provider {0} expected to get callable, '
'got {0}'.format('.'.join((self.__class__.__module__,
self.__class__.__name__)),
provides))
self._provides = provides
self._args = tuple()
self._kwargs = tuple()
super(Callable, self).__init__()
@property
def injections(self):
"""Read-only tuple of all injections.
:rtype: tuple[:py:class:`dependency_injector.injections.Injection`]
"""
return self._args + self._kwargs
def args(self, *args):
"""Add postional argument injections.
:param args: Tuple of injections.
:type args: tuple
:return: Reference ``self``
"""
self._args += tuple(Arg(value) for value in args)
return self
def kwargs(self, **kwargs):
"""Add keyword argument injections.
:param kwargs: Dictionary of injections.
:type kwargs: dict
:return: Reference ``self``
"""
self._kwargs += tuple(KwArg(name, value)
for name, value in six.iteritems(kwargs))
return self
def _provide(self, *args, **kwargs):
"""Return provided instance.
:param args: Tuple of context positional arguments.
:type args: tuple[object]
:param kwargs: Dictionary of context keyword arguments.
:type kwargs: dict[str, object]
:rtype: object
"""
if self._args:
args = tuple(arg.value for arg in self._args) + args
for kwarg in self._kwargs:
if kwarg.name not in kwargs:
kwargs[kwarg.name] = kwarg.value
return self._provides(*args, **kwargs)
def __str__(self):
"""Return string representation of provider.
:rtype: str
"""
return represent_provider(provider=self, provides=self._provides)
__repr__ = __str__
class DelegatedCallable(Callable):
""":py:class:`DelegatedCallable` is a delegated :py:class:`Callable`.
:py:class:`DelegatedCallable` is a :py:class:`Callable`, that is injected
"as is".
"""
__IS_DELEGATED__ = True