mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2025-02-14 10:30:51 +03:00
Add implementation
This commit is contained in:
parent
ce6d3df72c
commit
41f8009811
File diff suppressed because it is too large
Load Diff
|
@ -35,6 +35,7 @@ class Container:
|
|||
def __setattr__(self, name: str, value: Union[Provider, Any]) -> None: ...
|
||||
def __delattr__(self, name: str) -> None: ...
|
||||
def set_providers(self, **providers: Provider): ...
|
||||
def set_provider(self, name: str, provider: Provider) -> None: ...
|
||||
def override(self, overriding: C_Base) -> None: ...
|
||||
def override_providers(self, **overriding_providers: Provider) -> None: ...
|
||||
def reset_last_overriding(self) -> None: ...
|
||||
|
|
|
@ -69,7 +69,7 @@ class DynamicContainer(Container):
|
|||
self.declarative_parent = None
|
||||
self.wired_to_modules = []
|
||||
self.wired_to_packages = []
|
||||
self.__self__ = providers.Object(self)
|
||||
self.__self__ = providers.Self(self)
|
||||
super(DynamicContainer, self).__init__()
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
|
@ -102,7 +102,7 @@ class DynamicContainer(Container):
|
|||
|
||||
:rtype: None
|
||||
"""
|
||||
if isinstance(value, providers.Provider) and name != '__self__':
|
||||
if isinstance(value, providers.Provider) and not isinstance(value, providers.Self):
|
||||
_check_provider_type(self, value)
|
||||
self.providers[name] = value
|
||||
super(DynamicContainer, self).__setattr__(name, value)
|
||||
|
@ -154,6 +154,19 @@ class DynamicContainer(Container):
|
|||
for name, provider in six.iteritems(providers):
|
||||
setattr(self, name, provider)
|
||||
|
||||
def set_provider(self, name, provider):
|
||||
"""Set container provider.
|
||||
|
||||
:param name: Provider name
|
||||
:type name: str
|
||||
|
||||
:param provider: Provider
|
||||
:type provider: :py:class:`dependency_injector.providers.Provider`
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
setattr(self, name, provider)
|
||||
|
||||
def override(self, object overriding):
|
||||
"""Override current container by overriding container.
|
||||
|
||||
|
@ -282,6 +295,10 @@ class DeclarativeContainerMetaClass(type):
|
|||
|
||||
def __new__(type mcs, str class_name, tuple bases, dict attributes):
|
||||
"""Declarative container class factory."""
|
||||
self = mcs.__fetch_self(attributes)
|
||||
if self is None:
|
||||
self = providers.Self()
|
||||
|
||||
containers = {
|
||||
name: container
|
||||
for name, container in six.iteritems(attributes)
|
||||
|
@ -291,7 +308,7 @@ class DeclarativeContainerMetaClass(type):
|
|||
cls_providers = {
|
||||
name: provider
|
||||
for name, provider in six.iteritems(attributes)
|
||||
if isinstance(provider, providers.Provider)
|
||||
if isinstance(provider, providers.Provider) and not isinstance(provider, providers.Self)
|
||||
}
|
||||
|
||||
inherited_providers = {
|
||||
|
@ -312,7 +329,8 @@ class DeclarativeContainerMetaClass(type):
|
|||
|
||||
cls = <type>type.__new__(mcs, class_name, bases, attributes)
|
||||
|
||||
cls.__self__ = providers.Object(cls)
|
||||
self.set_container(cls)
|
||||
cls.__self__ = self
|
||||
|
||||
for provider in six.itervalues(cls.providers):
|
||||
_check_provider_type(cls, provider)
|
||||
|
@ -375,6 +393,28 @@ class DeclarativeContainerMetaClass(type):
|
|||
"""Return providers traversal generator."""
|
||||
yield from providers.traverse(*cls.providers.values(), types=types)
|
||||
|
||||
@staticmethod
|
||||
def __fetch_self(attributes):
|
||||
self = None
|
||||
alt_names = []
|
||||
|
||||
for name, value in attributes.items():
|
||||
if not isinstance(value, providers.Self):
|
||||
continue
|
||||
|
||||
if self is not None and value is not self:
|
||||
raise errors.Error('Container can have only one "Self" provider')
|
||||
|
||||
if name != '__self__':
|
||||
alt_names.append(name)
|
||||
|
||||
self = value
|
||||
|
||||
if self:
|
||||
self.set_alt_names(alt_names)
|
||||
|
||||
return self
|
||||
|
||||
|
||||
@six.add_metaclass(DeclarativeContainerMetaClass)
|
||||
class DeclarativeContainer(Container):
|
||||
|
@ -448,9 +488,21 @@ class DeclarativeContainer(Container):
|
|||
container = cls.instance_type()
|
||||
container.provider_type = cls.provider_type
|
||||
container.declarative_parent = cls
|
||||
container.set_providers(**providers.deepcopy(cls.providers))
|
||||
|
||||
copied_providers = providers.deepcopy({ **cls.providers, **{'@@self@@': cls.__self__}})
|
||||
copied_self = copied_providers.pop('@@self@@')
|
||||
copied_self.set_container(container)
|
||||
|
||||
container.__self__ = copied_self
|
||||
for name in copied_self.alt_names:
|
||||
container.set_provider(name, copied_self)
|
||||
|
||||
for name, provider in copied_providers.items():
|
||||
container.set_provider(name, provider)
|
||||
|
||||
container.override_providers(**overriding_providers)
|
||||
container.apply_container_providers_overridings()
|
||||
|
||||
return container
|
||||
|
||||
@classmethod
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -27,6 +27,11 @@ cdef class Object(Provider):
|
|||
cpdef object _provide(self, tuple args, dict kwargs)
|
||||
|
||||
|
||||
cdef class Self(Provider):
|
||||
cdef object __container
|
||||
cdef tuple __alt_names
|
||||
|
||||
|
||||
cdef class Delegate(Provider):
|
||||
cdef object __provides
|
||||
|
||||
|
|
|
@ -85,6 +85,14 @@ class Object(Provider[T]):
|
|||
def __init__(self, provides: T) -> None: ...
|
||||
|
||||
|
||||
class Self(Provider[T]):
|
||||
def __init__(self, container: Optional[T] = None) -> None: ...
|
||||
def set_container(self, container: T) -> None: ...
|
||||
def set_alt_names(self, alt_names: _Iterable[Any]) -> None: ...
|
||||
@property
|
||||
def alt_names(self) -> Tuple[Any]: ...
|
||||
|
||||
|
||||
class Delegate(Provider[Provider]):
|
||||
def __init__(self, provides: Provider) -> None: ...
|
||||
@property
|
||||
|
|
|
@ -458,6 +458,62 @@ cdef class Object(Provider):
|
|||
return self.__provides
|
||||
|
||||
|
||||
cdef class Self(Provider):
|
||||
"""Self provider returns own container."""
|
||||
|
||||
def __init__(self, container=None):
|
||||
"""Initialize provider."""
|
||||
self.__container = container
|
||||
self.__alt_names = tuple()
|
||||
super().__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__()
|
||||
copied.set_container(deepcopy(self.__container, memo))
|
||||
copied.set_alt_names(self.__alt_names)
|
||||
|
||||
self._copy_overridings(copied, memo)
|
||||
|
||||
return copied
|
||||
|
||||
def __str__(self):
|
||||
"""Return string representation of provider.
|
||||
|
||||
:rtype: str
|
||||
"""
|
||||
return represent_provider(provider=self, provides=self.__container)
|
||||
|
||||
def __repr__(self):
|
||||
"""Return string representation of provider.
|
||||
|
||||
:rtype: str
|
||||
"""
|
||||
return self.__str__()
|
||||
|
||||
def set_container(self, container):
|
||||
self.__container = container
|
||||
|
||||
def set_alt_names(self, alt_names):
|
||||
self.__alt_names = tuple(set(alt_names))
|
||||
|
||||
@property
|
||||
def alt_names(self):
|
||||
return self.__alt_names
|
||||
|
||||
@property
|
||||
def related(self):
|
||||
"""Return related providers generator."""
|
||||
yield from super().related
|
||||
|
||||
cpdef object _provide(self, tuple args, dict kwargs):
|
||||
return self.__container
|
||||
|
||||
|
||||
cdef class Delegate(Provider):
|
||||
"""Delegate provider returns provider "as is".
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user