mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-22 09:36:48 +03:00
235 Fix Delegate cannot be used in overridden container (#236)
* Add test for bug #235 * Fix issue + refactoring * Update changelog
This commit is contained in:
parent
fb264a8379
commit
08de710b2f
|
@ -7,6 +7,13 @@ that were made in every particular version.
|
||||||
From version 0.7.6 *Dependency Injector* framework strictly
|
From version 0.7.6 *Dependency Injector* framework strictly
|
||||||
follows `Semantic versioning`_
|
follows `Semantic versioning`_
|
||||||
|
|
||||||
|
Development version
|
||||||
|
-------------------
|
||||||
|
+ Fix ``3.14.11`` degradation issue causing inability of using ``Delegate`` provider in
|
||||||
|
``DeclarativeContainer`` when this container is instantiated with overriding of delegating
|
||||||
|
provider (thanks to `GitterRemote <https://github .com/GitterRemote>`_, issue details are
|
||||||
|
`here <https://github.com/ets-labs/python-dependency-injector/issues/235>`_).
|
||||||
|
|
||||||
3.14.11
|
3.14.11
|
||||||
-------
|
-------
|
||||||
+ Fix issue causing creation of a copy of provided object by ``Object`` provider when it was a
|
+ Fix issue causing creation of a copy of provided object by ``Object`` provider when it was a
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -21,8 +21,10 @@ cdef class Object(Provider):
|
||||||
cpdef object _provide(self, tuple args, dict kwargs)
|
cpdef object _provide(self, tuple args, dict kwargs)
|
||||||
|
|
||||||
|
|
||||||
cdef class Delegate(Object):
|
cdef class Delegate(Provider):
|
||||||
pass
|
cdef object __provides
|
||||||
|
|
||||||
|
cpdef object _provide(self, tuple args, dict kwargs)
|
||||||
|
|
||||||
|
|
||||||
cdef class Dependency(Provider):
|
cdef class Dependency(Provider):
|
||||||
|
|
|
@ -291,7 +291,7 @@ cdef class Object(Provider):
|
||||||
return self.__provides
|
return self.__provides
|
||||||
|
|
||||||
|
|
||||||
cdef class Delegate(Object):
|
cdef class Delegate(Provider):
|
||||||
"""Delegate provider returns provider "as is".
|
"""Delegate provider returns provider "as is".
|
||||||
|
|
||||||
.. py:attribute:: provides
|
.. py:attribute:: provides
|
||||||
|
@ -305,9 +305,49 @@ cdef class Delegate(Object):
|
||||||
"""Initializer.
|
"""Initializer.
|
||||||
|
|
||||||
:param provides: Value that have to be provided.
|
:param provides: Value that have to be provided.
|
||||||
:type provides: object
|
:type provides: :py:class:`Provider`
|
||||||
"""
|
"""
|
||||||
super(Delegate, self).__init__(ensure_is_provider(provides))
|
self.__provides = ensure_is_provider(provides)
|
||||||
|
super(Delegate, self).__init__()
|
||||||
|
|
||||||
|
def __deepcopy__(self, memo):
|
||||||
|
"""Create and return full copy of provider."""
|
||||||
|
copied = memo.get(id(self))
|
||||||
|
if copied is not None:
|
||||||
|
return copied
|
||||||
|
|
||||||
|
copied = self.__class__(deepcopy(self.__provides, memo))
|
||||||
|
|
||||||
|
self._copy_overridings(copied, memo)
|
||||||
|
|
||||||
|
return copied
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
"""Return string representation of provider.
|
||||||
|
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
return represent_provider(provider=self, provides=self.__provides)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
"""Return string representation of provider.
|
||||||
|
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
return self.__str__()
|
||||||
|
|
||||||
|
cpdef object _provide(self, tuple args, dict kwargs):
|
||||||
|
"""Return provided instance.
|
||||||
|
|
||||||
|
:param args: Tuple of context positional arguments.
|
||||||
|
:type args: tuple[object]
|
||||||
|
|
||||||
|
:param kwargs: Dictionary of context keyword arguments.
|
||||||
|
:type kwargs: dict[str, object]
|
||||||
|
|
||||||
|
:rtype: object
|
||||||
|
"""
|
||||||
|
return self.__provides
|
||||||
|
|
||||||
|
|
||||||
cdef class Dependency(Provider):
|
cdef class Dependency(Provider):
|
||||||
|
@ -834,7 +874,7 @@ cdef class CallableDelegate(Delegate):
|
||||||
if isinstance(callable, Callable) is False:
|
if isinstance(callable, Callable) is False:
|
||||||
raise Error('{0} can wrap only {1} providers'.format(
|
raise Error('{0} can wrap only {1} providers'.format(
|
||||||
self.__class__, Callable))
|
self.__class__, Callable))
|
||||||
super(Delegate, self).__init__(callable)
|
super(CallableDelegate, self).__init__(callable)
|
||||||
|
|
||||||
|
|
||||||
cdef class Coroutine(Callable):
|
cdef class Coroutine(Callable):
|
||||||
|
@ -1416,7 +1456,7 @@ cdef class FactoryDelegate(Delegate):
|
||||||
if isinstance(factory, Factory) is False:
|
if isinstance(factory, Factory) is False:
|
||||||
raise Error('{0} can wrap only {1} providers'.format(
|
raise Error('{0} can wrap only {1} providers'.format(
|
||||||
self.__class__, Factory))
|
self.__class__, Factory))
|
||||||
super(Delegate, self).__init__(factory)
|
super(FactoryDelegate, self).__init__(factory)
|
||||||
|
|
||||||
|
|
||||||
cdef class FactoryAggregate(Provider):
|
cdef class FactoryAggregate(Provider):
|
||||||
|
@ -1923,7 +1963,7 @@ cdef class SingletonDelegate(Delegate):
|
||||||
if isinstance(singleton, BaseSingleton) is False:
|
if isinstance(singleton, BaseSingleton) is False:
|
||||||
raise Error('{0} can wrap only {1} providers'.format(
|
raise Error('{0} can wrap only {1} providers'.format(
|
||||||
self.__class__, BaseSingleton))
|
self.__class__, BaseSingleton))
|
||||||
super(Delegate, self).__init__(singleton)
|
super(SingletonDelegate, self).__init__(singleton)
|
||||||
|
|
||||||
|
|
||||||
cdef class Injection(object):
|
cdef class Injection(object):
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
"""Dependency injector declarative container unit tests."""
|
"""Dependency injector declarative container unit tests."""
|
||||||
|
|
||||||
|
import collections
|
||||||
import unittest2 as unittest
|
import unittest2 as unittest
|
||||||
|
|
||||||
from dependency_injector import (
|
from dependency_injector import (
|
||||||
|
@ -313,3 +314,19 @@ class DeclarativeContainerTests(unittest.TestCase):
|
||||||
self.assertIs(container.p2.cls, container.p1)
|
self.assertIs(container.p2.cls, container.p1)
|
||||||
self.assertIs(_Container.p2.cls, _Container.p1)
|
self.assertIs(_Container.p2.cls, _Container.p1)
|
||||||
self.assertIsNot(container.p2.cls, _Container.p1)
|
self.assertIsNot(container.p2.cls, _Container.p1)
|
||||||
|
|
||||||
|
def test_init_with_dependency_delegation(self):
|
||||||
|
# Bug:
|
||||||
|
# https://github.com/ets-labs/python-dependency-injector/issues/235
|
||||||
|
A = collections.namedtuple('A', [])
|
||||||
|
B = collections.namedtuple('B', ['fa'])
|
||||||
|
C = collections.namedtuple('B', ['a'])
|
||||||
|
|
||||||
|
class Services(containers.DeclarativeContainer):
|
||||||
|
a = providers.Dependency()
|
||||||
|
c = providers.Factory(C, a=a)
|
||||||
|
b = providers.Factory(B, fa=a.delegate())
|
||||||
|
|
||||||
|
a = providers.Factory(A)
|
||||||
|
assert isinstance(Services(a=a).c().a, A) # ok
|
||||||
|
Services(a=a).b().fa()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user