injectable

This is the injectable’s public API.

See also

The Usage Examples section presents a collection of examples on how to use this API.

injectable.load_injection_container(search_path: str = None, *, default_namespace: str = 'DEFAULT_NAMESPACE', encoding: str = 'utf-8')[source]

Loads injectables under the search path to a shared injection container under the designated namespaces.

Parameters:
  • search_path – (optional) path under which to search for injectables. Can be either a relative or absolute path. Defaults to the caller’s file directory.
  • default_namespace – (optional) designated namespace for registering injectables which does not explicitly request to be addressed in a specific namespace. Defaults to injectable.constants.DEFAULT_NAMESPACE.
  • encoding – (optional) defines which encoding to use when reading project files to discover and register injectables. Defaults to utf-8.

Usage:

>>> from injectable import load_injection_container
>>> load_injection_container()

Note

This method will not scan any file already scanned by previous calls to it. Multiple invocations to different search paths will add found injectables into the injection container without clearing previously loaded ones but never loading a same injectable more than once.

New in version 3.4.0.

class injectable.InjectionContainer[source]

InjectionContainer globally manages injection namespaces and the respective injectables registries.

This class shouldn’t be used directly and will be removed from the injectable’s public API in the future.

Invoking load_injection_container() is the only necessary action before injecting dependencies. Attempting to call an autowired function before invoking load_injection_container() will log a warning indicating that the injection container is empty.

This class is not meant to be instantiated and will raise an error if instantiation is attempted.

Deprecated since version 3.4.0: This class will be removed from the public API in the future.

classmethod load(search_path: str = None, *, default_namespace: str = 'DEFAULT_NAMESPACE')[source]

Loads injectables under the search path to the InjectionContainer under the designated namespaces.

Parameters:
  • search_path – (optional) path under which to search for injectables. Can be either a relative or absolute path. Defaults to the caller’s file directory.
  • default_namespace – (optional) designated namespace for registering injectables which does not explicitly request to be addressed in a specific namespace. Defaults to injectable.constants.DEFAULT_NAMESPACE.

Usage:

>>> from injectable import InjectionContainer
>>> InjectionContainer.load()

Note

This method will not scan any file more than once regardless of being called successively. Multiple invocations to different search paths will add found injectables to the InjectionContainer without clearing previously found ones.

Deprecated since version 3.4.0: This method will be removed from the public API in the future. Use load_injection_container() instead.

class injectable.Injectable(constructor: callable, unique_id: str = <factory>, primary: bool = False, group: Optional[str] = None, singleton: bool = False)[source]

Injectable is the low-level container class in which information regarding an injectable dependency is stored for registering in a namespace.

This class is not meant for direct usage. It should be used in conjunction with the injectable.testing module utilities for testing purposes only.

Parameters:
  • constructor – callable to be used as constructor when injecting.
  • unique_id – (optional) unique identifier for the injectable which prevents duplicates of the same injectable to be registered. Defaults to a UUID generated at initialization time.
  • primary – (optional) marks the injectable as primary for resolution in ambiguous cases. Defaults to False.
  • group – (optional) group to be assigned to the injectable. Defaults to None.
  • singleton – (optional) when True the injectable will be a singleton, i.e. only one instance of it will be created and shared globally. Defaults to False.
injectable.autowired(func: T) → T[source]

Function decorator to setup dependency injection autowiring.

Only parameters annotated with Autowired will be autowired for injection.

If no parameter is annotated with Autowired an AutowiringError will be raised.

An AutowiringError will also be raised if a parameter annotated with Autowired is given a default value or if a non Autowired-annotated positional parameter is placed after an Autowired-annotated positional parameter.

Before attempting to call an autowired function make sure load_injection_container was invoked.

Note

This decorator can be applied to any function, not only an __init__ method.

Note

This decorator accepts no arguments and must be used without trailing parenthesis.

Usage:

>>> from injectable import Autowired, autowired
>>>
>>> @autowired
... def foo(dep: Autowired(...)):
...     ...
class injectable.Autowired[source]

Autowired type annotation marks a parameter to be autowired for injection.

Autowired parameters must be last in declaration if there are others which aren’t autowired. Also, autowired parameters must not be given default values.

This type annotation does not performs the function autowiring by itself. The function must be decorated with @autowired for autowiring.

Parameters:
  • dependency – class, base class or qualifier of the dependency to be used for lookup among the registered injectables. Can be wrapped in a typing sequence, e.g. List[...], to inject a list containing all matching injectables. Can be wrapped in a optional, e.g. Optional[...], to inject None if no matches are found to inject. Optional[List[...]] is valid and will inject an empty list if no matches are found to inject.
  • namespace – (optional) namespace in which to look for the dependency. Defaults to injectable.constants.DEFAULT_NAMESPACE.
  • group – (optional) group to filter out other injectables outside of this group. Defaults to None.
  • exclude_groups – (optional) list of groups to be excluded. Defaults to None.
  • lazy – (optional) when True will return an instance which will automatically initialize itself when first used but not before that. Defaults to False.

Usage:

>>> from injectable import Autowired, autowired
>>>
>>> @autowired
... def foo(arg: Autowired("qualifier")):
...     ...
injectable.injectable_factory(dependency: T = None, *, qualifier: str = None, primary: bool = False, namespace: str = None, group: str = None, singleton: bool = False) → Callable[[...], Callable[[...], T]][source]

Function decorator to mark it as a injectable factory for the dependency.

At least one of dependency or qualifier parameters need to be defined. An InjectableLoadError will be raised if none are defined.

Note

This decorator shall be the first decorator of the function since only the received function will be registered as an injectable factory

Note

All files using this decorator will be executed when load_injection_container is invoked.

Parameters:
  • dependency – (optional) the dependency class for which the factory will be registered to. Defaults to None.
  • qualifier – (optional) string qualifier for which the factory will be registered to. Defaults to None.
  • primary – (optional) marks the factory as primary for the dependency resolution in ambiguous cases. Defaults to False.
  • namespace – (optional) namespace in which the factory will be registered. Defaults to injectable.constants.DEFAULT_NAMESPACE.
  • group – (optional) group to be assigned to the factory. Defaults to None.
  • singleton – (optional) when True the factory will be used to instantiate a singleton, i.e. only one call to the factory will be made and the created instance will be shared globally. Defaults to False.

Usage:

>>> from injectable import injectable_factory
>>> from foo import Foo
>>>
>>> @injectable_factory(Foo)
... def foo_factory() -> Foo:
...     return Foo(...)
injectable.injectable(cls: T = None, *, qualifier: str = None, primary: bool = False, namespace: str = None, group: str = None, singleton: bool = False) → T[source]

Class decorator to mark it as an injectable dependency.

This decorator accepts customization parameters but can be invoked without the parenthesis when no parameter will be specified.

Note

All files using this decorator will be executed when load_injection_container is invoked.

Parameters:
  • cls – (cannot be explicitly passed) the decorated class. This will be automatically passed to the decorator by Python magic.
  • qualifier – (optional) string qualifier for the injectable to be registered with. Defaults to None.
  • primary – (optional) marks the injectable as primary for resolution in ambiguous cases. Defaults to False.
  • namespace – (optional) namespace in which the injectable will be registered. Defaults to injectable.constants.DEFAULT_NAMESPACE.
  • group – (optional) group to be assigned to the injectable. Defaults to None.
  • singleton – (optional) when True the injectable will be a singleton, i.e. only one instance of it will be created and shared globally. Defaults to False.

Usage:

>>> from injectable import injectable
>>>
>>> @injectable
... class Foo:
...     ...
injectable.inject(dependency: Union[Type[T], str], *, namespace: str = None, group: str = None, exclude_groups: Sequence[str] = None, lazy: bool = False, optional: bool = False) → T[source]

Injects the requested dependency by instantiating a new instance of it or a singleton instance if specified by the injectable. Returns an instance of the requested dependency.

One can use this method directly for injecting dependencies though this is not recommended. Use the @autowired decorator and the Autowired type annotation for dependency injection to be automatically wired to a function’s call instead.

Will log a warning indicating that the injection container is empty when invoked before load_injection_container is called.

Raises InjectionError when unable to resolve the requested dependency. This can be due to a variety of reasons: the requested dependency wasn’t loaded into the container; the namespace isn’t correct; the group isn’t correct; there are multiple injectables for the dependency and none or multiple are marked as primary. When parameter optional is True no error will be raised when no injectable that matches requested qualifier/class and group is found in the specified namespace though in ambiguous cases that resolving a primary injectable is impossible an error will still be raised.

Parameters:
  • dependency – class, base class or qualifier of the dependency to be used for lookup among the registered injectables.
  • namespace – (optional) namespace in which to look for the dependency. Defaults to injectable.constants.DEFAULT_NAMESPACE.
  • group – (optional) group to filter out other injectables outside of this group. Defaults to None.
  • exclude_groups – (optional) list of groups to be excluded. Defaults to None.
  • lazy – (optional) when True will return an instance which will automatically initialize itself when first used but not before that. Defaults to False.
  • optional – (optional) when True this function returns None if no injectable matches the qualifier/class and group inside the specified namespace instead of raising an InjectionError. Ambiguous cases where resolving a primary injectable is impossible will still raise InjectionError. Defaults to False.

Usage:

>>> from foo import Foo
>>> from injectable import inject
>>>
>>> class Bar:
...     def __init__(self, foo: Foo = None):
...         self.foo = foo or inject(Foo)
injectable.inject_multiple(dependency: Union[Type[T], str], *, namespace: str = None, group: str = None, exclude_groups: Sequence[str] = None, lazy: bool = False, optional: bool = False) → List[T][source]

Injects all injectables that resolves to the specified dependency. Returns a list of instances matching the requested dependency.

One can use this method directly for injecting dependencies though this is not recommended. Use the @autowired decorator and the Autowired type annotation for dependency injection to be automatically wired to a function’s call instead.

Logs a warning indicating that the injection container is empty when invoked before load_injection_container is called.

Raises InjectionError when unable to resolve the requested dependency. This can be due to a variety of reasons: there is no injectable loaded into the container that matches the dependency; the namespace isn’t correct; the group specifications aren’t correct. When parameter optional is True no error will be raised when no injectable that matches requested qualifier/class and group is found in the specified namespace.

Parameters:
  • dependency – class, base class or qualifier of the dependency to be used for lookup among the registered injectables.
  • namespace – (optional) namespace in which to look for the dependency. Defaults to injectable.constants.DEFAULT_NAMESPACE.
  • group – (optional) group to filter out other injectables outside of this group. Defaults to None.
  • exclude_groups – (optional) list of groups to be excluded. Defaults to None.
  • lazy – (optional) when True will returned instances will automatically initialize themselves when first used but not before that. Defaults to False.
  • optional – (optional) when True this function returns an empty list if no injectable matches the qualifier/class and group inside the specified namespace. Defaults to False.

Usage:

>>> from com import AbstractService
>>> from injectable import inject_multiple
>>> from typing import Sequence
>>>
>>> class Foo:
...     def __init__(self, services: Sequence[AbstractService] = None):
...         self.services = services or inject_multiple(AbstractService)