2015-03-08 22:01:39 +00:00
|
|
|
"""Injections module."""
|
2015-01-10 09:24:25 +00:00
|
|
|
|
2015-08-31 21:30:38 +00:00
|
|
|
import six
|
2015-08-03 09:57:42 +00:00
|
|
|
|
2016-05-29 13:39:39 +00:00
|
|
|
from dependency_injector.providers.base import (
|
|
|
|
_parse_positional_injections,
|
|
|
|
_parse_keyword_injections,
|
2016-04-03 14:27:53 +00:00
|
|
|
)
|
2016-05-29 13:39:39 +00:00
|
|
|
from dependency_injector import utils
|
|
|
|
from dependency_injector import errors
|
2015-03-11 13:18:42 +00:00
|
|
|
|
2015-01-10 09:24:25 +00:00
|
|
|
|
2015-08-31 21:30:38 +00:00
|
|
|
def inject(*args, **kwargs):
|
2015-08-03 09:57:42 +00:00
|
|
|
"""Dependency injection decorator.
|
|
|
|
|
2015-11-24 08:33:10 +00:00
|
|
|
:py:func:`inject` decorator can be used for making inline dependency
|
|
|
|
injections. It patches decorated callable in such way that dependency
|
|
|
|
injection will be done during every call of decorated callable.
|
|
|
|
|
|
|
|
:py:func:`inject` decorator supports different syntaxes of passing
|
|
|
|
injections:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
2016-05-29 13:39:39 +00:00
|
|
|
# Positional arguments injections:
|
2015-11-24 08:33:10 +00:00
|
|
|
@inject(1, 2)
|
|
|
|
def some_function(arg1, arg2):
|
|
|
|
pass
|
|
|
|
|
2016-05-29 13:39:39 +00:00
|
|
|
# Keyword arguments injections:
|
2015-11-24 08:33:10 +00:00
|
|
|
@inject(arg1=1)
|
|
|
|
@inject(arg2=2)
|
|
|
|
def some_function(arg1, arg2):
|
|
|
|
pass
|
|
|
|
|
2016-05-29 13:39:39 +00:00
|
|
|
# Keyword arguments injections into class init:
|
2015-11-24 08:33:10 +00:00
|
|
|
@inject(arg1=1)
|
|
|
|
@inject(arg2=2)
|
|
|
|
class SomeClass(object):
|
|
|
|
|
|
|
|
def __init__(self, arg1, arg2):
|
|
|
|
pass
|
|
|
|
|
2015-11-25 13:02:20 +00:00
|
|
|
:param args: Tuple of context positional arguments.
|
|
|
|
:type args: tuple[object]
|
|
|
|
|
|
|
|
:param kwargs: Dictionary of context keyword arguments.
|
|
|
|
:type kwargs: dict[str, object]
|
|
|
|
|
2015-11-24 08:33:10 +00:00
|
|
|
:return: Class / callable decorator
|
|
|
|
:rtype: (callable) -> (type | callable)
|
2015-08-03 09:57:42 +00:00
|
|
|
"""
|
2016-05-29 13:39:39 +00:00
|
|
|
arg_injections = _parse_positional_injections(args)
|
|
|
|
kwarg_injections = _parse_keyword_injections(kwargs)
|
2015-08-03 09:57:42 +00:00
|
|
|
|
2015-09-28 19:10:17 +00:00
|
|
|
def decorator(callback_or_cls):
|
2015-08-03 09:57:42 +00:00
|
|
|
"""Dependency injection decorator."""
|
2015-09-28 19:10:17 +00:00
|
|
|
if isinstance(callback_or_cls, six.class_types):
|
|
|
|
cls = callback_or_cls
|
2016-05-29 13:39:39 +00:00
|
|
|
cls_init = utils.fetch_cls_init(cls)
|
2016-03-01 13:42:06 +00:00
|
|
|
if not cls_init:
|
2016-05-29 13:39:39 +00:00
|
|
|
raise errors.Error(
|
2016-03-01 13:42:06 +00:00
|
|
|
'Class {0}.{1} has no __init__() '.format(cls.__module__,
|
|
|
|
cls.__name__) +
|
|
|
|
'method and could not be decorated with @inject decorator')
|
|
|
|
cls.__init__ = decorator(cls_init)
|
2015-09-28 11:19:22 +00:00
|
|
|
return cls
|
|
|
|
|
2015-09-28 19:10:17 +00:00
|
|
|
callback = callback_or_cls
|
2016-03-01 10:25:54 +00:00
|
|
|
|
2016-03-01 14:28:05 +00:00
|
|
|
if hasattr(callback, '__INJECT_DECORATED__'):
|
2015-10-23 06:53:53 +00:00
|
|
|
callback.args += arg_injections
|
2016-05-29 13:39:39 +00:00
|
|
|
callback.kwargs.update(kwarg_injections)
|
2015-08-31 21:30:38 +00:00
|
|
|
return callback
|
2015-08-03 09:57:42 +00:00
|
|
|
|
2015-08-31 21:30:38 +00:00
|
|
|
@six.wraps(callback)
|
2015-08-03 09:57:42 +00:00
|
|
|
def decorated(*args, **kwargs):
|
|
|
|
"""Decorated with dependency injection callback."""
|
2016-02-07 22:29:41 +00:00
|
|
|
if decorated.args:
|
2016-05-29 13:39:39 +00:00
|
|
|
args = tuple(arg.inject() for arg in decorated.args) + args
|
2016-02-07 22:29:41 +00:00
|
|
|
|
2016-05-29 13:39:39 +00:00
|
|
|
for name, arg in six.iteritems(decorated.kwargs):
|
|
|
|
if name not in kwargs:
|
|
|
|
kwargs[name] = arg.inject()
|
2016-02-07 22:29:41 +00:00
|
|
|
|
|
|
|
return callback(*args, **kwargs)
|
2015-08-03 09:57:42 +00:00
|
|
|
|
2016-03-01 14:28:05 +00:00
|
|
|
decorated.__INJECT_DECORATED__ = True
|
|
|
|
decorated.origin = callback
|
2015-10-23 06:53:53 +00:00
|
|
|
decorated.args = arg_injections
|
|
|
|
decorated.kwargs = kwarg_injections
|
2015-08-03 09:57:42 +00:00
|
|
|
|
|
|
|
return decorated
|
|
|
|
return decorator
|