# 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)](#class-setup-for-injectables)
2. [Constructor Setup (for accepting Injectables)](#constructor-setup-for-accepting-injectables)
3. [Registration](#registration)
3.1. [Type Registration](#type-registration)
3.2. [Instance Registration](#instance-registration)
3.3. [Lambda Registration (for decorators)](#lambda-registration-for-decorators)
4. [Resolving](#resolving)
4.1. [Lambda Registration with a Resolve](#lambda-registration-with-a-resolve)
4.2. [Resolve for application execution](#resolve-for-application-execution)
5. [Validation](#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:
```python
from abc import ABC, abstractmethod
class IFoo(ABC):
@abstractmethod
def do_something(self) -> None:
pass
```
or
```python
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`:
```python
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.
```python
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:
```python
Container.add_transient(interface= IFoo, implementation= Foo)
```
#### Instance Registration:
```python
# Note this is registered as transient but will be resolved as a singleton
Container.add_transient(interface= IFoo, implementation= Foo())
```
#### Lambda Registration (for decorators):
```python
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
```python
...
Container.add_transient(interface= IFoo, implementation= Foo)
Container.add_transient(
interface= IBar,
implementation= lambda: Bar(foo= Container.resolve(interface= IFoo)
)
```
#### Resolve for application execution
```python
...
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:
```python
...
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)
---
Raw data
{
"_id": null,
"home_page": null,
"name": "pyInjection",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.12",
"maintainer_email": null,
"keywords": "dependency injection, Python3, utilities",
"author": null,
"author_email": "Joshua Loader <pyInjection@joshloader.com>",
"download_url": "https://files.pythonhosted.org/packages/39/4d/04f562ee98b522dc05806efe400688076c42043895a251f001a109234284/pyinjection-2.1.tar.gz",
"platform": null,
"description": "# pyInjection\npyInjector is a .Net style dependency injection container built for Python3 and utilising the typing module.\n\n- Register `type`, `instance` and `lambda` functions against a base type for constructor injecting.\n- Supports `ABC` base types and mock interfaces.\n- Validates container for duplicate registrations, missing registrations and inconsistent scope registrations at runtime.\n\n## Table of Contents\n1. [Class Setup (for Injectables)](#class-setup-for-injectables)\n2. [Constructor Setup (for accepting Injectables)](#constructor-setup-for-accepting-injectables)\n3. [Registration](#registration)\n3.1. [Type Registration](#type-registration)\n3.2. [Instance Registration](#instance-registration)\n3.3. [Lambda Registration (for decorators)](#lambda-registration-for-decorators)\n4. [Resolving](#resolving)\n4.1. [Lambda Registration with a Resolve](#lambda-registration-with-a-resolve)\n4.2. [Resolve for application execution](#resolve-for-application-execution)\n5. [Validation](#validation)\n\n-------\n## Class Setup (for Injectables)\nIn 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:\n\n```python\nfrom abc import ABC, abstractmethod\n\nclass IFoo(ABC):\n @abstractmethod\n def do_something(self) -> None:\n\t pass\n```\nor\n```python\nclass IFoo:\n\tdef do_something(self) -> None:\n\t\tpass\n```\n\n## Constructor Setup (for accepting Injectables)\nIn order for pyInjection to inject objects into class constructors, the constructor must be decorated with `@Container.inject`:\n\n```python\nfrom pjInjection import Container\n\nclass Bar:\n\t__foo: IFoo\n\n\t@Container.inject\n\tdef __init__(self, foo: IFoo):\n\t\tself.__foo = foo\n\n\tdef run(self) -> None:\n\t\tself.__foo.do_something()\n```\n## Registration\npyInjection supports 3 types of injectable registration across both `transient` and `singleton` lifetimes.\n```python\nfrom pyInjection import Container\n\nContainer.add_transient(interface= IFoo, implementation= Foo)\nContainer.add_singleton(interface= IBar, implementation= Bar)\n```\nContainer registrations (like in .Net) maps an `implementation` to the `interface` base within supported constructors.\n\n#### Type Registration:\n```python\nContainer.add_transient(interface= IFoo, implementation= Foo)\n```\n#### Instance Registration:\n```python\n# Note this is registered as transient but will be resolved as a singleton\nContainer.add_transient(interface= IFoo, implementation= Foo())\n```\n#### Lambda Registration (for decorators):\n```python\nContainer.add_transient(interface= IFoo, implementation= lambda: Foo())\n```\n\n## Resolving\nIn some cases you may wish to resolve an instance from the container (for a lambda function or running the application).\n#### Lambda Registration with a Resolve\n```python\n...\n\nContainer.add_transient(interface= IFoo, implementation= Foo)\nContainer.add_transient(\n interface= IBar,\n implementation= lambda: Bar(foo= Container.resolve(interface= IFoo)\n)\n```\n#### Resolve for application execution\n```python\n...\n\nContainer.add_singleton(interface= IFoo, implementation= Foo)\nContainer.add_singleton(interface= IBar, implementation= Bar)\n\nbar: IBar = Container.resolve(interface= IBar)\nbar.run()\n```\n## Validation\nIn 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:\n\n```python\n...\n\nContainer.validate()\n```\n\nAny issues found within the container will be raised as an Exception. Exceptions will be raised for the following:\n- Duplicate registrations\n- Missing registrations\n- Type registrations for constructors with primitive types (these should be an instance registration)\n\n---\n",
"bugtrack_url": null,
"license": "MIT License",
"summary": "Dependency injection container for Python3",
"version": "2.1",
"project_urls": null,
"split_keywords": [
"dependency injection",
" python3",
" utilities"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "691433fad04f00d03aa81f749e7d701e31925edd9cf4c302e3299dabeaa3a80b",
"md5": "5e1a25243077c2c5a0bd175148a58c82",
"sha256": "9ba465a997327f44affea3bc5f0af8a39a3ddcdd8fcd2a114d3a3788f2d7cc27"
},
"downloads": -1,
"filename": "pyInjection-2.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "5e1a25243077c2c5a0bd175148a58c82",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.12",
"size": 13131,
"upload_time": "2025-02-16T22:17:42",
"upload_time_iso_8601": "2025-02-16T22:17:42.529215Z",
"url": "https://files.pythonhosted.org/packages/69/14/33fad04f00d03aa81f749e7d701e31925edd9cf4c302e3299dabeaa3a80b/pyInjection-2.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "394d04f562ee98b522dc05806efe400688076c42043895a251f001a109234284",
"md5": "eb187f5fff8b1842da931bda72923e48",
"sha256": "89a7a94990c38d88d1757fd2e44a3d76127b38f162f48bc23144bc50fc2061a2"
},
"downloads": -1,
"filename": "pyinjection-2.1.tar.gz",
"has_sig": false,
"md5_digest": "eb187f5fff8b1842da931bda72923e48",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.12",
"size": 9228,
"upload_time": "2025-02-16T22:17:43",
"upload_time_iso_8601": "2025-02-16T22:17:43.486879Z",
"url": "https://files.pythonhosted.org/packages/39/4d/04f562ee98b522dc05806efe400688076c42043895a251f001a109234284/pyinjection-2.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-02-16 22:17:43",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "pyinjection"
}