mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-22 09:36:48 +03:00
Add dynamic containers
+ Drop catalogs
This commit is contained in:
parent
be94a1badc
commit
3416728309
|
@ -1,20 +0,0 @@
|
|||
"""Dependency injector catalogs package."""
|
||||
|
||||
from dependency_injector.catalogs.dynamic import DynamicCatalog
|
||||
from dependency_injector.catalogs.declarative import (
|
||||
DeclarativeCatalogMetaClass,
|
||||
DeclarativeCatalog,
|
||||
)
|
||||
from dependency_injector.catalogs.utils import (
|
||||
copy,
|
||||
override
|
||||
)
|
||||
|
||||
|
||||
__all__ = (
|
||||
'DynamicCatalog',
|
||||
'DeclarativeCatalogMetaClass',
|
||||
'DeclarativeCatalog',
|
||||
'copy',
|
||||
'override',
|
||||
)
|
|
@ -1,440 +0,0 @@
|
|||
"""Dependency injector declarative catalog module."""
|
||||
|
||||
import six
|
||||
|
||||
from dependency_injector.catalogs.dynamic import DynamicCatalog
|
||||
from dependency_injector.utils import (
|
||||
is_provider,
|
||||
is_catalog,
|
||||
is_declarative_catalog,
|
||||
)
|
||||
from dependency_injector.errors import (
|
||||
Error,
|
||||
UndefinedProviderError,
|
||||
)
|
||||
|
||||
|
||||
@six.python_2_unicode_compatible
|
||||
class DeclarativeCatalogMetaClass(type):
|
||||
"""Declarative catalog meta class."""
|
||||
|
||||
def __new__(mcs, class_name, bases, attributes):
|
||||
"""Declarative catalog class factory."""
|
||||
cls_providers = tuple((name, provider)
|
||||
for name, provider in six.iteritems(attributes)
|
||||
if is_provider(provider))
|
||||
|
||||
inherited_providers = tuple((name, provider)
|
||||
for base in bases if is_catalog(base)
|
||||
for name, provider in six.iteritems(
|
||||
base.providers))
|
||||
|
||||
providers = cls_providers + inherited_providers
|
||||
|
||||
cls = type.__new__(mcs, class_name, bases, attributes)
|
||||
|
||||
if cls.provider_type:
|
||||
cls._catalog = type('DynamicCatalog',
|
||||
(DynamicCatalog,),
|
||||
dict(provider_type=cls.provider_type))()
|
||||
else:
|
||||
cls._catalog = DynamicCatalog()
|
||||
|
||||
cls._catalog.bind_providers(dict(providers))
|
||||
|
||||
cls._cls_providers = dict(cls_providers)
|
||||
cls._inherited_providers = dict(inherited_providers)
|
||||
|
||||
return cls
|
||||
|
||||
@property
|
||||
def providers(cls):
|
||||
"""Read-only dictionary of all providers.
|
||||
|
||||
:type: dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||
"""
|
||||
return cls._catalog.providers
|
||||
|
||||
@property
|
||||
def cls_providers(cls):
|
||||
"""Read-only dictionary of current catalog providers.
|
||||
|
||||
:rtype: dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||
"""
|
||||
return cls._cls_providers
|
||||
|
||||
@property
|
||||
def inherited_providers(cls):
|
||||
"""Read-only dictionary of inherited providers.
|
||||
|
||||
:rtype: dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||
"""
|
||||
return cls._inherited_providers
|
||||
|
||||
@property
|
||||
def overridden_by(cls):
|
||||
"""Tuple of overriding catalogs.
|
||||
|
||||
:type: tuple[
|
||||
:py:class:`DeclarativeCatalog` |
|
||||
:py:class:`DynamicCatalog`]
|
||||
"""
|
||||
return cls._catalog.overridden_by
|
||||
|
||||
@property
|
||||
def is_overridden(cls):
|
||||
"""Read-only property that is set to ``True`` if catalog is overridden.
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
return cls._catalog.is_overridden
|
||||
|
||||
@property
|
||||
def last_overriding(cls):
|
||||
"""Read-only reference to the last overriding catalog, if any.
|
||||
|
||||
:type: :py:class:`DeclarativeCatalog` | :py:class:`DynamicCatalog` |
|
||||
None
|
||||
"""
|
||||
return cls._catalog.last_overriding
|
||||
|
||||
def __getattr__(cls, name):
|
||||
"""Return provider with specified name or raise en error.
|
||||
|
||||
:param name: Attribute's name.
|
||||
:type name: str
|
||||
|
||||
:raise: :py:exc:`dependency_injector.errors.UndefinedProviderError`
|
||||
"""
|
||||
raise UndefinedProviderError('There is no provider "{0}" in '
|
||||
'catalog {1}'.format(name, cls))
|
||||
|
||||
def __setattr__(cls, name, value):
|
||||
"""Handle setting of catalog attributes.
|
||||
|
||||
Setting of attributes works as usual, but if value of attribute is
|
||||
provider, this provider will be bound to catalog.
|
||||
|
||||
:param name: Attribute's name.
|
||||
:type name: str
|
||||
|
||||
:param value: Attribute's value.
|
||||
:type value: :py:class:`dependency_injector.providers.Provider` |
|
||||
object
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
if is_provider(value):
|
||||
cls.bind_provider(name, value, _set_as_attribute=False)
|
||||
return super(DeclarativeCatalogMetaClass, cls).__setattr__(name, value)
|
||||
|
||||
def __delattr__(cls, name):
|
||||
"""Handle deleting of catalog attibute.
|
||||
|
||||
Deleting of attributes works as usual, but if value of attribute is
|
||||
provider, this provider will be unbound from catalog.
|
||||
|
||||
:param name: Attribute's name.
|
||||
:type name: str
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
if is_provider(getattr(cls, name)):
|
||||
delattr(cls._catalog, name)
|
||||
return super(DeclarativeCatalogMetaClass, cls).__delattr__(name)
|
||||
|
||||
def __repr__(cls):
|
||||
"""Return string representation of the catalog.
|
||||
|
||||
:rtype: str
|
||||
"""
|
||||
return '<{0}({1})>'.format('.'.join((cls.__module__, cls.__name__)),
|
||||
', '.join(six.iterkeys(cls.providers)))
|
||||
|
||||
__str__ = __repr__
|
||||
|
||||
|
||||
@six.add_metaclass(DeclarativeCatalogMetaClass)
|
||||
class DeclarativeCatalog(object):
|
||||
"""Declarative catalog of providers.
|
||||
|
||||
:py:class:`DeclarativeCatalog` is a catalog of providers that could be
|
||||
defined in declarative manner. It should cover most of the cases when list
|
||||
of providers that would be included in catalog is deterministic (catalog
|
||||
will not change its structure in runtime).
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class Services(DeclarativeCatalog):
|
||||
|
||||
auth = providers.Factory(AuthService)
|
||||
|
||||
users = providers.Factory(UsersService)
|
||||
|
||||
users_service = Services.users()
|
||||
|
||||
.. py:attribute:: provider_type
|
||||
|
||||
If provider type is defined, :py:class:`DeclarativeCatalog` checks that
|
||||
all of its providers are instances of
|
||||
:py:attr:`DeclarativeCatalog.provider_type`.
|
||||
|
||||
:type: type | None
|
||||
"""
|
||||
|
||||
provider_type = None
|
||||
|
||||
_catalog = DynamicCatalog
|
||||
|
||||
_cls_providers = dict()
|
||||
_inherited_providers = dict()
|
||||
|
||||
__IS_CATALOG__ = True
|
||||
|
||||
@property
|
||||
def providers(self):
|
||||
"""Read-only dictionary of all providers.
|
||||
|
||||
:rtype: dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||
"""
|
||||
return self.__class__.providers
|
||||
|
||||
@property
|
||||
def cls_providers(self):
|
||||
"""Read-only dictionary of current catalog providers.
|
||||
|
||||
:rtype: dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||
"""
|
||||
return self.__class__.cls_providers
|
||||
|
||||
@property
|
||||
def inherited_providers(self):
|
||||
"""Read-only dictionary of inherited providers.
|
||||
|
||||
:rtype: dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||
"""
|
||||
return self.__class__.inherited_providers
|
||||
|
||||
@property
|
||||
def overridden_by(self):
|
||||
"""Tuple of overriding catalogs.
|
||||
|
||||
:rtype: tuple[:py:class:`DeclarativeCatalog` |
|
||||
:py:class:`DynamicCatalog`]
|
||||
"""
|
||||
return self.__class__.overridden_by
|
||||
|
||||
@property
|
||||
def is_overridden(self):
|
||||
"""Read-only property that is set to ``True`` if catalog is overridden.
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
return self.__class__.is_overridden
|
||||
|
||||
@property
|
||||
def last_overriding(self):
|
||||
"""Read-only reference to the last overriding catalog, if any.
|
||||
|
||||
:rtype: :py:class:`DeclarativeCatalog` | :py:class:`DynamicCatalog` |
|
||||
None
|
||||
"""
|
||||
return self.__class__.last_overriding
|
||||
|
||||
@classmethod
|
||||
def get_provider_bind_name(cls, provider):
|
||||
"""Return provider's name in catalog.
|
||||
|
||||
:param provider: Provider instance.
|
||||
:type provider: :py:class:`dependency_injector.providers.Provider`
|
||||
|
||||
:raise: :py:exc:`dependency_injector.errors.UndefinedProviderError`
|
||||
|
||||
:return: Provider's name.
|
||||
:rtype: str
|
||||
"""
|
||||
return cls._catalog.get_provider_bind_name(provider)
|
||||
|
||||
@classmethod
|
||||
def is_provider_bound(cls, provider):
|
||||
"""Check if provider is bound to the catalog.
|
||||
|
||||
:param provider: Provider instance.
|
||||
:type provider: :py:class:`dependency_injector.providers.Provider`
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
return cls._catalog.is_provider_bound(provider)
|
||||
|
||||
@classmethod
|
||||
def filter(cls, provider_type):
|
||||
"""Return dictionary of providers, that are instance of provided type.
|
||||
|
||||
:param provider_type: Provider's type.
|
||||
:type provider_type: :py:class:`dependency_injector.providers.Provider`
|
||||
|
||||
:rtype: dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||
"""
|
||||
return cls._catalog.filter(provider_type)
|
||||
|
||||
@classmethod
|
||||
def override(cls, overriding):
|
||||
"""Override current catalog providers by overriding catalog providers.
|
||||
|
||||
:param overriding: Overriding catalog.
|
||||
:type overriding: :py:class:`DeclarativeCatalog` |
|
||||
:py:class:`DynamicCatalog`
|
||||
|
||||
:raise: :py:exc:`dependency_injector.errors.Error` if trying to
|
||||
override catalog by itself or its subclasses
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
if is_declarative_catalog(overriding) and issubclass(cls, overriding):
|
||||
raise Error('Catalog {0} could not be overridden '
|
||||
'with itself or its subclasses'.format(cls))
|
||||
return cls._catalog.override(overriding)
|
||||
|
||||
@classmethod
|
||||
def reset_last_overriding(cls):
|
||||
"""Reset last overriding catalog.
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
cls._catalog.reset_last_overriding()
|
||||
|
||||
@classmethod
|
||||
def reset_override(cls):
|
||||
"""Reset all overridings for all catalog providers.
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
cls._catalog.reset_override()
|
||||
|
||||
@classmethod
|
||||
def get_provider(cls, name):
|
||||
"""Return provider with specified name or raise an error.
|
||||
|
||||
:param name: Provider's name.
|
||||
:type name: str
|
||||
|
||||
:raise: :py:exc:`dependency_injector.errors.UndefinedProviderError`
|
||||
|
||||
:return: Provider with specified name.
|
||||
:rtype: :py:class:`dependency_injector.providers.Provider`
|
||||
"""
|
||||
return cls._catalog.get_provider(name)
|
||||
|
||||
@classmethod
|
||||
def bind_provider(cls, name, provider, force=False,
|
||||
_set_as_attribute=True):
|
||||
"""Bind provider to catalog with specified name.
|
||||
|
||||
:param name: Name of the provider.
|
||||
:type name: str
|
||||
|
||||
:param provider: Provider instance.
|
||||
:type provider: :py:class:`dependency_injector.providers.Provider`
|
||||
|
||||
:param force: Force binding of provider.
|
||||
:type force: bool
|
||||
|
||||
:raise: :py:exc:`dependency_injector.errors.Error`
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
if cls._catalog.is_provider_bound(provider):
|
||||
bindind_name = cls._catalog.get_provider_bind_name(provider)
|
||||
if bindind_name == name and not force:
|
||||
return
|
||||
|
||||
cls._catalog.bind_provider(name, provider, force)
|
||||
cls.cls_providers[name] = provider
|
||||
|
||||
if _set_as_attribute:
|
||||
setattr(cls, name, provider)
|
||||
|
||||
@classmethod
|
||||
def bind_providers(cls, providers, force=False):
|
||||
"""Bind providers dictionary to catalog.
|
||||
|
||||
:param providers: Dictionary of providers, where key is a name
|
||||
and value is a provider.
|
||||
:type providers:
|
||||
dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||
|
||||
:param force: Force binding of providers.
|
||||
:type force: bool
|
||||
|
||||
:raise: :py:exc:`dependency_injector.errors.Error`
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
for name, provider in six.iteritems(providers):
|
||||
cls.bind_provider(name, provider, force=force)
|
||||
|
||||
@classmethod
|
||||
def has_provider(cls, name):
|
||||
"""Check if there is provider with certain name.
|
||||
|
||||
:param name: Provider's name.
|
||||
:type name: str
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
return hasattr(cls, name)
|
||||
|
||||
@classmethod
|
||||
def unbind_provider(cls, name):
|
||||
"""Remove provider binding.
|
||||
|
||||
:param name: Provider's name.
|
||||
:type name: str
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
delattr(cls, name)
|
||||
del cls.cls_providers[name]
|
||||
|
||||
@classmethod
|
||||
def __getattr__(cls, name): # pragma: no cover
|
||||
"""Return provider with specified name or raise en error.
|
||||
|
||||
:param name: Attribute's name.
|
||||
:type name: str
|
||||
|
||||
:raise: :py:exc:`dependency_injector.errors.UndefinedProviderError`
|
||||
"""
|
||||
raise NotImplementedError('Implementated in metaclass')
|
||||
|
||||
@classmethod
|
||||
def __setattr__(cls, name, value): # pragma: no cover
|
||||
"""Handle setting of catalog attributes.
|
||||
|
||||
Setting of attributes works as usual, but if value of attribute is
|
||||
provider, this provider will be bound to catalog.
|
||||
|
||||
:param name: Attribute's name.
|
||||
:type name: str
|
||||
|
||||
:param value: Attribute's value.
|
||||
:type value: :py:class:`dependency_injector.providers.Provider` |
|
||||
object
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
raise NotImplementedError('Implementated in metaclass')
|
||||
|
||||
@classmethod
|
||||
def __delattr__(cls, name): # pragma: no cover
|
||||
"""Handle deleting of catalog attibute.
|
||||
|
||||
Deleting of attributes works as usual, but if value of attribute is
|
||||
provider, this provider will be unbound from catalog.
|
||||
|
||||
:param name: Attribute's name.
|
||||
:type name: str
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
raise NotImplementedError('Implementated in metaclass')
|
|
@ -1,309 +0,0 @@
|
|||
"""Dependency injector dynamic catalog module."""
|
||||
|
||||
import six
|
||||
|
||||
from dependency_injector.utils import (
|
||||
is_provider,
|
||||
ensure_is_provider,
|
||||
)
|
||||
from dependency_injector.errors import (
|
||||
Error,
|
||||
UndefinedProviderError,
|
||||
)
|
||||
|
||||
|
||||
@six.python_2_unicode_compatible
|
||||
class DynamicCatalog(object):
|
||||
"""Dynamic catalog of providers.
|
||||
|
||||
:py:class:`DynamicCatalog` is a catalog of providers that could be created
|
||||
in application's runtime. It should cover most of the cases when list of
|
||||
providers that would be included in catalog is non-deterministic in terms
|
||||
of apllication code (catalog's structure could be determined just after
|
||||
application will be started and will do some initial work, like parsing
|
||||
list of catalog's providers from the configuration).
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
services = DynamicCatalog(auth=providers.Factory(AuthService),
|
||||
users=providers.Factory(UsersService))
|
||||
|
||||
users_service = services.users()
|
||||
|
||||
.. py:attribute:: providers
|
||||
|
||||
Dictionary of all providers.
|
||||
|
||||
:type: dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||
|
||||
.. py:attribute:: overridden_by
|
||||
|
||||
Tuple of overriding catalogs.
|
||||
|
||||
:type: tuple[
|
||||
:py:class:`DeclarativeCatalog` | :py:class:`DynamicCatalog`]
|
||||
|
||||
.. py:attribute:: provider_type
|
||||
|
||||
If provider type is defined, :py:class:`DynamicCatalog` checks that
|
||||
all of its providers are instances of
|
||||
:py:attr:`DynamicCatalog.provider_type`.
|
||||
|
||||
:type: type | None
|
||||
"""
|
||||
|
||||
provider_type = None
|
||||
|
||||
__IS_CATALOG__ = True
|
||||
__slots__ = ('providers', 'provider_names', 'overridden_by')
|
||||
|
||||
def __init__(self, **providers):
|
||||
"""Initializer.
|
||||
|
||||
:param providers: Dictionary of catalog providers.
|
||||
:type providers:
|
||||
dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||
"""
|
||||
self.providers = dict()
|
||||
self.provider_names = dict()
|
||||
self.overridden_by = tuple()
|
||||
self.bind_providers(providers)
|
||||
super(DynamicCatalog, self).__init__()
|
||||
|
||||
def get_provider_bind_name(self, provider):
|
||||
"""Return provider's name in catalog.
|
||||
|
||||
:param provider: Provider instance.
|
||||
:type provider: :py:class:`dependency_injector.providers.Provider`
|
||||
|
||||
:raise: :py:exc:`dependency_injector.errors.UndefinedProviderError`
|
||||
|
||||
:return: Provider's name.
|
||||
:rtype: str
|
||||
"""
|
||||
if not self.is_provider_bound(provider):
|
||||
raise Error('Can not find bind name for {0} in catalog {1}'.format(
|
||||
provider, self))
|
||||
return self.provider_names[provider]
|
||||
|
||||
def is_provider_bound(self, provider):
|
||||
"""Check if provider is bound to the catalog.
|
||||
|
||||
:param provider: Provider instance.
|
||||
:type provider: :py:class:`dependency_injector.providers.Provider`
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
return provider in self.provider_names
|
||||
|
||||
def filter(self, provider_type):
|
||||
"""Return dictionary of providers, that are instance of provided type.
|
||||
|
||||
:param provider_type: Provider's type.
|
||||
:type provider_type: :py:class:`dependency_injector.providers.Provider`
|
||||
|
||||
:rtype: dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||
"""
|
||||
return dict((name, provider)
|
||||
for name, provider in six.iteritems(self.providers)
|
||||
if isinstance(provider, provider_type))
|
||||
|
||||
@property
|
||||
def is_overridden(self):
|
||||
"""Read-only property that is set to ``True`` if catalog is overridden.
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
return bool(self.overridden_by)
|
||||
|
||||
@property
|
||||
def last_overriding(self):
|
||||
"""Read-only reference to the last overriding catalog, if any.
|
||||
|
||||
:type: :py:class:`DeclarativeCatalog` | :py:class:`DynamicCatalog` |
|
||||
None
|
||||
"""
|
||||
return self.overridden_by[-1] if self.overridden_by else None
|
||||
|
||||
def override(self, overriding):
|
||||
"""Override current catalog providers by overriding catalog providers.
|
||||
|
||||
:param overriding: Overriding catalog.
|
||||
:type overriding: :py:class:`DeclarativeCatalog` |
|
||||
:py:class:`DynamicCatalog`
|
||||
|
||||
:raise: :py:exc:`dependency_injector.errors.Error` if trying to
|
||||
override catalog by itself
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
if overriding is self:
|
||||
raise Error('Catalog {0} could not be overridden '
|
||||
'with itself'.format(self))
|
||||
self.overridden_by += (overriding,)
|
||||
for name, provider in six.iteritems(overriding.providers):
|
||||
self.get_provider(name).override(provider)
|
||||
|
||||
def reset_last_overriding(self):
|
||||
"""Reset last overriding catalog.
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
if not self.is_overridden:
|
||||
raise Error('Catalog {0} is not overridden'.format(self))
|
||||
self.overridden_by = self.overridden_by[:-1]
|
||||
for provider in six.itervalues(self.providers):
|
||||
provider.reset_last_overriding()
|
||||
|
||||
def reset_override(self):
|
||||
"""Reset all overridings for all catalog providers.
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
self.overridden_by = tuple()
|
||||
for provider in six.itervalues(self.providers):
|
||||
provider.reset_override()
|
||||
|
||||
def get_provider(self, name):
|
||||
"""Return provider with specified name or raise an error.
|
||||
|
||||
:param name: Provider's name.
|
||||
:type name: str
|
||||
|
||||
:raise: :py:exc:`dependency_injector.errors.UndefinedProviderError`
|
||||
|
||||
:return: Provider with specified name.
|
||||
:rtype: :py:class:`dependency_injector.providers.Provider`
|
||||
"""
|
||||
try:
|
||||
return self.providers[name]
|
||||
except KeyError:
|
||||
raise UndefinedProviderError('{0} has no provider with such '
|
||||
'name - {1}'.format(self, name))
|
||||
|
||||
def bind_provider(self, name, provider, force=False):
|
||||
"""Bind provider to catalog with specified name.
|
||||
|
||||
:param name: Name of the provider.
|
||||
:type name: str
|
||||
|
||||
:param provider: Provider instance.
|
||||
:type provider: :py:class:`dependency_injector.providers.Provider`
|
||||
|
||||
:param force: Force binding of provider.
|
||||
:type force: bool
|
||||
|
||||
:raise: :py:exc:`dependency_injector.errors.Error`
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
provider = ensure_is_provider(provider)
|
||||
|
||||
if (self.__class__.provider_type and
|
||||
not isinstance(provider, self.__class__.provider_type)):
|
||||
raise Error('{0} can contain only {1} instances'.format(
|
||||
self, self.__class__.provider_type))
|
||||
|
||||
if not force:
|
||||
if name in self.providers:
|
||||
raise Error('Catalog {0} already has provider with '
|
||||
'such name - {1}'.format(self, name))
|
||||
if provider in self.provider_names:
|
||||
raise Error('Catalog {0} already has such provider '
|
||||
'instance - {1}'.format(self, provider))
|
||||
|
||||
self.providers[name] = provider
|
||||
self.provider_names[provider] = name
|
||||
|
||||
def bind_providers(self, providers, force=False):
|
||||
"""Bind providers dictionary to catalog.
|
||||
|
||||
:param providers: Dictionary of providers, where key is a name
|
||||
and value is a provider.
|
||||
:type providers:
|
||||
dict[str, :py:class:`dependency_injector.providers.Provider`]
|
||||
|
||||
:param force: Force binding of providers.
|
||||
:type force: bool
|
||||
|
||||
:raise: :py:exc:`dependency_injector.errors.Error`
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
for name, provider in six.iteritems(providers):
|
||||
self.bind_provider(name, provider, force)
|
||||
|
||||
def has_provider(self, name):
|
||||
"""Check if there is provider with certain name.
|
||||
|
||||
:param name: Provider's name.
|
||||
:type name: str
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
return name in self.providers
|
||||
|
||||
def unbind_provider(self, name):
|
||||
"""Remove provider binding.
|
||||
|
||||
:param name: Provider's name.
|
||||
:type name: str
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
provider = self.get_provider(name)
|
||||
del self.providers[name]
|
||||
del self.provider_names[provider]
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""Return provider with specified name or raise en error.
|
||||
|
||||
:param name: Attribute's name.
|
||||
:type name: str
|
||||
|
||||
:raise: :py:exc:`dependency_injector.errors.UndefinedProviderError`
|
||||
"""
|
||||
return self.get_provider(name)
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
"""Handle setting of catalog attributes.
|
||||
|
||||
Setting of attributes works as usual, but if value of attribute is
|
||||
provider, this provider will be bound to catalog.
|
||||
|
||||
:param name: Attribute's name.
|
||||
:type name: str
|
||||
|
||||
:param value: Attribute's value.
|
||||
:type value: :py:class:`dependency_injector.providers.Provider` |
|
||||
object
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
if is_provider(value):
|
||||
return self.bind_provider(name, value)
|
||||
return super(DynamicCatalog, self).__setattr__(name, value)
|
||||
|
||||
def __delattr__(self, name):
|
||||
"""Handle deleting of catalog attibute.
|
||||
|
||||
Deleting of attributes works as usual, but if value of attribute is
|
||||
provider, this provider will be unbound from catalog.
|
||||
|
||||
:param name: Attribute's name.
|
||||
:type name: str
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
self.unbind_provider(name)
|
||||
|
||||
def __repr__(self):
|
||||
"""Return Python representation of catalog.
|
||||
|
||||
:rtype: str
|
||||
"""
|
||||
return '<{0}({1})>'.format('.'.join((self.__class__.__module__,
|
||||
self.__class__.__name__)),
|
||||
', '.join(six.iterkeys(self.providers)))
|
||||
|
||||
__str__ = __repr__
|
|
@ -1,62 +0,0 @@
|
|||
"""Dependency injector catalog utils."""
|
||||
|
||||
import six
|
||||
|
||||
from dependency_injector.utils import _copy_providers
|
||||
from dependency_injector.errors import UndefinedProviderError
|
||||
|
||||
|
||||
def copy(catalog):
|
||||
""":py:class:`DeclarativeCatalog` copying decorator.
|
||||
|
||||
This decorator copy all providers from provided catalog to decorated one.
|
||||
If one of the decorated catalog providers matches to source catalog
|
||||
providers by name, it would be replaced by reference.
|
||||
|
||||
:param catalog: Catalog that should be copied by decorated catalog.
|
||||
:type catalog: :py:class:`DeclarativeCatalog`
|
||||
|
||||
:return: Declarative catalog's copying decorator.
|
||||
:rtype:
|
||||
callable(:py:class:`DeclarativeCatalog`)
|
||||
"""
|
||||
def decorator(copied_catalog):
|
||||
"""Copying decorator.
|
||||
|
||||
:param copied_catalog: Decorated catalog.
|
||||
:type copied_catalog: :py:class:`DeclarativeCatalog`
|
||||
|
||||
:return: Decorated catalog.
|
||||
:rtype:
|
||||
:py:class:`DeclarativeCatalog`
|
||||
"""
|
||||
memo = dict()
|
||||
for name, provider in six.iteritems(copied_catalog.cls_providers):
|
||||
try:
|
||||
source_provider = catalog.get_provider(name)
|
||||
except UndefinedProviderError:
|
||||
pass
|
||||
else:
|
||||
memo[id(source_provider)] = provider
|
||||
|
||||
copied_catalog.bind_providers(_copy_providers(catalog.providers, memo),
|
||||
force=True)
|
||||
|
||||
return copied_catalog
|
||||
return decorator
|
||||
|
||||
|
||||
def override(catalog):
|
||||
""":py:class:`DeclarativeCatalog` overriding decorator.
|
||||
|
||||
:param catalog: Catalog that should be overridden by decorated catalog.
|
||||
:type catalog: :py:class:`DeclarativeCatalog`
|
||||
|
||||
:return: Declarative catalog's overriding decorator.
|
||||
:rtype: callable(:py:class:`DeclarativeCatalog`)
|
||||
"""
|
||||
def decorator(overriding_catalog):
|
||||
"""Overriding decorator."""
|
||||
catalog.override(overriding_catalog)
|
||||
return overriding_catalog
|
||||
return decorator
|
|
@ -9,6 +9,86 @@ from dependency_injector import (
|
|||
)
|
||||
|
||||
|
||||
class DynamicContainer(object):
|
||||
"""Dynamic inversion of control container."""
|
||||
|
||||
__IS_CONTAINER__ = True
|
||||
|
||||
def __init__(self):
|
||||
"""Initializer."""
|
||||
self.provider_type = providers.Provider
|
||||
self.providers = dict()
|
||||
self.overridden_by = tuple()
|
||||
super(DynamicContainer, self).__init__()
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
"""Set instance attribute.
|
||||
|
||||
If value of attribute is provider, it will be added into providers
|
||||
dictionary.
|
||||
"""
|
||||
if utils.is_provider(value):
|
||||
_check_provider_type(self, value)
|
||||
self.providers[name] = value
|
||||
super(DynamicContainer, self).__setattr__(name, value)
|
||||
|
||||
def __delattr__(self, name):
|
||||
"""Delete instance attribute.
|
||||
|
||||
If value of attribute is provider, it will be deleted from providers
|
||||
dictionary.
|
||||
"""
|
||||
if name in self.providers:
|
||||
del self.providers[name]
|
||||
super(DynamicContainer, self).__delattr__(name)
|
||||
|
||||
def override(self, overriding):
|
||||
"""Override current container by overriding container.
|
||||
|
||||
:param overriding: Overriding container.
|
||||
:type overriding: :py:class:`DeclarativeContainer`
|
||||
|
||||
:raise: :py:exc:`dependency_injector.errors.Error` if trying to
|
||||
override container by itself or its subclasses
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
if overriding is self:
|
||||
raise errors.Error('Container {0} could not be overridden '
|
||||
'with itself'.format(self))
|
||||
|
||||
self.overridden_by += (overriding,)
|
||||
|
||||
for name, provider in six.iteritems(overriding.providers):
|
||||
try:
|
||||
getattr(self, name).override(provider)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def reset_last_overriding(self):
|
||||
"""Reset last overriding provider for each container providers.
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
if not self.overridden_by:
|
||||
raise errors.Error('Container {0} is not overridden'.format(self))
|
||||
|
||||
self.overridden_by = self.overridden_by[:-1]
|
||||
|
||||
for provider in six.itervalues(self.providers):
|
||||
provider.reset_last_overriding()
|
||||
|
||||
def reset_override(self):
|
||||
"""Reset all overridings for each container providers.
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
self.overridden_by = tuple()
|
||||
|
||||
for provider in six.itervalues(self.providers):
|
||||
provider.reset_override()
|
||||
|
||||
|
||||
class DeclarativeContainerMetaClass(type):
|
||||
"""Declarative inversion of control container meta class."""
|
||||
|
||||
|
@ -20,7 +100,7 @@ class DeclarativeContainerMetaClass(type):
|
|||
|
||||
inherited_providers = tuple((name, provider)
|
||||
for base in bases if utils.is_container(
|
||||
base)
|
||||
base) and base is not DynamicContainer
|
||||
for name, provider in six.iteritems(
|
||||
base.cls_providers))
|
||||
|
||||
|
@ -70,9 +150,20 @@ class DeclarativeContainer(object):
|
|||
providers = dict()
|
||||
cls_providers = dict()
|
||||
inherited_providers = dict()
|
||||
|
||||
overridden_by = tuple()
|
||||
|
||||
instance_type = DynamicContainer
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
"""Constructor."""
|
||||
container = cls.instance_type(*args, **kwargs)
|
||||
container.provider_type = cls.provider_type
|
||||
|
||||
for name, provider in six.iteritems(utils.deepcopy(cls.providers)):
|
||||
setattr(container, name, provider)
|
||||
|
||||
return container
|
||||
|
||||
@classmethod
|
||||
def override(cls, overriding):
|
||||
"""Override current container by overriding container.
|
||||
|
@ -163,7 +254,7 @@ def copy(container):
|
|||
else:
|
||||
memo[id(source_provider)] = provider
|
||||
|
||||
providers_copy = utils._copy_providers(container.providers, memo)
|
||||
providers_copy = utils.deepcopy(container.providers, memo)
|
||||
for name, provider in six.iteritems(providers_copy):
|
||||
setattr(copied_container, name, provider)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
"""Utils module."""
|
||||
|
||||
import sys
|
||||
import copy
|
||||
import copy as _copy
|
||||
import types
|
||||
import threading
|
||||
|
||||
|
@ -23,9 +23,9 @@ else: # pragma: no cover
|
|||
_OBJECT_INIT = None
|
||||
|
||||
if six.PY2: # pragma: no cover
|
||||
copy._deepcopy_dispatch[types.MethodType] = \
|
||||
_copy._deepcopy_dispatch[types.MethodType] = \
|
||||
lambda obj, memo: type(obj)(obj.im_func,
|
||||
copy.deepcopy(obj.im_self, memo),
|
||||
_copy.deepcopy(obj.im_self, memo),
|
||||
obj.im_class)
|
||||
|
||||
|
||||
|
@ -71,40 +71,6 @@ def is_container(instance):
|
|||
getattr(instance, '__IS_CONTAINER__', False) is True)
|
||||
|
||||
|
||||
def is_catalog(instance):
|
||||
"""Check if instance is catalog instance.
|
||||
|
||||
:param instance: Instance to be checked.
|
||||
:type instance: object
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
return (hasattr(instance, '__IS_CATALOG__') and
|
||||
getattr(instance, '__IS_CATALOG__', False) is True)
|
||||
|
||||
|
||||
def is_dynamic_catalog(instance):
|
||||
"""Check if instance is dynamic catalog instance.
|
||||
|
||||
:param instance: Instance to be checked.
|
||||
:type instance: object
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
return (not isinstance(instance, six.class_types) and is_catalog(instance))
|
||||
|
||||
|
||||
def is_declarative_catalog(instance):
|
||||
"""Check if instance is declarative catalog instance.
|
||||
|
||||
:param instance: Instance to be checked.
|
||||
:type instance: object
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
return (isinstance(instance, six.class_types) and is_catalog(instance))
|
||||
|
||||
|
||||
def represent_provider(provider, provides):
|
||||
"""Return string representation of provider.
|
||||
|
||||
|
@ -142,6 +108,6 @@ def fetch_cls_init(cls):
|
|||
return cls_init
|
||||
|
||||
|
||||
def _copy_providers(providers, memo=None):
|
||||
"""Make full copy of providers dictionary."""
|
||||
return copy.deepcopy(providers, memo)
|
||||
def deepcopy(instance, memo=None):
|
||||
"""Make full copy of instance."""
|
||||
return _copy.deepcopy(instance, memo)
|
||||
|
|
1
setup.py
1
setup.py
|
@ -54,7 +54,6 @@ setup(name='dependency_injector',
|
|||
download_url='https://pypi.python.org/pypi/dependency_injector',
|
||||
license='BSD New',
|
||||
packages=['dependency_injector',
|
||||
'dependency_injector.catalogs',
|
||||
'dependency_injector.providers'],
|
||||
platforms=['any'],
|
||||
zip_safe=True,
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
"""Dependency injector catalogs unittests."""
|
|
@ -1,443 +0,0 @@
|
|||
"""Dependency injector declarative catalog unittests."""
|
||||
|
||||
import unittest2 as unittest
|
||||
|
||||
from dependency_injector import (
|
||||
catalogs,
|
||||
providers,
|
||||
injections,
|
||||
errors,
|
||||
)
|
||||
|
||||
|
||||
class CatalogA(catalogs.DeclarativeCatalog):
|
||||
"""Test catalog A."""
|
||||
|
||||
p11 = providers.Provider()
|
||||
p12 = providers.Provider()
|
||||
|
||||
|
||||
class CatalogB(CatalogA):
|
||||
"""Test catalog B."""
|
||||
|
||||
p21 = providers.Provider()
|
||||
p22 = providers.Provider()
|
||||
|
||||
|
||||
class DeclarativeCatalogTests(unittest.TestCase):
|
||||
"""Declarative catalog tests."""
|
||||
|
||||
def test_cls_providers(self):
|
||||
"""Test `di.DeclarativeCatalog.cls_providers` contents."""
|
||||
class CatalogA(catalogs.DeclarativeCatalog):
|
||||
"""Test catalog A."""
|
||||
|
||||
p11 = providers.Provider()
|
||||
p12 = providers.Provider()
|
||||
|
||||
class CatalogB(CatalogA):
|
||||
"""Test catalog B."""
|
||||
|
||||
p21 = providers.Provider()
|
||||
p22 = providers.Provider()
|
||||
self.assertDictEqual(CatalogA.cls_providers,
|
||||
dict(p11=CatalogA.p11,
|
||||
p12=CatalogA.p12))
|
||||
self.assertDictEqual(CatalogB.cls_providers,
|
||||
dict(p21=CatalogB.p21,
|
||||
p22=CatalogB.p22))
|
||||
|
||||
def test_inherited_providers(self):
|
||||
"""Test `di.DeclarativeCatalog.inherited_providers` contents."""
|
||||
self.assertDictEqual(CatalogA.inherited_providers, dict())
|
||||
self.assertDictEqual(CatalogB.inherited_providers,
|
||||
dict(p11=CatalogA.p11,
|
||||
p12=CatalogA.p12))
|
||||
|
||||
def test_providers(self):
|
||||
"""Test `di.DeclarativeCatalog.inherited_providers` contents."""
|
||||
self.assertDictEqual(CatalogA.providers,
|
||||
dict(p11=CatalogA.p11,
|
||||
p12=CatalogA.p12))
|
||||
self.assertDictEqual(CatalogB.providers,
|
||||
dict(p11=CatalogA.p11,
|
||||
p12=CatalogA.p12,
|
||||
p21=CatalogB.p21,
|
||||
p22=CatalogB.p22))
|
||||
|
||||
def test_bind_provider(self):
|
||||
"""Test setting of provider via bind_provider() to catalog."""
|
||||
px = providers.Provider()
|
||||
py = providers.Provider()
|
||||
|
||||
CatalogA.bind_provider('px', px)
|
||||
CatalogA.bind_provider('py', py)
|
||||
|
||||
self.assertIs(CatalogA.px, px)
|
||||
self.assertIs(CatalogA.get_provider('px'), px)
|
||||
|
||||
self.assertIs(CatalogA.py, py)
|
||||
self.assertIs(CatalogA.get_provider('py'), py)
|
||||
|
||||
del CatalogA.px
|
||||
del CatalogA.py
|
||||
|
||||
def test_bind_existing_provider(self):
|
||||
"""Test setting of provider via bind_provider() to catalog."""
|
||||
with self.assertRaises(errors.Error):
|
||||
CatalogA.p11 = providers.Provider()
|
||||
|
||||
with self.assertRaises(errors.Error):
|
||||
CatalogA.bind_provider('p11', providers.Provider())
|
||||
|
||||
def test_bind_provider_with_valid_provided_type(self):
|
||||
"""Test setting of provider with provider type restriction."""
|
||||
class SomeProvider(providers.Provider):
|
||||
"""Some provider."""
|
||||
|
||||
class SomeCatalog(catalogs.DeclarativeCatalog):
|
||||
"""Some catalog with provider type restriction."""
|
||||
|
||||
provider_type = SomeProvider
|
||||
|
||||
px = SomeProvider()
|
||||
py = SomeProvider()
|
||||
|
||||
SomeCatalog.bind_provider('px', px)
|
||||
SomeCatalog.py = py
|
||||
|
||||
self.assertIs(SomeCatalog.px, px)
|
||||
self.assertIs(SomeCatalog.get_provider('px'), px)
|
||||
|
||||
self.assertIs(SomeCatalog.py, py)
|
||||
self.assertIs(SomeCatalog.get_provider('py'), py)
|
||||
|
||||
def test_bind_provider_with_invalid_provided_type(self):
|
||||
"""Test setting of provider with provider type restriction."""
|
||||
class SomeProvider(providers.Provider):
|
||||
"""Some provider."""
|
||||
|
||||
class SomeCatalog(catalogs.DeclarativeCatalog):
|
||||
"""Some catalog with provider type restriction."""
|
||||
|
||||
provider_type = SomeProvider
|
||||
|
||||
px = providers.Provider()
|
||||
|
||||
with self.assertRaises(errors.Error):
|
||||
SomeCatalog.bind_provider('px', px)
|
||||
|
||||
with self.assertRaises(errors.Error):
|
||||
SomeCatalog.px = px
|
||||
|
||||
with self.assertRaises(errors.Error):
|
||||
SomeCatalog.bind_providers(dict(px=px))
|
||||
|
||||
def test_bind_providers(self):
|
||||
"""Test setting of provider via bind_providers() to catalog."""
|
||||
px = providers.Provider()
|
||||
py = providers.Provider()
|
||||
|
||||
CatalogB.bind_providers(dict(px=px, py=py))
|
||||
|
||||
self.assertIs(CatalogB.px, px)
|
||||
self.assertIs(CatalogB.get_provider('px'), px)
|
||||
|
||||
self.assertIs(CatalogB.py, py)
|
||||
self.assertIs(CatalogB.get_provider('py'), py)
|
||||
|
||||
del CatalogB.px
|
||||
del CatalogB.py
|
||||
|
||||
def test_setattr(self):
|
||||
"""Test setting of providers via attributes to catalog."""
|
||||
px = providers.Provider()
|
||||
py = providers.Provider()
|
||||
|
||||
CatalogB.px = px
|
||||
CatalogB.py = py
|
||||
|
||||
self.assertIs(CatalogB.px, px)
|
||||
self.assertIs(CatalogB.get_provider('px'), px)
|
||||
|
||||
self.assertIs(CatalogB.py, py)
|
||||
self.assertIs(CatalogB.get_provider('py'), py)
|
||||
|
||||
del CatalogB.px
|
||||
del CatalogB.py
|
||||
|
||||
def test_unbind_provider(self):
|
||||
"""Test that catalog unbinds provider correct."""
|
||||
CatalogB.px = providers.Provider()
|
||||
CatalogB.unbind_provider('px')
|
||||
self.assertFalse(CatalogB.has_provider('px'))
|
||||
|
||||
def test_unbind_via_delattr(self):
|
||||
"""Test that catalog unbinds provider correct."""
|
||||
CatalogB.px = providers.Provider()
|
||||
del CatalogB.px
|
||||
self.assertFalse(CatalogB.has_provider('px'))
|
||||
|
||||
def test_provider_is_bound(self):
|
||||
"""Test that providers are bound to the catalogs."""
|
||||
self.assertTrue(CatalogA.is_provider_bound(CatalogA.p11))
|
||||
self.assertEquals(CatalogA.get_provider_bind_name(CatalogA.p11), 'p11')
|
||||
|
||||
self.assertTrue(CatalogA.is_provider_bound(CatalogA.p12))
|
||||
self.assertEquals(CatalogA.get_provider_bind_name(CatalogA.p12), 'p12')
|
||||
|
||||
def test_provider_binding_to_different_catalogs(self):
|
||||
"""Test that provider could be bound to different catalogs."""
|
||||
p11 = CatalogA.p11
|
||||
p12 = CatalogA.p12
|
||||
|
||||
class CatalogD(catalogs.DeclarativeCatalog):
|
||||
"""Test catalog."""
|
||||
|
||||
pd1 = p11
|
||||
pd2 = p12
|
||||
|
||||
class CatalogE(catalogs.DeclarativeCatalog):
|
||||
"""Test catalog."""
|
||||
|
||||
pe1 = p11
|
||||
pe2 = p12
|
||||
|
||||
self.assertTrue(CatalogA.is_provider_bound(p11))
|
||||
self.assertTrue(CatalogD.is_provider_bound(p11))
|
||||
self.assertTrue(CatalogE.is_provider_bound(p11))
|
||||
self.assertEquals(CatalogA.get_provider_bind_name(p11), 'p11')
|
||||
self.assertEquals(CatalogD.get_provider_bind_name(p11), 'pd1')
|
||||
self.assertEquals(CatalogE.get_provider_bind_name(p11), 'pe1')
|
||||
|
||||
self.assertTrue(CatalogA.is_provider_bound(p12))
|
||||
self.assertTrue(CatalogD.is_provider_bound(p12))
|
||||
self.assertTrue(CatalogE.is_provider_bound(p12))
|
||||
self.assertEquals(CatalogA.get_provider_bind_name(p12), 'p12')
|
||||
self.assertEquals(CatalogD.get_provider_bind_name(p12), 'pd2')
|
||||
self.assertEquals(CatalogE.get_provider_bind_name(p12), 'pe2')
|
||||
|
||||
def test_provider_rebinding_to_the_same_catalog(self):
|
||||
"""Test provider rebinding to the same catalog."""
|
||||
with self.assertRaises(errors.Error):
|
||||
class TestCatalog(catalogs.DeclarativeCatalog):
|
||||
"""Test catalog."""
|
||||
|
||||
p1 = providers.Provider()
|
||||
p2 = p1
|
||||
|
||||
def test_provider_rebinding_to_the_same_catalogs_hierarchy(self):
|
||||
"""Test provider rebinding to the same catalogs hierarchy."""
|
||||
class TestCatalog1(catalogs.DeclarativeCatalog):
|
||||
"""Test catalog."""
|
||||
|
||||
p1 = providers.Provider()
|
||||
|
||||
with self.assertRaises(errors.Error):
|
||||
class TestCatalog2(TestCatalog1):
|
||||
"""Test catalog."""
|
||||
|
||||
p2 = TestCatalog1.p1
|
||||
|
||||
def test_get(self):
|
||||
"""Test getting of providers using get() method."""
|
||||
self.assertIs(CatalogB.get_provider('p11'), CatalogB.p11)
|
||||
self.assertIs(CatalogB.get_provider('p12'), CatalogB.p12)
|
||||
self.assertIs(CatalogB.get_provider('p22'), CatalogB.p22)
|
||||
self.assertIs(CatalogB.get_provider('p22'), CatalogB.p22)
|
||||
|
||||
def test_get_undefined(self):
|
||||
"""Test getting of undefined providers using get() method."""
|
||||
with self.assertRaises(errors.UndefinedProviderError):
|
||||
CatalogB.get('undefined')
|
||||
|
||||
with self.assertRaises(errors.UndefinedProviderError):
|
||||
CatalogB.get_provider('undefined')
|
||||
|
||||
with self.assertRaises(errors.UndefinedProviderError):
|
||||
CatalogB.undefined
|
||||
|
||||
def test_has(self):
|
||||
"""Test checks of providers availability in catalog."""
|
||||
self.assertTrue(CatalogB.has_provider('p11'))
|
||||
self.assertTrue(CatalogB.has_provider('p12'))
|
||||
self.assertTrue(CatalogB.has_provider('p21'))
|
||||
self.assertTrue(CatalogB.has_provider('p22'))
|
||||
self.assertFalse(CatalogB.has_provider('undefined'))
|
||||
|
||||
def test_filter_all_providers_by_type(self):
|
||||
"""Test getting of all catalog providers of specific type."""
|
||||
self.assertTrue(len(CatalogB.filter(providers.Provider)) == 4)
|
||||
self.assertTrue(len(CatalogB.filter(providers.Object)) == 0)
|
||||
|
||||
def test_repr(self):
|
||||
"""Test catalog representation."""
|
||||
self.assertIn('CatalogA', repr(CatalogA))
|
||||
self.assertIn('p11', repr(CatalogA))
|
||||
self.assertIn('p12', repr(CatalogA))
|
||||
|
||||
self.assertIn('CatalogB', repr(CatalogB))
|
||||
self.assertIn('p11', repr(CatalogB))
|
||||
self.assertIn('p12', repr(CatalogB))
|
||||
self.assertIn('p21', repr(CatalogB))
|
||||
self.assertIn('p22', repr(CatalogB))
|
||||
|
||||
|
||||
class TestCatalogWithProvidingCallbacks(unittest.TestCase):
|
||||
"""Catalog with providing callback tests."""
|
||||
|
||||
def test_concept(self):
|
||||
"""Test concept."""
|
||||
class UsersService(object):
|
||||
"""Users service, that has dependency on database."""
|
||||
|
||||
class AuthService(object):
|
||||
"""Auth service, that has dependencies on users service."""
|
||||
|
||||
def __init__(self, users_service):
|
||||
"""Initializer."""
|
||||
self.users_service = users_service
|
||||
|
||||
class Services(catalogs.DeclarativeCatalog):
|
||||
"""Catalog of service providers."""
|
||||
|
||||
@providers.Factory
|
||||
def users():
|
||||
"""Provide users service.
|
||||
|
||||
:rtype: providers.Provider -> UsersService
|
||||
"""
|
||||
return UsersService()
|
||||
|
||||
@providers.Factory
|
||||
@injections.inject(users_service=users)
|
||||
def auth(**kwargs):
|
||||
"""Provide users service.
|
||||
|
||||
:rtype: providers.Provider -> AuthService
|
||||
"""
|
||||
return AuthService(**kwargs)
|
||||
|
||||
# Retrieving catalog providers:
|
||||
users_service = Services.users()
|
||||
auth_service = Services.auth()
|
||||
|
||||
# Making some asserts:
|
||||
self.assertIsInstance(auth_service.users_service, UsersService)
|
||||
self.assertIsNot(users_service, Services.users())
|
||||
self.assertIsNot(auth_service, Services.auth())
|
||||
|
||||
# Overriding auth service provider and making some asserts:
|
||||
class ExtendedAuthService(AuthService):
|
||||
"""Extended version of auth service."""
|
||||
|
||||
def __init__(self, users_service, ttl):
|
||||
"""Initializer."""
|
||||
self.ttl = ttl
|
||||
super(ExtendedAuthService, self).__init__(
|
||||
users_service=users_service)
|
||||
|
||||
class OverriddenServices(Services):
|
||||
"""Catalog of service providers."""
|
||||
|
||||
@providers.override(Services.auth)
|
||||
@providers.Factory
|
||||
@injections.inject(users_service=Services.users)
|
||||
@injections.inject(ttl=3600)
|
||||
def auth(**kwargs):
|
||||
"""Provide users service.
|
||||
|
||||
:rtype: providers.Provider -> AuthService
|
||||
"""
|
||||
return ExtendedAuthService(**kwargs)
|
||||
|
||||
auth_service = Services.auth()
|
||||
|
||||
self.assertIsInstance(auth_service, ExtendedAuthService)
|
||||
|
||||
|
||||
class CopyingTests(unittest.TestCase):
|
||||
"""Declarative catalogs copying tests."""
|
||||
|
||||
def test_copy(self):
|
||||
"""Test catalog providers copying."""
|
||||
@catalogs.copy(CatalogA)
|
||||
class CatalogA1(CatalogA):
|
||||
pass
|
||||
|
||||
@catalogs.copy(CatalogA)
|
||||
class CatalogA2(CatalogA):
|
||||
pass
|
||||
|
||||
self.assertIsNot(CatalogA.p11, CatalogA1.p11)
|
||||
self.assertIsNot(CatalogA.p12, CatalogA1.p12)
|
||||
|
||||
self.assertIsNot(CatalogA.p11, CatalogA2.p11)
|
||||
self.assertIsNot(CatalogA.p12, CatalogA2.p12)
|
||||
|
||||
self.assertIsNot(CatalogA1.p11, CatalogA2.p11)
|
||||
self.assertIsNot(CatalogA1.p12, CatalogA2.p12)
|
||||
|
||||
def test_copy_with_replacing(self):
|
||||
"""Test catalog providers copying."""
|
||||
class CatalogA(catalogs.DeclarativeCatalog):
|
||||
p11 = providers.Object(0)
|
||||
p12 = providers.Factory(dict) \
|
||||
.add_kwargs(p11=p11)
|
||||
|
||||
@catalogs.copy(CatalogA)
|
||||
class CatalogA1(CatalogA):
|
||||
p11 = providers.Object(1)
|
||||
p13 = providers.Object(11)
|
||||
|
||||
@catalogs.copy(CatalogA)
|
||||
class CatalogA2(CatalogA):
|
||||
p11 = providers.Object(2)
|
||||
p13 = providers.Object(22)
|
||||
|
||||
self.assertIsNot(CatalogA.p11, CatalogA1.p11)
|
||||
self.assertIsNot(CatalogA.p12, CatalogA1.p12)
|
||||
|
||||
self.assertIsNot(CatalogA.p11, CatalogA2.p11)
|
||||
self.assertIsNot(CatalogA.p12, CatalogA2.p12)
|
||||
|
||||
self.assertIsNot(CatalogA1.p11, CatalogA2.p11)
|
||||
self.assertIsNot(CatalogA1.p12, CatalogA2.p12)
|
||||
|
||||
self.assertIs(CatalogA.p12.kwargs['p11'], CatalogA.p11)
|
||||
self.assertIs(CatalogA1.p12.kwargs['p11'], CatalogA1.p11)
|
||||
self.assertIs(CatalogA2.p12.kwargs['p11'], CatalogA2.p11)
|
||||
|
||||
self.assertEqual(CatalogA.p12(), dict(p11=0))
|
||||
self.assertEqual(CatalogA1.p12(), dict(p11=1))
|
||||
self.assertEqual(CatalogA2.p12(), dict(p11=2))
|
||||
|
||||
self.assertEqual(CatalogA1.p13(), 11)
|
||||
self.assertEqual(CatalogA2.p13(), 22)
|
||||
|
||||
|
||||
class InstantiationTests(unittest.TestCase):
|
||||
"""Declarative catalogs instantiation tests."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set test environment up."""
|
||||
self.catalog = CatalogA()
|
||||
|
||||
def tearDown(self):
|
||||
"""Tear test environment down."""
|
||||
self.catalog = None
|
||||
|
||||
def test_access_instance_attributes(self):
|
||||
"""Test accessing declarative catalog instance attributes."""
|
||||
self.assertEqual(self.catalog.providers,
|
||||
CatalogA.providers)
|
||||
self.assertEqual(self.catalog.cls_providers,
|
||||
CatalogA.cls_providers)
|
||||
self.assertEqual(self.catalog.inherited_providers,
|
||||
CatalogA.inherited_providers)
|
||||
self.assertEqual(self.catalog.overridden_by,
|
||||
CatalogA.overridden_by)
|
||||
self.assertEqual(self.catalog.is_overridden,
|
||||
CatalogA.is_overridden)
|
||||
self.assertEqual(self.catalog.last_overriding,
|
||||
CatalogA.last_overriding)
|
|
@ -1,221 +0,0 @@
|
|||
"""Dependency injector dynamic catalog unittests."""
|
||||
|
||||
import unittest2 as unittest
|
||||
|
||||
from dependency_injector import (
|
||||
catalogs,
|
||||
providers,
|
||||
errors,
|
||||
)
|
||||
|
||||
|
||||
class DynamicCatalogTests(unittest.TestCase):
|
||||
"""Dynamic catalog tests."""
|
||||
|
||||
catalog = None
|
||||
""":type: di.DynamicCatalog"""
|
||||
|
||||
def setUp(self):
|
||||
"""Set test environment up."""
|
||||
self.catalog = catalogs.DynamicCatalog(p1=providers.Provider(),
|
||||
p2=providers.Provider())
|
||||
|
||||
def test_providers(self):
|
||||
"""Test `di.DeclarativeCatalog.inherited_providers` contents."""
|
||||
self.assertDictEqual(self.catalog.providers,
|
||||
dict(p1=self.catalog.p1,
|
||||
p2=self.catalog.p2))
|
||||
|
||||
def test_bind_provider(self):
|
||||
"""Test setting of provider via bind_provider() to catalog."""
|
||||
px = providers.Provider()
|
||||
py = providers.Provider()
|
||||
|
||||
self.catalog.bind_provider('px', px)
|
||||
self.catalog.bind_provider('py', py)
|
||||
|
||||
self.assertIs(self.catalog.px, px)
|
||||
self.assertIs(self.catalog.get_provider('px'), px)
|
||||
|
||||
self.assertIs(self.catalog.py, py)
|
||||
self.assertIs(self.catalog.get_provider('py'), py)
|
||||
|
||||
def test_bind_existing_provider(self):
|
||||
"""Test setting of provider via bind_provider() to catalog."""
|
||||
with self.assertRaises(errors.Error):
|
||||
self.catalog.bind_provider('p1', providers.Factory(object))
|
||||
|
||||
def test_force_bind_existing_provider(self):
|
||||
"""Test setting of provider via bind_provider() to catalog."""
|
||||
p1 = providers.Factory(object)
|
||||
self.catalog.bind_provider('p1', p1, force=True)
|
||||
self.assertIs(self.catalog.p1, p1)
|
||||
|
||||
def test_bind_provider_with_valid_provided_type(self):
|
||||
"""Test setting of provider with provider type restriction."""
|
||||
class SomeProvider(providers.Provider):
|
||||
"""Some provider."""
|
||||
|
||||
class SomeCatalog(catalogs.DynamicCatalog):
|
||||
"""Some catalog with provider type restriction."""
|
||||
|
||||
provider_type = SomeProvider
|
||||
|
||||
px = SomeProvider()
|
||||
py = SomeProvider()
|
||||
catalog = SomeCatalog()
|
||||
|
||||
catalog.bind_provider('px', px)
|
||||
catalog.py = py
|
||||
|
||||
self.assertIs(catalog.px, px)
|
||||
self.assertIs(catalog.get_provider('px'), px)
|
||||
|
||||
self.assertIs(catalog.py, py)
|
||||
self.assertIs(catalog.get_provider('py'), py)
|
||||
|
||||
def test_bind_provider_with_invalid_provided_type(self):
|
||||
"""Test setting of provider with provider type restriction."""
|
||||
class SomeProvider(providers.Provider):
|
||||
"""Some provider."""
|
||||
|
||||
class SomeCatalog(catalogs.DynamicCatalog):
|
||||
"""Some catalog with provider type restriction."""
|
||||
|
||||
provider_type = SomeProvider
|
||||
|
||||
px = providers.Provider()
|
||||
catalog = SomeCatalog()
|
||||
|
||||
with self.assertRaises(errors.Error):
|
||||
catalog.bind_provider('px', px)
|
||||
|
||||
with self.assertRaises(errors.Error):
|
||||
catalog.px = px
|
||||
|
||||
with self.assertRaises(errors.Error):
|
||||
catalog.bind_providers(dict(px=px))
|
||||
|
||||
def test_bind_providers(self):
|
||||
"""Test setting of provider via bind_providers() to catalog."""
|
||||
px = providers.Provider()
|
||||
py = providers.Provider()
|
||||
|
||||
self.catalog.bind_providers(dict(px=px, py=py))
|
||||
|
||||
self.assertIs(self.catalog.px, px)
|
||||
self.assertIs(self.catalog.get_provider('px'), px)
|
||||
|
||||
self.assertIs(self.catalog.py, py)
|
||||
self.assertIs(self.catalog.get_provider('py'), py)
|
||||
|
||||
def test_bind_providers_with_existing(self):
|
||||
"""Test setting of provider via bind_providers() to catalog."""
|
||||
with self.assertRaises(errors.Error):
|
||||
self.catalog.bind_providers(dict(p1=providers.Factory(object)))
|
||||
|
||||
def test_bind_providers_force(self):
|
||||
"""Test setting of provider via bind_providers() to catalog."""
|
||||
p1 = providers.Factory(object)
|
||||
self.catalog.bind_providers(dict(p1=p1), force=True)
|
||||
self.assertIs(self.catalog.p1, p1)
|
||||
|
||||
def test_setattr(self):
|
||||
"""Test setting of providers via attributes to catalog."""
|
||||
px = providers.Provider()
|
||||
py = providers.Provider()
|
||||
|
||||
self.catalog.px = px
|
||||
self.catalog.py = py
|
||||
|
||||
self.assertIs(self.catalog.px, px)
|
||||
self.assertIs(self.catalog.get_provider('px'), px)
|
||||
|
||||
self.assertIs(self.catalog.py, py)
|
||||
self.assertIs(self.catalog.get_provider('py'), py)
|
||||
|
||||
def test_unbind_provider(self):
|
||||
"""Test that catalog unbinds provider correct."""
|
||||
self.catalog.px = providers.Provider()
|
||||
self.catalog.unbind_provider('px')
|
||||
self.assertFalse(self.catalog.has_provider('px'))
|
||||
|
||||
def test_unbind_via_delattr(self):
|
||||
"""Test that catalog unbinds provider correct."""
|
||||
self.catalog.px = providers.Provider()
|
||||
del self.catalog.px
|
||||
self.assertFalse(self.catalog.has_provider('px'))
|
||||
|
||||
def test_provider_is_bound(self):
|
||||
"""Test that providers are bound to the catalogs."""
|
||||
self.assertTrue(self.catalog.is_provider_bound(self.catalog.p1))
|
||||
self.assertEquals(
|
||||
self.catalog.get_provider_bind_name(self.catalog.p1), 'p1')
|
||||
self.assertTrue(self.catalog.is_provider_bound(self.catalog.p2))
|
||||
self.assertEquals(
|
||||
self.catalog.get_provider_bind_name(self.catalog.p2), 'p2')
|
||||
|
||||
def test_provider_binding_to_different_catalogs(self):
|
||||
"""Test that provider could be bound to different catalogs."""
|
||||
p1 = self.catalog.p1
|
||||
p2 = self.catalog.p2
|
||||
|
||||
catalog_a = catalogs.DynamicCatalog(pa1=p1, pa2=p2)
|
||||
catalog_b = catalogs.DynamicCatalog(pb1=p1, pb2=p2)
|
||||
|
||||
self.assertTrue(self.catalog.is_provider_bound(p1))
|
||||
self.assertTrue(catalog_a.is_provider_bound(p1))
|
||||
self.assertTrue(catalog_b.is_provider_bound(p1))
|
||||
self.assertEquals(self.catalog.get_provider_bind_name(p1), 'p1')
|
||||
self.assertEquals(catalog_a.get_provider_bind_name(p1), 'pa1')
|
||||
self.assertEquals(catalog_b.get_provider_bind_name(p1), 'pb1')
|
||||
|
||||
self.assertTrue(self.catalog.is_provider_bound(p2))
|
||||
self.assertTrue(catalog_a.is_provider_bound(p2))
|
||||
self.assertTrue(catalog_b.is_provider_bound(p2))
|
||||
self.assertEquals(self.catalog.get_provider_bind_name(p2), 'p2')
|
||||
self.assertEquals(catalog_a.get_provider_bind_name(p2), 'pa2')
|
||||
self.assertEquals(catalog_b.get_provider_bind_name(p2), 'pb2')
|
||||
|
||||
def test_provider_rebinding_to_the_same_catalog(self):
|
||||
"""Test provider rebinding to the same catalog."""
|
||||
with self.assertRaises(errors.Error):
|
||||
self.catalog.p3 = self.catalog.p1
|
||||
|
||||
def test_provider_binding_with_the_same_name(self):
|
||||
"""Test binding of provider with the same name."""
|
||||
with self.assertRaises(errors.Error):
|
||||
self.catalog.bind_provider('p1', providers.Provider())
|
||||
|
||||
def test_get(self):
|
||||
"""Test getting of providers using get() method."""
|
||||
self.assertIs(self.catalog.get_provider('p1'), self.catalog.p1)
|
||||
self.assertIs(self.catalog.get_provider('p2'), self.catalog.p2)
|
||||
|
||||
def test_get_undefined(self):
|
||||
"""Test getting of undefined providers using get() method."""
|
||||
with self.assertRaises(errors.UndefinedProviderError):
|
||||
self.catalog.get_provider('undefined')
|
||||
|
||||
with self.assertRaises(errors.UndefinedProviderError):
|
||||
self.catalog.undefined
|
||||
|
||||
def test_has_provider(self):
|
||||
"""Test checks of providers availability in catalog."""
|
||||
self.assertTrue(self.catalog.has_provider('p1'))
|
||||
self.assertTrue(self.catalog.has_provider('p2'))
|
||||
self.assertFalse(self.catalog.has_provider('undefined'))
|
||||
|
||||
def test_filter_all_providers_by_type(self):
|
||||
"""Test getting of all catalog providers of specific type."""
|
||||
self.assertTrue(len(self.catalog.filter(providers.Provider)) == 2)
|
||||
self.assertTrue(len(self.catalog.filter(providers.Object)) == 0)
|
||||
|
||||
def test_repr(self):
|
||||
"""Test catalog representation."""
|
||||
representation = repr(self.catalog)
|
||||
|
||||
self.assertIn('dependency_injector.catalogs.dynamic.DynamicCatalog',
|
||||
representation)
|
||||
self.assertIn('p1', representation)
|
||||
self.assertIn('p2', representation)
|
|
@ -1,142 +0,0 @@
|
|||
"""Dependency injector catalogs overriding unittests."""
|
||||
|
||||
import unittest2 as unittest
|
||||
|
||||
from dependency_injector import (
|
||||
catalogs,
|
||||
providers,
|
||||
errors,
|
||||
)
|
||||
|
||||
|
||||
class CatalogA(catalogs.DeclarativeCatalog):
|
||||
"""Test catalog A."""
|
||||
|
||||
p11 = providers.Provider()
|
||||
p12 = providers.Provider()
|
||||
|
||||
|
||||
class CatalogB(CatalogA):
|
||||
"""Test catalog B."""
|
||||
|
||||
p21 = providers.Provider()
|
||||
p22 = providers.Provider()
|
||||
|
||||
|
||||
class OverrideTests(unittest.TestCase):
|
||||
"""Catalog overriding and override decorator test cases."""
|
||||
|
||||
def tearDown(self):
|
||||
"""Tear test environment down."""
|
||||
CatalogA.reset_override()
|
||||
|
||||
def test_overriding(self):
|
||||
"""Test catalog overriding with another catalog."""
|
||||
@catalogs.override(CatalogA)
|
||||
class OverridingCatalog(catalogs.DeclarativeCatalog):
|
||||
"""Overriding catalog."""
|
||||
|
||||
p11 = providers.Object(1)
|
||||
p12 = providers.Object(2)
|
||||
|
||||
self.assertEqual(CatalogA.p11(), 1)
|
||||
self.assertEqual(CatalogA.p12(), 2)
|
||||
self.assertEqual(len(CatalogA.overridden_by), 1)
|
||||
|
||||
def test_override_declarative_catalog_with_itself(self):
|
||||
"""Test catalog overriding of declarative catalog with itself."""
|
||||
with self.assertRaises(errors.Error):
|
||||
CatalogA.override(CatalogA)
|
||||
|
||||
def test_override_declarative_catalog_with_subclass(self):
|
||||
"""Test catalog overriding of declarative catalog with subclass."""
|
||||
with self.assertRaises(errors.Error):
|
||||
CatalogB.override(CatalogA)
|
||||
|
||||
def test_override_dynamic_catalog_with_itself(self):
|
||||
"""Test catalog overriding of dynamic catalog with itself."""
|
||||
catalog = catalogs.DynamicCatalog(p11=providers.Object(1),
|
||||
p12=providers.Object(2))
|
||||
with self.assertRaises(errors.Error):
|
||||
catalog.override(catalog)
|
||||
|
||||
def test_overriding_with_dynamic_catalog(self):
|
||||
"""Test catalog overriding with another dynamic catalog."""
|
||||
CatalogA.override(catalogs.DynamicCatalog(p11=providers.Object(1),
|
||||
p12=providers.Object(2)))
|
||||
self.assertEqual(CatalogA.p11(), 1)
|
||||
self.assertEqual(CatalogA.p12(), 2)
|
||||
self.assertEqual(len(CatalogA.overridden_by), 1)
|
||||
|
||||
def test_is_overridden(self):
|
||||
"""Test catalog is_overridden property."""
|
||||
self.assertFalse(CatalogA.is_overridden)
|
||||
|
||||
@catalogs.override(CatalogA)
|
||||
class OverridingCatalog(catalogs.DeclarativeCatalog):
|
||||
"""Overriding catalog."""
|
||||
|
||||
self.assertTrue(CatalogA.is_overridden)
|
||||
|
||||
def test_last_overriding(self):
|
||||
"""Test catalog last_overriding property."""
|
||||
@catalogs.override(CatalogA)
|
||||
class OverridingCatalog1(catalogs.DeclarativeCatalog):
|
||||
"""Overriding catalog."""
|
||||
|
||||
@catalogs.override(CatalogA)
|
||||
class OverridingCatalog2(catalogs.DeclarativeCatalog):
|
||||
"""Overriding catalog."""
|
||||
|
||||
self.assertIs(CatalogA.last_overriding, OverridingCatalog2)
|
||||
|
||||
def test_last_overriding_on_not_overridden(self):
|
||||
"""Test catalog last_overriding property on not overridden catalog."""
|
||||
self.assertIsNone(CatalogA.last_overriding)
|
||||
|
||||
def test_reset_last_overriding(self):
|
||||
"""Test resetting last overriding catalog."""
|
||||
@catalogs.override(CatalogA)
|
||||
class OverridingCatalog1(catalogs.DeclarativeCatalog):
|
||||
"""Overriding catalog."""
|
||||
|
||||
p11 = providers.Object(1)
|
||||
p12 = providers.Object(2)
|
||||
|
||||
@catalogs.override(CatalogA)
|
||||
class OverridingCatalog2(catalogs.DeclarativeCatalog):
|
||||
"""Overriding catalog."""
|
||||
|
||||
p11 = providers.Object(3)
|
||||
p12 = providers.Object(4)
|
||||
|
||||
CatalogA.reset_last_overriding()
|
||||
|
||||
self.assertEqual(CatalogA.p11(), 1)
|
||||
self.assertEqual(CatalogA.p12(), 2)
|
||||
|
||||
def test_reset_last_overriding_when_not_overridden(self):
|
||||
"""Test resetting last overriding catalog when it is not overridden."""
|
||||
with self.assertRaises(errors.Error):
|
||||
CatalogA.reset_last_overriding()
|
||||
|
||||
def test_reset_override(self):
|
||||
"""Test resetting all catalog overrides."""
|
||||
@catalogs.override(CatalogA)
|
||||
class OverridingCatalog1(catalogs.DeclarativeCatalog):
|
||||
"""Overriding catalog."""
|
||||
|
||||
p11 = providers.Object(1)
|
||||
p12 = providers.Object(2)
|
||||
|
||||
@catalogs.override(CatalogA)
|
||||
class OverridingCatalog2(catalogs.DeclarativeCatalog):
|
||||
"""Overriding catalog."""
|
||||
|
||||
p11 = providers.Object(3)
|
||||
p12 = providers.Object(4)
|
||||
|
||||
CatalogA.reset_override()
|
||||
|
||||
self.assertFalse(CatalogA.p11.is_overridden)
|
||||
self.assertFalse(CatalogA.p12.is_overridden)
|
|
@ -276,5 +276,162 @@ class DeclarativeContainerTests(unittest.TestCase):
|
|||
self.assertEqual(_Container1.p13(), 11)
|
||||
self.assertEqual(_Container2.p13(), 22)
|
||||
|
||||
|
||||
class DeclarativeContainerInstanceTests(unittest.TestCase):
|
||||
"""Declarative container instance tests."""
|
||||
|
||||
def test_providers_attribute(self):
|
||||
"""Test providers attribute."""
|
||||
container_a1 = ContainerA()
|
||||
container_a2 = ContainerA()
|
||||
|
||||
self.assertIsNot(container_a1.p11, container_a2.p11)
|
||||
self.assertIsNot(container_a1.p12, container_a2.p12)
|
||||
self.assertNotEqual(container_a1.providers, container_a2.providers)
|
||||
|
||||
def test_set_get_del_providers(self):
|
||||
"""Test set/get/del provider attributes."""
|
||||
p13 = providers.Provider()
|
||||
|
||||
container_a1 = ContainerA()
|
||||
container_a2 = ContainerA()
|
||||
|
||||
container_a1.p13 = p13
|
||||
container_a2.p13 = p13
|
||||
|
||||
self.assertEqual(ContainerA.providers, dict(p11=ContainerA.p11,
|
||||
p12=ContainerA.p12))
|
||||
self.assertEqual(ContainerA.cls_providers, dict(p11=ContainerA.p11,
|
||||
p12=ContainerA.p12))
|
||||
|
||||
self.assertEqual(container_a1.providers, dict(p11=container_a1.p11,
|
||||
p12=container_a1.p12,
|
||||
p13=p13))
|
||||
self.assertEqual(container_a2.providers, dict(p11=container_a2.p11,
|
||||
p12=container_a2.p12,
|
||||
p13=p13))
|
||||
|
||||
del container_a1.p13
|
||||
self.assertEqual(container_a1.providers, dict(p11=container_a1.p11,
|
||||
p12=container_a1.p12))
|
||||
|
||||
del container_a2.p13
|
||||
self.assertEqual(container_a2.providers, dict(p11=container_a2.p11,
|
||||
p12=container_a2.p12))
|
||||
|
||||
del container_a1.p11
|
||||
del container_a1.p12
|
||||
self.assertEqual(container_a1.providers, dict())
|
||||
self.assertEqual(ContainerA.providers, dict(p11=ContainerA.p11,
|
||||
p12=ContainerA.p12))
|
||||
|
||||
del container_a2.p11
|
||||
del container_a2.p12
|
||||
self.assertEqual(container_a2.providers, dict())
|
||||
self.assertEqual(ContainerA.providers, dict(p11=ContainerA.p11,
|
||||
p12=ContainerA.p12))
|
||||
|
||||
def test_set_invalid_provider_type(self):
|
||||
"""Test setting of invalid provider."""
|
||||
container_a = ContainerA()
|
||||
container_a.provider_type = providers.Object
|
||||
|
||||
with self.assertRaises(errors.Error):
|
||||
container_a.px = providers.Provider()
|
||||
|
||||
self.assertIs(ContainerA.provider_type,
|
||||
containers.DeclarativeContainer.provider_type)
|
||||
|
||||
def test_override(self):
|
||||
"""Test override."""
|
||||
class _Container(containers.DeclarativeContainer):
|
||||
p11 = providers.Provider()
|
||||
|
||||
class _OverridingContainer1(containers.DeclarativeContainer):
|
||||
p11 = providers.Provider()
|
||||
|
||||
class _OverridingContainer2(containers.DeclarativeContainer):
|
||||
p11 = providers.Provider()
|
||||
p12 = providers.Provider()
|
||||
|
||||
container = _Container()
|
||||
overriding_container1 = _OverridingContainer1()
|
||||
overriding_container2 = _OverridingContainer2()
|
||||
|
||||
container.override(overriding_container1)
|
||||
container.override(overriding_container2)
|
||||
|
||||
self.assertEqual(container.overridden_by,
|
||||
(overriding_container1,
|
||||
overriding_container2))
|
||||
self.assertEqual(container.p11.overridden_by,
|
||||
(overriding_container1.p11,
|
||||
overriding_container2.p11))
|
||||
|
||||
self.assertEqual(_Container.overridden_by, tuple())
|
||||
self.assertEqual(_Container.p11.overridden_by, tuple())
|
||||
|
||||
def test_override_with_itself(self):
|
||||
"""Test override container with itself."""
|
||||
container = ContainerA()
|
||||
with self.assertRaises(errors.Error):
|
||||
container.override(container)
|
||||
|
||||
def test_reset_last_overridding(self):
|
||||
"""Test reset of last overriding."""
|
||||
class _Container(containers.DeclarativeContainer):
|
||||
p11 = providers.Provider()
|
||||
|
||||
class _OverridingContainer1(containers.DeclarativeContainer):
|
||||
p11 = providers.Provider()
|
||||
|
||||
class _OverridingContainer2(containers.DeclarativeContainer):
|
||||
p11 = providers.Provider()
|
||||
p12 = providers.Provider()
|
||||
|
||||
container = _Container()
|
||||
overriding_container1 = _OverridingContainer1()
|
||||
overriding_container2 = _OverridingContainer2()
|
||||
|
||||
container.override(overriding_container1)
|
||||
container.override(overriding_container2)
|
||||
container.reset_last_overriding()
|
||||
|
||||
self.assertEqual(container.overridden_by,
|
||||
(overriding_container1,))
|
||||
self.assertEqual(container.p11.overridden_by,
|
||||
(overriding_container1.p11,))
|
||||
|
||||
def test_reset_last_overridding_when_not_overridden(self):
|
||||
"""Test reset of last overriding."""
|
||||
container = ContainerA()
|
||||
|
||||
with self.assertRaises(errors.Error):
|
||||
container.reset_last_overriding()
|
||||
|
||||
def test_reset_override(self):
|
||||
"""Test reset all overridings."""
|
||||
class _Container(containers.DeclarativeContainer):
|
||||
p11 = providers.Provider()
|
||||
|
||||
class _OverridingContainer1(containers.DeclarativeContainer):
|
||||
p11 = providers.Provider()
|
||||
|
||||
class _OverridingContainer2(containers.DeclarativeContainer):
|
||||
p11 = providers.Provider()
|
||||
p12 = providers.Provider()
|
||||
|
||||
container = _Container()
|
||||
overriding_container1 = _OverridingContainer1()
|
||||
overriding_container2 = _OverridingContainer2()
|
||||
|
||||
container.override(overriding_container1)
|
||||
container.override(overriding_container2)
|
||||
container.reset_override()
|
||||
|
||||
self.assertEqual(container.overridden_by, tuple())
|
||||
self.assertEqual(container.p11.overridden_by, tuple())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -4,7 +4,6 @@ import unittest2 as unittest
|
|||
|
||||
from dependency_injector import utils
|
||||
from dependency_injector import providers
|
||||
from dependency_injector import catalogs
|
||||
from dependency_injector import errors
|
||||
|
||||
|
||||
|
@ -69,56 +68,3 @@ class EnsureIsProviderTests(unittest.TestCase):
|
|||
def test_with_object(self):
|
||||
"""Test with object."""
|
||||
self.assertRaises(errors.Error, utils.ensure_is_provider, object())
|
||||
|
||||
|
||||
class IsCatalogTests(unittest.TestCase):
|
||||
"""`is_catalog()` test cases."""
|
||||
|
||||
def test_with_declarative_catalog(self):
|
||||
"""Test with class."""
|
||||
self.assertTrue(utils.is_catalog(catalogs.DeclarativeCatalog))
|
||||
|
||||
def test_with_dynamic_catalog(self):
|
||||
"""Test with class."""
|
||||
self.assertTrue(utils.is_catalog(catalogs.DynamicCatalog()))
|
||||
|
||||
def test_with_child_class(self):
|
||||
"""Test with parent class."""
|
||||
class Catalog(catalogs.DeclarativeCatalog):
|
||||
"""Example catalog child class."""
|
||||
|
||||
self.assertTrue(utils.is_catalog(Catalog))
|
||||
|
||||
def test_with_string(self):
|
||||
"""Test with string."""
|
||||
self.assertFalse(utils.is_catalog('some_string'))
|
||||
|
||||
def test_with_object(self):
|
||||
"""Test with object."""
|
||||
self.assertFalse(utils.is_catalog(object()))
|
||||
|
||||
|
||||
class IsDynamicCatalogTests(unittest.TestCase):
|
||||
"""`is_dynamic_catalog()` test cases."""
|
||||
|
||||
def test_with_declarative_catalog(self):
|
||||
"""Test with declarative catalog."""
|
||||
self.assertFalse(utils.is_dynamic_catalog(catalogs.DeclarativeCatalog))
|
||||
|
||||
def test_with_dynamic_catalog(self):
|
||||
"""Test with dynamic catalog."""
|
||||
self.assertTrue(utils.is_dynamic_catalog(catalogs.DynamicCatalog()))
|
||||
|
||||
|
||||
class IsDeclarativeCatalogTests(unittest.TestCase):
|
||||
"""`is_declarative_catalog()` test cases."""
|
||||
|
||||
def test_with_declarative_catalog(self):
|
||||
"""Test with declarative catalog."""
|
||||
self.assertTrue(utils.is_declarative_catalog(
|
||||
catalogs.DeclarativeCatalog))
|
||||
|
||||
def test_with_dynamic_catalog(self):
|
||||
"""Test with dynamic catalog."""
|
||||
self.assertFalse(utils.is_declarative_catalog(
|
||||
catalogs.DynamicCatalog()))
|
||||
|
|
Loading…
Reference in New Issue
Block a user