Package: autocontainer
AutoContainerPython really needed a modern reflection based dependency injection container
that "just works". Alas, welcome toAutoContainerfor python. The dependency injection service contaienr that just works.FeaturesDirect class as serviceSeparate provider functionsService Behaviors:SingletonFactoryAssemblerInstanceNaming ServicesContainer Bound FunctionsDependency GraphAutomatic InjectionService registration checkingInject typehint by namePrimitive types by nameInstallationpip3installautocontainerRequirements:Python >= 3.5UsageIt's all about types and hints, but first create the containerfromautocontianerimportContainercontainer=Container()# Party TimeClasses & InjectionWe'll use singleton as an example.classA:passclassB:def__init__(self,obj_a:A):assertisinstance(obj_a,A)# Order does not matter.container.singleton(B)container.singleton(A)obj_b=container.get(B)assertisinstance(obj_b,B)Naming ServicesclassA:passcontainer.singleton(A,'ayy')obj_a=container.get(A)obj_b=container.get('ayy')assertobj_aisobj_bOther ways togetobj_a=container.get(A)# <--- Best IDE Support due to type hints.obj_b=container.get('ayy')obj_c=container.ayy# <--- the most concise way.obj_d=container('ayy')Builder FunctionsYou won't always put raw classes into the service container
sometimes, it's necessary to write a function that custom
initializes a class or object.classA:passclassB:def__init__(self):self.fruit='tomato'defmakeB(obj_a:A)->B:# Return type MUST be annotatedb=B()b.fruit='mango'returnbcontainer.singleton(makeB)obj_b=container(B)assertobj_b.fruit=='mango'FactoryFactories can also take builder function as well as classes.
The container returns a new instance every time.classA:passcontainer.factory(A)aa=container.get(A)ab=container.get(A)assertaaisnotabassertisinstance(aa,A)assertisinstance(ab,A)BindingThis is the coolest feature, trust me. Imagine you have a function
that needs both classes out of a container and vanilla arguments
like int and str, this would be a pain to do manually. Unless...classA:passclassB:passcontainer.singleton(A)container.singleton(B)defcrazy_function(a:A,repeating:str,b:B,times:int):assertisinstance(a,A)assertisinstance(b,B)returnrepeating*timeless_crazy_function=container.bind(crazy_function)result=less_crazy_function("pew",3)assertresult=='pewpewpew'InjectingSame as binding but for simpler times.classA:passclassB:passcontainer.singleton(A)container.singleton(B)defcrazy_function(a:A,b:B):assertisinstance(a,A)assertisinstance(b,B)return'potato'assertcontianer.inject(crazy_function)=='potato'Specificity InjectorThe container maintains an internal graph of dependencies that allows
it to efficiently push instances of ancestor classes.classA:passclassB:passclassC(A):passclassD(C,B):passcontainer.factory(A)container.singleton(B)container.factory(C)container.singleton(D)obj=container.get(A)assertisinstance(obj,D)assertisinstance(obj,A)Hinting by NameThis is completely valid with the containerclassA:passcontainer.singleton(A,'apple')defmagic(ap:'apple'):assertisinstance(ap,A)container.inject(magic)Available Methodsget(service: Union[Type, str])Retreives a servicehas(service: Union[Type, str])Returns if a service existssingleton(service: Union[Type, Callable[..., Instance]], name?: str)Adds a service as a singleton into container.
(Returns the same object on everyget)factory(service: Union[Type, Callable[..., Instance]], name?: str)Adds a service as a factory into container.
(Returns a fresh object on everyget)instance(service: object, name?: str)Adds a service as an instance into container.
(Returns the same object on everyget, but does not try to instantiate)assembler(service: Union[Type, Callable[..., Instance]], name?: str)Adds a service such that on every get, the container returns aboundcallable
that produces a fresh object everytime.bind(func: Callable)Returns a new callable but in which the arguments recognized by the container
are automatically pushed when calling. (see examples below)inject(func: Callable)Takes a callable and calls it by injecting all the services it requires
and then returns the return value.Running Testspython-munittestdiscover-s./LicenseMIT. Go crazy.