mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-22 09:36:48 +03:00
Update containers documentation
+ Refactor provider overriding system
This commit is contained in:
parent
71c871caf7
commit
1eee0fe529
|
@ -10,15 +10,44 @@ from dependency_injector import (
|
||||||
|
|
||||||
|
|
||||||
class DynamicContainer(object):
|
class DynamicContainer(object):
|
||||||
"""Dynamic inversion of control container."""
|
"""Dynamic inversion of control container.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
services = DynamicContainer()
|
||||||
|
services.auth = providers.Factory(AuthService)
|
||||||
|
services.users = providers.Factory(UsersService,
|
||||||
|
auth_service=services.auth)
|
||||||
|
|
||||||
|
.. py:attribute:: providers
|
||||||
|
|
||||||
|
Read-only dictionary of all providers.
|
||||||
|
|
||||||
|
:type: dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||||
|
|
||||||
|
.. py:attribute:: overridden
|
||||||
|
|
||||||
|
Tuple of overriding containers.
|
||||||
|
|
||||||
|
:type: tuple[:py:class:`DynamicContainer`]
|
||||||
|
|
||||||
|
.. py:attribute:: provider_type
|
||||||
|
|
||||||
|
Type of providers that could be placed in container.
|
||||||
|
|
||||||
|
:type: type
|
||||||
|
"""
|
||||||
|
|
||||||
__IS_CONTAINER__ = True
|
__IS_CONTAINER__ = True
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Initializer."""
|
"""Initializer.
|
||||||
|
|
||||||
|
:rtype: None
|
||||||
|
"""
|
||||||
self.provider_type = providers.Provider
|
self.provider_type = providers.Provider
|
||||||
self.providers = dict()
|
self.providers = dict()
|
||||||
self.overridden_by = tuple()
|
self.overridden = tuple()
|
||||||
super(DynamicContainer, self).__init__()
|
super(DynamicContainer, self).__init__()
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
|
@ -26,6 +55,14 @@ class DynamicContainer(object):
|
||||||
|
|
||||||
If value of attribute is provider, it will be added into providers
|
If value of attribute is provider, it will be added into providers
|
||||||
dictionary.
|
dictionary.
|
||||||
|
|
||||||
|
:param name: Attribute's name
|
||||||
|
:type name: str
|
||||||
|
|
||||||
|
:param value: Attribute's value
|
||||||
|
:type value: object
|
||||||
|
|
||||||
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if utils.is_provider(value):
|
if utils.is_provider(value):
|
||||||
_check_provider_type(self, value)
|
_check_provider_type(self, value)
|
||||||
|
@ -37,6 +74,11 @@ class DynamicContainer(object):
|
||||||
|
|
||||||
If value of attribute is provider, it will be deleted from providers
|
If value of attribute is provider, it will be deleted from providers
|
||||||
dictionary.
|
dictionary.
|
||||||
|
|
||||||
|
:param name: Attribute's name
|
||||||
|
:type name: str
|
||||||
|
|
||||||
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if name in self.providers:
|
if name in self.providers:
|
||||||
del self.providers[name]
|
del self.providers[name]
|
||||||
|
@ -46,10 +88,10 @@ class DynamicContainer(object):
|
||||||
"""Override current container by overriding container.
|
"""Override current container by overriding container.
|
||||||
|
|
||||||
:param overriding: Overriding container.
|
:param overriding: Overriding container.
|
||||||
:type overriding: :py:class:`DeclarativeContainer`
|
:type overriding: :py:class:`DynamicContainer`
|
||||||
|
|
||||||
:raise: :py:exc:`dependency_injector.errors.Error` if trying to
|
:raise: :py:exc:`dependency_injector.errors.Error` if trying to
|
||||||
override container by itself or its subclasses
|
override container by itself
|
||||||
|
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
|
@ -57,7 +99,7 @@ class DynamicContainer(object):
|
||||||
raise errors.Error('Container {0} could not be overridden '
|
raise errors.Error('Container {0} could not be overridden '
|
||||||
'with itself'.format(self))
|
'with itself'.format(self))
|
||||||
|
|
||||||
self.overridden_by += (overriding,)
|
self.overridden += (overriding,)
|
||||||
|
|
||||||
for name, provider in six.iteritems(overriding.providers):
|
for name, provider in six.iteritems(overriding.providers):
|
||||||
try:
|
try:
|
||||||
|
@ -70,10 +112,10 @@ class DynamicContainer(object):
|
||||||
|
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if not self.overridden_by:
|
if not self.overridden:
|
||||||
raise errors.Error('Container {0} is not overridden'.format(self))
|
raise errors.Error('Container {0} is not overridden'.format(self))
|
||||||
|
|
||||||
self.overridden_by = self.overridden_by[:-1]
|
self.overridden = self.overridden[:-1]
|
||||||
|
|
||||||
for provider in six.itervalues(self.providers):
|
for provider in six.itervalues(self.providers):
|
||||||
provider.reset_last_overriding()
|
provider.reset_last_overriding()
|
||||||
|
@ -83,7 +125,7 @@ class DynamicContainer(object):
|
||||||
|
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
self.overridden_by = tuple()
|
self.overridden = tuple()
|
||||||
|
|
||||||
for provider in six.itervalues(self.providers):
|
for provider in six.itervalues(self.providers):
|
||||||
provider.reset_override()
|
provider.reset_override()
|
||||||
|
@ -120,6 +162,14 @@ class DeclarativeContainerMetaClass(type):
|
||||||
|
|
||||||
If value of attribute is provider, it will be added into providers
|
If value of attribute is provider, it will be added into providers
|
||||||
dictionary.
|
dictionary.
|
||||||
|
|
||||||
|
:param name: Attribute's name
|
||||||
|
:type name: str
|
||||||
|
|
||||||
|
:param value: Attribute's value
|
||||||
|
:type value: object
|
||||||
|
|
||||||
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if utils.is_provider(value):
|
if utils.is_provider(value):
|
||||||
_check_provider_type(cls, value)
|
_check_provider_type(cls, value)
|
||||||
|
@ -132,6 +182,11 @@ class DeclarativeContainerMetaClass(type):
|
||||||
|
|
||||||
If value of attribute is provider, it will be deleted from providers
|
If value of attribute is provider, it will be deleted from providers
|
||||||
dictionary.
|
dictionary.
|
||||||
|
|
||||||
|
:param name: Attribute's name
|
||||||
|
:type name: str
|
||||||
|
|
||||||
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if name in cls.providers and name in cls.cls_providers:
|
if name in cls.providers and name in cls.cls_providers:
|
||||||
del cls.providers[name]
|
del cls.providers[name]
|
||||||
|
@ -141,21 +196,61 @@ class DeclarativeContainerMetaClass(type):
|
||||||
|
|
||||||
@six.add_metaclass(DeclarativeContainerMetaClass)
|
@six.add_metaclass(DeclarativeContainerMetaClass)
|
||||||
class DeclarativeContainer(object):
|
class DeclarativeContainer(object):
|
||||||
"""Declarative inversion of control container."""
|
"""Declarative inversion of control container.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class Services(DeclarativeContainer):
|
||||||
|
auth = providers.Factory(AuthService)
|
||||||
|
users = providers.Factory(UsersService,
|
||||||
|
auth_service=auth)
|
||||||
|
"""
|
||||||
|
|
||||||
__IS_CONTAINER__ = True
|
__IS_CONTAINER__ = True
|
||||||
|
|
||||||
provider_type = providers.Provider
|
provider_type = providers.Provider
|
||||||
|
"""Type of providers that could be placed in container.
|
||||||
|
|
||||||
providers = dict()
|
:type: type
|
||||||
cls_providers = dict()
|
"""
|
||||||
inherited_providers = dict()
|
|
||||||
overridden_by = tuple()
|
|
||||||
|
|
||||||
instance_type = DynamicContainer
|
instance_type = DynamicContainer
|
||||||
|
"""Type of container that is returned on instantiating declarative
|
||||||
|
container.
|
||||||
|
|
||||||
|
:type: type
|
||||||
|
"""
|
||||||
|
|
||||||
|
providers = dict()
|
||||||
|
"""Read-only dictionary of all providers.
|
||||||
|
|
||||||
|
:type: dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||||
|
"""
|
||||||
|
|
||||||
|
cls_providers = dict()
|
||||||
|
"""Read-only dictionary of current container providers.
|
||||||
|
|
||||||
|
:type: dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||||
|
"""
|
||||||
|
|
||||||
|
inherited_providers = dict()
|
||||||
|
"""Read-only dictionary of inherited providers.
|
||||||
|
|
||||||
|
:type: dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||||
|
"""
|
||||||
|
|
||||||
|
overridden = tuple()
|
||||||
|
"""Tuple of overriding containers.
|
||||||
|
|
||||||
|
:type: tuple[:py:class:`DeclarativeContainer`]
|
||||||
|
"""
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
"""Constructor."""
|
"""Constructor.
|
||||||
|
|
||||||
|
:return: Dynamic container with copy of all providers.
|
||||||
|
:rtype: :py:class:`DynamicContainer`
|
||||||
|
"""
|
||||||
container = cls.instance_type(*args, **kwargs)
|
container = cls.instance_type(*args, **kwargs)
|
||||||
container.provider_type = cls.provider_type
|
container.provider_type = cls.provider_type
|
||||||
|
|
||||||
|
@ -180,7 +275,7 @@ class DeclarativeContainer(object):
|
||||||
raise errors.Error('Container {0} could not be overridden '
|
raise errors.Error('Container {0} could not be overridden '
|
||||||
'with itself or its subclasses'.format(cls))
|
'with itself or its subclasses'.format(cls))
|
||||||
|
|
||||||
cls.overridden_by += (overriding,)
|
cls.overridden += (overriding,)
|
||||||
|
|
||||||
for name, provider in six.iteritems(overriding.cls_providers):
|
for name, provider in six.iteritems(overriding.cls_providers):
|
||||||
try:
|
try:
|
||||||
|
@ -194,10 +289,10 @@ class DeclarativeContainer(object):
|
||||||
|
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if not cls.overridden_by:
|
if not cls.overridden:
|
||||||
raise errors.Error('Container {0} is not overridden'.format(cls))
|
raise errors.Error('Container {0} is not overridden'.format(cls))
|
||||||
|
|
||||||
cls.overridden_by = cls.overridden_by[:-1]
|
cls.overridden = cls.overridden[:-1]
|
||||||
|
|
||||||
for provider in six.itervalues(cls.providers):
|
for provider in six.itervalues(cls.providers):
|
||||||
provider.reset_last_overriding()
|
provider.reset_last_overriding()
|
||||||
|
@ -208,7 +303,7 @@ class DeclarativeContainer(object):
|
||||||
|
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
cls.overridden_by = tuple()
|
cls.overridden = tuple()
|
||||||
|
|
||||||
for provider in six.itervalues(cls.providers):
|
for provider in six.itervalues(cls.providers):
|
||||||
provider.reset_override()
|
provider.reset_override()
|
||||||
|
|
|
@ -51,7 +51,7 @@ class Provider(object):
|
||||||
|
|
||||||
All providers should extend this class.
|
All providers should extend this class.
|
||||||
|
|
||||||
.. py:attribute:: overridden_by
|
.. py:attribute:: overridden
|
||||||
|
|
||||||
Tuple of overriding providers, if any.
|
Tuple of overriding providers, if any.
|
||||||
|
|
||||||
|
@ -60,11 +60,11 @@ class Provider(object):
|
||||||
|
|
||||||
__IS_PROVIDER__ = True
|
__IS_PROVIDER__ = True
|
||||||
__OPTIMIZED_CALLS__ = True
|
__OPTIMIZED_CALLS__ = True
|
||||||
__slots__ = ('overridden_by', 'provide', '__call__')
|
__slots__ = ('overridden', 'provide', '__call__')
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Initializer."""
|
"""Initializer."""
|
||||||
self.overridden_by = tuple()
|
self.overridden = tuple()
|
||||||
super(Provider, self).__init__()
|
super(Provider, self).__init__()
|
||||||
# Enable __call__() / _provide() optimization
|
# Enable __call__() / _provide() optimization
|
||||||
if self.__class__.__OPTIMIZED_CALLS__:
|
if self.__class__.__OPTIMIZED_CALLS__:
|
||||||
|
@ -81,7 +81,9 @@ class Provider(object):
|
||||||
|
|
||||||
def _call_last_overriding(self, *args, **kwargs):
|
def _call_last_overriding(self, *args, **kwargs):
|
||||||
"""Call last overriding provider and return result."""
|
"""Call last overriding provider and return result."""
|
||||||
return self.last_overriding(*args, **kwargs)
|
return (self.overridden[-1](*args, **kwargs)
|
||||||
|
if self.overridden
|
||||||
|
else None)
|
||||||
|
|
||||||
def provide_injection(self):
|
def provide_injection(self):
|
||||||
"""Injection strategy implementation.
|
"""Injection strategy implementation.
|
||||||
|
@ -90,22 +92,6 @@ class Provider(object):
|
||||||
"""
|
"""
|
||||||
return self.provide()
|
return self.provide()
|
||||||
|
|
||||||
@property
|
|
||||||
def is_overridden(self):
|
|
||||||
"""Read-only property that is set to ``True`` if provider is overridden.
|
|
||||||
|
|
||||||
:rtype: bool
|
|
||||||
"""
|
|
||||||
return bool(self.overridden_by)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def last_overriding(self):
|
|
||||||
"""Read-only reference to the last overriding provider, if any.
|
|
||||||
|
|
||||||
:type: :py:class:`Provider` | None
|
|
||||||
"""
|
|
||||||
return self.overridden_by[-1] if self.overridden_by else None
|
|
||||||
|
|
||||||
def override(self, provider):
|
def override(self, provider):
|
||||||
"""Override provider with another provider.
|
"""Override provider with another provider.
|
||||||
|
|
||||||
|
@ -124,7 +110,7 @@ class Provider(object):
|
||||||
if not is_provider(provider):
|
if not is_provider(provider):
|
||||||
provider = Object(provider)
|
provider = Object(provider)
|
||||||
|
|
||||||
self.overridden_by += (ensure_is_provider(provider),)
|
self.overridden += (ensure_is_provider(provider),)
|
||||||
|
|
||||||
# Disable __call__() / _provide() optimization
|
# Disable __call__() / _provide() optimization
|
||||||
if self.__class__.__OPTIMIZED_CALLS__:
|
if self.__class__.__OPTIMIZED_CALLS__:
|
||||||
|
@ -140,12 +126,12 @@ class Provider(object):
|
||||||
|
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if not self.overridden_by:
|
if not self.overridden:
|
||||||
raise Error('Provider {0} is not overridden'.format(str(self)))
|
raise Error('Provider {0} is not overridden'.format(str(self)))
|
||||||
|
|
||||||
self.overridden_by = self.overridden_by[:-1]
|
self.overridden = self.overridden[:-1]
|
||||||
|
|
||||||
if not self.is_overridden:
|
if not self.overridden:
|
||||||
# Enable __call__() / _provide() optimization
|
# Enable __call__() / _provide() optimization
|
||||||
if self.__class__.__OPTIMIZED_CALLS__:
|
if self.__class__.__OPTIMIZED_CALLS__:
|
||||||
self.__call__ = self.provide = self._provide
|
self.__call__ = self.provide = self._provide
|
||||||
|
@ -155,7 +141,7 @@ class Provider(object):
|
||||||
|
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
self.overridden_by = tuple()
|
self.overridden = tuple()
|
||||||
|
|
||||||
# Enable __call__() / _provide() optimization
|
# Enable __call__() / _provide() optimization
|
||||||
if self.__class__.__OPTIMIZED_CALLS__:
|
if self.__class__.__OPTIMIZED_CALLS__:
|
||||||
|
@ -324,10 +310,10 @@ class ExternalDependency(Provider):
|
||||||
|
|
||||||
:rtype: object
|
:rtype: object
|
||||||
"""
|
"""
|
||||||
if not self.is_overridden:
|
if not self.overridden:
|
||||||
raise Error('Dependency is not defined')
|
raise Error('Dependency is not defined')
|
||||||
|
|
||||||
instance = self.last_overriding(*args, **kwargs)
|
instance = self._call_last_overriding(*args, **kwargs)
|
||||||
|
|
||||||
if not isinstance(instance, self.instance_of):
|
if not isinstance(instance, self.instance_of):
|
||||||
raise Error('{0} is not an '.format(instance) +
|
raise Error('{0} is not an '.format(instance) +
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
Declarative containers
|
Declarative containers
|
||||||
--------------------
|
----------------------
|
||||||
|
|
||||||
.. currentmodule:: dependency_injector.containers
|
.. currentmodule:: dependency_injector.containers
|
||||||
|
|
||||||
:py:class:`DeclarativeContainer` is a container of providers that could be
|
:py:class:`DeclarativeContainer` is inversion of control container that
|
||||||
defined in declarative manner. It should cover most of the cases when list
|
could be defined in declarative manner. It should cover most of the cases
|
||||||
of providers that would be included in container is deterministic (container
|
when list of providers that would be included in container is deterministic
|
||||||
will not change its structure in runtime).
|
(container will not change its structure in runtime).
|
||||||
|
|
||||||
Declarative containers have to extend base declarative container class -
|
Declarative containers have to extend base declarative container class -
|
||||||
:py:class:`dependency_injector.containers.DeclarativeContainer`.
|
:py:class:`dependency_injector.containers.DeclarativeContainer`.
|
||||||
|
|
|
@ -1,31 +1,27 @@
|
||||||
Dynamic catalogs
|
Dynamic containers
|
||||||
----------------
|
------------------
|
||||||
|
|
||||||
.. currentmodule:: dependency_injector.containers
|
.. currentmodule:: dependency_injector.containers
|
||||||
|
|
||||||
:py:class:`DynamicCatalog` is a catalog of providers that could be created in
|
:py:class:`DynamicContainer` is an inversion of control container with dynamic
|
||||||
application's runtime. It should cover most of the cases when list of
|
structure. It should cover most of the cases when list of providers that
|
||||||
providers that would be included in catalog is non-deterministic in terms of
|
would be included in container is non-deterministic and depends on
|
||||||
apllication code (catalog's structure could be determined just after
|
application's flow or its configuration (container's structure could be
|
||||||
application will be started and will do some initial work, like parsing list
|
determined just after application will be started and will do some initial
|
||||||
of catalog's providers from the configuration).
|
work, like parsing list of container's providers from the configuration).
|
||||||
|
|
||||||
:py:class:`DeclarativeCatalog` and :py:class:`DynamicCatalog` have
|
While :py:class:`DeclarativeContainer` acts on class-level,
|
||||||
100% API parity.
|
:py:class:`DynamicContainer` does the same on instance-level.
|
||||||
|
|
||||||
Main difference between :py:class:`DeclarativeCatalog` and
|
Here is an simple example of defining dynamic container with several factories:
|
||||||
:py:class:`DynamicCatalog` is that :py:class:`DeclarativeCatalog` acts on
|
|
||||||
class-level, while :py:class:`DynamicCatalog` do the same on
|
|
||||||
instance-level.
|
|
||||||
|
|
||||||
Here is an simple example of defining dynamic catalog with several factories:
|
.. literalinclude:: ../../examples/containers/dynamic.py
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/catalogs/dynamic.py
|
|
||||||
:language: python
|
:language: python
|
||||||
:linenos:
|
:linenos:
|
||||||
|
|
||||||
Next one example demonstrates creation and runtime filling of dynamic catalog:
|
Next example demonstrates creation of dynamic container based on some
|
||||||
|
configuration:
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/catalogs/dynamic_runtime_creation.py
|
.. literalinclude:: ../../examples/containers/dynamic_runtime_creation.py
|
||||||
:language: python
|
:language: python
|
||||||
:linenos:
|
:linenos:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
Containers
|
IoC Containers
|
||||||
==========
|
==============
|
||||||
|
|
||||||
Containers are collections of providers. Main purpose of containers is to group
|
Containers are collections of providers. Main purpose of containers is to group
|
||||||
providers.
|
providers.
|
||||||
|
|
|
@ -1,52 +1,40 @@
|
||||||
Overriding of catalogs
|
Overriding of containers
|
||||||
----------------------
|
------------------------
|
||||||
|
|
||||||
.. currentmodule:: dependency_injector.containers
|
.. currentmodule:: dependency_injector.containers
|
||||||
|
|
||||||
Catalogs can be overridden by other catalogs. This, actually, means that
|
Containers can be overridden by other containers. This, actually, means that
|
||||||
all of the providers from overriding catalog will override providers with the
|
all of the providers from overriding container will override providers with
|
||||||
same names in overridden catalog.
|
the same names in overridden container.
|
||||||
|
|
||||||
There are two ways to override :py:class:`DeclarativeCatalog` with another
|
There are two ways to override :py:class:`DeclarativeContainer` with another
|
||||||
catalog:
|
container:
|
||||||
|
|
||||||
- Use :py:meth:`DeclarativeCatalog.override` method.
|
- Use :py:meth:`DeclarativeContainer.override` method.
|
||||||
- Use :py:func:`override` class decorator.
|
- Use :py:func:`override` class decorator.
|
||||||
|
|
||||||
Example of overriding catalog using :py:meth:`DeclarativeCatalog.override`
|
Example of overriding container using :py:meth:`DeclarativeContainer.override`
|
||||||
method:
|
method:
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/catalogs/override_declarative.py
|
.. literalinclude:: ../../examples/containers/override_declarative.py
|
||||||
:language: python
|
:language: python
|
||||||
:linenos:
|
:linenos:
|
||||||
|
|
||||||
Example of overriding catalog using :py:func:`override` decorator:
|
Example of overriding container using :py:func:`override` decorator:
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/catalogs/override_declarative_decorator.py
|
.. literalinclude:: ../../examples/containers/override_declarative_decorator.py
|
||||||
:language: python
|
:language: python
|
||||||
:linenos:
|
:linenos:
|
||||||
|
|
||||||
Also there are several useful :py:class:`DeclarativeCatalog` methods and
|
Also there are several useful :py:class:`DeclarativeContainer` methods and
|
||||||
properties that help to work with catalog overridings:
|
properties that help to work with container overridings:
|
||||||
|
|
||||||
- :py:attr:`DeclarativeCatalog.is_overridden` - read-only property that is set
|
- :py:attr:`DeclarativeContainer.overridden` - tuple of all overriding
|
||||||
to ``True`` if catalog is overridden.
|
containers.
|
||||||
- :py:attr:`DeclarativeCatalog.last_overriding` - read-only reference to
|
- :py:meth:`DeclarativeContainer.reset_last_overriding()` - reset last
|
||||||
the last overriding catalog, if any.
|
overriding provider for each container providers.
|
||||||
- :py:attr:`DeclarativeCatalog.overridden_by` - tuple of all overriding
|
- :py:meth:`DeclarativeContainer.reset_override()` - reset all overridings
|
||||||
catalogs.
|
for each container providers.
|
||||||
- :py:meth:`DeclarativeCatalog.reset_last_overriding()` - reset last
|
|
||||||
overriding catalog.
|
|
||||||
- :py:meth:`DeclarativeCatalog.reset_override()` - reset all overridings for
|
|
||||||
all catalog providers.
|
|
||||||
|
|
||||||
:py:class:`DynamicCatalog` has exactly the same functionality, except of
|
:py:class:`DynamicContainer` has exactly the same functionality, except of
|
||||||
:py:func:`override` decorator. Also :py:class:`DynamicCatalog` can override
|
:py:func:`override` decorator.
|
||||||
:py:class:`DeclarativeCatalog` and vise versa.
|
|
||||||
|
|
||||||
Example of overriding :py:class:`DeclarativeCatalog` by
|
|
||||||
:py:class:`DynamicCatalog`:
|
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/catalogs/override_declarative_by_dynamic.py
|
|
||||||
:language: python
|
|
||||||
:linenos:
|
|
||||||
|
|
|
@ -1,45 +1,24 @@
|
||||||
Specialization of catalogs
|
Specialization of containers
|
||||||
--------------------------
|
----------------------------
|
||||||
|
|
||||||
.. currentmodule:: dependency_injector.containers
|
.. currentmodule:: dependency_injector.containers
|
||||||
|
|
||||||
:py:class:`DeclarativeCatalog` and :py:class:`DynamicCatalog` could be
|
:py:class:`DeclarativeContainer` could be specialized for any kind of needs
|
||||||
specialized for any kind of needs via declaring its subclasses.
|
via declaring its subclasses.
|
||||||
|
|
||||||
One of such `builtin` features is a limitation to
|
One of such `builtin` features is a limitation for providers type.
|
||||||
:py:class:`DeclarativeCatalog` (and :py:class:`DynamicCatalog`) provider type.
|
|
||||||
|
|
||||||
Next example shows usage of this feature with :py:class:`DeclarativeCatalog`
|
Next example shows usage of this feature with :py:class:`DeclarativeContainer`
|
||||||
in couple with feature of :py:class:`dependency_injector.providers.Factory`
|
in couple with feature of :py:class:`dependency_injector.providers.Factory`
|
||||||
for limitation of its provided type:
|
for limitation of its provided type:
|
||||||
|
|
||||||
|
.. literalinclude:: ../../examples/containers/declarative_provider_type.py
|
||||||
Listing of `services.py`:
|
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/catalogs/declarative_provider_type/services.py
|
|
||||||
:language: python
|
:language: python
|
||||||
:linenos:
|
:linenos:
|
||||||
|
|
||||||
Listing of `catalog.py`:
|
Limitation for providers type could be used with :py:class:`DynamicContainer`
|
||||||
|
as well:
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/catalogs/declarative_provider_type/catalog.py
|
.. literalinclude:: ../../examples/containers/dynamic_provider_type.py
|
||||||
:language: python
|
|
||||||
:linenos:
|
|
||||||
|
|
||||||
Limitation to provider type could be used with :py:class:`DynamicCatalog`
|
|
||||||
as well.
|
|
||||||
|
|
||||||
Next example does the same that previous one, but use
|
|
||||||
:py:class:`DynamicCatalog` instead of :py:class:`DeclarativeCatalog`:
|
|
||||||
|
|
||||||
Listing of `services.py`:
|
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/catalogs/dynamic_provider_type/services.py
|
|
||||||
:language: python
|
|
||||||
:linenos:
|
|
||||||
|
|
||||||
Listing of `catalog.py`:
|
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/catalogs/dynamic_provider_type/catalog.py
|
|
||||||
:language: python
|
:language: python
|
||||||
:linenos:
|
:linenos:
|
||||||
|
|
48
examples/containers/declarative_provider_type.py
Normal file
48
examples/containers/declarative_provider_type.py
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
"""Specializing declarative container and factory provider example."""
|
||||||
|
|
||||||
|
import collections
|
||||||
|
|
||||||
|
import dependency_injector.containers as containers
|
||||||
|
import dependency_injector.providers as providers
|
||||||
|
import dependency_injector.errors as errors
|
||||||
|
|
||||||
|
|
||||||
|
class SequenceProvider(providers.Factory):
|
||||||
|
"""Sequence factory.
|
||||||
|
|
||||||
|
Can provide only sequence objects.
|
||||||
|
"""
|
||||||
|
|
||||||
|
provided_type = collections.Sequence
|
||||||
|
|
||||||
|
|
||||||
|
class SequencesContainer(containers.DeclarativeContainer):
|
||||||
|
"""IoC container.
|
||||||
|
|
||||||
|
Can contain only sequence providers.
|
||||||
|
"""
|
||||||
|
|
||||||
|
provider_type = SequenceProvider
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
class _SequenceContainer1(SequencesContainer):
|
||||||
|
object_provider = providers.Factory(object)
|
||||||
|
except errors.Error as exception:
|
||||||
|
print exception
|
||||||
|
# <class '__main__._SequenceContainer1'> can contain only
|
||||||
|
# <class '__main__.SequenceProvider'> instances
|
||||||
|
|
||||||
|
try:
|
||||||
|
class _SequenceContainer2(SequencesContainer):
|
||||||
|
object_provider = SequenceProvider(object)
|
||||||
|
except errors.Error as exception:
|
||||||
|
print exception
|
||||||
|
# <class '__main__.SequenceProvider'> can provide only
|
||||||
|
# <class '_abcoll.Sequence'> instances
|
||||||
|
|
||||||
|
class _SequenceContaier3(SequencesContainer):
|
||||||
|
list_provider = SequenceProvider(list)
|
||||||
|
|
||||||
|
assert _SequenceContaier3.list_provider() == list()
|
|
@ -1,17 +0,0 @@
|
||||||
"""Specialized declarative IoC container example."""
|
|
||||||
|
|
||||||
import core
|
|
||||||
import services
|
|
||||||
|
|
||||||
|
|
||||||
class Services(core.ServicesContainer):
|
|
||||||
"""IoC container of service providers."""
|
|
||||||
|
|
||||||
users = core.ServiceProvider(services.UsersService,
|
|
||||||
config={'option1': '111',
|
|
||||||
'option2': '222'})
|
|
||||||
|
|
||||||
auth = core.ServiceProvider(services.AuthService,
|
|
||||||
config={'option3': '333',
|
|
||||||
'option4': '444'},
|
|
||||||
users_service=users)
|
|
|
@ -1,26 +0,0 @@
|
||||||
"""Base classes for services."""
|
|
||||||
|
|
||||||
from dependency_injector import containers
|
|
||||||
from dependency_injector import providers
|
|
||||||
|
|
||||||
|
|
||||||
class BaseService(object):
|
|
||||||
"""Base service class."""
|
|
||||||
|
|
||||||
|
|
||||||
class ServiceProvider(providers.Factory):
|
|
||||||
"""Service provider.
|
|
||||||
|
|
||||||
Can provide :py:class:`Base` only.
|
|
||||||
"""
|
|
||||||
|
|
||||||
provided_type = BaseService
|
|
||||||
|
|
||||||
|
|
||||||
class ServicesContainer(containers.DeclarativeContainer):
|
|
||||||
"""Base IoC container of service providers.
|
|
||||||
|
|
||||||
Can include :py:class:`Provider`'s only.
|
|
||||||
"""
|
|
||||||
|
|
||||||
provider_type = ServiceProvider
|
|
|
@ -1,42 +0,0 @@
|
||||||
"""Main module."""
|
|
||||||
|
|
||||||
import core
|
|
||||||
import services
|
|
||||||
import container
|
|
||||||
|
|
||||||
from dependency_injector import providers
|
|
||||||
from dependency_injector import errors
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
# Creating users & auth services:
|
|
||||||
users_service = container.Services.users()
|
|
||||||
auth_service = container.Services.auth()
|
|
||||||
|
|
||||||
# Making some asserts:
|
|
||||||
assert users_service.config == {'option1': '111',
|
|
||||||
'option2': '222'}
|
|
||||||
assert auth_service.config == {'option3': '333',
|
|
||||||
'option4': '444'}
|
|
||||||
assert isinstance(auth_service.users_service, services.UsersService)
|
|
||||||
|
|
||||||
# Trying to declare services container with other provider type:
|
|
||||||
try:
|
|
||||||
class _Services1(core.ServicesContainer):
|
|
||||||
|
|
||||||
users = providers.Factory(services.UsersService)
|
|
||||||
except errors.Error as exception:
|
|
||||||
print exception
|
|
||||||
# <class '__main__._Services1'> can contain only
|
|
||||||
# <class 'core.ServiceProvider'> instances
|
|
||||||
|
|
||||||
# Trying to declare services container with correct provider by invalid
|
|
||||||
# provided type:
|
|
||||||
try:
|
|
||||||
class _Services2(core.ServicesContainer):
|
|
||||||
|
|
||||||
users = core.ServiceProvider(object)
|
|
||||||
except errors.Error as exception:
|
|
||||||
print exception
|
|
||||||
# <class 'core.ServiceProvider'> can provide only
|
|
||||||
# <class 'core.BaseService'> instances
|
|
|
@ -1,22 +0,0 @@
|
||||||
"""Base classes for services."""
|
|
||||||
|
|
||||||
import core
|
|
||||||
|
|
||||||
|
|
||||||
class UsersService(core.BaseService):
|
|
||||||
"""Users service."""
|
|
||||||
|
|
||||||
def __init__(self, config):
|
|
||||||
"""Initializer."""
|
|
||||||
self.config = config
|
|
||||||
super(UsersService, self).__init__()
|
|
||||||
|
|
||||||
|
|
||||||
class AuthService(core.BaseService):
|
|
||||||
"""Auth service."""
|
|
||||||
|
|
||||||
def __init__(self, config, users_service):
|
|
||||||
"""Initializer."""
|
|
||||||
self.config = config
|
|
||||||
self.users_service = users_service
|
|
||||||
super(AuthService, self).__init__()
|
|
18
examples/containers/dynamic.py
Normal file
18
examples/containers/dynamic.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
"""Dynamic container simple example."""
|
||||||
|
|
||||||
|
import dependency_injector.containers as containers
|
||||||
|
import dependency_injector.providers as providers
|
||||||
|
|
||||||
|
|
||||||
|
# Defining dynamic container:
|
||||||
|
container = containers.DynamicContainer()
|
||||||
|
container.factory1 = providers.Factory(object)
|
||||||
|
container.factory2 = providers.Factory(object)
|
||||||
|
|
||||||
|
# Creating some objects:
|
||||||
|
object1 = container.factory1()
|
||||||
|
object2 = container.factory2()
|
||||||
|
|
||||||
|
# Making some asserts:
|
||||||
|
assert object1 is not object2
|
||||||
|
assert isinstance(object1, object) and isinstance(object2, object)
|
41
examples/containers/dynamic_provider_type.py
Normal file
41
examples/containers/dynamic_provider_type.py
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
"""Specializing dynamic container and factory provider example."""
|
||||||
|
|
||||||
|
import collections
|
||||||
|
|
||||||
|
import dependency_injector.containers as containers
|
||||||
|
import dependency_injector.providers as providers
|
||||||
|
import dependency_injector.errors as errors
|
||||||
|
|
||||||
|
|
||||||
|
class SequenceProvider(providers.Factory):
|
||||||
|
"""Sequence factory.
|
||||||
|
|
||||||
|
Can provide only sequence objects.
|
||||||
|
"""
|
||||||
|
|
||||||
|
provided_type = collections.Sequence
|
||||||
|
|
||||||
|
|
||||||
|
sequences_container = containers.DynamicContainer()
|
||||||
|
sequences_container.provider_type = SequenceProvider
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
sequences_container.object_provider = providers.Factory(object)
|
||||||
|
except errors.Error as exception:
|
||||||
|
print exception
|
||||||
|
# <dependency_injector.containers.DynamicContainer object at
|
||||||
|
# 0x107820ed0> can contain only <class '__main__.SequenceProvider'>
|
||||||
|
# instances
|
||||||
|
|
||||||
|
try:
|
||||||
|
sequences_container.object_provider = SequenceProvider(object)
|
||||||
|
except errors.Error as exception:
|
||||||
|
print exception
|
||||||
|
# <class '__main__.SequenceProvider'> can provide only
|
||||||
|
# <class '_abcoll.Sequence'> instances
|
||||||
|
|
||||||
|
sequences_container.list_provider = SequenceProvider(list)
|
||||||
|
|
||||||
|
assert sequences_container.list_provider() == list()
|
61
examples/containers/dynamic_runtime_creation.py
Normal file
61
examples/containers/dynamic_runtime_creation.py
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
"""Creation of dynamic container based on some configuration example."""
|
||||||
|
|
||||||
|
import dependency_injector.containers as containers
|
||||||
|
|
||||||
|
|
||||||
|
# Defining several example services:
|
||||||
|
class UsersService(object):
|
||||||
|
"""Example users service."""
|
||||||
|
|
||||||
|
|
||||||
|
class AuthService(object):
|
||||||
|
"""Example auth service."""
|
||||||
|
|
||||||
|
|
||||||
|
def import_cls(cls_name):
|
||||||
|
"""Import class by its fully qualified name.
|
||||||
|
|
||||||
|
In terms of current example it is just a small helper function. Please,
|
||||||
|
don't use it in production approaches.
|
||||||
|
"""
|
||||||
|
path_components = cls_name.split('.')
|
||||||
|
module = __import__('.'.join(path_components[:-1]),
|
||||||
|
locals(),
|
||||||
|
globals(),
|
||||||
|
fromlist=path_components[-1:])
|
||||||
|
return getattr(module, path_components[-1])
|
||||||
|
|
||||||
|
|
||||||
|
# "Parsing" some configuration:
|
||||||
|
config = {
|
||||||
|
'services': {
|
||||||
|
'users': {
|
||||||
|
'class': '__main__.UsersService',
|
||||||
|
'provider_class': 'dependency_injector.providers.Factory',
|
||||||
|
},
|
||||||
|
'auth': {
|
||||||
|
'class': '__main__.AuthService',
|
||||||
|
'provider_class': 'dependency_injector.providers.Factory',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Creating empty container of service providers:
|
||||||
|
services = containers.DynamicContainer()
|
||||||
|
|
||||||
|
# Filling dynamic container with service providers using configuration:
|
||||||
|
for service_name, service_info in config['services'].iteritems():
|
||||||
|
# Runtime importing of service and service provider classes:
|
||||||
|
service_cls = import_cls(service_info['class'])
|
||||||
|
service_provider_cls = import_cls(service_info['provider_class'])
|
||||||
|
|
||||||
|
# Binding service provider to the dynamic service providers catalog:
|
||||||
|
setattr(services, service_name, service_provider_cls(service_cls))
|
||||||
|
|
||||||
|
# Creating some objects:
|
||||||
|
users_service = services.users()
|
||||||
|
auth_service = services.auth()
|
||||||
|
|
||||||
|
# Making some asserts:
|
||||||
|
assert isinstance(users_service, UsersService)
|
||||||
|
assert isinstance(auth_service, AuthService)
|
|
@ -1,45 +1,28 @@
|
||||||
"""Declarative IoC container overriding example."""
|
"""Declarative IoC container overriding example."""
|
||||||
|
|
||||||
import collections
|
import dependency_injector.containers as containers
|
||||||
|
import dependency_injector.providers as providers
|
||||||
from dependency_injector import containers
|
|
||||||
from dependency_injector import providers
|
|
||||||
|
|
||||||
|
|
||||||
# Creating some example classes:
|
|
||||||
Object1 = collections.namedtuple('Object1', ['arg1', 'arg2'])
|
|
||||||
Object2 = collections.namedtuple('Object2', ['object1'])
|
|
||||||
ExtendedObject2 = collections.namedtuple('ExtendedObject2', [])
|
|
||||||
|
|
||||||
|
|
||||||
class Container(containers.DeclarativeContainer):
|
class Container(containers.DeclarativeContainer):
|
||||||
"""Example IoC container."""
|
"""IoC container."""
|
||||||
|
|
||||||
object1_factory = providers.Factory(Object1,
|
sequence_factory = providers.Factory(list)
|
||||||
arg1=1,
|
|
||||||
arg2=2)
|
|
||||||
|
|
||||||
object2_factory = providers.Factory(Object2,
|
|
||||||
object1=object1_factory)
|
|
||||||
|
|
||||||
|
|
||||||
class OverridingContainer(containers.DeclarativeContainer):
|
class OverridingContainer(containers.DeclarativeContainer):
|
||||||
"""Overriding IoC container."""
|
"""Overriding IoC container."""
|
||||||
|
|
||||||
object2_factory = providers.Factory(ExtendedObject2)
|
sequence_factory = providers.Factory(tuple)
|
||||||
|
|
||||||
|
|
||||||
# Overriding `Container` with `OverridingContainer`:
|
# Overriding `Container` with `OverridingContainer`:
|
||||||
Container.override(OverridingContainer)
|
Container.override(OverridingContainer)
|
||||||
|
|
||||||
# Creating some objects using overridden container:
|
# Creating some objects using overridden container:
|
||||||
object2_1 = Container.object2_factory()
|
sequence_1 = Container.sequence_factory([1, 2, 3])
|
||||||
object2_2 = Container.object2_factory()
|
sequence_2 = Container.sequence_factory([3, 2, 1])
|
||||||
|
|
||||||
# Making some asserts:
|
# Making some asserts:
|
||||||
assert Container.overridden_by == (OverridingContainer,)
|
assert Container.overridden == (OverridingContainer,)
|
||||||
|
assert sequence_1 == (1, 2, 3) and sequence_2 == (3, 2, 1)
|
||||||
assert object2_1 is not object2_2
|
|
||||||
|
|
||||||
assert isinstance(object2_1, ExtendedObject2)
|
|
||||||
assert isinstance(object2_2, ExtendedObject2)
|
|
||||||
|
|
|
@ -1,23 +1,13 @@
|
||||||
"""Declarative IoC container overriding using `@override()` decorator."""
|
"""Declarative IoC container overriding using `@override()` decorator."""
|
||||||
|
|
||||||
import collections
|
import dependency_injector.containers as containers
|
||||||
|
import dependency_injector.providers as providers
|
||||||
from dependency_injector import containers
|
|
||||||
from dependency_injector import providers
|
|
||||||
|
|
||||||
|
|
||||||
# Creating some example classes:
|
|
||||||
Object1 = collections.namedtuple('Object1', ['arg1', 'arg2'])
|
|
||||||
Object2 = collections.namedtuple('Object2', ['object1'])
|
|
||||||
ExtendedObject2 = collections.namedtuple('ExtendedObject2', [])
|
|
||||||
|
|
||||||
|
|
||||||
class Container(containers.DeclarativeContainer):
|
class Container(containers.DeclarativeContainer):
|
||||||
"""Example IoC container."""
|
"""IoC container."""
|
||||||
|
|
||||||
object1_factory = providers.Factory(Object1, arg1=1, arg2=2)
|
sequence_factory = providers.Factory(list)
|
||||||
|
|
||||||
object2_factory = providers.Factory(Object2, object1=object1_factory)
|
|
||||||
|
|
||||||
|
|
||||||
# Overriding `Container` with `OverridingContainer`:
|
# Overriding `Container` with `OverridingContainer`:
|
||||||
|
@ -25,17 +15,13 @@ class Container(containers.DeclarativeContainer):
|
||||||
class OverridingContainer(containers.DeclarativeContainer):
|
class OverridingContainer(containers.DeclarativeContainer):
|
||||||
"""Overriding IoC container."""
|
"""Overriding IoC container."""
|
||||||
|
|
||||||
object2_factory = providers.Factory(ExtendedObject2)
|
sequence_factory = providers.Factory(tuple)
|
||||||
|
|
||||||
|
|
||||||
# Creating some objects using overridden container:
|
# Creating some objects using overridden container:
|
||||||
object2_1 = Container.object2_factory()
|
sequence_1 = Container.sequence_factory([1, 2, 3])
|
||||||
object2_2 = Container.object2_factory()
|
sequence_2 = Container.sequence_factory([3, 2, 1])
|
||||||
|
|
||||||
# Making some asserts:
|
# Making some asserts:
|
||||||
assert Container.overridden_by == (OverridingContainer,)
|
assert Container.overridden == (OverridingContainer,)
|
||||||
|
assert sequence_1 == (1, 2, 3) and sequence_2 == (3, 2, 1)
|
||||||
assert object2_1 is not object2_2
|
|
||||||
|
|
||||||
assert isinstance(object2_1, ExtendedObject2)
|
|
||||||
assert isinstance(object2_2, ExtendedObject2)
|
|
||||||
|
|
|
@ -42,14 +42,14 @@ class ProviderTests(unittest.TestCase):
|
||||||
"""Test provider overriding."""
|
"""Test provider overriding."""
|
||||||
overriding_provider = providers.Provider()
|
overriding_provider = providers.Provider()
|
||||||
self.provider.override(overriding_provider)
|
self.provider.override(overriding_provider)
|
||||||
self.assertTrue(self.provider.is_overridden)
|
self.assertTrue(self.provider.overridden)
|
||||||
|
|
||||||
def test_overriding_context(self):
|
def test_overriding_context(self):
|
||||||
"""Test provider overriding context."""
|
"""Test provider overriding context."""
|
||||||
overriding_provider = providers.Provider()
|
overriding_provider = providers.Provider()
|
||||||
with self.provider.override(overriding_provider):
|
with self.provider.override(overriding_provider):
|
||||||
self.assertTrue(self.provider.is_overridden)
|
self.assertTrue(self.provider.overridden)
|
||||||
self.assertFalse(self.provider.is_overridden)
|
self.assertFalse(self.provider.overridden)
|
||||||
|
|
||||||
def test_override_with_itself(self):
|
def test_override_with_itself(self):
|
||||||
"""Test provider overriding with itself."""
|
"""Test provider overriding with itself."""
|
||||||
|
@ -61,21 +61,6 @@ class ProviderTests(unittest.TestCase):
|
||||||
self.provider.override(obj)
|
self.provider.override(obj)
|
||||||
self.assertIs(self.provider(), obj)
|
self.assertIs(self.provider(), obj)
|
||||||
|
|
||||||
def test_last_overriding(self):
|
|
||||||
"""Test getting last overriding provider."""
|
|
||||||
overriding_provider1 = providers.Provider()
|
|
||||||
overriding_provider2 = providers.Provider()
|
|
||||||
|
|
||||||
self.provider.override(overriding_provider1)
|
|
||||||
self.assertIs(self.provider.last_overriding, overriding_provider1)
|
|
||||||
|
|
||||||
self.provider.override(overriding_provider2)
|
|
||||||
self.assertIs(self.provider.last_overriding, overriding_provider2)
|
|
||||||
|
|
||||||
def test_last_overriding_of_not_overridden_provider(self):
|
|
||||||
"""Test getting last overriding from not overridden provider."""
|
|
||||||
self.assertIsNone(self.provider.last_overriding)
|
|
||||||
|
|
||||||
def test_reset_last_overriding(self):
|
def test_reset_last_overriding(self):
|
||||||
"""Test reseting of last overriding provider."""
|
"""Test reseting of last overriding provider."""
|
||||||
overriding_provider1 = providers.Provider()
|
overriding_provider1 = providers.Provider()
|
||||||
|
@ -84,13 +69,13 @@ class ProviderTests(unittest.TestCase):
|
||||||
self.provider.override(overriding_provider1)
|
self.provider.override(overriding_provider1)
|
||||||
self.provider.override(overriding_provider2)
|
self.provider.override(overriding_provider2)
|
||||||
|
|
||||||
self.assertIs(self.provider.last_overriding, overriding_provider2)
|
self.assertIs(self.provider.overridden[-1], overriding_provider2)
|
||||||
|
|
||||||
self.provider.reset_last_overriding()
|
self.provider.reset_last_overriding()
|
||||||
self.assertIs(self.provider.last_overriding, overriding_provider1)
|
self.assertIs(self.provider.overridden[-1], overriding_provider1)
|
||||||
|
|
||||||
self.provider.reset_last_overriding()
|
self.provider.reset_last_overriding()
|
||||||
self.assertFalse(self.provider.is_overridden)
|
self.assertFalse(self.provider.overridden)
|
||||||
|
|
||||||
def test_reset_last_overriding_of_not_overridden_provider(self):
|
def test_reset_last_overriding_of_not_overridden_provider(self):
|
||||||
"""Test resetting of last overriding on not overridden provier."""
|
"""Test resetting of last overriding on not overridden provier."""
|
||||||
|
@ -101,13 +86,12 @@ class ProviderTests(unittest.TestCase):
|
||||||
overriding_provider = providers.Provider()
|
overriding_provider = providers.Provider()
|
||||||
self.provider.override(overriding_provider)
|
self.provider.override(overriding_provider)
|
||||||
|
|
||||||
self.assertTrue(self.provider.is_overridden)
|
self.assertTrue(self.provider.overridden)
|
||||||
self.assertIs(self.provider.last_overriding, overriding_provider)
|
self.assertEqual(self.provider.overridden, (overriding_provider,))
|
||||||
|
|
||||||
self.provider.reset_override()
|
self.provider.reset_override()
|
||||||
|
|
||||||
self.assertFalse(self.provider.is_overridden)
|
self.assertEqual(self.provider.overridden, tuple())
|
||||||
self.assertIsNone(self.provider.last_overriding)
|
|
||||||
|
|
||||||
def test_repr(self):
|
def test_repr(self):
|
||||||
"""Test representation of provider."""
|
"""Test representation of provider."""
|
||||||
|
|
|
@ -138,10 +138,10 @@ class DeclarativeContainerTests(unittest.TestCase):
|
||||||
_Container.override(_OverridingContainer1)
|
_Container.override(_OverridingContainer1)
|
||||||
_Container.override(_OverridingContainer2)
|
_Container.override(_OverridingContainer2)
|
||||||
|
|
||||||
self.assertEqual(_Container.overridden_by,
|
self.assertEqual(_Container.overridden,
|
||||||
(_OverridingContainer1,
|
(_OverridingContainer1,
|
||||||
_OverridingContainer2))
|
_OverridingContainer2))
|
||||||
self.assertEqual(_Container.p11.overridden_by,
|
self.assertEqual(_Container.p11.overridden,
|
||||||
(_OverridingContainer1.p11,
|
(_OverridingContainer1.p11,
|
||||||
_OverridingContainer2.p11))
|
_OverridingContainer2.p11))
|
||||||
|
|
||||||
|
@ -169,10 +169,10 @@ class DeclarativeContainerTests(unittest.TestCase):
|
||||||
p11 = providers.Provider()
|
p11 = providers.Provider()
|
||||||
p12 = providers.Provider()
|
p12 = providers.Provider()
|
||||||
|
|
||||||
self.assertEqual(_Container.overridden_by,
|
self.assertEqual(_Container.overridden,
|
||||||
(_OverridingContainer1,
|
(_OverridingContainer1,
|
||||||
_OverridingContainer2))
|
_OverridingContainer2))
|
||||||
self.assertEqual(_Container.p11.overridden_by,
|
self.assertEqual(_Container.p11.overridden,
|
||||||
(_OverridingContainer1.p11,
|
(_OverridingContainer1.p11,
|
||||||
_OverridingContainer2.p11))
|
_OverridingContainer2.p11))
|
||||||
|
|
||||||
|
@ -192,9 +192,9 @@ class DeclarativeContainerTests(unittest.TestCase):
|
||||||
_Container.override(_OverridingContainer2)
|
_Container.override(_OverridingContainer2)
|
||||||
_Container.reset_last_overriding()
|
_Container.reset_last_overriding()
|
||||||
|
|
||||||
self.assertEqual(_Container.overridden_by,
|
self.assertEqual(_Container.overridden,
|
||||||
(_OverridingContainer1,))
|
(_OverridingContainer1,))
|
||||||
self.assertEqual(_Container.p11.overridden_by,
|
self.assertEqual(_Container.p11.overridden,
|
||||||
(_OverridingContainer1.p11,))
|
(_OverridingContainer1.p11,))
|
||||||
|
|
||||||
def test_reset_last_overridding_when_not_overridden(self):
|
def test_reset_last_overridding_when_not_overridden(self):
|
||||||
|
@ -218,8 +218,8 @@ class DeclarativeContainerTests(unittest.TestCase):
|
||||||
_Container.override(_OverridingContainer2)
|
_Container.override(_OverridingContainer2)
|
||||||
_Container.reset_override()
|
_Container.reset_override()
|
||||||
|
|
||||||
self.assertEqual(_Container.overridden_by, tuple())
|
self.assertEqual(_Container.overridden, tuple())
|
||||||
self.assertEqual(_Container.p11.overridden_by, tuple())
|
self.assertEqual(_Container.p11.overridden, tuple())
|
||||||
|
|
||||||
def test_copy(self):
|
def test_copy(self):
|
||||||
"""Test copy decorator."""
|
"""Test copy decorator."""
|
||||||
|
@ -361,15 +361,15 @@ class DeclarativeContainerInstanceTests(unittest.TestCase):
|
||||||
container.override(overriding_container1)
|
container.override(overriding_container1)
|
||||||
container.override(overriding_container2)
|
container.override(overriding_container2)
|
||||||
|
|
||||||
self.assertEqual(container.overridden_by,
|
self.assertEqual(container.overridden,
|
||||||
(overriding_container1,
|
(overriding_container1,
|
||||||
overriding_container2))
|
overriding_container2))
|
||||||
self.assertEqual(container.p11.overridden_by,
|
self.assertEqual(container.p11.overridden,
|
||||||
(overriding_container1.p11,
|
(overriding_container1.p11,
|
||||||
overriding_container2.p11))
|
overriding_container2.p11))
|
||||||
|
|
||||||
self.assertEqual(_Container.overridden_by, tuple())
|
self.assertEqual(_Container.overridden, tuple())
|
||||||
self.assertEqual(_Container.p11.overridden_by, tuple())
|
self.assertEqual(_Container.p11.overridden, tuple())
|
||||||
|
|
||||||
def test_override_with_itself(self):
|
def test_override_with_itself(self):
|
||||||
"""Test override container with itself."""
|
"""Test override container with itself."""
|
||||||
|
@ -397,9 +397,9 @@ class DeclarativeContainerInstanceTests(unittest.TestCase):
|
||||||
container.override(overriding_container2)
|
container.override(overriding_container2)
|
||||||
container.reset_last_overriding()
|
container.reset_last_overriding()
|
||||||
|
|
||||||
self.assertEqual(container.overridden_by,
|
self.assertEqual(container.overridden,
|
||||||
(overriding_container1,))
|
(overriding_container1,))
|
||||||
self.assertEqual(container.p11.overridden_by,
|
self.assertEqual(container.p11.overridden,
|
||||||
(overriding_container1.p11,))
|
(overriding_container1.p11,))
|
||||||
|
|
||||||
def test_reset_last_overridding_when_not_overridden(self):
|
def test_reset_last_overridding_when_not_overridden(self):
|
||||||
|
@ -429,8 +429,8 @@ class DeclarativeContainerInstanceTests(unittest.TestCase):
|
||||||
container.override(overriding_container2)
|
container.override(overriding_container2)
|
||||||
container.reset_override()
|
container.reset_override()
|
||||||
|
|
||||||
self.assertEqual(container.overridden_by, tuple())
|
self.assertEqual(container.overridden, tuple())
|
||||||
self.assertEqual(container.p11.overridden_by, tuple())
|
self.assertEqual(container.p11.overridden, tuple())
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
Loading…
Reference in New Issue
Block a user