mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-29 04:53:59 +03:00
Merge branch 'release/3.31.0' into master
This commit is contained in:
commit
69ebc19b5f
|
@ -12,3 +12,4 @@ Dependency Injector Contributors
|
|||
+ supakeen (supakeen)
|
||||
+ Bruno P. Kinoshita (kinow)
|
||||
+ RobinsonMa (RobinsonMa)
|
||||
+ Rüdiger Busche (JarnoRFB)
|
||||
|
|
|
@ -7,6 +7,13 @@ that were made in every particular version.
|
|||
From version 0.7.6 *Dependency Injector* framework strictly
|
||||
follows `Semantic versioning`_
|
||||
|
||||
3.31.0
|
||||
------
|
||||
- Add a feature that helps to inject provided instance attribute, item, or method call result
|
||||
(see `Issue 281 <https://github.com/ets-labs/python-dependency-injector/issues/281>`_). Design
|
||||
for this feature was provided by `JarnoRFB <https://github.com/JarnoRFB>`_. Many thanks to you,
|
||||
JarnoRFB.
|
||||
|
||||
3.30.4
|
||||
------
|
||||
- Update README.
|
||||
|
|
|
@ -29,4 +29,5 @@ Providers package API docs - :py:mod:`dependency_injector.providers`
|
|||
selector
|
||||
dependency
|
||||
overriding
|
||||
provided_instance
|
||||
custom
|
||||
|
|
64
docs/providers/provided_instance.rst
Normal file
64
docs/providers/provided_instance.rst
Normal file
|
@ -0,0 +1,64 @@
|
|||
Injecting attributes, items, or call methods of the provided instance
|
||||
---------------------------------------------------------------------
|
||||
|
||||
.. currentmodule:: dependency_injector.providers
|
||||
|
||||
In this section you will know how to inject provided instance attribute or item into the other
|
||||
provider.
|
||||
|
||||
It also describes how to call a method of the provided instance and use the result of
|
||||
this call as an injection value.
|
||||
|
||||
.. literalinclude:: ../../examples/providers/provided_instance.py
|
||||
:language: python
|
||||
:emphasize-lines: 26-32
|
||||
:lines: 3-
|
||||
|
||||
To use the feature you should use the ``.provided`` attribute of the injected provider. This
|
||||
attribute helps to specify what happens with the provided instance. You can retrieve an injection
|
||||
value from:
|
||||
|
||||
- an attribute of the provided instance
|
||||
- an item of the provided instance
|
||||
- a call of the provided instance method
|
||||
|
||||
When you use the call of the provided instance method you can specify the injections into this
|
||||
method like you do with any other provider.
|
||||
|
||||
You can do nested constructions:
|
||||
|
||||
.. literalinclude:: ../../examples/providers/provided_instance_complex.py
|
||||
:language: python
|
||||
:emphasize-lines: 24-30
|
||||
:lines: 3-
|
||||
|
||||
Attribute ``.provided`` is available for the providers that return instances. Providers that
|
||||
have ``.provided`` attribute:
|
||||
|
||||
- :py:class:`Callable` and its subclasses
|
||||
- :py:class:`Factory` and its subclasses
|
||||
- :py:class:`Singleton` and its subclasses
|
||||
- :py:class:`Object`
|
||||
- :py:class:`List`
|
||||
- :py:class:`Selector`
|
||||
- :py:class:`Dependency`
|
||||
|
||||
Special providers like :py:class:`Configuration` or :py:class:`Delegate` do not have the
|
||||
``.provided`` attribute.
|
||||
|
||||
Provider subclasses
|
||||
-------------------
|
||||
|
||||
When you create a new provider subclass and want to implement the ``.provided`` attribute, you
|
||||
should use the :py:class:`ProvidedInstance` provider.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@property
|
||||
def provided(self):
|
||||
"""Return :py:class:`ProvidedInstance` provider."""
|
||||
return ProvidedInstance(self)
|
||||
|
||||
In all other cases you should not use :py:class:`ProvidedInstance`, :py:class:`AttributeGetter`,
|
||||
:py:class:`ItemGetter`, or :py:class:`MethodCaller` providers directly. Use the ``.provided``
|
||||
attribute of the injected provider instead.
|
38
examples/providers/provided_instance.py
Normal file
38
examples/providers/provided_instance.py
Normal file
|
@ -0,0 +1,38 @@
|
|||
"""Example of the injecting of provided instance attributes and items."""
|
||||
|
||||
from dependency_injector import providers
|
||||
|
||||
|
||||
class Service:
|
||||
def __init__(self):
|
||||
self.value = 'foo'
|
||||
self.values = [self.value]
|
||||
|
||||
def get_value(self):
|
||||
return self.value
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self.values[item]
|
||||
|
||||
|
||||
class Client:
|
||||
def __init__(self, value1, value2, value3, value4):
|
||||
self.value1 = value1
|
||||
self.value2 = value2
|
||||
self.value3 = value3
|
||||
self.value4 = value4
|
||||
|
||||
|
||||
service = providers.Singleton(Service)
|
||||
|
||||
client_factory = providers.Factory(
|
||||
Client,
|
||||
value1=service.provided[0],
|
||||
value2=service.provided.value,
|
||||
value3=service.provided.values[0],
|
||||
value4=service.provided.get_value.call(),
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
client = client_factory()
|
||||
assert client.value1 == client.value2 == client.value3 == 'foo'
|
41
examples/providers/provided_instance_complex.py
Normal file
41
examples/providers/provided_instance_complex.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
"""Complex example of the injecting of provided instance attributes and items."""
|
||||
|
||||
from dependency_injector import providers
|
||||
|
||||
|
||||
class Service:
|
||||
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def get_value(self):
|
||||
return self.value
|
||||
|
||||
|
||||
service = providers.Singleton(Service, value=42)
|
||||
|
||||
dependency = providers.Object(
|
||||
{
|
||||
'foo': {
|
||||
'bar': 10,
|
||||
'baz': lambda arg: {'arg': arg}
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
demo_list = providers.List(
|
||||
dependency.provided['foo']['bar'],
|
||||
dependency.provided['foo']['baz'].call(22)['arg'],
|
||||
dependency.provided['foo']['baz'].call(service)['arg'],
|
||||
dependency.provided['foo']['baz'].call(service)['arg'].value,
|
||||
dependency.provided['foo']['baz'].call(service)['arg'].get_value.call(),
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
assert demo_list() == [
|
||||
10,
|
||||
22,
|
||||
service(),
|
||||
42,
|
||||
42,
|
||||
]
|
|
@ -1,6 +1,6 @@
|
|||
"""Dependency injector top-level package."""
|
||||
|
||||
__version__ = '3.30.4'
|
||||
__version__ = '3.31.0'
|
||||
"""Version number that follows semantic versioning.
|
||||
|
||||
:type: str
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -197,6 +197,37 @@ cdef class Selector(Provider):
|
|||
|
||||
cpdef object _provide(self, tuple args, dict kwargs)
|
||||
|
||||
# Provided instance
|
||||
|
||||
cdef class ProvidedInstance(Provider):
|
||||
cdef Provider __provider
|
||||
|
||||
cpdef object _provide(self, tuple args, dict kwargs)
|
||||
|
||||
|
||||
cdef class AttributeGetter(Provider):
|
||||
cdef Provider __provider
|
||||
cdef object __attribute
|
||||
|
||||
cpdef object _provide(self, tuple args, dict kwargs)
|
||||
|
||||
|
||||
cdef class ItemGetter(Provider):
|
||||
cdef Provider __provider
|
||||
cdef object __item
|
||||
|
||||
cpdef object _provide(self, tuple args, dict kwargs)
|
||||
|
||||
|
||||
cdef class MethodCaller(Provider):
|
||||
cdef Provider __provider
|
||||
cdef tuple __args
|
||||
cdef int __args_len
|
||||
cdef tuple __kwargs
|
||||
cdef int __kwargs_len
|
||||
|
||||
cpdef object _provide(self, tuple args, dict kwargs)
|
||||
|
||||
|
||||
# Injections
|
||||
cdef class Injection(object):
|
||||
|
@ -352,18 +383,42 @@ cdef inline object __inject_attributes(
|
|||
__get_value(attr_injection))
|
||||
|
||||
|
||||
cdef inline object __callable_call(Callable self, tuple args, dict kwargs):
|
||||
cdef inline object __call(
|
||||
object call,
|
||||
tuple context_args,
|
||||
tuple injection_args,
|
||||
int injection_args_len,
|
||||
dict kwargs,
|
||||
tuple injection_kwargs,
|
||||
int injection_kwargs_len,
|
||||
):
|
||||
cdef tuple positional_args
|
||||
cdef dict keyword_args
|
||||
|
||||
positional_args = __provide_positional_args(args,
|
||||
self.__args,
|
||||
self.__args_len)
|
||||
keyword_args = __provide_keyword_args(kwargs,
|
||||
self.__kwargs,
|
||||
self.__kwargs_len)
|
||||
positional_args = __provide_positional_args(
|
||||
context_args,
|
||||
injection_args,
|
||||
injection_args_len,
|
||||
)
|
||||
keyword_args = __provide_keyword_args(
|
||||
kwargs,
|
||||
injection_kwargs,
|
||||
injection_kwargs_len,
|
||||
)
|
||||
|
||||
return self.__provides(*positional_args, **keyword_args)
|
||||
return call(*positional_args, **keyword_args)
|
||||
|
||||
|
||||
cdef inline object __callable_call(Callable self, tuple args, dict kwargs):
|
||||
return __call(
|
||||
self.__provides,
|
||||
args,
|
||||
self.__args,
|
||||
self.__args_len,
|
||||
kwargs,
|
||||
self.__kwargs,
|
||||
self.__kwargs_len,
|
||||
)
|
||||
|
||||
|
||||
cdef inline object __factory_call(Factory self, tuple args, dict kwargs):
|
||||
|
|
|
@ -324,6 +324,11 @@ cdef class Object(Provider):
|
|||
"""
|
||||
return self.__str__()
|
||||
|
||||
@property
|
||||
def provided(self):
|
||||
"""Return :py:class:`ProvidedInstance` provider."""
|
||||
return ProvidedInstance(self)
|
||||
|
||||
cpdef object _provide(self, tuple args, dict kwargs):
|
||||
"""Return provided instance.
|
||||
|
||||
|
@ -479,6 +484,11 @@ cdef class Dependency(Provider):
|
|||
"""
|
||||
return self.__str__()
|
||||
|
||||
@property
|
||||
def provided(self):
|
||||
"""Return :py:class:`ProvidedInstance` provider."""
|
||||
return ProvidedInstance(self)
|
||||
|
||||
@property
|
||||
def instance_of(self):
|
||||
"""Return class of required dependency."""
|
||||
|
@ -769,6 +779,11 @@ cdef class Callable(Provider):
|
|||
"""Return wrapped callable."""
|
||||
return self.__provides
|
||||
|
||||
@property
|
||||
def provided(self):
|
||||
"""Return :py:class:`ProvidedInstance` provider."""
|
||||
return ProvidedInstance(self)
|
||||
|
||||
@property
|
||||
def args(self):
|
||||
"""Return positional argument injections."""
|
||||
|
@ -1599,6 +1614,11 @@ cdef class Factory(Provider):
|
|||
"""Return provided type."""
|
||||
return self.__instantiator.provides
|
||||
|
||||
@property
|
||||
def provided(self):
|
||||
"""Return :py:class:`ProvidedInstance` provider."""
|
||||
return ProvidedInstance(self)
|
||||
|
||||
@property
|
||||
def args(self):
|
||||
"""Return positional argument injections."""
|
||||
|
@ -1932,6 +1952,11 @@ cdef class BaseSingleton(Provider):
|
|||
"""Return provided type."""
|
||||
return self.__instantiator.cls
|
||||
|
||||
@property
|
||||
def provided(self):
|
||||
"""Return :py:class:`ProvidedInstance` provider."""
|
||||
return ProvidedInstance(self)
|
||||
|
||||
@property
|
||||
def args(self):
|
||||
"""Return positional argument injections."""
|
||||
|
@ -2360,6 +2385,11 @@ cdef class List(Provider):
|
|||
"""
|
||||
return represent_provider(provider=self, provides=list(self.args))
|
||||
|
||||
@property
|
||||
def provided(self):
|
||||
"""Return :py:class:`ProvidedInstance` provider."""
|
||||
return ProvidedInstance(self)
|
||||
|
||||
@property
|
||||
def args(self):
|
||||
"""Return positional argument injections."""
|
||||
|
@ -2537,6 +2567,11 @@ cdef class Selector(Provider):
|
|||
address=hex(id(self)),
|
||||
)
|
||||
|
||||
@property
|
||||
def provided(self):
|
||||
"""Return :py:class:`ProvidedInstance` provider."""
|
||||
return ProvidedInstance(self)
|
||||
|
||||
@property
|
||||
def providers(self):
|
||||
"""Return providers."""
|
||||
|
@ -2555,6 +2590,207 @@ cdef class Selector(Provider):
|
|||
return self.__providers[selector_value](*args, **kwargs)
|
||||
|
||||
|
||||
cdef class ProvidedInstance(Provider):
|
||||
"""Provider that helps to inject attributes and items of the injected instance.
|
||||
|
||||
You can use it like that:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
service = providers.Singleton(Service)
|
||||
|
||||
client_factory = providers.Factory(
|
||||
Client,
|
||||
value1=service.provided[0],
|
||||
value2=service.provided.value,
|
||||
value3=service.provided.values[0],
|
||||
value4=service.provided.get_value.call(),
|
||||
)
|
||||
|
||||
You should not create this provider directly. Get it from the ``.provided`` attribute of the
|
||||
injected provider. This attribute returns the :py:class:`ProvidedInstance` for that provider.
|
||||
|
||||
Providers that have ``.provided`` attribute:
|
||||
|
||||
- :py:class:`Callable` and its subclasses
|
||||
- :py:class:`Factory` and its subclasses
|
||||
- :py:class:`Singleton` and its subclasses
|
||||
- :py:class:`Object`
|
||||
- :py:class:`List`
|
||||
- :py:class:`Selector`
|
||||
- :py:class:`Dependency`
|
||||
"""
|
||||
|
||||
def __init__(self, provider):
|
||||
self.__provider = provider
|
||||
super().__init__()
|
||||
|
||||
def __repr__(self):
|
||||
return f'{self.__class__.__name__}(\'{self.__provider}\')'
|
||||
|
||||
def __deepcopy__(self, memo=None):
|
||||
cdef ProvidedInstance copied
|
||||
|
||||
copied = memo.get(id(self))
|
||||
if copied is not None:
|
||||
return copied
|
||||
|
||||
return self.__class__(
|
||||
deepcopy(self.__provider, memo),
|
||||
)
|
||||
|
||||
def __getattr__(self, item):
|
||||
return AttributeGetter(self, item)
|
||||
|
||||
def __getitem__(self, item):
|
||||
return ItemGetter(self, item)
|
||||
|
||||
def call(self, *args, **kwargs):
|
||||
return MethodCaller(self, *args, **kwargs)
|
||||
|
||||
cpdef object _provide(self, tuple args, dict kwargs):
|
||||
return self.__provider(*args, **kwargs)
|
||||
|
||||
|
||||
cdef class AttributeGetter(Provider):
|
||||
"""Provider that returns the attribute of the injected instance.
|
||||
|
||||
You should not create this provider directly. See :py:class:`ProvidedInstance` instead.
|
||||
"""
|
||||
|
||||
def __init__(self, provider, attribute):
|
||||
self.__provider = provider
|
||||
self.__attribute = attribute
|
||||
super().__init__()
|
||||
|
||||
def __repr__(self):
|
||||
return f'{self.__class__.__name__}(\'{self.__attribute}\')'
|
||||
|
||||
def __deepcopy__(self, memo=None):
|
||||
cdef AttributeGetter copied
|
||||
|
||||
copied = memo.get(id(self))
|
||||
if copied is not None:
|
||||
return copied
|
||||
|
||||
return self.__class__(
|
||||
deepcopy(self.__provider, memo),
|
||||
self.__attribute,
|
||||
)
|
||||
|
||||
def __getattr__(self, item):
|
||||
return AttributeGetter(self, item)
|
||||
|
||||
def __getitem__(self, item):
|
||||
return ItemGetter(self, item)
|
||||
|
||||
def call(self, *args, **kwargs):
|
||||
return MethodCaller(self, *args, **kwargs)
|
||||
|
||||
cpdef object _provide(self, tuple args, dict kwargs):
|
||||
provided = self.__provider(*args, **kwargs)
|
||||
return getattr(provided, self.__attribute)
|
||||
|
||||
|
||||
cdef class ItemGetter(Provider):
|
||||
"""Provider that returns the item of the injected instance.
|
||||
|
||||
You should not create this provider directly. See :py:class:`ProvidedInstance` instead.
|
||||
"""
|
||||
|
||||
def __init__(self, Provider provider, object item):
|
||||
self.__provider = provider
|
||||
self.__item = item
|
||||
super().__init__()
|
||||
|
||||
def __repr__(self):
|
||||
return f'{self.__class__.__name__}(\'{self.__item}\')'
|
||||
|
||||
def __deepcopy__(self, memo=None):
|
||||
cdef ItemGetter copied
|
||||
|
||||
copied = memo.get(id(self))
|
||||
if copied is not None:
|
||||
return copied
|
||||
|
||||
return self.__class__(
|
||||
deepcopy(self.__provider, memo),
|
||||
self.__item,
|
||||
)
|
||||
|
||||
def __getattr__(self, item):
|
||||
return AttributeGetter(self, item)
|
||||
|
||||
def __getitem__(self, item):
|
||||
return ItemGetter(self, item)
|
||||
|
||||
def call(self, *args, **kwargs):
|
||||
return MethodCaller(self, *args, **kwargs)
|
||||
|
||||
cpdef object _provide(self, tuple args, dict kwargs):
|
||||
provided = self.__provider(*args, **kwargs)
|
||||
return provided[self.__item]
|
||||
|
||||
|
||||
cdef class MethodCaller(Provider):
|
||||
"""Provider that calls the method of the injected instance.
|
||||
|
||||
You should not create this provider directly. See :py:class:`ProvidedInstance` instead.
|
||||
"""
|
||||
|
||||
def __init__(self, provider, *args, **kwargs):
|
||||
self.__provider = provider
|
||||
|
||||
self.__args = parse_positional_injections(args)
|
||||
self.__args_len = len(self.__args)
|
||||
|
||||
self.__kwargs = parse_named_injections(kwargs)
|
||||
self.__kwargs_len = len(self.__kwargs)
|
||||
|
||||
super().__init__()
|
||||
|
||||
def __repr__(self):
|
||||
return f'{self.__class__.__name__}({self.__provider})'
|
||||
|
||||
def __deepcopy__(self, memo=None):
|
||||
cdef MethodCaller copied
|
||||
|
||||
copied = memo.get(id(self))
|
||||
if copied is not None:
|
||||
return copied
|
||||
|
||||
copied = self.__class__(deepcopy(self.__provider, memo))
|
||||
copied.__args = deepcopy(self.__args, memo)
|
||||
copied.__args_len = self.__args_len
|
||||
copied.__kwargs = deepcopy(self.__kwargs, memo)
|
||||
copied.__kwargs_len = self.__kwargs_len
|
||||
|
||||
self._copy_overridings(copied, memo)
|
||||
|
||||
return copied
|
||||
|
||||
def __getattr__(self, item):
|
||||
return AttributeGetter(self, item)
|
||||
|
||||
def __getitem__(self, item):
|
||||
return ItemGetter(self, item)
|
||||
|
||||
def call(self, *args, **kwargs):
|
||||
return MethodCaller(self, *args, **kwargs)
|
||||
|
||||
cpdef object _provide(self, tuple args, dict kwargs):
|
||||
call = self.__provider()
|
||||
return __call(
|
||||
call,
|
||||
args,
|
||||
self.__args,
|
||||
self.__args_len,
|
||||
kwargs,
|
||||
self.__kwargs,
|
||||
self.__kwargs_len,
|
||||
)
|
||||
|
||||
|
||||
cdef class Injection(object):
|
||||
"""Abstract injection class."""
|
||||
|
||||
|
|
|
@ -150,6 +150,10 @@ class ObjectProviderTests(unittest.TestCase):
|
|||
def test_is_provider(self):
|
||||
self.assertTrue(providers.is_provider(providers.Object(object())))
|
||||
|
||||
def test_provided_instance_provider(self):
|
||||
provider = providers.Object(object())
|
||||
self.assertIsInstance(provider.provided, providers.ProvidedInstance)
|
||||
|
||||
def test_call_object_provider(self):
|
||||
obj = object()
|
||||
self.assertIs(providers.Object(obj)(), obj)
|
||||
|
@ -264,6 +268,9 @@ class DependencyTests(unittest.TestCase):
|
|||
def test_is_provider(self):
|
||||
self.assertTrue(providers.is_provider(self.provider))
|
||||
|
||||
def test_provided_instance_provider(self):
|
||||
self.assertIsInstance(self.provider.provided, providers.ProvidedInstance)
|
||||
|
||||
def test_call_overridden(self):
|
||||
self.provider.provided_by(providers.Factory(list))
|
||||
self.assertIsInstance(self.provider(), list)
|
||||
|
|
|
@ -22,6 +22,10 @@ class CallableTests(unittest.TestCase):
|
|||
def test_init_with_not_callable(self):
|
||||
self.assertRaises(errors.Error, providers.Callable, 123)
|
||||
|
||||
def test_provided_instance_provider(self):
|
||||
provider = providers.Callable(_example)
|
||||
self.assertIsInstance(provider.provided, providers.ProvidedInstance)
|
||||
|
||||
def test_call(self):
|
||||
provider = providers.Callable(lambda: True)
|
||||
self.assertTrue(provider())
|
||||
|
|
|
@ -60,6 +60,10 @@ class FactoryTests(unittest.TestCase):
|
|||
with self.assertRaises(errors.Error):
|
||||
ExampleProvider(list)
|
||||
|
||||
def test_provided_instance_provider(self):
|
||||
provider = providers.Factory(Example)
|
||||
self.assertIsInstance(provider.provided, providers.ProvidedInstance)
|
||||
|
||||
def test_call(self):
|
||||
provider = providers.Factory(Example)
|
||||
|
||||
|
|
|
@ -12,6 +12,10 @@ class ListTests(unittest.TestCase):
|
|||
def test_is_provider(self):
|
||||
self.assertTrue(providers.is_provider(providers.List()))
|
||||
|
||||
def test_provided_instance_provider(self):
|
||||
provider = providers.List()
|
||||
self.assertIsInstance(provider.provided, providers.ProvidedInstance)
|
||||
|
||||
def test_call_with_init_positional_args(self):
|
||||
provider = providers.List('i1', 'i2')
|
||||
|
||||
|
|
139
tests/unit/providers/test_provided_instance_py2_py3.py
Normal file
139
tests/unit/providers/test_provided_instance_py2_py3.py
Normal file
|
@ -0,0 +1,139 @@
|
|||
"""Dependency injector provided instance provider unit tests."""
|
||||
|
||||
import unittest2 as unittest
|
||||
|
||||
from dependency_injector import containers, providers
|
||||
|
||||
|
||||
class Service:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
self.values = [self.value]
|
||||
|
||||
def get_value(self):
|
||||
return self.value
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self.values[item]
|
||||
|
||||
|
||||
class Client:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
|
||||
class Container(containers.DeclarativeContainer):
|
||||
|
||||
service = providers.Singleton(Service, value='foo')
|
||||
|
||||
client_attribute = providers.Factory(
|
||||
Client,
|
||||
value=service.provided.value,
|
||||
)
|
||||
|
||||
client_item = providers.Factory(
|
||||
Client,
|
||||
value=service.provided[0],
|
||||
)
|
||||
|
||||
client_attribute_item = providers.Factory(
|
||||
Client,
|
||||
value=service.provided.values[0],
|
||||
)
|
||||
|
||||
client_method_call = providers.Factory(
|
||||
Client,
|
||||
value=service.provided.get_value.call(),
|
||||
)
|
||||
|
||||
|
||||
class ProvidedInstanceTests(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.container = Container()
|
||||
|
||||
def test_is_provider(self):
|
||||
self.assertTrue(providers.is_provider(self.container.service.provided))
|
||||
|
||||
def test_attribute(self):
|
||||
client = self.container.client_attribute()
|
||||
self.assertEqual(client.value, 'foo')
|
||||
|
||||
def test_item(self):
|
||||
client = self.container.client_item()
|
||||
self.assertEqual(client.value, 'foo')
|
||||
|
||||
def test_attribute_item(self):
|
||||
client = self.container.client_attribute_item()
|
||||
self.assertEqual(client.value, 'foo')
|
||||
|
||||
def test_method_call(self):
|
||||
client = self.container.client_method_call()
|
||||
self.assertEqual(client.value, 'foo')
|
||||
|
||||
def test_call_overridden(self):
|
||||
value = 'bar'
|
||||
with self.container.service.override(Service(value)):
|
||||
self.assertEqual(self.container.client_attribute().value, value)
|
||||
self.assertEqual(self.container.client_item().value, value)
|
||||
self.assertEqual(self.container.client_attribute_item().value, value)
|
||||
self.assertEqual(self.container.client_method_call().value, value)
|
||||
|
||||
def test_repr_provided_instance(self):
|
||||
provider = self.container.service.provided
|
||||
self.assertEqual(
|
||||
'ProvidedInstance(\'{0}\')'.format(repr(self.container.service)),
|
||||
repr(provider),
|
||||
)
|
||||
|
||||
def test_repr_attribute_getter(self):
|
||||
provider = self.container.service.provided.value
|
||||
self.assertEqual(
|
||||
'AttributeGetter(\'value\')',
|
||||
repr(provider),
|
||||
)
|
||||
|
||||
def test_repr_item_getter(self):
|
||||
provider = self.container.service.provided['test-test']
|
||||
self.assertEqual(
|
||||
'ItemGetter(\'test-test\')',
|
||||
repr(provider),
|
||||
)
|
||||
|
||||
|
||||
class ProvidedInstancePuzzleTests(unittest.TestCase):
|
||||
|
||||
def test_puzzled(self):
|
||||
service = providers.Singleton(Service, value='foo-bar')
|
||||
|
||||
dependency = providers.Object(
|
||||
{
|
||||
'a': {
|
||||
'b': {
|
||||
'c1': 10,
|
||||
'c2': lambda arg: {'arg': arg}
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
test_list = providers.List(
|
||||
dependency.provided['a']['b']['c1'],
|
||||
dependency.provided['a']['b']['c2'].call(22)['arg'],
|
||||
dependency.provided['a']['b']['c2'].call(service)['arg'],
|
||||
dependency.provided['a']['b']['c2'].call(service)['arg'].value,
|
||||
dependency.provided['a']['b']['c2'].call(service)['arg'].get_value.call(),
|
||||
)
|
||||
|
||||
result = test_list()
|
||||
|
||||
self.assertEqual(
|
||||
result,
|
||||
[
|
||||
10,
|
||||
22,
|
||||
service(),
|
||||
'foo-bar',
|
||||
'foo-bar',
|
||||
],
|
||||
)
|
|
@ -16,6 +16,10 @@ class SelectorTests(unittest.TestCase):
|
|||
def test_is_provider(self):
|
||||
self.assertTrue(providers.is_provider(providers.Selector(self.selector)))
|
||||
|
||||
def test_provided_instance_provider(self):
|
||||
provider = providers.Selector(self.selector)
|
||||
self.assertIsInstance(provider.provided, providers.ProvidedInstance)
|
||||
|
||||
def test_call(self):
|
||||
provider = providers.Selector(
|
||||
self.selector,
|
||||
|
|
|
@ -62,6 +62,10 @@ class _BaseSingletonTestCase(object):
|
|||
with self.assertRaises(errors.Error):
|
||||
ExampleProvider(list)
|
||||
|
||||
def test_provided_instance_provider(self):
|
||||
provider = providers.Singleton(Example)
|
||||
self.assertIsInstance(provider.provided, providers.ProvidedInstance)
|
||||
|
||||
def test_call(self):
|
||||
provider = self.singleton_cls(Example)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user