Skip to main content

Dependency injection container for Python3

Project description

pyInjection

pyInjector is a .Net style dependency injection container built for Python3 and utilising the typing module.

  • Register type, instance and lambda functions against a base type for constructor injecting.
  • Supports ABC base types and mock interfaces.
  • Validates container for duplicate registrations, missing registrations and inconsistent scope registrations at runtime.

Table of Contents

  1. Class Setup (for Injectables)
  2. Constructor Setup (for accepting Injectables)
  3. Registration 3.1. Type Registration 3.2. Instance Registration 3.3. Lambda Registration (for decorators)
  4. Resolving 4.1. Lambda Registration with a Resolve 4.2. Resolve for application execution
  5. Validation

Class Setup (for Injectables)

In order for pyInjection to register and inject a class into a constructor, classes must extend a base class. This class can be an abstract class (using ABC) or a mock interface:

from abc import ABC, abstractmethod

class IFoo(ABC):
    @abstractmethod
    def do_something(self) -> None:
	    pass

or

class IFoo:
	def do_something(self) -> None:
		pass

Constructor Setup (for accepting Injectables)

In order for pyInjection to inject objects into class constructors, the constructor must be decorated with @Container.inject:

from pjInjection import Container

class Bar:
	__foo: IFoo

	@Container.inject
	def __init__(self, foo: IFoo):
		self.__foo = foo

	def run(self) -> None:
		self.__foo.do_something()

Registration

pyInjection supports 3 types of injectable registration across both transient and singleton lifetimes.

from pyInjection import Container

Container.add_transient(interface= IFoo, implementation= Foo)
Container.add_singleton(interface= IBar, implementation= Bar)

Container registrations (like in .Net) maps an implementation to the interface base within supported constructors.

Type Registration:

Container.add_transient(interface= IFoo, implementation= Foo)

Instance Registration:

# Note this is registered as transient but will be resolved as a singleton
Container.add_transient(interface= IFoo, implementation= Foo())

Lambda Registration (for decorators):

Container.add_transient(interface= IFoo, implementation= lambda: Foo())

Resolving

In some cases you may wish to resolve an instance from the container (for a lambda function or running the application).

Lambda Registration with a Resolve

...

Container.add_transient(interface= IFoo, implementation= Foo)
Container.add_transient(
    interface= IBar,
    implementation= lambda: Bar(foo= Container.resolve(interface= IFoo)
)

Resolve for application execution

...

Container.add_singleton(interface= IFoo, implementation= Foo)
Container.add_singleton(interface= IBar, implementation= Bar)

bar: IBar = Container.resolve(interface= IBar)
bar.run()

Validation

In order to ensure that the container has been configured correctly and has everything necessary to build all injectable dependencies run the validate method in the composition root:

...

Container.validate()

Any issues found within the container will be raised as an Exception. Exceptions will be raised for the following:

  • Duplicate registrations
  • Missing registrations
  • Type registrations for constructors with primitive types (these should be an instance registration)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyInjection-1.0.10.tar.gz (8.7 kB view hashes)

Uploaded Source

Built Distribution

pyInjection-1.0.10-py3-none-any.whl (12.3 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page