Refactor callable and creational providers

This commit is contained in:
Roman Mogilatov 2016-05-18 01:17:15 +03:00
parent f2a9b35c6d
commit 65512366d2
3 changed files with 36 additions and 206 deletions

View File

@ -261,7 +261,3 @@ def _parse_kwargs_injections(args, kwargs):
kwarg_injections += tuple(itertools.starmap(KwArg, kwarg_injections += tuple(itertools.starmap(KwArg,
six.iteritems(kwargs))) six.iteritems(kwargs)))
return kwarg_injections return kwarg_injections
def _parse_attribute_injections(attributes):
return tuple(itertools.starmap(Attribute, six.iteritems(attributes)))

View File

@ -3,10 +3,7 @@
import six import six
from dependency_injector.providers.base import Provider from dependency_injector.providers.base import Provider
from dependency_injector.injections import ( from dependency_injector.injections import Arg, KwArg
_parse_args_injections,
_parse_kwargs_injections,
)
from dependency_injector.utils import represent_provider from dependency_injector.utils import represent_provider
from dependency_injector.errors import Error from dependency_injector.errors import Error
@ -25,27 +22,9 @@ class Callable(Provider):
some_function = Callable(some_function) \ some_function = Callable(some_function) \
.args('arg1', 'arg2') \ .args('arg1', 'arg2') \
.kwargs(arg3=3, arg4=4) .kwargs(arg3=3, arg4=4)
.. py:attribute:: provides
Provided callable.
:type: callable
.. py:attribute:: _args
Tuple of positional argument injections.
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
.. py:attribute:: _kwargs
Tuple of keyword argument injections.
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
""" """
__slots__ = ('provides', '_args', '_kwargs') __slots__ = ('_provides', '_args', '_kwargs')
def __init__(self, provides): def __init__(self, provides):
"""Initializer. """Initializer.
@ -59,8 +38,7 @@ class Callable(Provider):
self.__class__.__name__)), self.__class__.__name__)),
provides)) provides))
self.provides = provides self._provides = provides
self._args = tuple() self._args = tuple()
self._kwargs = tuple() self._kwargs = tuple()
@ -82,7 +60,7 @@ class Callable(Provider):
:return: Reference ``self`` :return: Reference ``self``
""" """
self._args += _parse_args_injections(args) self._args += tuple(Arg(value) for value in args)
return self return self
def kwargs(self, **kwargs): def kwargs(self, **kwargs):
@ -93,7 +71,8 @@ class Callable(Provider):
:return: Reference ``self`` :return: Reference ``self``
""" """
self._kwargs += _parse_kwargs_injections(tuple(), kwargs) self._kwargs += tuple(KwArg(name, value)
for name, value in six.iteritems(kwargs))
return self return self
def _provide(self, *args, **kwargs): def _provide(self, *args, **kwargs):
@ -114,14 +93,14 @@ class Callable(Provider):
if kwarg.name not in kwargs: if kwarg.name not in kwargs:
kwargs[kwarg.name] = kwarg.value kwargs[kwarg.name] = kwarg.value
return self.provides(*args, **kwargs) return self._provides(*args, **kwargs)
def __str__(self): def __str__(self):
"""Return string representation of provider. """Return string representation of provider.
:rtype: str :rtype: str
""" """
return represent_provider(provider=self, provides=self.provides) return represent_provider(provider=self, provides=self._provides)
__repr__ = __str__ __repr__ = __str__
@ -131,24 +110,6 @@ class DelegatedCallable(Callable):
:py:class:`DelegatedCallable` is a :py:class:`Callable`, that is injected :py:class:`DelegatedCallable` is a :py:class:`Callable`, that is injected
"as is". "as is".
.. py:attribute:: provides
Provided callable.
:type: callable
.. py:attribute:: args
Tuple of positional argument injections.
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
.. py:attribute:: kwargs
Tuple of keyword argument injections.
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
""" """
__IS_DELEGATED__ = True __IS_DELEGATED__ = True

View File

@ -1,38 +1,32 @@
"""Dependency injector creational providers.""" """Dependency injector creational providers."""
import six
from dependency_injector.providers.callable import Callable from dependency_injector.providers.callable import Callable
from dependency_injector.injections import _parse_attribute_injections from dependency_injector.injections import Attribute
from dependency_injector.utils import GLOBAL_LOCK from dependency_injector.utils import GLOBAL_LOCK
from dependency_injector.errors import Error from dependency_injector.errors import Error
class Factory(Callable): class Factory(Callable):
""":py:class:`Factory` provider creates new instance on every call. r""":py:class:`Factory` provider creates new instance on every call.
:py:class:`Factory` supports different syntaxes of passing injections: :py:class:`Factory` supports positional & keyword argument injections,
as well as attribute injections:
.. code-block:: python .. code-block:: python
# simplified syntax for passing positional and keyword argument factory = Factory(SomeClass) \
# injections only: .args('arg1', 'arg2') \
factory = Factory(SomeClass, 'arg1', 'arg2', arg3=3, arg4=4) .kwargs(arg3=3, arg4=4) \
.attributes(attribute1=5, attribute2=6)
# extended (full) syntax for passing any type of injections:
factory = Factory(SomeClass,
injections.Arg(1),
injections.Arg(2),
injections.KwArg('some_arg', 3),
injections.KwArg('other_arg', 4),
injections.Attribute('some_attribute', 5))
Retrieving of provided instance can be performed via calling Retrieving of provided instance can be performed via calling
:py:class:`Factory` object: :py:class:`Factory` object:
.. code-block:: python .. code-block:: python
factory = Factory(SomeClass, factory = Factory(SomeClass)
some_arg1=1,
some_arg2=2)
some_object = factory() some_object = factory()
.. py:attribute:: provided_type .. py:attribute:: provided_type
@ -43,54 +37,24 @@ class Factory(Callable):
:type: type | None :type: type | None
.. py:attribute:: provides
Class or other callable that provides object.
:type: type | callable
.. py:attribute:: cls .. py:attribute:: cls
Class that provides object. Class that provides object.
Alias for :py:attr:`provides`. Alias for :py:attr:`provides`.
:type: type :type: type
.. py:attribute:: args
Tuple of positional argument injections.
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
.. py:attribute:: kwargs
Tuple of keyword argument injections.
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
.. py:attribute:: attributes
Tuple of attribute injections.
:type: tuple[:py:class:`dependency_injector.injections.Attribute`]
""" """
provided_type = None provided_type = None
__slots__ = ('cls', '_attributes') __slots__ = ('cls', '_attributes')
def __init__(self, provides, *args, **kwargs): def __init__(self, provides):
"""Initializer. """Initializer.
:param provides: Class or other callable that provides object :param provides: Class or other callable that provides object
for creation. for creation.
:type provides: type | callable :type provides: type | callable
:param args: Tuple of injections.
:type args: tuple
:param kwargs: Dictionary of injections.
:type kwargs: dict
""" """
if (self.__class__.provided_type and if (self.__class__.provided_type and
not issubclass(provides, self.__class__.provided_type)): not issubclass(provides, self.__class__.provided_type)):
@ -99,9 +63,9 @@ class Factory(Callable):
self._attributes = tuple() self._attributes = tuple()
super(Factory, self).__init__(provides, *args, **kwargs) super(Factory, self).__init__(provides)
self.cls = self.provides self.cls = self._provides
@property @property
def injections(self): def injections(self):
@ -109,7 +73,7 @@ class Factory(Callable):
:rtype: tuple[:py:class:`dependency_injector.injections.Injection`] :rtype: tuple[:py:class:`dependency_injector.injections.Injection`]
""" """
return self._args + self._kwargs + self._attributes return super(Factory, self).injections + self._attributes
def attributes(self, **kwargs): def attributes(self, **kwargs):
"""Add attribute injections. """Add attribute injections.
@ -119,7 +83,8 @@ class Factory(Callable):
:return: Reference ``self`` :return: Reference ``self``
""" """
self._attributes += _parse_attribute_injections(kwargs) self._attributes += tuple(Attribute(name, value)
for name, value in six.iteritems(kwargs))
return self return self
def _provide(self, *args, **kwargs): def _provide(self, *args, **kwargs):
@ -140,7 +105,7 @@ class Factory(Callable):
if kwarg.name not in kwargs: if kwarg.name not in kwargs:
kwargs[kwarg.name] = kwarg.value kwargs[kwarg.name] = kwarg.value
instance = self.provides(*args, **kwargs) instance = self._provides(*args, **kwargs)
for attribute in self._attributes: for attribute in self._attributes:
setattr(instance, attribute.name, attribute.value) setattr(instance, attribute.name, attribute.value)
@ -162,36 +127,12 @@ class DelegatedFactory(Factory):
:type: type | None :type: type | None
.. py:attribute:: provides
Class or other callable that provides object.
:type: type | callable
.. py:attribute:: cls .. py:attribute:: cls
Class that provides object. Class that provides object.
Alias for :py:attr:`provides`. Alias for :py:attr:`provides`.
:type: type :type: type
.. py:attribute:: args
Tuple of positional argument injections.
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
.. py:attribute:: kwargs
Tuple of keyword argument injections.
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
.. py:attribute:: attributes
Tuple of attribute injections.
:type: tuple[:py:class:`dependency_injector.injections.Attribute`]
""" """
__IS_DELEGATED__ = True __IS_DELEGATED__ = True
@ -212,9 +153,7 @@ class Singleton(Factory):
.. code-block:: python .. code-block:: python
singleton = Singleton(SomeClass, singleton = Singleton(SomeClass)
some_arg1=1,
some_arg2=2)
some_object = singleton() some_object = singleton()
.. py:attribute:: provided_type .. py:attribute:: provided_type
@ -225,68 +164,32 @@ class Singleton(Factory):
:type: type | None :type: type | None
.. py:attribute:: instance
Read-only reference to singleton's instance.
:type: object
.. py:attribute:: provides
Class or other callable that provides object.
:type: type | callable
.. py:attribute:: cls .. py:attribute:: cls
Class that provides object. Class that provides object.
Alias for :py:attr:`provides`. Alias for :py:attr:`provides`.
:type: type :type: type
.. py:attribute:: args
Tuple of positional argument injections.
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
.. py:attribute:: kwargs
Tuple of keyword argument injections.
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
.. py:attribute:: attributes
Tuple of attribute injections.
:type: tuple[:py:class:`dependency_injector.injections.Attribute`]
""" """
__slots__ = ('instance',) __slots__ = ('_instance',)
def __init__(self, provides, *args, **kwargs): def __init__(self, provides):
"""Initializer. """Initializer.
:param provides: Class or other callable that provides object :param provides: Class or other callable that provides object
for creation. for creation.
:type provides: type | callable :type provides: type | callable
:param args: Tuple of injections.
:type args: tuple
:param kwargs: Dictionary of injections.
:type kwargs: dict
""" """
self.instance = None self._instance = None
super(Singleton, self).__init__(provides, *args, **kwargs) super(Singleton, self).__init__(provides)
def reset(self): def reset(self):
"""Reset cached instance, if any. """Reset cached instance, if any.
:rtype: None :rtype: None
""" """
self.instance = None self._instance = None
def _provide(self, *args, **kwargs): def _provide(self, *args, **kwargs):
"""Return provided instance. """Return provided instance.
@ -299,13 +202,13 @@ class Singleton(Factory):
:rtype: object :rtype: object
""" """
if self.instance: if self._instance:
return self.instance return self._instance
with GLOBAL_LOCK: with GLOBAL_LOCK:
self.instance = super(Singleton, self)._provide(*args, **kwargs) self._instance = super(Singleton, self)._provide(*args, **kwargs)
return self.instance return self._instance
class DelegatedSingleton(Singleton): class DelegatedSingleton(Singleton):
@ -322,42 +225,12 @@ class DelegatedSingleton(Singleton):
:type: type | None :type: type | None
.. py:attribute:: instance
Read-only reference to singleton's instance.
:type: object
.. py:attribute:: provides
Class or other callable that provides object.
:type: type | callable
.. py:attribute:: cls .. py:attribute:: cls
Class that provides object. Class that provides object.
Alias for :py:attr:`provides`. Alias for :py:attr:`provides`.
:type: type :type: type
.. py:attribute:: args
Tuple of positional argument injections.
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
.. py:attribute:: kwargs
Tuple of keyword argument injections.
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
.. py:attribute:: attributes
Tuple of attribute injections.
:type: tuple[:py:class:`dependency_injector.injections.Attribute`]
""" """
__IS_DELEGATED__ = True __IS_DELEGATED__ = True