Add attributes forwarding for the `Dependency` provider

This commit is contained in:
Roman Mogylatov 2021-02-18 17:49:23 -05:00
parent c0d1e48f7b
commit 990fd3a554
5 changed files with 5875 additions and 5662 deletions

View File

@ -14646,7 +14646,7 @@ static PyObject *__pyx_pf_19dependency_injector_10containers_4override(CYTHON_UN
/* Python wrapper */
static PyObject *__pyx_pw_19dependency_injector_10containers_7copy(PyObject *__pyx_self, PyObject *__pyx_v_container); /*proto*/
static char __pyx_doc_19dependency_injector_10containers_6copy[] = ":py:class:`DeclarativeContainer` copying decorator.\n\n This decorator copy all providers from provided container to decorated one.\n If one of the decorated container providers matches to source container\n providers by name, it would be replaced by reference.\n\n :param container: Container that should be copied by decorated container.\n :type container: :py:class:`DeclarativeContainer`\n\n :return: Declarative container's copying decorator.\n :rtype: callable(:py:class:`DeclarativeContainer`)\n ";
static char __pyx_doc_19dependency_injector_10containers_6copy[] = ":py:class:`DeclarativeContainer` copying decorator.\n\n This decorator copies all providers from provided container to decorated one.\n If one of the decorated container providers matches to source container\n providers by name, it would be replaced by reference.\n\n :param container: Container that should be copied by decorated container.\n :type container: :py:class:`DeclarativeContainer`\n\n :return: Declarative container's copying decorator.\n :rtype: callable(:py:class:`DeclarativeContainer`)\n ";
static PyMethodDef __pyx_mdef_19dependency_injector_10containers_7copy = {"copy", (PyCFunction)__pyx_pw_19dependency_injector_10containers_7copy, METH_O, __pyx_doc_19dependency_injector_10containers_6copy};
static PyObject *__pyx_pw_19dependency_injector_10containers_7copy(PyObject *__pyx_self, PyObject *__pyx_v_container) {
PyObject *__pyx_r = 0;

File diff suppressed because it is too large Load Diff

View File

@ -102,6 +102,7 @@ class Delegate(Provider[Provider]):
class Dependency(Provider[T]):
def __init__(self, instance_of: Type[T] = object, default: Optional[Union[Provider, Any]] = None) -> None: ...
def __getattr__(self, name: str) -> Any: ...
@property
def instance_of(self) -> Type[T]: ...
@property

View File

@ -680,6 +680,13 @@ cdef class Dependency(Provider):
self._check_instance_type(result)
return result
def __getattr__(self, name):
if self.__last_overriding:
return getattr(self.__last_overriding, name)
elif self.__default is not UNDEFINED:
return getattr(self.__default, name)
return super().__getattr__(name)
def __str__(self):
"""Return string representation of provider.

View File

@ -496,6 +496,28 @@ class DependencyTests(unittest.TestCase):
self.assertIsNot(container.name, copied.name)
self.assertIsNot(container.name.parent, copied.name.parent)
def test_forward_attr_to_default(self):
default = providers.Configuration()
provider = providers.Dependency(default=default)
provider.from_dict({'foo': 'bar'})
self.assertEqual(default(), {'foo': 'bar'})
def test_forward_attr_to_overriding(self):
overriding = providers.Configuration()
provider = providers.Dependency()
provider.override(overriding)
provider.from_dict({'foo': 'bar'})
self.assertEqual(overriding(), {'foo': 'bar'})
def test_forward_attr_to_none(self):
provider = providers.Dependency()
with self.assertRaises(AttributeError):
provider.from_dict
def test_deepcopy(self):
provider = providers.Dependency(int)