@@ -69,7 +69,7 @@ class DynamicContainer(Container):
6969 self .declarative_parent = None
7070 self .wired_to_modules = []
7171 self .wired_to_packages = []
72- self .__self__ = providers.Object (self )
72+ self .__self__ = providers.Self (self )
7373 super (DynamicContainer, self ).__init__()
7474
7575 def __deepcopy__ (self , memo ):
@@ -79,12 +79,18 @@ class DynamicContainer(Container):
7979 return copied
8080
8181 copied = self .__class__ ()
82+ memo[id (self )] = copied
83+
8284 copied.provider_type = providers.Provider
8385 copied.overridden = providers.deepcopy(self .overridden, memo)
8486 copied.declarative_parent = self .declarative_parent
8587
88+ copied.__self__ = providers.deepcopy(self .__self__, memo)
89+ for name in copied.__self__.alt_names:
90+ copied.set_provider(name, copied.__self__)
91+
8692 for name, provider in providers.deepcopy(self .providers, memo).items():
87- setattr ( copied, name, provider)
93+ copied.set_provider( name, provider)
8894
8995 return copied
9096
@@ -102,7 +108,7 @@ class DynamicContainer(Container):
102108
103109 :rtype: None
104110 """
105- if isinstance (value, providers.Provider) and name ! = ' __self__ ' :
111+ if isinstance (value, providers.Provider) and not isinstance (value, providers.Self) :
106112 _check_provider_type(self , value)
107113 self .providers[name] = value
108114 super (DynamicContainer, self ).__setattr__(name, value)
@@ -154,6 +160,19 @@ class DynamicContainer(Container):
154160 for name, provider in six.iteritems(providers):
155161 setattr (self , name, provider)
156162
163+ def set_provider (self , name , provider ):
164+ """ Set container provider.
165+
166+ :param name: Provider name
167+ :type name: str
168+
169+ :param provider: Provider
170+ :type provider: :py:class:`dependency_injector.providers.Provider`
171+
172+ :rtype: None
173+ """
174+ setattr (self , name, provider)
175+
157176 def override (self , object overriding ):
158177 """ Override current container by overriding container.
159178
@@ -282,6 +301,10 @@ class DeclarativeContainerMetaClass(type):
282301
283302 def __new__ (type mcs , str class_name , tuple bases , dict attributes ):
284303 """ Declarative container class factory."""
304+ self = mcs.__fetch_self(attributes)
305+ if self is None :
306+ self = providers.Self()
307+
285308 containers = {
286309 name: container
287310 for name, container in six.iteritems(attributes)
@@ -291,7 +314,7 @@ class DeclarativeContainerMetaClass(type):
291314 cls_providers = {
292315 name: provider
293316 for name, provider in six.iteritems(attributes)
294- if isinstance (provider, providers.Provider)
317+ if isinstance (provider, providers.Provider) and not isinstance (provider, providers.Self)
295318 }
296319
297320 inherited_providers = {
@@ -312,7 +335,8 @@ class DeclarativeContainerMetaClass(type):
312335
313336 cls = < type > type .__new__ (mcs, class_name, bases, attributes)
314337
315- cls .__self__ = providers.Object(cls )
338+ self .set_container(cls )
339+ cls .__self__ = self
316340
317341 for provider in six.itervalues(cls .providers):
318342 _check_provider_type(cls , provider)
@@ -375,6 +399,28 @@ class DeclarativeContainerMetaClass(type):
375399 """ Return providers traversal generator."""
376400 yield from providers.traverse(* cls .providers.values(), types = types)
377401
402+ @staticmethod
403+ def __fetch_self (attributes ):
404+ self = None
405+ alt_names = []
406+
407+ for name, value in attributes.items():
408+ if not isinstance (value, providers.Self):
409+ continue
410+
411+ if self is not None and value is not self :
412+ raise errors.Error(' Container can have only one "Self" provider' )
413+
414+ if name != ' __self__' :
415+ alt_names.append(name)
416+
417+ self = value
418+
419+ if self :
420+ self .set_alt_names(alt_names)
421+
422+ return self
423+
378424
379425@ six.add_metaclass (DeclarativeContainerMetaClass)
380426class DeclarativeContainer (Container ):
@@ -448,9 +494,21 @@ class DeclarativeContainer(Container):
448494 container = cls .instance_type()
449495 container.provider_type = cls .provider_type
450496 container.declarative_parent = cls
451- container.set_providers(** providers.deepcopy(cls .providers))
497+
498+ copied_providers = providers.deepcopy({ ** cls .providers, ** {' @@self@@' : cls .__self__}})
499+ copied_self = copied_providers.pop(' @@self@@' )
500+ copied_self.set_container(container)
501+
502+ container.__self__ = copied_self
503+ for name in copied_self.alt_names:
504+ container.set_provider(name, copied_self)
505+
506+ for name, provider in copied_providers.items():
507+ container.set_provider(name, provider)
508+
452509 container.override_providers(** overriding_providers)
453510 container.apply_container_providers_overridings()
511+
454512 return container
455513
456514 @classmethod
0 commit comments