Update project structure

This commit is contained in:
Roman Mogilatov 2016-11-04 13:06:47 +02:00
parent 7bcb882425
commit 5695c781c9
18 changed files with 641 additions and 651 deletions

View File

@ -40,22 +40,15 @@ setup(name='dependency-injector',
install_requires=requirements,
packages=[
'dependency_injector',
'dependency_injector.containers',
'dependency_injector.providers',
],
package_dir={
'': 'src',
},
ext_modules=[
Extension('dependency_injector.injections',
['src/dependency_injector/injections.c'],
define_macros=defined_macros,
extra_compile_args=['-O2']),
Extension('dependency_injector.utils',
['src/dependency_injector/utils.c'],
define_macros=defined_macros,
extra_compile_args=['-O2']),
Extension('dependency_injector.errors',
['src/dependency_injector/errors.c'],
Extension('dependency_injector.providers.injections',
['src/dependency_injector/providers/injections.c'],
define_macros=defined_macros,
extra_compile_args=['-O2']),
],

View File

@ -1,363 +0,0 @@
"""Dependency injector IoC containers module."""
import six
from dependency_injector import (
providers,
utils,
errors,
)
class DynamicContainer(object):
"""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
def __init__(self):
"""Initializer.
:rtype: None
"""
self.provider_type = providers.Provider
self.providers = dict()
self.overridden = 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.
:param name: Attribute's name
:type name: str
:param value: Attribute's value
:type value: object
:rtype: None
"""
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.
:param name: Attribute's name
:type name: str
:rtype: None
"""
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:`DynamicContainer`
:raise: :py:exc:`dependency_injector.errors.Error` if trying to
override container by itself
:rtype: None
"""
if overriding is self:
raise errors.Error('Container {0} could not be overridden '
'with itself'.format(self))
self.overridden += (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:
raise errors.Error('Container {0} is not overridden'.format(self))
self.overridden = self.overridden[:-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 = tuple()
for provider in six.itervalues(self.providers):
provider.reset_override()
class DeclarativeContainerMetaClass(type):
"""Declarative inversion of control container meta class."""
def __new__(mcs, class_name, bases, attributes):
"""Declarative container class factory."""
cls_providers = tuple((name, provider)
for name, provider in six.iteritems(attributes)
if utils.is_provider(provider))
inherited_providers = tuple((name, provider)
for base in bases if utils.is_container(
base) and base is not DynamicContainer
for name, provider in six.iteritems(
base.cls_providers))
attributes['cls_providers'] = dict(cls_providers)
attributes['inherited_providers'] = dict(inherited_providers)
attributes['providers'] = dict(cls_providers + inherited_providers)
cls = type.__new__(mcs, class_name, bases, attributes)
for provider in six.itervalues(cls.providers):
_check_provider_type(cls, provider)
return cls
def __setattr__(cls, name, value):
"""Set class attribute.
If value of attribute is provider, it will be added into providers
dictionary.
:param name: Attribute's name
:type name: str
:param value: Attribute's value
:type value: object
:rtype: None
"""
if utils.is_provider(value):
_check_provider_type(cls, value)
cls.providers[name] = value
cls.cls_providers[name] = value
super(DeclarativeContainerMetaClass, cls).__setattr__(name, value)
def __delattr__(cls, name):
"""Delete class attribute.
If value of attribute is provider, it will be deleted from providers
dictionary.
:param name: Attribute's name
:type name: str
:rtype: None
"""
if name in cls.providers and name in cls.cls_providers:
del cls.providers[name]
del cls.cls_providers[name]
super(DeclarativeContainerMetaClass, cls).__delattr__(name)
@six.add_metaclass(DeclarativeContainerMetaClass)
class DeclarativeContainer(object):
"""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
provider_type = providers.Provider
"""Type of providers that could be placed in container.
:type: type
"""
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):
"""Constructor.
:return: Dynamic container with copy of all providers.
:rtype: :py:class:`DynamicContainer`
"""
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.
: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 issubclass(cls, overriding):
raise errors.Error('Container {0} could not be overridden '
'with itself or its subclasses'.format(cls))
cls.overridden += (overriding,)
for name, provider in six.iteritems(overriding.cls_providers):
try:
getattr(cls, name).override(provider)
except AttributeError:
pass
@classmethod
def reset_last_overriding(cls):
"""Reset last overriding provider for each container providers.
:rtype: None
"""
if not cls.overridden:
raise errors.Error('Container {0} is not overridden'.format(cls))
cls.overridden = cls.overridden[:-1]
for provider in six.itervalues(cls.providers):
provider.reset_last_overriding()
@classmethod
def reset_override(cls):
"""Reset all overridings for each container providers.
:rtype: None
"""
cls.overridden = tuple()
for provider in six.itervalues(cls.providers):
provider.reset_override()
def override(container):
""":py:class:`DeclarativeContainer` overriding decorator.
:param container: Container that should be overridden by decorated
container.
:type container: :py:class:`DeclarativeContainer`
:return: Declarative container's overriding decorator.
:rtype: callable(:py:class:`DeclarativeContainer`)
"""
def _decorator(overriding_container):
"""Overriding decorator."""
container.override(overriding_container)
return overriding_container
return _decorator
def copy(container):
""":py:class:`DeclarativeContainer` copying decorator.
This decorator copy all providers from provided container to decorated one.
If one of the decorated container providers matches to source container
providers by name, it would be replaced by reference.
:param container: Container that should be copied by decorated container.
:type container: :py:class:`DeclarativeContainer`
:return: Declarative container's copying decorator.
:rtype: callable(:py:class:`DeclarativeContainer`)
"""
def _decorator(copied_container):
memo = dict()
for name, provider in six.iteritems(copied_container.cls_providers):
try:
source_provider = getattr(container, name)
except AttributeError:
pass
else:
memo[id(source_provider)] = provider
providers_copy = utils.deepcopy(container.providers, memo)
for name, provider in six.iteritems(providers_copy):
setattr(copied_container, name, provider)
return copied_container
return _decorator
def _check_provider_type(cls, provider):
if not isinstance(provider, cls.provider_type):
raise errors.Error('{0} can contain only {1} '
'instances'.format(cls, cls.provider_type))

View File

@ -0,0 +1,26 @@
"""Dependency injector containers."""
from .declarative import (
DeclarativeContainerMetaClass,
DeclarativeContainer,
)
from .dynamic import (
DynamicContainer,
)
from .utils import (
is_container,
override,
copy,
)
__all__ = (
'DeclarativeContainerMetaClass',
'DeclarativeContainer',
'DynamicContainer',
'is_container',
'override',
'copy',
)

View File

@ -0,0 +1,191 @@
"""Dependency injector declarative container."""
import six
from dependency_injector.providers import Provider
from dependency_injector.errors import Error
from .dynamic import DynamicContainer
from .utils import (
is_container,
deepcopy,
_check_provider_type,
)
class DeclarativeContainerMetaClass(type):
"""Declarative inversion of control container meta class."""
def __new__(mcs, class_name, bases, attributes):
"""Declarative container class factory."""
cls_providers = tuple((name, provider)
for name, provider in six.iteritems(attributes)
if isinstance(provider, Provider))
inherited_providers = tuple((name, provider)
for base in bases if is_container(
base) and base is not DynamicContainer
for name, provider in six.iteritems(
base.cls_providers))
attributes['cls_providers'] = dict(cls_providers)
attributes['inherited_providers'] = dict(inherited_providers)
attributes['providers'] = dict(cls_providers + inherited_providers)
cls = type.__new__(mcs, class_name, bases, attributes)
for provider in six.itervalues(cls.providers):
_check_provider_type(cls, provider)
return cls
def __setattr__(cls, name, value):
"""Set class attribute.
If value of attribute is provider, it will be added into providers
dictionary.
:param name: Attribute's name
:type name: str
:param value: Attribute's value
:type value: object
:rtype: None
"""
if isinstance(value, Provider):
_check_provider_type(cls, value)
cls.providers[name] = value
cls.cls_providers[name] = value
super(DeclarativeContainerMetaClass, cls).__setattr__(name, value)
def __delattr__(cls, name):
"""Delete class attribute.
If value of attribute is provider, it will be deleted from providers
dictionary.
:param name: Attribute's name
:type name: str
:rtype: None
"""
if name in cls.providers and name in cls.cls_providers:
del cls.providers[name]
del cls.cls_providers[name]
super(DeclarativeContainerMetaClass, cls).__delattr__(name)
@six.add_metaclass(DeclarativeContainerMetaClass)
class DeclarativeContainer(object):
"""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
provider_type = Provider
"""Type of providers that could be placed in container.
:type: type
"""
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):
"""Constructor.
:return: Dynamic container with copy of all providers.
:rtype: :py:class:`DynamicContainer`
"""
container = cls.instance_type(*args, **kwargs)
container.provider_type = cls.provider_type
for name, provider in six.iteritems(deepcopy(cls.providers)):
setattr(container, name, provider)
return container
@classmethod
def override(cls, 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 issubclass(cls, overriding):
raise Error('Container {0} could not be overridden '
'with itself or its subclasses'.format(cls))
cls.overridden += (overriding,)
for name, provider in six.iteritems(overriding.cls_providers):
try:
getattr(cls, name).override(provider)
except AttributeError:
pass
@classmethod
def reset_last_overriding(cls):
"""Reset last overriding provider for each container providers.
:rtype: None
"""
if not cls.overridden:
raise Error('Container {0} is not overridden'.format(cls))
cls.overridden = cls.overridden[:-1]
for provider in six.itervalues(cls.providers):
provider.reset_last_overriding()
@classmethod
def reset_override(cls):
"""Reset all overridings for each container providers.
:rtype: None
"""
cls.overridden = tuple()
for provider in six.itervalues(cls.providers):
provider.reset_override()

View File

@ -0,0 +1,130 @@
"""Dependency injector dynamic container."""
import six
from dependency_injector.providers import Provider
from dependency_injector.errors import Error
from .utils import _check_provider_type
class DynamicContainer(object):
"""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
def __init__(self):
"""Initializer.
:rtype: None
"""
self.provider_type = Provider
self.providers = dict()
self.overridden = 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.
:param name: Attribute's name
:type name: str
:param value: Attribute's value
:type value: object
:rtype: None
"""
if isinstance(value, Provider):
_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.
:param name: Attribute's name
:type name: str
:rtype: None
"""
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:`DynamicContainer`
:raise: :py:exc:`dependency_injector.errors.Error` if trying to
override container by itself
:rtype: None
"""
if overriding is self:
raise Error('Container {0} could not be overridden '
'with itself'.format(self))
self.overridden += (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:
raise Error('Container {0} is not overridden'.format(self))
self.overridden = self.overridden[:-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 = tuple()
for provider in six.itervalues(self.providers):
provider.reset_override()

View File

@ -0,0 +1,85 @@
"""Dependency injector container utils."""
import copy as _copy
import types
import six
from dependency_injector.errors import Error
if six.PY2: # pragma: no cover
_copy._deepcopy_dispatch[types.MethodType] = \
lambda obj, memo: type(obj)(obj.im_func,
_copy.deepcopy(obj.im_self, memo),
obj.im_class)
def is_container(instance):
"""Check if instance is container instance.
:param instance: Instance to be checked.
:type instance: object
:rtype: bool
"""
return getattr(instance, '__IS_CONTAINER__', False) is True
def override(container):
""":py:class:`DeclarativeContainer` overriding decorator.
:param container: Container that should be overridden by decorated
container.
:type container: :py:class:`DeclarativeContainer`
:return: Declarative container's overriding decorator.
:rtype: callable(:py:class:`DeclarativeContainer`)
"""
def _decorator(overriding_container):
"""Overriding decorator."""
container.override(overriding_container)
return overriding_container
return _decorator
def copy(container):
""":py:class:`DeclarativeContainer` copying decorator.
This decorator copy all providers from provided container to decorated one.
If one of the decorated container providers matches to source container
providers by name, it would be replaced by reference.
:param container: Container that should be copied by decorated container.
:type container: :py:class:`DeclarativeContainer`
:return: Declarative container's copying decorator.
:rtype: callable(:py:class:`DeclarativeContainer`)
"""
def _decorator(copied_container):
memo = dict()
for name, provider in six.iteritems(copied_container.cls_providers):
try:
source_provider = getattr(container, name)
except AttributeError:
pass
else:
memo[id(source_provider)] = provider
providers_copy = deepcopy(container.providers, memo)
for name, provider in six.iteritems(providers_copy):
setattr(copied_container, name, provider)
return copied_container
return _decorator
def deepcopy(instance, memo=None):
"""Make full copy of instance."""
return _copy.deepcopy(instance, memo)
def _check_provider_type(cls, provider):
if not isinstance(provider, cls.provider_type):
raise Error('{0} can contain only {1} '
'instances'.format(cls, cls.provider_type))

View File

@ -1,8 +0,0 @@
"""Dependency injector errors.
Powered by Cython.
"""
cdef class Error(Exception):
pass

View File

@ -1,10 +1,7 @@
"""Dependency injector errors.
Powered by Cython.
"""
"""Dependency injector errors."""
cdef class Error(Exception):
class Error(Exception):
"""Base error.
All dependency injector errors extend this error class.

View File

@ -1,6 +1,6 @@
"""Dependency injector providers package."""
"""Dependency injector providers."""
from dependency_injector.providers.base import (
from .base import (
Provider,
Delegate,
Object,
@ -8,17 +8,22 @@ from dependency_injector.providers.base import (
OverridingContext,
override,
)
from dependency_injector.providers.callable import (
from .callable import (
Callable,
DelegatedCallable,
)
from dependency_injector.providers.creational import (
from .creational import (
Factory,
DelegatedFactory,
Singleton,
DelegatedSingleton,
ThreadLocalSingleton,
DelegatedThreadLocalSingleton
DelegatedThreadLocalSingleton,
)
from .injections import (
Injection,
PositionalInjection,
NamedInjection,
)
@ -42,4 +47,8 @@ __all__ = (
'ThreadLocalSingleton',
'DelegatedThreadLocalSingleton',
'Injection',
'PositionalInjection',
'NamedInjection',
)

View File

@ -5,7 +5,7 @@ Powered by Cython.
cimport cython
from .utils cimport (
from dependency_injector.utils import (
is_provider,
is_delegated,
)

View File

@ -1,16 +0,0 @@
"""Dependency injector utils.
Powered by Cython.
"""
cpdef bint is_provider(object instance)
cpdef object ensure_is_provider(object instance)
cpdef bint is_delegated(object instance)
cpdef bint is_container(object instance)
cpdef str represent_provider(object provider, object provides)
cpdef object deepcopy(object instance, dict memo=*)

View File

@ -1,36 +1,19 @@
"""Dependency injector utils.
"""Dependency injector utils."""
Powered by Cython.
"""
import six
cimport cpython.version
from dependency_injector cimport errors
import copy as _copy
import types
import threading
from .errors import Error
GLOBAL_LOCK = threading.RLock()
"""Dependency injector global reentrant lock.
"""Global reentrant lock.
:type: :py:class:`threading.RLock`
"""
if cpython.version.PY_MAJOR_VERSION < 3: # pragma: no cover
CLASS_TYPES = (type, types.ClassType)
_copy._deepcopy_dispatch[types.MethodType] = \
lambda obj, memo: type(obj)(obj.im_func,
_copy.deepcopy(obj.im_self, memo),
obj.im_class)
else: # pragma: no cover
CLASS_TYPES = (type,)
cpdef bint is_provider(object instance):
def is_provider(instance):
"""Check if instance is provider instance.
:param instance: Instance to be checked.
@ -38,11 +21,11 @@ cpdef bint is_provider(object instance):
:rtype: bool
"""
return (not isinstance(instance, CLASS_TYPES) and
return (not isinstance(instance, six.class_types) and
getattr(instance, '__IS_PROVIDER__', False) is True)
cpdef object ensure_is_provider(object instance):
def ensure_is_provider(instance):
"""Check if instance is provider instance and return it.
:param instance: Instance to be checked.
@ -54,12 +37,12 @@ cpdef object ensure_is_provider(object instance):
:rtype: :py:class:`dependency_injector.providers.Provider`
"""
if not is_provider(instance):
raise errors.Error('Expected provider instance, '
'got {0}'.format(str(instance)))
raise Error('Expected provider instance, '
'got {0}'.format(str(instance)))
return instance
cpdef bint is_delegated(object instance):
def is_delegated(instance):
"""Check if instance is delegated provider.
:param instance: Instance to be checked.
@ -67,22 +50,11 @@ cpdef bint is_delegated(object instance):
:rtype: bool
"""
return (not isinstance(instance, CLASS_TYPES) and
return (not isinstance(instance, six.class_types) and
getattr(instance, '__IS_DELEGATED__', False) is True)
cpdef bint is_container(object instance):
"""Check if instance is container instance.
:param instance: Instance to be checked.
:type instance: object
:rtype: bool
"""
return getattr(instance, '__IS_CONTAINER__', False) is True
cpdef str represent_provider(object provider, object provides):
def represent_provider(provider, provides):
"""Return string representation of provider.
:param provider: Provider object
@ -99,9 +71,3 @@ cpdef str represent_provider(object provider, object provides):
provider.__class__.__name__)),
provides=repr(provides) if provides is not None else '',
address=hex(id(provider)))
cpdef object deepcopy(object instance, dict memo=None):
"""Make full copy of instance."""
return _copy.deepcopy(instance, memo)

View File

@ -0,0 +1 @@
"""Dependency injector container unit tests."""

View File

@ -1,4 +1,4 @@
"""Dependency injector container unit tests."""
"""Dependency injector declarative container unit tests."""
import unittest2 as unittest
@ -10,27 +10,18 @@ from dependency_injector import (
class ContainerA(containers.DeclarativeContainer):
"""Declarative IoC container A."""
p11 = providers.Provider()
p12 = providers.Provider()
class ContainerB(ContainerA):
"""Declarative IoC container B.
Extends container A.
"""
p21 = providers.Provider()
p22 = providers.Provider()
class DeclarativeContainerTests(unittest.TestCase):
"""Declarative container tests."""
def test_providers_attribute(self):
"""Test providers attribute."""
self.assertEqual(ContainerA.providers, dict(p11=ContainerA.p11,
p12=ContainerA.p12))
self.assertEqual(ContainerB.providers, dict(p11=ContainerA.p11,
@ -39,21 +30,18 @@ class DeclarativeContainerTests(unittest.TestCase):
p22=ContainerB.p22))
def test_cls_providers_attribute(self):
"""Test cls_providers attribute."""
self.assertEqual(ContainerA.cls_providers, dict(p11=ContainerA.p11,
p12=ContainerA.p12))
self.assertEqual(ContainerB.cls_providers, dict(p21=ContainerB.p21,
p22=ContainerB.p22))
def test_inherited_providers_attribute(self):
"""Test inherited_providers attribute."""
self.assertEqual(ContainerA.inherited_providers, dict())
self.assertEqual(ContainerB.inherited_providers,
dict(p11=ContainerA.p11,
p12=ContainerA.p12))
def test_set_get_del_providers(self):
"""Test set/get/del provider attributes."""
a_p13 = providers.Provider()
b_p23 = providers.Provider()
@ -92,7 +80,6 @@ class DeclarativeContainerTests(unittest.TestCase):
p22=ContainerB.p22))
def test_declare_with_valid_provider_type(self):
"""Test declaration of container with valid provider type."""
class _Container(containers.DeclarativeContainer):
provider_type = providers.Object
px = providers.Object(object())
@ -100,14 +87,12 @@ class DeclarativeContainerTests(unittest.TestCase):
self.assertIsInstance(_Container.px, providers.Object)
def test_declare_with_invalid_provider_type(self):
"""Test declaration of container with invalid provider type."""
with self.assertRaises(errors.Error):
class _Container(containers.DeclarativeContainer):
provider_type = providers.Object
px = providers.Provider()
def test_seth_valid_provider_type(self):
"""Test setting of valid provider."""
class _Container(containers.DeclarativeContainer):
provider_type = providers.Object
@ -116,7 +101,6 @@ class DeclarativeContainerTests(unittest.TestCase):
self.assertIsInstance(_Container.px, providers.Object)
def test_set_invalid_provider_type(self):
"""Test setting of invalid provider."""
class _Container(containers.DeclarativeContainer):
provider_type = providers.Object
@ -124,7 +108,6 @@ class DeclarativeContainerTests(unittest.TestCase):
_Container.px = providers.Provider()
def test_override(self):
"""Test override."""
class _Container(containers.DeclarativeContainer):
p11 = providers.Provider()
@ -146,17 +129,14 @@ class DeclarativeContainerTests(unittest.TestCase):
_OverridingContainer2.p11))
def test_override_with_itself(self):
"""Test override with itself."""
with self.assertRaises(errors.Error):
ContainerA.override(ContainerA)
def test_override_with_parent(self):
"""Test override with parent."""
with self.assertRaises(errors.Error):
ContainerB.override(ContainerA)
def test_override_decorator(self):
"""Test override decorator."""
class _Container(containers.DeclarativeContainer):
p11 = providers.Provider()
@ -177,7 +157,6 @@ class DeclarativeContainerTests(unittest.TestCase):
_OverridingContainer2.p11))
def test_reset_last_overridding(self):
"""Test reset of last overriding."""
class _Container(containers.DeclarativeContainer):
p11 = providers.Provider()
@ -198,12 +177,10 @@ class DeclarativeContainerTests(unittest.TestCase):
(_OverridingContainer1.p11,))
def test_reset_last_overridding_when_not_overridden(self):
"""Test reset of last overriding."""
with self.assertRaises(errors.Error):
ContainerA.reset_last_overriding()
def test_reset_override(self):
"""Test reset all overridings."""
class _Container(containers.DeclarativeContainer):
p11 = providers.Provider()
@ -222,7 +199,6 @@ class DeclarativeContainerTests(unittest.TestCase):
self.assertEqual(_Container.p11.overridden, tuple())
def test_copy(self):
"""Test copy decorator."""
@containers.copy(ContainerA)
class _Container1(ContainerA):
pass
@ -241,7 +217,6 @@ class DeclarativeContainerTests(unittest.TestCase):
self.assertIsNot(_Container1.p12, _Container2.p12)
def test_copy_with_replacing(self):
"""Test copy decorator with providers replacement."""
class _Container(containers.DeclarativeContainer):
p11 = providers.Object(0)
p12 = providers.Factory(dict, p11=p11)
@ -275,163 +250,3 @@ 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,
(overriding_container1,
overriding_container2))
self.assertEqual(container.p11.overridden,
(overriding_container1.p11,
overriding_container2.p11))
self.assertEqual(_Container.overridden, tuple())
self.assertEqual(_Container.p11.overridden, 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,
(overriding_container1,))
self.assertEqual(container.p11.overridden,
(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, tuple())
self.assertEqual(container.p11.overridden, tuple())
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1,165 @@
"""Dependency injector dynamic container unit tests."""
import unittest2 as unittest
from dependency_injector import (
containers,
providers,
errors,
)
class ContainerA(containers.DeclarativeContainer):
p11 = providers.Provider()
p12 = providers.Provider()
class DeclarativeContainerInstanceTests(unittest.TestCase):
def test_providers_attribute(self):
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):
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):
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):
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,
(overriding_container1,
overriding_container2))
self.assertEqual(container.p11.overridden,
(overriding_container1.p11,
overriding_container2.p11))
self.assertEqual(_Container.overridden, tuple())
self.assertEqual(_Container.p11.overridden, tuple())
def test_override_with_itself(self):
container = ContainerA()
with self.assertRaises(errors.Error):
container.override(container)
def test_reset_last_overridding(self):
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,
(overriding_container1,))
self.assertEqual(container.p11.overridden,
(overriding_container1.p11,))
def test_reset_last_overridding_when_not_overridden(self):
container = ContainerA()
with self.assertRaises(errors.Error):
container.reset_last_overriding()
def test_reset_override(self):
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, tuple())
self.assertEqual(container.p11.overridden, tuple())
if __name__ == '__main__':
unittest.main()

View File

@ -2,22 +2,21 @@
import unittest2 as unittest
from dependency_injector import injections
from dependency_injector import providers
class PositionalInjectionTests(unittest.TestCase):
def test_isinstance(self):
injection = injections.PositionalInjection(1)
self.assertIsInstance(injection, injections.Injection)
injection = providers.PositionalInjection(1)
self.assertIsInstance(injection, providers.Injection)
def test_get_value_with_not_provider(self):
injection = injections.PositionalInjection(123)
injection = providers.PositionalInjection(123)
self.assertEquals(injection.get_value(), 123)
def test_get_value_with_factory(self):
injection = injections.PositionalInjection(providers.Factory(object))
injection = providers.PositionalInjection(providers.Factory(object))
obj1 = injection.get_value()
obj2 = injection.get_value()
@ -30,20 +29,20 @@ class PositionalInjectionTests(unittest.TestCase):
class NamedInjectionTests(unittest.TestCase):
def test_isinstance(self):
injection = injections.NamedInjection('name', 1)
self.assertIsInstance(injection, injections.Injection)
injection = providers.NamedInjection('name', 1)
self.assertIsInstance(injection, providers.Injection)
def test_get_name(self):
injection = injections.NamedInjection('name', 123)
injection = providers.NamedInjection('name', 123)
self.assertEquals(injection.get_name(), 'name')
def test_get_value_with_not_provider(self):
injection = injections.NamedInjection('name', 123)
injection = providers.NamedInjection('name', 123)
self.assertEquals(injection.get_value(), 123)
def test_get_value_with_factory(self):
injection = injections.NamedInjection('name',
providers.Factory(object))
injection = providers.NamedInjection('name',
providers.Factory(object))
obj1 = injection.get_value()
obj2 = injection.get_value()