Injector API reference¶
Note
Unless specified otherwise, instance methods are not thread safe.
The following functions are thread safe:
Injector.get()
injection provided by
inject()
decorator (please note, however, that it doesn’t say anything about decorated function thread safety)
Injector - Python dependency injection framework, inspired by Guice
- copyright
2012 by Alec Thomas
- license
BSD
-
class
injector.
Binder
(injector, auto_bind=True, parent=None)¶ Bases:
object
Bind interfaces to implementations.
Note
This class is instantiated internally for you and there’s no need to instantiate it on your own.
-
bind
(interface, to=None, scope=None)¶ Bind an interface to an implementation.
-
install
(module)¶ Install a module into this binder.
In this context the module is one of the following:
function taking the
Binder
as it’s only parameterdef configure(binder): bind(str, to='s') binder.install(configure)
instance of
Module
(instance of it’s subclass counts)class MyModule(Module): def configure(self, binder): binder.bind(str, to='s') binder.install(MyModule())
subclass of
Module
- the subclass needs to be instantiable so if it expects any parameters they need to be injectedbinder.install(MyModule)
-
multibind
(interface, to, scope=None)¶ Creates or extends a multi-binding.
A multi-binding maps from a key to a sequence, where each element in the sequence is provided separately.
- Parameters
interface –
MappingKey()
orSequenceKey()
to bind to.to – Instance, class to bind to, or an explicit
Provider
subclass. Must provide a sequence.scope – Optional Scope in which to bind.
-
-
class
injector.
BoundKey
¶ Bases:
tuple
A BoundKey provides a key to a type with pre-injected arguments.
>>> class A: ... def __init__(self, a, b): ... self.a = a ... self.b = b >>> InjectedA = BoundKey(A, a=InstanceProvider(1), b=InstanceProvider(2)) >>> injector = Injector() >>> a = injector.get(InjectedA) >>> a.a, a.b (1, 2)
-
exception
injector.
CallError
¶ Bases:
injector.Error
Call to callable object fails.
-
class
injector.
CallableProvider
(callable: Callable[[...], T])¶ Bases:
injector.Provider
Provides something using a callable.
The callable is called every time new value is requested from the provider.
>>> key = Key('key') >>> def factory(): ... print('providing') ... return [] ... >>> def configure(binder): ... binder.bind(key, to=CallableProvider(factory)) ... >>> injector = Injector(configure) >>> injector.get(key) is injector.get(key) providing providing False
-
exception
injector.
CircularDependency
¶ Bases:
injector.Error
Circular dependency detected.
-
class
injector.
ClassProvider
(cls: Type[T])¶ Bases:
injector.Provider
Provides instances from a given class, created using an Injector.
-
exception
injector.
Error
¶ Bases:
Exception
Base exception.
-
class
injector.
Injector
(modules=None, auto_bind=True, parent=None)¶ Bases:
object
- Parameters
modules –
Optional - a configuration module or iterable of configuration modules. Each module will be installed in current
Binder
usingBinder.install()
.Consult
Binder.install()
documentation for the details.auto_bind – Whether to automatically bind missing types.
parent – Parent injector.
New in version 0.7.5:
use_annotations
parameterChanged in version 0.13.0:
use_annotations
parameter is removed-
call_with_injection
(callable, self_=None, args=(), kwargs={})¶ Call a callable and provide it’s dependencies if needed.
- Parameters
self – Instance of a class callable belongs to if it’s a method, None otherwise.
args (tuple of objects) – Arguments to pass to callable.
kwargs (dict of string -> object) – Keyword arguments to pass to callable.
- Returns
Value returned by callable.
-
create_object
(cls: Type[T], additional_kwargs=None) → T¶ Create a new instance, satisfying any dependencies on cls.
-
get
(interface: Type[T], scope=None) → T¶ Get an instance of the given interface.
Note
Although this method is part of
Injector
’s public interface it’s meant to be used in limited set of circumstances.For example, to create some kind of root object (application object) of your application (note that only one get call is needed, inside the Application class and any of its dependencies
inject()
can and should be used):class Application: @inject def __init__(self, dep1: Dep1, dep2: Dep2): self.dep1 = dep1 self.dep2 = dep2 def run(self): self.dep1.something() injector = Injector(configuration) application = injector.get(Application) application.run()
- Parameters
interface – Interface whose implementation we want.
scope – Class of the Scope in which to resolve.
- Returns
An implementation of interface.
-
class
injector.
InstanceProvider
(instance: T)¶ Bases:
injector.Provider
Provide a specific instance.
>>> my_list = Key('my_list') >>> def configure(binder): ... binder.bind(my_list, to=InstanceProvider([])) ... >>> injector = Injector(configure) >>> injector.get(my_list) is injector.get(my_list) True >>> injector.get(my_list).append('x') >>> injector.get(my_list) ['x']
-
injector.
Key
(name: str) → injector.BaseKey¶ Create a new type key.
>>> Age = Key('Age') >>> def configure(binder): ... binder.bind(Age, to=90) >>> Injector(configure).get(Age) 90
-
injector.
MappingKey
(name: str) → injector.BaseMappingKey¶ As for Key, but declares a multibind mapping.
-
class
injector.
Module
¶ Bases:
object
Configures injector and providers.
-
configure
(binder)¶ Override to configure bindings.
-
-
class
injector.
NoScope
(injector=None)¶ Bases:
injector.Scope
An unscoped provider.
-
class
injector.
Provider
¶ Bases:
typing.Generic
Provides class instances.
-
class
injector.
ProviderOf
(injector: injector.Injector, interface: Type[T])¶ Bases:
typing.Generic
Can be used to get a provider of an interface, for example:
>>> def provide_int(): ... print('providing') ... return 123 >>> >>> def configure(binder): ... binder.bind(int, to=provide_int) >>> >>> injector = Injector(configure) >>> provider = injector.get(ProviderOf[int]) >>> value = provider.get() providing >>> value 123
-
get
() → T¶ Get an implementation for the specified interface.
-
-
class
injector.
Scope
(injector)¶ Bases:
object
A Scope looks up the Provider for a binding.
By default (ie.
NoScope
) this simply returns the defaultProvider
.-
configure
()¶ Configure the scope.
-
-
injector.
SequenceKey
(name: str) → injector.BaseSequenceKey¶ As for Key, but declares a multibind sequence.
-
class
injector.
SingletonScope
(injector)¶ Bases:
injector.Scope
A
Scope
that returns a per-Injector instance for a key.singleton
can be used as a convenience class decorator.>>> class A: pass >>> injector = Injector() >>> provider = ClassProvider(A) >>> singleton = SingletonScope(injector) >>> a = singleton.get(A, provider) >>> b = singleton.get(A, provider) >>> a is b True
-
class
injector.
ThreadLocalScope
(injector)¶ Bases:
injector.Scope
A
Scope
that returns a per-thread instance for a key.
-
exception
injector.
UnknownArgument
¶ Bases:
injector.Error
Tried to mark an unknown argument as noninjectable.
-
exception
injector.
UnknownProvider
¶ Bases:
injector.Error
Tried to bind to a type whose provider couldn’t be determined.
-
exception
injector.
UnsatisfiedRequirement
¶ Bases:
injector.Error
Requirement could not be satisfied.
-
injector.
inject
(function=None, **bindings)¶ Decorator declaring parameters to be injected.
eg.
>>> Sizes = Key('sizes') >>> Names = Key('names') >>> >>> class A: ... @inject ... def __init__(self, number: int, name: str, sizes: Sizes): ... print([number, name, sizes]) ... >>> def configure(binder): ... binder.bind(A) ... binder.bind(int, to=123) ... binder.bind(str, to='Bob') ... binder.bind(Sizes, to=[1, 2, 3])
Use the Injector to get a new instance of A:
>>> a = Injector(configure).get(A) [123, 'Bob', [1, 2, 3]]
Note
This decorator is to be used on class constructors. Using it on non-constructor methods worked in the past but it was an implementation detail rather than a design decision.
Third party libraries may, however, provide support for injecting dependencies into non-constructor methods or free functions in one form or another.
-
injector.
is_decorated_with_inject
(function: Callable[[...], Any]) → bool¶ See if given callable is declared to want some dependencies injected.
Example use:
>>> def fun(i: int) -> str: ... return str(i)
>>> is_decorated_with_inject(fun) False >>> >>> @inject ... def fun2(i: int) -> str: ... return str(i)
>>> is_decorated_with_inject(fun2) True
-
injector.
noninjectable
(*args)¶ Mark some parameters as not injectable.
This serves as documentation for people reading the code and will prevent Injector from ever attempting to provide the parameters.
For example:
>>> class Service: ... pass ... >>> class SomeClass: ... @inject ... @noninjectable('user_id') ... def __init__(self, service: Service, user_id: int): ... # ... ... pass
noninjectable()
decorations can be stacked on top of each other and the order in which a function is decorated withinject()
andnoninjectable()
doesn’t matter.
-
injector.
provider
(function)¶ Decorator for
Module
methods, registering a provider of a type.>>> class MyModule(Module): ... @provider ... def provide_name(self) -> str: ... return 'Bob'
@provider-decoration implies @inject so you can omit it and things will work just the same:
>>> class MyModule2(Module): ... def configure(self, binder): ... binder.bind(int, to=654) ... ... @provider ... def provide_str(self, i: int) -> str: ... return str(i) ... >>> injector = Injector(MyModule2) >>> injector.get(str) '654'