mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-22 01:26:51 +03:00
Add DelegatedCallable, DelegatedFactory & DelegatedSingleton providers
This commit is contained in:
parent
0d00e2b0f5
commit
319128260a
|
@ -8,15 +8,18 @@ from .catalogs import override
|
|||
|
||||
from .providers import Provider
|
||||
from .providers import Delegate
|
||||
from .providers import Callable
|
||||
from .providers import DelegatedCallable
|
||||
from .providers import Factory
|
||||
from .providers import DelegatedFactory
|
||||
from .providers import Singleton
|
||||
from .providers import DelegatedSingleton
|
||||
from .providers import ExternalDependency
|
||||
from .providers import StaticProvider
|
||||
from .providers import Class
|
||||
from .providers import Object
|
||||
from .providers import Function
|
||||
from .providers import Value
|
||||
from .providers import Callable
|
||||
from .providers import Config
|
||||
|
||||
from .injections import Injection
|
||||
|
@ -28,6 +31,7 @@ from .injections import inject
|
|||
|
||||
from .utils import is_provider
|
||||
from .utils import ensure_is_provider
|
||||
from .utils import is_delegated_provider
|
||||
from .utils import is_injection
|
||||
from .utils import ensure_is_injection
|
||||
from .utils import is_arg_injection
|
||||
|
@ -65,15 +69,18 @@ __all__ = (
|
|||
# Providers
|
||||
'Provider',
|
||||
'Delegate',
|
||||
'Callable',
|
||||
'DelegatedCallable',
|
||||
'Factory',
|
||||
'DelegatedFactory',
|
||||
'Singleton',
|
||||
'DelegatedSingleton',
|
||||
'ExternalDependency',
|
||||
'StaticProvider',
|
||||
'Class',
|
||||
'Object',
|
||||
'Function',
|
||||
'Value',
|
||||
'Callable',
|
||||
'Config',
|
||||
|
||||
# Injections
|
||||
|
@ -87,6 +94,7 @@ __all__ = (
|
|||
# Utils
|
||||
'is_provider',
|
||||
'ensure_is_provider',
|
||||
'is_delegated_provider',
|
||||
'is_injection',
|
||||
'ensure_is_injection',
|
||||
'is_arg_injection',
|
||||
|
|
|
@ -6,6 +6,7 @@ import itertools
|
|||
import six
|
||||
|
||||
from .utils import is_provider
|
||||
from .utils import is_delegated_provider
|
||||
from .utils import is_injection
|
||||
from .utils import is_arg_injection
|
||||
from .utils import is_kwarg_injection
|
||||
|
@ -32,15 +33,17 @@ class Injection(object):
|
|||
|
||||
:type: object | :py:class:`dependency_injector.providers.Provider`
|
||||
|
||||
.. py:attribute:: injectable_is_provider
|
||||
.. py:attribute:: call_injectable
|
||||
|
||||
Flag that is set to ``True`` if injectable value is provider.
|
||||
Flag that is set to ``True`` if it is needed to call injectable.
|
||||
|
||||
Injectable needs to be called if it is not delegated provider.
|
||||
|
||||
:type: bool
|
||||
"""
|
||||
|
||||
__IS_INJECTION__ = True
|
||||
__slots__ = ('injectable', 'injectable_is_provider')
|
||||
__slots__ = ('injectable', 'call_injectable')
|
||||
|
||||
def __init__(self, injectable):
|
||||
"""Initializer.
|
||||
|
@ -51,20 +54,21 @@ class Injection(object):
|
|||
:py:class:`dependency_injector.providers.Provider`
|
||||
"""
|
||||
self.injectable = injectable
|
||||
self.injectable_is_provider = is_provider(injectable)
|
||||
self.call_injectable = (is_provider(injectable) and
|
||||
not is_delegated_provider(injectable))
|
||||
super(Injection, self).__init__()
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
"""Read-only property that represents injectable value.
|
||||
|
||||
Injectable values are provided "as is", except of providers
|
||||
(subclasses of :py:class:`dependency_injector.providers.Provider`).
|
||||
Providers will be called every time, when injection needs to be done.
|
||||
Injectable values and delegated providers are provided "as is".
|
||||
Other providers will be called every time, when injection needs to
|
||||
be done.
|
||||
|
||||
:rtype: object
|
||||
"""
|
||||
if self.injectable_is_provider:
|
||||
if self.call_injectable:
|
||||
return self.injectable()
|
||||
return self.injectable
|
||||
|
||||
|
|
|
@ -319,6 +319,34 @@ class Callable(Provider):
|
|||
__repr__ = __str__
|
||||
|
||||
|
||||
class DelegatedCallable(Callable):
|
||||
""":py:class:`DelegatedCallable` is a delegated :py:class:`Callable`.
|
||||
|
||||
:py:class:`DelegatedCallable` is a :py:class:`Callable`, that is injected
|
||||
"as is".
|
||||
|
||||
.. py:attribute:: provides
|
||||
|
||||
Provided callable.
|
||||
|
||||
:type: callable
|
||||
|
||||
.. py:attribute:: args
|
||||
|
||||
Tuple of positional argument injections.
|
||||
|
||||
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
|
||||
|
||||
.. py:attribute:: kwargs
|
||||
|
||||
Tuple of keyword argument injections.
|
||||
|
||||
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
|
||||
"""
|
||||
|
||||
__IS_DELEGATED__ = True
|
||||
|
||||
|
||||
class Factory(Callable):
|
||||
""":py:class:`Factory` provider creates new instance on every call.
|
||||
|
||||
|
@ -448,6 +476,54 @@ class Factory(Callable):
|
|||
return instance
|
||||
|
||||
|
||||
class DelegatedFactory(Factory):
|
||||
""":py:class:`DelegatedFactory` is a delegated :py:class:`Factory`.
|
||||
|
||||
:py:class:`DelegatedFactory` is a :py:class:`Factory`, that is injected
|
||||
"as is".
|
||||
|
||||
.. py:attribute:: provided_type
|
||||
|
||||
If provided type is defined, :py:class:`Factory` checks that
|
||||
:py:attr:`Factory.provides` is subclass of
|
||||
:py:attr:`Factory.provided_type`.
|
||||
|
||||
:type: type | None
|
||||
|
||||
.. py:attribute:: provides
|
||||
|
||||
Class or other callable that provides object.
|
||||
|
||||
:type: type | callable
|
||||
|
||||
.. py:attribute:: args
|
||||
|
||||
Tuple of positional argument injections.
|
||||
|
||||
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
|
||||
|
||||
.. py:attribute:: kwargs
|
||||
|
||||
Tuple of keyword argument injections.
|
||||
|
||||
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
|
||||
|
||||
.. py:attribute:: attributes
|
||||
|
||||
Tuple of attribute injections.
|
||||
|
||||
:type: tuple[:py:class:`dependency_injector.injections.Attribute`]
|
||||
|
||||
.. py:attribute:: methods
|
||||
|
||||
Tuple of method injections.
|
||||
|
||||
:type: tuple[:py:class:`dependency_injector.injections.Method`]
|
||||
"""
|
||||
|
||||
__IS_DELEGATED__ = True
|
||||
|
||||
|
||||
class Singleton(Factory):
|
||||
""":py:class:`Singleton` provider returns same instance on every call.
|
||||
|
||||
|
@ -556,6 +632,60 @@ class Singleton(Factory):
|
|||
return self.instance
|
||||
|
||||
|
||||
class DelegatedSingleton(Singleton):
|
||||
""":py:class:`DelegatedSingleton` is a delegated :py:class:`Singleton`.
|
||||
|
||||
:py:class:`DelegatedSingleton` is a :py:class:`Singleton`, that is injected
|
||||
"as is".
|
||||
|
||||
.. py:attribute:: provided_type
|
||||
|
||||
If provided type is defined, :py:class:`Factory` checks that
|
||||
:py:attr:`Factory.provides` is subclass of
|
||||
:py:attr:`Factory.provided_type`.
|
||||
|
||||
:type: type | None
|
||||
|
||||
.. py:attribute:: instance
|
||||
|
||||
Read-only reference to singleton's instance.
|
||||
|
||||
:type: object
|
||||
|
||||
.. py:attribute:: provides
|
||||
|
||||
Class or other callable that provides object.
|
||||
|
||||
:type: type | callable
|
||||
|
||||
.. py:attribute:: args
|
||||
|
||||
Tuple of positional argument injections.
|
||||
|
||||
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
|
||||
|
||||
.. py:attribute:: kwargs
|
||||
|
||||
Tuple of keyword argument injections.
|
||||
|
||||
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
|
||||
|
||||
.. py:attribute:: attributes
|
||||
|
||||
Tuple of attribute injections.
|
||||
|
||||
:type: tuple[:py:class:`dependency_injector.injections.Attribute`]
|
||||
|
||||
.. py:attribute:: methods
|
||||
|
||||
Tuple of method injections.
|
||||
|
||||
:type: tuple[:py:class:`dependency_injector.injections.Method`]
|
||||
"""
|
||||
|
||||
__IS_DELEGATED__ = True
|
||||
|
||||
|
||||
@six.python_2_unicode_compatible
|
||||
class ExternalDependency(Provider):
|
||||
""":py:class:`ExternalDependency` provider describes dependency interface.
|
||||
|
|
|
@ -44,6 +44,19 @@ def ensure_is_provider(instance):
|
|||
return instance
|
||||
|
||||
|
||||
def is_delegated_provider(instance):
|
||||
"""Check if instance is delegated provider instance.
|
||||
|
||||
:param instance: Instance to be checked.
|
||||
:type instance: object
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
return (is_provider(instance) and
|
||||
hasattr(instance, '__IS_DELEGATED__') and
|
||||
getattr(instance, '__IS_DELEGATED__') is True)
|
||||
|
||||
|
||||
def is_injection(instance):
|
||||
"""Check if instance is injection instance.
|
||||
|
||||
|
|
|
@ -9,7 +9,9 @@ follows `Semantic versioning`_
|
|||
|
||||
Development version
|
||||
-------------------
|
||||
- No features.
|
||||
- Add ``DelegatedCallable`` provider.
|
||||
- Add ``DelegatedFactory`` provider.
|
||||
- Add ``DelegatedSingleton`` provider.
|
||||
|
||||
1.12.0
|
||||
------
|
||||
|
|
|
@ -16,12 +16,17 @@ arguments that are used as decorated callable injections. Every time, when
|
|||
would be passed as an callable arguments.
|
||||
|
||||
Such behaviour is very similar to the standard Python ``functools.partial``
|
||||
object, except of one thing: all injectable values are provided
|
||||
*"as is"*, except of providers (subclasses of :py:class:`Provider`). Providers
|
||||
will be called every time, when injection needs to be done. For example,
|
||||
if injectable value of injection is a :py:class:`Factory`, it will provide
|
||||
new one instance (as a result of its call) every time, when injection needs
|
||||
to be done.
|
||||
object with several more things:
|
||||
|
||||
+ All providers (instances of :py:class:`Provider`) are called every time
|
||||
when injection needs to be done.
|
||||
+ Providers could be injected "as is" (delegated), if it is defined obviously.
|
||||
Check out `Callable providers delegation`_.
|
||||
+ All other injectable values are provided *"as is"*
|
||||
|
||||
For example, if injectable value of injection is a :py:class:`Factory`, it
|
||||
will provide new one instance (as a result of its call) every time, when
|
||||
injection needs to be done.
|
||||
|
||||
:py:class:`Callable` behaviour with context positional and keyword arguments
|
||||
is very like a standard Python ``functools.partial``:
|
||||
|
@ -47,6 +52,8 @@ injections:
|
|||
.. literalinclude:: ../../examples/providers/callable_kwargs.py
|
||||
:language: python
|
||||
|
||||
.. _callable_delegation:
|
||||
|
||||
Callable providers delegation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -62,3 +69,12 @@ Example:
|
|||
|
||||
.. literalinclude:: ../../examples/providers/callable_delegation.py
|
||||
:language: python
|
||||
|
||||
Alternative way of doing :py:class:`Callable` delegation is an usage of
|
||||
:py:class:`DelegatedCallable`. :py:class:`DelegatedCallable` is a
|
||||
:py:class:`Callable` that is always injected "as is".
|
||||
|
||||
Example:
|
||||
|
||||
.. literalinclude:: ../../examples/providers/delegated_callable.py
|
||||
:language: python
|
||||
|
|
|
@ -24,12 +24,17 @@ that are used as ``__init__()`` injections. Every time, when
|
|||
argument injections would be passed as an instance's arguments.
|
||||
|
||||
Such behaviour is very similar to the standard Python ``functools.partial``
|
||||
object, except of one thing: all injectable values are provided
|
||||
*"as is"*, except of providers (subclasses of :py:class:`Provider`). Providers
|
||||
will be called every time, when injection needs to be done. For example,
|
||||
if injectable value of injection is a :py:class:`Factory`, it will provide
|
||||
new one instance (as a result of its call) every time, when injection needs
|
||||
to be done.
|
||||
object with several more things:
|
||||
|
||||
+ All providers (instances of :py:class:`Provider`) are called every time
|
||||
when injection needs to be done.
|
||||
+ Providers could be injected "as is" (delegated), if it is defined obviously.
|
||||
Check out `Factory providers delegation`_.
|
||||
+ All other injectable values are provided *"as is"*
|
||||
|
||||
For example, if injectable value of injection is a :py:class:`Factory`, it
|
||||
will provide new one instance (as a result of its call) every time, when
|
||||
injection needs to be done.
|
||||
|
||||
Example below is a little bit more complicated. It shows how to create
|
||||
:py:class:`Factory` of particular class with ``__init__()`` argument
|
||||
|
@ -175,6 +180,15 @@ Example:
|
|||
.. literalinclude:: ../../examples/providers/factory_delegation.py
|
||||
:language: python
|
||||
|
||||
Alternative way of doing :py:class:`Factory` delegation is an usage of
|
||||
:py:class:`DelegatedFactory`. :py:class:`DelegatedFactory` is a
|
||||
:py:class:`Factory` that is always injected "as is".
|
||||
|
||||
Example:
|
||||
|
||||
.. literalinclude:: ../../examples/providers/delegated_factory.py
|
||||
:language: python
|
||||
|
||||
Factory providers specialization
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -24,8 +24,8 @@ Providers module API docs - :py:mod:`dependency_injector.providers`
|
|||
|
||||
factory
|
||||
singleton
|
||||
static
|
||||
callable
|
||||
external_dependency
|
||||
static
|
||||
overriding
|
||||
custom
|
||||
|
|
|
@ -36,9 +36,10 @@ provider.
|
|||
during the first call). Be aware that such behaviour was made with opened
|
||||
eyes and is not a bug.
|
||||
|
||||
By the way, in such case, :py:class:`Delegate` provider can be useful. It
|
||||
makes possible to inject providers *as is*. Please check out full example
|
||||
in *Providers delegation* section.
|
||||
By the way, in such case, :py:class:`Delegate` or
|
||||
:py:class:`DelegatedSingleton` provider can be useful
|
||||
. It makes possible to inject providers *as is*. Please check out
|
||||
`Singleton providers delegation`_ section.
|
||||
|
||||
Singleton providers resetting
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -70,6 +71,15 @@ Example:
|
|||
.. literalinclude:: ../../examples/providers/singleton_delegation.py
|
||||
:language: python
|
||||
|
||||
Alternative way of doing :py:class:`Singleton` delegation is an usage of
|
||||
:py:class:`DelegatedSingleton`. :py:class:`DelegatedSingleton` is a
|
||||
:py:class:`Singleton` that is always injected "as is".
|
||||
|
||||
Example:
|
||||
|
||||
.. literalinclude:: ../../examples/providers/delegated_singleton.py
|
||||
:language: python
|
||||
|
||||
Singleton providers specialization
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
22
examples/providers/delegated_callable.py
Normal file
22
examples/providers/delegated_callable.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
"""`DelegatedCallable` providers example."""
|
||||
|
||||
from dependency_injector import providers
|
||||
|
||||
|
||||
def command1(config):
|
||||
"""Some example command."""
|
||||
return config['some_value'] * 5
|
||||
|
||||
|
||||
def command2(command1):
|
||||
"""Some example command."""
|
||||
return command1() / 2
|
||||
|
||||
# Creating callable providers for commands:
|
||||
command1_provider = providers.DelegatedCallable(command1,
|
||||
config={'some_value': 4})
|
||||
command2_provider = providers.DelegatedCallable(command2,
|
||||
command1=command1_provider)
|
||||
|
||||
# Making some asserts:
|
||||
assert command2_provider() == 10
|
46
examples/providers/delegated_factory.py
Normal file
46
examples/providers/delegated_factory.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
"""`DelegatedFactory` providers example."""
|
||||
|
||||
from dependency_injector import providers
|
||||
|
||||
|
||||
class User(object):
|
||||
"""Example class User."""
|
||||
|
||||
def __init__(self, photos_factory):
|
||||
"""Initializer.
|
||||
|
||||
:param photos_factory: providers.Factory -> Photo
|
||||
"""
|
||||
self.photos_factory = photos_factory
|
||||
self._main_photo = None
|
||||
super(User, self).__init__()
|
||||
|
||||
@property
|
||||
def main_photo(self):
|
||||
"""Return user's main photo."""
|
||||
if not self._main_photo:
|
||||
self._main_photo = self.photos_factory()
|
||||
return self._main_photo
|
||||
|
||||
|
||||
class Photo(object):
|
||||
"""Example class Photo."""
|
||||
|
||||
# User and Photo factories:
|
||||
photos_factory = providers.DelegatedFactory(Photo)
|
||||
users_factory = providers.DelegatedFactory(User,
|
||||
photos_factory=photos_factory)
|
||||
|
||||
# Creating several User objects:
|
||||
user1 = users_factory()
|
||||
user2 = users_factory()
|
||||
|
||||
# Making some asserts:
|
||||
assert isinstance(user1, User)
|
||||
assert isinstance(user1.main_photo, Photo)
|
||||
|
||||
assert isinstance(user2, User)
|
||||
assert isinstance(user2.main_photo, Photo)
|
||||
|
||||
assert user1 is not user2
|
||||
assert user1.main_photo is not user2.main_photo
|
18
examples/providers/delegated_singleton.py
Normal file
18
examples/providers/delegated_singleton.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
"""`DelegatedSingleton` providers example."""
|
||||
|
||||
from dependency_injector import providers
|
||||
|
||||
|
||||
# Some delegated singleton provider:
|
||||
singleton_provider = providers.DelegatedSingleton(object)
|
||||
registry = providers.DelegatedSingleton(dict,
|
||||
object1=singleton_provider,
|
||||
object2=singleton_provider)
|
||||
|
||||
# Getting several references to singleton object:
|
||||
registry = registry()
|
||||
singleton_object1 = registry['object1']()
|
||||
singleton_object2 = registry['object2']()
|
||||
|
||||
# Making some asserts:
|
||||
assert singleton_object1 is singleton_object2
|
|
@ -165,6 +165,136 @@ class DelegateTests(unittest.TestCase):
|
|||
hex(id(self.delegate))))
|
||||
|
||||
|
||||
class CallableTests(unittest.TestCase):
|
||||
"""Callable test cases."""
|
||||
|
||||
def example(self, arg1, arg2, arg3, arg4):
|
||||
"""Example callback."""
|
||||
return arg1, arg2, arg3, arg4
|
||||
|
||||
def test_init_with_callable(self):
|
||||
"""Test creation of provider with a callable."""
|
||||
self.assertTrue(providers.Callable(self.example))
|
||||
|
||||
def test_init_with_not_callable(self):
|
||||
"""Test creation of provider with not a callable."""
|
||||
self.assertRaises(errors.Error, providers.Callable, 123)
|
||||
|
||||
def test_call(self):
|
||||
"""Test call."""
|
||||
provider = providers.Callable(lambda: True)
|
||||
self.assertTrue(provider())
|
||||
|
||||
def test_call_with_positional_args(self):
|
||||
"""Test call with positional args.
|
||||
|
||||
New simplified syntax.
|
||||
"""
|
||||
provider = providers.Callable(self.example, 1, 2, 3, 4)
|
||||
self.assertTupleEqual(provider(), (1, 2, 3, 4))
|
||||
|
||||
def test_call_with_keyword_args(self):
|
||||
"""Test call with keyword args.
|
||||
|
||||
New simplified syntax.
|
||||
"""
|
||||
provider = providers.Callable(self.example,
|
||||
arg1=1,
|
||||
arg2=2,
|
||||
arg3=3,
|
||||
arg4=4)
|
||||
self.assertTupleEqual(provider(), (1, 2, 3, 4))
|
||||
|
||||
def test_call_with_positional_and_keyword_args(self):
|
||||
"""Test call with positional and keyword args.
|
||||
|
||||
Simplified syntax of positional and keyword arg injections.
|
||||
"""
|
||||
provider = providers.Callable(self.example, 1, 2, arg3=3, arg4=4)
|
||||
self.assertTupleEqual(provider(), (1, 2, 3, 4))
|
||||
|
||||
def test_call_with_positional_and_keyword_args_extended_syntax(self):
|
||||
"""Test call with positional and keyword args.
|
||||
|
||||
Extended syntax of positional and keyword arg injections.
|
||||
"""
|
||||
provider = providers.Callable(self.example,
|
||||
injections.Arg(1),
|
||||
injections.Arg(2),
|
||||
injections.KwArg('arg3', 3),
|
||||
injections.KwArg('arg4', 4))
|
||||
self.assertTupleEqual(provider(), (1, 2, 3, 4))
|
||||
|
||||
def test_call_with_context_args(self):
|
||||
"""Test call with context args."""
|
||||
provider = providers.Callable(self.example, 1, 2)
|
||||
self.assertTupleEqual(provider(3, 4), (1, 2, 3, 4))
|
||||
|
||||
def test_call_with_context_kwargs(self):
|
||||
"""Test call with context kwargs."""
|
||||
provider = providers.Callable(self.example,
|
||||
injections.KwArg('arg1', 1))
|
||||
self.assertTupleEqual(provider(arg2=2, arg3=3, arg4=4), (1, 2, 3, 4))
|
||||
|
||||
def test_call_with_context_args_and_kwargs(self):
|
||||
"""Test call with context args and kwargs."""
|
||||
provider = providers.Callable(self.example, 1)
|
||||
self.assertTupleEqual(provider(2, arg3=3, arg4=4), (1, 2, 3, 4))
|
||||
|
||||
def test_call_overridden(self):
|
||||
"""Test creation of new instances on overridden provider."""
|
||||
provider = providers.Callable(self.example)
|
||||
provider.override(providers.Value((4, 3, 2, 1)))
|
||||
provider.override(providers.Value((1, 2, 3, 4)))
|
||||
|
||||
self.assertTupleEqual(provider(), (1, 2, 3, 4))
|
||||
|
||||
def test_injections(self):
|
||||
"""Test getting a full list of injections using injections property."""
|
||||
provider = providers.Callable(self.example, 1, 2, arg3=3, arg4=4)
|
||||
self.assertEquals(len(provider.injections), 4)
|
||||
|
||||
def test_repr(self):
|
||||
"""Test representation of provider."""
|
||||
provider = providers.Callable(self.example,
|
||||
injections.KwArg(
|
||||
'arg1',
|
||||
providers.Factory(dict)),
|
||||
injections.KwArg(
|
||||
'arg2',
|
||||
providers.Factory(list)),
|
||||
injections.KwArg(
|
||||
'arg3',
|
||||
providers.Factory(set)),
|
||||
injections.KwArg(
|
||||
'arg4',
|
||||
providers.Factory(tuple)))
|
||||
self.assertEqual(repr(provider),
|
||||
'<dependency_injector.providers.'
|
||||
'Callable({0}) at {1}>'.format(
|
||||
repr(self.example),
|
||||
hex(id(provider))))
|
||||
|
||||
|
||||
class DelegatedCallableTests(unittest.TestCase):
|
||||
"""DelegatedCallable test cases."""
|
||||
|
||||
def test_inheritance(self):
|
||||
"""Test inheritance."""
|
||||
self.assertIsInstance(providers.DelegatedCallable(len),
|
||||
providers.Callable)
|
||||
|
||||
def test_is_provider(self):
|
||||
"""Test is_provider."""
|
||||
self.assertTrue(utils.is_provider(providers.DelegatedCallable(len)))
|
||||
|
||||
def test_is_delegated_provider(self):
|
||||
"""Test is_delegated_provider."""
|
||||
self.assertTrue(utils.is_delegated_provider(
|
||||
providers.DelegatedCallable(len)))
|
||||
self.assertFalse(utils.is_delegated_provider(providers.Callable(len)))
|
||||
|
||||
|
||||
class FactoryTests(unittest.TestCase):
|
||||
"""Factory test cases."""
|
||||
|
||||
|
@ -419,6 +549,26 @@ class FactoryTests(unittest.TestCase):
|
|||
hex(id(provider))))
|
||||
|
||||
|
||||
class DelegatedFactoryTests(unittest.TestCase):
|
||||
"""DelegatedFactory test cases."""
|
||||
|
||||
def test_inheritance(self):
|
||||
"""Test inheritance."""
|
||||
self.assertIsInstance(providers.DelegatedFactory(object),
|
||||
providers.Factory)
|
||||
|
||||
def test_is_provider(self):
|
||||
"""Test is_provider."""
|
||||
self.assertTrue(utils.is_provider(providers.DelegatedFactory(object)))
|
||||
|
||||
def test_is_delegated_provider(self):
|
||||
"""Test is_delegated_provider."""
|
||||
self.assertTrue(utils.is_delegated_provider(
|
||||
providers.DelegatedFactory(object)))
|
||||
self.assertFalse(utils.is_delegated_provider(
|
||||
providers.Factory(object)))
|
||||
|
||||
|
||||
class SingletonTests(unittest.TestCase):
|
||||
"""Singleton test cases."""
|
||||
|
||||
|
@ -719,115 +869,25 @@ class SingletonTests(unittest.TestCase):
|
|||
hex(id(provider))))
|
||||
|
||||
|
||||
class CallableTests(unittest.TestCase):
|
||||
"""Callable test cases."""
|
||||
class DelegatedSingletonTests(unittest.TestCase):
|
||||
"""DelegatedSingleton test cases."""
|
||||
|
||||
def example(self, arg1, arg2, arg3, arg4):
|
||||
"""Example callback."""
|
||||
return arg1, arg2, arg3, arg4
|
||||
def test_inheritance(self):
|
||||
"""Test inheritance."""
|
||||
self.assertIsInstance(providers.DelegatedSingleton(object),
|
||||
providers.Singleton)
|
||||
|
||||
def test_init_with_callable(self):
|
||||
"""Test creation of provider with a callable."""
|
||||
self.assertTrue(providers.Callable(self.example))
|
||||
def test_is_provider(self):
|
||||
"""Test is_provider."""
|
||||
self.assertTrue(utils.is_provider(
|
||||
providers.DelegatedSingleton(object)))
|
||||
|
||||
def test_init_with_not_callable(self):
|
||||
"""Test creation of provider with not a callable."""
|
||||
self.assertRaises(errors.Error, providers.Callable, 123)
|
||||
|
||||
def test_call(self):
|
||||
"""Test call."""
|
||||
provider = providers.Callable(lambda: True)
|
||||
self.assertTrue(provider())
|
||||
|
||||
def test_call_with_positional_args(self):
|
||||
"""Test call with positional args.
|
||||
|
||||
New simplified syntax.
|
||||
"""
|
||||
provider = providers.Callable(self.example, 1, 2, 3, 4)
|
||||
self.assertTupleEqual(provider(), (1, 2, 3, 4))
|
||||
|
||||
def test_call_with_keyword_args(self):
|
||||
"""Test call with keyword args.
|
||||
|
||||
New simplified syntax.
|
||||
"""
|
||||
provider = providers.Callable(self.example,
|
||||
arg1=1,
|
||||
arg2=2,
|
||||
arg3=3,
|
||||
arg4=4)
|
||||
self.assertTupleEqual(provider(), (1, 2, 3, 4))
|
||||
|
||||
def test_call_with_positional_and_keyword_args(self):
|
||||
"""Test call with positional and keyword args.
|
||||
|
||||
Simplified syntax of positional and keyword arg injections.
|
||||
"""
|
||||
provider = providers.Callable(self.example, 1, 2, arg3=3, arg4=4)
|
||||
self.assertTupleEqual(provider(), (1, 2, 3, 4))
|
||||
|
||||
def test_call_with_positional_and_keyword_args_extended_syntax(self):
|
||||
"""Test call with positional and keyword args.
|
||||
|
||||
Extended syntax of positional and keyword arg injections.
|
||||
"""
|
||||
provider = providers.Callable(self.example,
|
||||
injections.Arg(1),
|
||||
injections.Arg(2),
|
||||
injections.KwArg('arg3', 3),
|
||||
injections.KwArg('arg4', 4))
|
||||
self.assertTupleEqual(provider(), (1, 2, 3, 4))
|
||||
|
||||
def test_call_with_context_args(self):
|
||||
"""Test call with context args."""
|
||||
provider = providers.Callable(self.example, 1, 2)
|
||||
self.assertTupleEqual(provider(3, 4), (1, 2, 3, 4))
|
||||
|
||||
def test_call_with_context_kwargs(self):
|
||||
"""Test call with context kwargs."""
|
||||
provider = providers.Callable(self.example,
|
||||
injections.KwArg('arg1', 1))
|
||||
self.assertTupleEqual(provider(arg2=2, arg3=3, arg4=4), (1, 2, 3, 4))
|
||||
|
||||
def test_call_with_context_args_and_kwargs(self):
|
||||
"""Test call with context args and kwargs."""
|
||||
provider = providers.Callable(self.example, 1)
|
||||
self.assertTupleEqual(provider(2, arg3=3, arg4=4), (1, 2, 3, 4))
|
||||
|
||||
def test_call_overridden(self):
|
||||
"""Test creation of new instances on overridden provider."""
|
||||
provider = providers.Callable(self.example)
|
||||
provider.override(providers.Value((4, 3, 2, 1)))
|
||||
provider.override(providers.Value((1, 2, 3, 4)))
|
||||
|
||||
self.assertTupleEqual(provider(), (1, 2, 3, 4))
|
||||
|
||||
def test_injections(self):
|
||||
"""Test getting a full list of injections using injections property."""
|
||||
provider = providers.Callable(self.example, 1, 2, arg3=3, arg4=4)
|
||||
self.assertEquals(len(provider.injections), 4)
|
||||
|
||||
def test_repr(self):
|
||||
"""Test representation of provider."""
|
||||
provider = providers.Callable(self.example,
|
||||
injections.KwArg(
|
||||
'arg1',
|
||||
providers.Factory(dict)),
|
||||
injections.KwArg(
|
||||
'arg2',
|
||||
providers.Factory(list)),
|
||||
injections.KwArg(
|
||||
'arg3',
|
||||
providers.Factory(set)),
|
||||
injections.KwArg(
|
||||
'arg4',
|
||||
providers.Factory(tuple)))
|
||||
self.assertEqual(repr(provider),
|
||||
'<dependency_injector.providers.'
|
||||
'Callable({0}) at {1}>'.format(
|
||||
repr(self.example),
|
||||
hex(id(provider))))
|
||||
def test_is_delegated_provider(self):
|
||||
"""Test is_delegated_provider."""
|
||||
self.assertTrue(utils.is_delegated_provider(
|
||||
providers.DelegatedSingleton(object)))
|
||||
self.assertFalse(utils.is_delegated_provider(
|
||||
providers.Singleton(object)))
|
||||
|
||||
|
||||
class ExternalDependencyTests(unittest.TestCase):
|
||||
|
|
Loading…
Reference in New Issue
Block a user