python-dependency-injector/dependency_injector/providers/callable.py

131 lines
3.7 KiB
Python
Raw Normal View History

"""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):
2016-05-18 00:05:10 +03:00
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.
2016-05-18 00:05:10 +03:00
:py:class:`Callable` supports positional and keyword argument injections:
.. code-block:: python
some_function = Callable(some_function,
'positional_arg1', 'positional_arg2',
keyword_argument1=3, keyword_argument=4)
# or
2016-05-18 00:05:10 +03:00
some_function = Callable(some_function) \
.args('positional_arg1', 'positional_arg2') \
.kwargs(keyword_argument1=3, keyword_argument=4)
# or
some_function = Callable(some_function)
some_function.args('positional_arg1', 'positional_arg2')
some_function.kwargs(keyword_argument1=3, keyword_argument=4)
"""
__slots__ = ('_provides', '_args', '_kwargs')
def __init__(self, provides, *args, **kwargs):
"""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
2016-05-18 00:05:10 +03:00
self._args = tuple()
self._kwargs = tuple()
self.args(*args)
self.kwargs(**kwargs)
super(Callable, self).__init__()
@property
def injections(self):
"""Read-only tuple of all injections.
:rtype: tuple[:py:class:`dependency_injector.injections.Injection`]
"""
2016-05-18 00:05:10 +03:00
return self._args + self._kwargs
2016-05-18 00:05:10 +03:00
def args(self, *args):
"""Add postional argument injections.
:param args: Tuple of injections.
:type args: tuple
2016-05-18 00:05:10 +03:00
:return: Reference ``self``
"""
self._args += tuple(Arg(value) for value in args)
2016-05-18 00:05:10 +03:00
return self
def kwargs(self, **kwargs):
"""Add keyword argument injections.
:param kwargs: Dictionary of injections.
:type kwargs: dict
2016-05-18 00:05:10 +03:00
:return: Reference ``self``
"""
self._kwargs += tuple(KwArg(name, value)
for name, value in six.iteritems(kwargs))
2016-05-18 00:05:10 +03:00
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
"""
2016-05-18 00:05:10 +03:00
if self._args:
2016-05-22 15:37:39 +03:00
args = tuple(arg.get_value() for arg in self._args) + args
2016-05-18 00:05:10 +03:00
for kwarg in self._kwargs:
if kwarg.name not in kwargs:
2016-05-22 15:37:39 +03:00
kwargs[kwarg.name] = kwarg.get_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