mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-23 01:56:58 +03:00
Merge remote-tracking branch 'origin/factory_provided_type'
This commit is contained in:
commit
790860f426
|
@ -56,6 +56,12 @@ class Provider(object):
|
||||||
assert provider is delegated
|
assert provider is delegated
|
||||||
|
|
||||||
All providers should extend this class.
|
All providers should extend this class.
|
||||||
|
|
||||||
|
.. py:attribute:: overridden_by
|
||||||
|
|
||||||
|
Tuple of overriding providers, if any.
|
||||||
|
|
||||||
|
:type: tuple[:py:class:`Provider`] | None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__IS_PROVIDER__ = True
|
__IS_PROVIDER__ = True
|
||||||
|
@ -64,11 +70,6 @@ class Provider(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Initializer."""
|
"""Initializer."""
|
||||||
self.overridden_by = None
|
self.overridden_by = None
|
||||||
"""Tuple of overriding providers, if any.
|
|
||||||
|
|
||||||
:type: tuple[:py:class:`Provider`] | None
|
|
||||||
"""
|
|
||||||
|
|
||||||
super(Provider, self).__init__()
|
super(Provider, self).__init__()
|
||||||
|
|
||||||
def __call__(self, *args, **kwargs):
|
def __call__(self, *args, **kwargs):
|
||||||
|
@ -174,6 +175,12 @@ class Delegate(Provider):
|
||||||
delegated = delegate()
|
delegated = delegate()
|
||||||
|
|
||||||
assert provider is delegated
|
assert provider is delegated
|
||||||
|
|
||||||
|
.. py:attribute:: delegated
|
||||||
|
|
||||||
|
Delegated provider.
|
||||||
|
|
||||||
|
:type: :py:class:`Provider`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ('delegated',)
|
__slots__ = ('delegated',)
|
||||||
|
@ -185,11 +192,6 @@ class Delegate(Provider):
|
||||||
:type delegated: :py:class:`Provider`
|
:type delegated: :py:class:`Provider`
|
||||||
"""
|
"""
|
||||||
self.delegated = ensure_is_provider(delegated)
|
self.delegated = ensure_is_provider(delegated)
|
||||||
"""Delegated provider.
|
|
||||||
|
|
||||||
:type: :py:class:`Provider`
|
|
||||||
"""
|
|
||||||
|
|
||||||
super(Delegate, self).__init__()
|
super(Delegate, self).__init__()
|
||||||
|
|
||||||
def _provide(self, *args, **kwargs):
|
def _provide(self, *args, **kwargs):
|
||||||
|
@ -216,7 +218,108 @@ class Delegate(Provider):
|
||||||
|
|
||||||
|
|
||||||
@six.python_2_unicode_compatible
|
@six.python_2_unicode_compatible
|
||||||
class Factory(Provider):
|
class Callable(Provider):
|
||||||
|
""":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` syntax of passing injections is the same like
|
||||||
|
:py:class:`Factory` one:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# simplified syntax for passing positional and keyword argument
|
||||||
|
# injections:
|
||||||
|
some_function = Callable(some_function, 'arg1', 'arg2', arg3=3, arg4=4)
|
||||||
|
|
||||||
|
# extended (full) syntax for passing positional and keyword argument
|
||||||
|
# injections:
|
||||||
|
some_function = Callable(some_function,
|
||||||
|
injections.Arg(1),
|
||||||
|
injections.Arg(2),
|
||||||
|
injections.KwArg('some_arg', 3),
|
||||||
|
injections.KwArg('other_arg', 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')
|
||||||
|
|
||||||
|
def __init__(self, provides, *args, **kwargs):
|
||||||
|
"""Initializer.
|
||||||
|
|
||||||
|
:param provides: Wrapped callable.
|
||||||
|
:type provides: callable
|
||||||
|
|
||||||
|
:param args: Tuple of injections.
|
||||||
|
:type args: tuple
|
||||||
|
|
||||||
|
:param kwargs: Dictionary of injections.
|
||||||
|
:type kwargs: dict
|
||||||
|
"""
|
||||||
|
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 = _parse_args_injections(args)
|
||||||
|
self.kwargs = _parse_kwargs_injections(args, kwargs)
|
||||||
|
|
||||||
|
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 _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
|
||||||
|
"""
|
||||||
|
return self.provides(*_get_injectable_args(args, self.args),
|
||||||
|
**_get_injectable_kwargs(kwargs, self.kwargs))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
"""Return string representation of provider.
|
||||||
|
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
return represent_provider(provider=self, provides=self.provides)
|
||||||
|
|
||||||
|
__repr__ = __str__
|
||||||
|
|
||||||
|
|
||||||
|
class Factory(Callable):
|
||||||
""":py:class:`Factory` provider creates new instance on every call.
|
""":py:class:`Factory` provider creates new instance on every call.
|
||||||
|
|
||||||
:py:class:`Factory` supports different syntaxes of passing injections:
|
:py:class:`Factory` supports different syntaxes of passing injections:
|
||||||
|
@ -244,9 +347,49 @@ class Factory(Provider):
|
||||||
some_arg1=1,
|
some_arg1=1,
|
||||||
some_arg2=2)
|
some_arg2=2)
|
||||||
some_object = factory()
|
some_object = factory()
|
||||||
|
|
||||||
|
.. py:attribute:: provided_type
|
||||||
|
|
||||||
|
If provided type is defined, :py:class:`Factory` checks that
|
||||||
|
:py:attr:`Factory.provides` is subclass of
|
||||||
|
:py:attr:`Factory.provided_type`.
|
||||||
|
|
||||||
|
:type: type | None
|
||||||
|
|
||||||
|
.. py:attribute:: provides
|
||||||
|
|
||||||
|
Class or other callable that provides object.
|
||||||
|
|
||||||
|
:type: 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`]
|
||||||
|
|
||||||
|
.. py:attribute:: attributes
|
||||||
|
|
||||||
|
Tuple of attribute injections.
|
||||||
|
|
||||||
|
:type: tuple[:py:class:`dependency_injector.injections.Attribute`]
|
||||||
|
|
||||||
|
.. py:attribute:: methods
|
||||||
|
|
||||||
|
Tuple of method injections.
|
||||||
|
|
||||||
|
:type: tuple[:py:class:`dependency_injector.injections.Method`]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ('provides', 'args', 'kwargs', 'attributes', 'methods')
|
provided_type = None
|
||||||
|
|
||||||
|
__slots__ = ('attributes', 'methods')
|
||||||
|
|
||||||
def __init__(self, provides, *args, **kwargs):
|
def __init__(self, provides, *args, **kwargs):
|
||||||
"""Initializer.
|
"""Initializer.
|
||||||
|
@ -261,44 +404,22 @@ class Factory(Provider):
|
||||||
:param kwargs: Dictionary of injections.
|
:param kwargs: Dictionary of injections.
|
||||||
:type kwargs: dict
|
:type kwargs: dict
|
||||||
"""
|
"""
|
||||||
if not callable(provides):
|
if (self.__class__.provided_type and
|
||||||
raise Error('Factory provider expects to get callable, ' +
|
not issubclass(provides, self.__class__.provided_type)):
|
||||||
'got {0} instead'.format(str(provides)))
|
raise Error('{0} can provide only {1} instances'.format(
|
||||||
self.provides = provides
|
'.'.join((self.__class__.__module__,
|
||||||
"""Class or other callable that provides object for creation.
|
self.__class__.__name__)),
|
||||||
|
self.__class__.provided_type))
|
||||||
:type: type | callable
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.args = _parse_args_injections(args)
|
|
||||||
"""Tuple of positional argument injections.
|
|
||||||
|
|
||||||
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.kwargs = _parse_kwargs_injections(args, kwargs)
|
|
||||||
"""Tuple of keyword argument injections.
|
|
||||||
|
|
||||||
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.attributes = tuple(injection
|
self.attributes = tuple(injection
|
||||||
for injection in args
|
for injection in args
|
||||||
if is_attribute_injection(injection))
|
if is_attribute_injection(injection))
|
||||||
"""Tuple of attribute injections.
|
|
||||||
|
|
||||||
:type: tuple[:py:class:`dependency_injector.injections.Attribute`]
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.methods = tuple(injection
|
self.methods = tuple(injection
|
||||||
for injection in args
|
for injection in args
|
||||||
if is_method_injection(injection))
|
if is_method_injection(injection))
|
||||||
"""Tuple of method injections.
|
|
||||||
|
|
||||||
:type: tuple[:py:class:`dependency_injector.injections.Method`]
|
super(Factory, self).__init__(provides, *args, **kwargs)
|
||||||
"""
|
|
||||||
|
|
||||||
super(Factory, self).__init__()
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def injections(self):
|
def injections(self):
|
||||||
|
@ -319,8 +440,8 @@ class Factory(Provider):
|
||||||
|
|
||||||
:rtype: object
|
:rtype: object
|
||||||
"""
|
"""
|
||||||
instance = self.provides(*_get_injectable_args(args, self.args),
|
instance = super(Factory, self)._provide(*args, **kwargs)
|
||||||
**_get_injectable_kwargs(kwargs, self.kwargs))
|
|
||||||
for attribute in self.attributes:
|
for attribute in self.attributes:
|
||||||
setattr(instance, attribute.name, attribute.value)
|
setattr(instance, attribute.name, attribute.value)
|
||||||
for method in self.methods:
|
for method in self.methods:
|
||||||
|
@ -328,24 +449,13 @@ class Factory(Provider):
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
"""Return string representation of provider.
|
|
||||||
|
|
||||||
:rtype: str
|
class Singleton(Factory):
|
||||||
"""
|
|
||||||
return represent_provider(provider=self, provides=self.provides)
|
|
||||||
|
|
||||||
__repr__ = __str__
|
|
||||||
|
|
||||||
|
|
||||||
@six.python_2_unicode_compatible
|
|
||||||
class Singleton(Provider):
|
|
||||||
""":py:class:`Singleton` provider returns same instance on every call.
|
""":py:class:`Singleton` provider returns same instance on every call.
|
||||||
|
|
||||||
:py:class:`Singleton` provider creates instance once and return it on every
|
:py:class:`Singleton` provider creates instance once and return it on every
|
||||||
call. :py:class:`Singleton` uses :py:class:`Factory` for creation of
|
call. :py:class:`Singleton` extends :py:class:`Factory`, so, please follow
|
||||||
instance, so, please follow :py:class:`Factory` documentation to go inside
|
:py:class:`Factory` documentation to go inside with injections syntax.
|
||||||
with injections syntax.
|
|
||||||
|
|
||||||
:py:class:`Singleton` is thread-safe and could be used in multithreading
|
:py:class:`Singleton` is thread-safe and could be used in multithreading
|
||||||
environment without any negative impact.
|
environment without any negative impact.
|
||||||
|
@ -360,9 +470,52 @@ class Singleton(Provider):
|
||||||
some_arg2=2)
|
some_arg2=2)
|
||||||
some_object = singleton()
|
some_object = singleton()
|
||||||
|
|
||||||
|
.. py:attribute:: provided_type
|
||||||
|
|
||||||
|
If provided type is defined, :py:class:`Factory` checks that
|
||||||
|
:py:attr:`Factory.provides` is subclass of
|
||||||
|
:py:attr:`Factory.provided_type`.
|
||||||
|
|
||||||
|
: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:: 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`]
|
||||||
|
|
||||||
|
.. py:attribute:: methods
|
||||||
|
|
||||||
|
Tuple of method injections.
|
||||||
|
|
||||||
|
:type: tuple[:py:class:`dependency_injector.injections.Method`]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ('instance', 'factory')
|
__slots__ = ('instance',)
|
||||||
|
|
||||||
def __init__(self, provides, *args, **kwargs):
|
def __init__(self, provides, *args, **kwargs):
|
||||||
"""Initializer.
|
"""Initializer.
|
||||||
|
@ -378,66 +531,7 @@ class Singleton(Provider):
|
||||||
:type kwargs: dict
|
:type kwargs: dict
|
||||||
"""
|
"""
|
||||||
self.instance = None
|
self.instance = None
|
||||||
"""Read-only reference to singleton's instance.
|
super(Singleton, self).__init__(provides, *args, **kwargs)
|
||||||
|
|
||||||
:type: object
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.factory = Factory(provides, *args, **kwargs)
|
|
||||||
"""Singleton's factory object.
|
|
||||||
|
|
||||||
:type: :py:class:`Factory`
|
|
||||||
"""
|
|
||||||
|
|
||||||
super(Singleton, self).__init__()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def provides(self):
|
|
||||||
"""Class or other callable that provides object for creation.
|
|
||||||
|
|
||||||
:type: type | callable
|
|
||||||
"""
|
|
||||||
return self.factory.provides
|
|
||||||
|
|
||||||
@property
|
|
||||||
def args(self):
|
|
||||||
"""Tuple of positional argument injections.
|
|
||||||
|
|
||||||
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
|
|
||||||
"""
|
|
||||||
return self.factory.args
|
|
||||||
|
|
||||||
@property
|
|
||||||
def kwargs(self):
|
|
||||||
"""Tuple of keyword argument injections.
|
|
||||||
|
|
||||||
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
|
|
||||||
"""
|
|
||||||
return self.factory.kwargs
|
|
||||||
|
|
||||||
@property
|
|
||||||
def attributes(self):
|
|
||||||
"""Tuple of attribute injections.
|
|
||||||
|
|
||||||
:type: tuple[:py:class:`dependency_injector.injections.Attribute`]
|
|
||||||
"""
|
|
||||||
return self.factory.attributes
|
|
||||||
|
|
||||||
@property
|
|
||||||
def methods(self):
|
|
||||||
"""Tuple of method injections.
|
|
||||||
|
|
||||||
:type: tuple[:py:class:`dependency_injector.injections.Method`]
|
|
||||||
"""
|
|
||||||
return self.factory.methods
|
|
||||||
|
|
||||||
@property
|
|
||||||
def injections(self):
|
|
||||||
"""Read-only tuple of all injections.
|
|
||||||
|
|
||||||
:rtype: tuple[:py:class:`dependency_injector.injections.Injection`]
|
|
||||||
"""
|
|
||||||
return self.factory.injections
|
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
"""Reset cached instance, if any.
|
"""Reset cached instance, if any.
|
||||||
|
@ -459,103 +553,10 @@ class Singleton(Provider):
|
||||||
"""
|
"""
|
||||||
with GLOBAL_LOCK:
|
with GLOBAL_LOCK:
|
||||||
if not self.instance:
|
if not self.instance:
|
||||||
self.instance = self.factory(*args, **kwargs)
|
self.instance = super(Singleton, self)._provide(*args,
|
||||||
|
**kwargs)
|
||||||
return self.instance
|
return self.instance
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
"""Return string representation of provider.
|
|
||||||
|
|
||||||
:rtype: str
|
|
||||||
"""
|
|
||||||
return represent_provider(provider=self, provides=self.provides)
|
|
||||||
|
|
||||||
__repr__ = __str__
|
|
||||||
|
|
||||||
|
|
||||||
@six.python_2_unicode_compatible
|
|
||||||
class Callable(Provider):
|
|
||||||
""":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` syntax of passing injections is the same like
|
|
||||||
:py:class:`Factory` one:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
some_function = Callable(some_function, 'arg1', 'arg2', arg3=3, arg4=4)
|
|
||||||
result = some_function()
|
|
||||||
"""
|
|
||||||
|
|
||||||
__slots__ = ('callback', 'args', 'kwargs')
|
|
||||||
|
|
||||||
def __init__(self, callback, *args, **kwargs):
|
|
||||||
"""Initializer.
|
|
||||||
|
|
||||||
:param provides: Wrapped callable.
|
|
||||||
:type provides: callable
|
|
||||||
|
|
||||||
:param args: Tuple of injections.
|
|
||||||
:type args: tuple
|
|
||||||
|
|
||||||
:param kwargs: Dictionary of injections.
|
|
||||||
:type kwargs: dict
|
|
||||||
"""
|
|
||||||
if not callable(callback):
|
|
||||||
raise Error('Callable expected, got {0}'.format(str(callback)))
|
|
||||||
|
|
||||||
self.callback = callback
|
|
||||||
"""Provided callable.
|
|
||||||
|
|
||||||
:type: callable
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.args = _parse_args_injections(args)
|
|
||||||
"""Tuple of positional argument injections.
|
|
||||||
|
|
||||||
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.kwargs = _parse_kwargs_injections(args, kwargs)
|
|
||||||
"""Tuple of keyword argument injections.
|
|
||||||
|
|
||||||
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
|
|
||||||
"""
|
|
||||||
|
|
||||||
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 _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
|
|
||||||
"""
|
|
||||||
return self.callback(*_get_injectable_args(args, self.args),
|
|
||||||
**_get_injectable_kwargs(kwargs, self.kwargs))
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
"""Return string representation of provider.
|
|
||||||
|
|
||||||
:rtype: str
|
|
||||||
"""
|
|
||||||
return represent_provider(provider=self, provides=self.callback)
|
|
||||||
|
|
||||||
__repr__ = __str__
|
|
||||||
|
|
||||||
|
|
||||||
@six.python_2_unicode_compatible
|
@six.python_2_unicode_compatible
|
||||||
class ExternalDependency(Provider):
|
class ExternalDependency(Provider):
|
||||||
|
@ -572,6 +573,12 @@ class ExternalDependency(Provider):
|
||||||
database_provider.override(Factory(sqlite3.connect, ':memory:'))
|
database_provider.override(Factory(sqlite3.connect, ':memory:'))
|
||||||
|
|
||||||
database = database_provider()
|
database = database_provider()
|
||||||
|
|
||||||
|
.. py:attribute:: instance_of
|
||||||
|
|
||||||
|
Class of required dependency.
|
||||||
|
|
||||||
|
:type: type
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ('instance_of',)
|
__slots__ = ('instance_of',)
|
||||||
|
@ -582,10 +589,6 @@ class ExternalDependency(Provider):
|
||||||
raise Error('ExternalDependency provider expects to get class, ' +
|
raise Error('ExternalDependency provider expects to get class, ' +
|
||||||
'got {0} instead'.format(str(instance_of)))
|
'got {0} instead'.format(str(instance_of)))
|
||||||
self.instance_of = instance_of
|
self.instance_of = instance_of
|
||||||
"""Class of required dependency.
|
|
||||||
|
|
||||||
:type: type
|
|
||||||
"""
|
|
||||||
super(ExternalDependency, self).__init__()
|
super(ExternalDependency, self).__init__()
|
||||||
|
|
||||||
def __call__(self, *args, **kwargs):
|
def __call__(self, *args, **kwargs):
|
||||||
|
@ -638,6 +641,12 @@ class Static(Provider):
|
||||||
|
|
||||||
:py:class:`Static` provider is base implementation that provides exactly
|
:py:class:`Static` provider is base implementation that provides exactly
|
||||||
the same as it got on input.
|
the same as it got on input.
|
||||||
|
|
||||||
|
.. py:attribute:: provides
|
||||||
|
|
||||||
|
Value that have to be provided.
|
||||||
|
|
||||||
|
:type: object
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ('provides',)
|
__slots__ = ('provides',)
|
||||||
|
@ -649,10 +658,6 @@ class Static(Provider):
|
||||||
:type provides: object
|
:type provides: object
|
||||||
"""
|
"""
|
||||||
self.provides = provides
|
self.provides = provides
|
||||||
"""Value that have to be provided.
|
|
||||||
|
|
||||||
:type: object
|
|
||||||
"""
|
|
||||||
super(Static, self).__init__()
|
super(Static, self).__init__()
|
||||||
|
|
||||||
def _provide(self, *args, **kwargs):
|
def _provide(self, *args, **kwargs):
|
||||||
|
@ -815,17 +820,7 @@ class ChildConfig(Provider):
|
||||||
:type root_config: :py:class:`Config`
|
:type root_config: :py:class:`Config`
|
||||||
"""
|
"""
|
||||||
self.parents = parents
|
self.parents = parents
|
||||||
"""Tuple of pieces of configuration option / section parent path.
|
|
||||||
|
|
||||||
:type: tuple[str]
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.root_config = root_config
|
self.root_config = root_config
|
||||||
"""Root configuration object.
|
|
||||||
|
|
||||||
:type: :py:class:`Config`
|
|
||||||
"""
|
|
||||||
|
|
||||||
super(ChildConfig, self).__init__()
|
super(ChildConfig, self).__init__()
|
||||||
|
|
||||||
def __getattr__(self, item):
|
def __getattr__(self, item):
|
||||||
|
|
|
@ -4,3 +4,4 @@
|
||||||
.. automodule:: dependency_injector.providers
|
.. automodule:: dependency_injector.providers
|
||||||
:members:
|
:members:
|
||||||
:inherited-members:
|
:inherited-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 26 KiB |
|
@ -9,7 +9,9 @@ follows `Semantic versioning`_
|
||||||
|
|
||||||
Development version
|
Development version
|
||||||
-------------------
|
-------------------
|
||||||
- No features.
|
- Add possibility to specialize ``Factory`` provided type.
|
||||||
|
- Add possibility to specialize ``Singleton`` provided type.
|
||||||
|
- Make some refactorings for providers.
|
||||||
|
|
||||||
1.11.2
|
1.11.2
|
||||||
------
|
------
|
||||||
|
|
|
@ -174,3 +174,14 @@ Example:
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/providers/factory_delegation.py
|
.. literalinclude:: ../../examples/providers/factory_delegation.py
|
||||||
:language: python
|
:language: python
|
||||||
|
|
||||||
|
Factory providers specialization
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
:py:class:`Factory` provider could be specialized for any kind of needs via
|
||||||
|
declaring its subclasses.
|
||||||
|
|
||||||
|
One of such features is a limitation to :py:class:`Factory` provided type:
|
||||||
|
|
||||||
|
.. literalinclude:: ../../examples/providers/factory_provided_type.py
|
||||||
|
:language: python
|
||||||
|
|
|
@ -18,13 +18,9 @@ Example:
|
||||||
Singleton providers and injections
|
Singleton providers and injections
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
:py:class:`Singleton` providers use :py:class:`Factory` providers for first
|
:py:class:`Singleton` provider extends :py:class:`Factory` provider, so, all
|
||||||
creation of specified class instance, so, all of the rules about injections
|
of the rules about injections are the same, as for :py:class:`Factory`
|
||||||
are the same, as for :py:class:`Factory` providers.
|
provider.
|
||||||
|
|
||||||
.. image:: /images/providers/singleton_internals.png
|
|
||||||
:width: 80%
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -73,3 +69,14 @@ Example:
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/providers/singleton_delegation.py
|
.. literalinclude:: ../../examples/providers/singleton_delegation.py
|
||||||
:language: python
|
:language: python
|
||||||
|
|
||||||
|
Singleton providers specialization
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
:py:class:`Singleton` provider could be specialized for any kind of needs via
|
||||||
|
declaring its subclasses.
|
||||||
|
|
||||||
|
One of such features is a limitation to :py:class:`Singleton` provided type:
|
||||||
|
|
||||||
|
.. literalinclude:: ../../examples/providers/singleton_provided_type.py
|
||||||
|
:language: python
|
||||||
|
|
35
examples/providers/factory_provided_type.py
Normal file
35
examples/providers/factory_provided_type.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
"""`Factory` specialization for limitation to provided type example."""
|
||||||
|
|
||||||
|
from dependency_injector import providers
|
||||||
|
from dependency_injector import errors
|
||||||
|
|
||||||
|
|
||||||
|
class BaseService(object):
|
||||||
|
"""Base service class."""
|
||||||
|
|
||||||
|
|
||||||
|
class UsersService(BaseService):
|
||||||
|
"""Users service."""
|
||||||
|
|
||||||
|
|
||||||
|
class PhotosService(BaseService):
|
||||||
|
"""Photos service."""
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceProvider(providers.Factory):
|
||||||
|
"""Service provider."""
|
||||||
|
|
||||||
|
provided_type = BaseService
|
||||||
|
|
||||||
|
|
||||||
|
# Creating several service providers with BaseService instances:
|
||||||
|
users_service_provider = ServiceProvider(UsersService)
|
||||||
|
photos_service_provider = ServiceProvider(PhotosService)
|
||||||
|
|
||||||
|
# Trying to create service provider with not a BaseService instance:
|
||||||
|
try:
|
||||||
|
some_service_provider = ServiceProvider(object)
|
||||||
|
except errors.Error as exception:
|
||||||
|
print exception
|
||||||
|
# __main__.ServiceProvider can provide only
|
||||||
|
# <class '__main__.BaseService'> instances
|
35
examples/providers/singleton_provided_type.py
Normal file
35
examples/providers/singleton_provided_type.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
"""`Singleton` specialization for limitation to provided type example."""
|
||||||
|
|
||||||
|
from dependency_injector import providers
|
||||||
|
from dependency_injector import errors
|
||||||
|
|
||||||
|
|
||||||
|
class BaseService(object):
|
||||||
|
"""Base service class."""
|
||||||
|
|
||||||
|
|
||||||
|
class UsersService(BaseService):
|
||||||
|
"""Users service."""
|
||||||
|
|
||||||
|
|
||||||
|
class PhotosService(BaseService):
|
||||||
|
"""Photos service."""
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceProvider(providers.Singleton):
|
||||||
|
"""Service provider."""
|
||||||
|
|
||||||
|
provided_type = BaseService
|
||||||
|
|
||||||
|
|
||||||
|
# Creating several service providers with BaseService instances:
|
||||||
|
users_service_provider = ServiceProvider(UsersService)
|
||||||
|
photos_service_provider = ServiceProvider(PhotosService)
|
||||||
|
|
||||||
|
# Trying to create service provider with not a BaseService instance:
|
||||||
|
try:
|
||||||
|
some_service_provider = ServiceProvider(object)
|
||||||
|
except errors.Error as exception:
|
||||||
|
print exception
|
||||||
|
# __main__.ServiceProvider can provide only
|
||||||
|
# <class '__main__.BaseService'> instances
|
|
@ -180,6 +180,41 @@ class FactoryTests(unittest.TestCase):
|
||||||
"""Test creation of provider with not a callable."""
|
"""Test creation of provider with not a callable."""
|
||||||
self.assertRaises(errors.Error, providers.Factory, 123)
|
self.assertRaises(errors.Error, providers.Factory, 123)
|
||||||
|
|
||||||
|
def test_init_with_valid_provided_type(self):
|
||||||
|
"""Test creation with not valid provided type."""
|
||||||
|
class ExampleProvider(providers.Factory):
|
||||||
|
"""Example provider."""
|
||||||
|
|
||||||
|
provided_type = Example
|
||||||
|
|
||||||
|
example_provider = ExampleProvider(Example, 1, 2)
|
||||||
|
|
||||||
|
self.assertIsInstance(example_provider(), Example)
|
||||||
|
|
||||||
|
def test_init_with_valid_provided_subtype(self):
|
||||||
|
"""Test creation with not valid provided type."""
|
||||||
|
class ExampleProvider(providers.Factory):
|
||||||
|
"""Example provider."""
|
||||||
|
|
||||||
|
provided_type = Example
|
||||||
|
|
||||||
|
class NewExampe(Example):
|
||||||
|
"""Example class subclass."""
|
||||||
|
|
||||||
|
example_provider = ExampleProvider(NewExampe, 1, 2)
|
||||||
|
|
||||||
|
self.assertIsInstance(example_provider(), NewExampe)
|
||||||
|
|
||||||
|
def test_init_with_invalid_provided_type(self):
|
||||||
|
"""Test creation with not valid provided type."""
|
||||||
|
class ExampleProvider(providers.Factory):
|
||||||
|
"""Example provider."""
|
||||||
|
|
||||||
|
provided_type = Example
|
||||||
|
|
||||||
|
with self.assertRaises(errors.Error):
|
||||||
|
ExampleProvider(list)
|
||||||
|
|
||||||
def test_call(self):
|
def test_call(self):
|
||||||
"""Test creation of new instances."""
|
"""Test creation of new instances."""
|
||||||
provider = providers.Factory(Example)
|
provider = providers.Factory(Example)
|
||||||
|
@ -399,6 +434,41 @@ class SingletonTests(unittest.TestCase):
|
||||||
"""Test creation of provider with not a callable."""
|
"""Test creation of provider with not a callable."""
|
||||||
self.assertRaises(errors.Error, providers.Singleton, 123)
|
self.assertRaises(errors.Error, providers.Singleton, 123)
|
||||||
|
|
||||||
|
def test_init_with_valid_provided_type(self):
|
||||||
|
"""Test creation with not valid provided type."""
|
||||||
|
class ExampleProvider(providers.Singleton):
|
||||||
|
"""Example provider."""
|
||||||
|
|
||||||
|
provided_type = Example
|
||||||
|
|
||||||
|
example_provider = ExampleProvider(Example, 1, 2)
|
||||||
|
|
||||||
|
self.assertIsInstance(example_provider(), Example)
|
||||||
|
|
||||||
|
def test_init_with_valid_provided_subtype(self):
|
||||||
|
"""Test creation with not valid provided type."""
|
||||||
|
class ExampleProvider(providers.Singleton):
|
||||||
|
"""Example provider."""
|
||||||
|
|
||||||
|
provided_type = Example
|
||||||
|
|
||||||
|
class NewExampe(Example):
|
||||||
|
"""Example class subclass."""
|
||||||
|
|
||||||
|
example_provider = ExampleProvider(NewExampe, 1, 2)
|
||||||
|
|
||||||
|
self.assertIsInstance(example_provider(), NewExampe)
|
||||||
|
|
||||||
|
def test_init_with_invalid_provided_type(self):
|
||||||
|
"""Test creation with not valid provided type."""
|
||||||
|
class ExampleProvider(providers.Singleton):
|
||||||
|
"""Example provider."""
|
||||||
|
|
||||||
|
provided_type = Example
|
||||||
|
|
||||||
|
with self.assertRaises(errors.Error):
|
||||||
|
ExampleProvider(list)
|
||||||
|
|
||||||
def test_call(self):
|
def test_call(self):
|
||||||
"""Test getting of instances."""
|
"""Test getting of instances."""
|
||||||
provider = providers.Singleton(Example)
|
provider = providers.Singleton(Example)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user