Transparent dependency injection.
Project description
Antidote
Antidote is dependency injection module for Python 2.7 and 3.4+. It is designed to work with simple decorators and annotations. The goal is to recognize dependencies and inject them automatically.
Features Highlight
Dependencies bound through type annotations and optionally from variable names and/or mapping.
Simple decorators to handle pretty much everything.
Standard dependency injection features: singleton, factories, auto-wiring (automatically injecting dependencies of defined services, etc.)
Python 2.7 support (without annotations, obviously :))
Integration with the attrs package (>= v17.1).
Other dependencies, such as configuration parameters, can be easily added for injection as a dictionary.
Quick Start
A simple example with a external database for which you have an adapter which will be injected in other services.
For Python 3.4+, the dependency management is straight-forward:
from antidote import antidote
class Database(object):
"""
Class from an external library.
"""
def __init__(self, *args, **kwargs):
""" Initializes the database. """
# Simple way to add some configuration.
# Any object implementing __getitem__ works
antidote.container.extend(dict(
database_host='host',
database_user='user',
database_password='password',
))
# Declare a factory which should be called to instantiate Database
# Variables names are used here for injection.
@antidote.factory(use_arg_name=True)
def database_factory(database_host, database_user, database_password) -> Database:
"""
Configure your database.
"""
return Database(
host=database_host,
user=database_user,
password=database_password
)
# Declare DatabaseWrapper as a dependency to be injected
@antidote.register
class DatabaseWrapper(object):
"""
Your class to manage the database.
"""
# Dependencies of __init__() are injected by default when registering
# a dependency.
def __init__(self, db: Database):
self.db = db
@antidote.inject
def f(db: DatabaseWrapper):
""" Do something with your database. """
For Python 2, the example is a bit more verbose as you need to compensate for the lack of annotations:
from antidote import antidote
class Database(object):
"""
Class from an external library.
"""
def __init__(self, *args, **kwargs):
""" Initializes the database. """
# Simple way to add some configuration.
# Any object implementing __getitem__ works
antidote.container.extend(dict(
database_host='host',
database_user='user',
database_password='password',
))
# Declare a factory which should be called to instantiate Database
# Variables names are used here for injection.
# PY2: The id of the returned service is specified
@antidote.factory(use_arg_name=True, id=Database)
def database_factory(database_host, database_user, database_password):
"""
Configure your database.
"""
return Database(
host=database_host,
user=database_user,
password=database_password
)
# Declare DatabaseWrapper as a dependency to be injected
# PY2: A class-wide argument -> dependency mapping is specified,
@antidote.register(mapping=dict(db=Database))
class DatabaseWrapper(object):
"""
Your class to manage the database.
"""
# Dependencies of __init__() are injected by default when registering
# a dependency.
def __init__(self, db):
self.db = db
# PY2: An argument -> dependency mapping is specified
@antidote.inject(mapping=dict(db=DatabaseWrapper))
def f(db):
""" Do something with your database. """
Documentation
The documentation is available at https://antidote.readthedocs.io/.
Why ?
Dependency injection is, IMHO, a fundamental tool when working on projects. As it grows the more necessary it becomes to decouple your code by defining clearly in only one place how an object or a function should be called with which dependencies.
So while searching for a dependency injection library, I had three requirements in mind:
Use of annotations compatible with type checker such as mypy to inject dependencies. But other ways should exist, as configuration parameters cannot be injected this way for example.
IMHO, the strict minimum of a dependency injection library: services, factories, and something to inject those in any callable which injects their dependencies.
The library should be easy to integrate in existing code, be it in Python 2 (it’s not gone, yet) or 3. Ideally one should be able to use injected classes or functions like any other. Usage should be transparent, which leads to easier integration and adoption.
However, I did not found a suitable library and was actually surprised to see that dependency injection was not commonly used in Python. So I created this project to answer those requirements.
TODO
Better support for configuration (ConfigParser typically)
tags to filter services and retrieve a list of them.
proxies ?
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file antidote-0.1.0.tar.gz
.
File metadata
- Download URL: antidote-0.1.0.tar.gz
- Upload date:
- Size: 10.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 68e14696aa9206912bddde51cc8ef9c72d8093e2efc42b457d074bc97e0c4a08 |
|
MD5 | 722e044841b57f2fdd9d8874017de996 |
|
BLAKE2b-256 | cfcea8142e14213a9a005b2e3b85fe6f1d0758be652b2bae2d31445f72d186f4 |
Provenance
File details
Details for the file antidote-0.1.0-py2.py3-none-any.whl
.
File metadata
- Download URL: antidote-0.1.0-py2.py3-none-any.whl
- Upload date:
- Size: 16.0 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | cd615b52899624af0177782d7cf69f6029a0b0c9eba13c29d57a5956412a3f79 |
|
MD5 | a3025fba0d4edbe6e972deee588c4df8 |
|
BLAKE2b-256 | ffd25cbc27cd872191dda529b1846f54ec771b0795b4714c259ab84ed43e45e5 |