.. _injectable:
.. role:: python(code)
:language: python
Injectable: Dependency Injection for Humans™
Usage Examples 🚩 <https://injectable.readthedocs.io/en/latest/usage/index.html>
_ | Developer Reference 👩💻 <https://injectable.readthedocs.io/en/latest/reference/index.html>
_ | Authors 👫 <https://injectable.readthedocs.io/en/latest/authors.html>
_
Injectable is an elegant and simple Dependency Injection framework built with Heart
and designed for Humans.
.. list-table::
:header-rows: 0
* - .. code:: python
from injectable import Autowired, autowired
from typing import List
from models import Database
from messaging import Broker
class Service:
@autowired
def __init__(
self,
database: Autowired(Database),
message_brokers: Autowired(List[Broker]),
):
pending = database.get_pending_messages()
for broker in message_brokers:
broker.send_pending(pending)
.. code:: python
from abc import ABC
class Broker(ABC):
def send_pending(messages):
...
- .. code:: python
from injectable import injectable
@injectable
class Database:
...
.. code:: python
from messaging import Broker
from injectable import injectable
@injectable
class KafkaProducer(Broker):
...
.. code:: python
from messaging import Broker
from injectable import injectable
@injectable
class SQSProducer(Broker):
...
Features you'll love ❤️
-
Autowiring: injection is transparent to the function. Just decorate the function
with :python:@autowired
and annotate parameters with :python:Autowired
, that's it.
-
Automatic dependency discovery: just call :python:load_injection_container()
at
the root of your project or pass the root path as an argument. All classes decorated
with :python:@injectable
will be automatically discovered and ready for injection.
-
Qualifier overloading: declare as many injectables as you like for a single
qualifier or extending the same base class. You can inject all of them just by
specifying a :python:typing.List
to :python:Autowired
: :python:deps: Autowired(List["qualifier"])
.
-
Transparent lazy initialization: passing the argument :python:lazy=True
for
:python:Autowired
will make your dependency to be initialized only when actually used, all
in a transparent fashion.
-
Singletons: decorate your class with :python:@injectable(singleton=True)
and only a
single instance will be initialized and shared for injection.
-
Namespaces: specify different namespaces for injectables as in
:python:@injectable(namespace="foo")
and then just use them when annotating your
parameters as in :python:dep: Autowired(..., namespace="foo")
.
-
Linters friendly: :python:Autowired
is carefully designed to comply with static linter
analysis such as PyCharm's to preserve the parameter original type hint.
These are just a few cool and carefully built features for you. Check out our docs <https://injectable.readthedocs.io/en/latest/>
_!
Changelog
3.4.7 (2021-08-15)
- Fix injectable crashing when relative imports are used in files containing injectables.
3.4.6 (2021-03-20)
- Fix
testing.register_injectables
not creating the namespace when it doesn't exist
yet
3.4.5 (2021-03-11)
- Fix opening of UTF-8 files & allow for user set encoding
3.4.4 (2020-07-29)
- Fix
inject
return type hint
3.4.3 (2020-06-24)
- Fix Injectable failing to resolve complex/entangled imports
3.4.2 (2020-05-22)
- Fix optional injection bug when the namespace is empty
3.4.1 (2020-05-11)
- Fix the use of named args by the caller breaking autowired functions injection
3.4.0 (2020-05-09)
- Deprecate
InjectionContainer::load
in favor of load_injection_container
. - Change default namespace name from
"_GLOBAL"
to "DEFAULT_NAMESPACE"
. - Fix minor quirks with Python 3.7 and 3.8.
- Add tons of unit tests.
- Add
reset_injection_container
utility to injectable.testing
.
3.3.0 (2020-04-20)
- Include the
injectable.testing
utilities to ease mocking injectables.
3.2.1 (2020-04-19)
InjectionContainer::load
is more resilient against duplicated injectables
registering
3.2.0 (2020-04-15)
- Support for optional injection in declarative fashion:
Autowired(Optional[...])
3.1.4 (2020-04-15)
- Fix
Autowired(List[...])
not working with qualifiers
3.1.3 (2020-04-15)
- Fix Windows injectables not being loaded.
3.1.2 (2020-04-14)
- Remove unused
inspect
imports.
3.1.1 (2020-04-13)
- Fix bug of scanning the same module more than once when
InjectionContainer.load()
is called multiple times with different relative search paths.
3.1.0 (2020-04-13)
- Added
@injectable_factory
decorator for declaring injectable factory methods - Include the console output in the examples
3.0.1 (2020-04-13)
- Fix package content missing
3.0.0 (2020-04-12)
- Drop support for autowiring without previous initialization of the InjectionContainer
- Refactor
@autowired
decorator for working with the Autowired
type annotation - Added
@injectable
decorator for registering injectables to the InjectionContainer - Support for qualifiers, groups and namespaces
- Added
Autowired
type annotation for marking parameters for autowiring - Added
inject
and inject_multiple
as service locators - Added InjectionContainer for registering injectables
- Official support for Python 3.7 and 3.8
- Official support for Ubuntu, Windows and MacOS
- Drop Python 3.4 and 3.5 official support
- General code refactoring
- Official documentation
- Added usage examples
2.0.0 (2018-02-24)
- Drop Python 3.3 official support
1.1.2 (2018-02-24)
- Support for dependencies of classes without signature
- Fix bug of builtin types not being accepted for injectable dependencies
1.1.1 (2018-02-23)
- Statically infer dependency's constructor suitability for injection instead of using
trial instantiation
- Fix bug of raising
TypeError
when injectable fails on the trial dependency
instantiation which can happen when the dependency does provide a default
constructor with no arguments but the running environment (possibly a test suite
environment) will make the instantiation fail
1.1.0 (2018-02-10)
- Enable the use of
@autowired
decorator without parenthesis
1.0.1 (2018-02-10)
- Fixes required dependency
lazy_object_proxy
not being installed when installing
injectable through pip
1.0.0 (2018-02-06)
0.2.0 (2018-02-06)
- Support for lazy dependency initialization
- Support for type annotations with strings
0.1.1 (2018-02-05)
- Python 3.3 and 3.4 support
0.1.0 (2018-02-05)