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

131 lines
3.6 KiB
Python
Raw Normal View History

"""Dependency injector callable providers."""
import six
2016-05-29 16:39:39 +03:00
from dependency_injector.providers.base import (
Provider,
_parse_positional_injections,
_parse_keyword_injections,
)
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) \
2016-05-29 16:39:39 +03:00
.add_args('positional_arg1', 'positional_arg2') \
.add_kwargs(keyword_argument1=3, keyword_argument=4)
# or
some_function = Callable(some_function)
2016-05-29 16:39:39 +03:00
some_function.add_args('positional_arg1', 'positional_arg2')
some_function.add_kwargs(keyword_argument1=3, keyword_argument=4)
"""
2016-05-29 16:39:39 +03:00
__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))
2016-05-29 16:39:39 +03:00
self.provides = provides
2016-05-29 16:39:39 +03:00
self.args = tuple()
self.kwargs = dict()
2016-05-29 16:39:39 +03:00
self.add_args(*args)
self.add_kwargs(**kwargs)
2016-05-29 16:39:39 +03:00
super(Callable, self).__init__()
2016-05-29 16:39:39 +03:00
def add_args(self, *args):
2016-05-18 00:05:10 +03:00
"""Add postional argument injections.
:param args: Tuple of injections.
:type args: tuple
2016-05-18 00:05:10 +03:00
:return: Reference ``self``
"""
2016-05-29 16:39:39 +03:00
self.args += _parse_positional_injections(args)
2016-05-18 00:05:10 +03:00
return self
2016-05-29 16:39:39 +03:00
def add_kwargs(self, **kwargs):
2016-05-18 00:05:10 +03:00
"""Add keyword argument injections.
:param kwargs: Dictionary of injections.
:type kwargs: dict
2016-05-18 00:05:10 +03:00
:return: Reference ``self``
"""
2016-05-29 16:39:39 +03:00
self.kwargs.update(_parse_keyword_injections(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-29 16:39:39 +03:00
if self.args:
args = tuple(arg.provide_injection() for arg in self.args) + args
2016-05-29 16:39:39 +03:00
for name, arg in six.iteritems(self.kwargs):
if name not in kwargs:
kwargs[name] = arg.provide_injection()
2016-05-29 16:39:39 +03:00
return self.provides(*args, **kwargs)
def __str__(self):
"""Return string representation of provider.
:rtype: str
"""
2016-05-29 16:39:39 +03:00
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".
"""
def provide_injection(self):
2016-05-29 16:39:39 +03:00
"""Injection strategy implementation.
:rtype: object
"""
return self