Skip to main content

Transparent dependency injection.

Project description

https://travis-ci.org/Finistere/antidote.svg?branch=master https://codecov.io/gh/Finistere/antidote/branch/master/graph/badge.svg Documentation Status

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


Download files

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

Source Distribution

antidote-0.1.0.tar.gz (10.6 kB view details)

Uploaded Source

Built Distribution

antidote-0.1.0-py2.py3-none-any.whl (16.0 kB view details)

Uploaded Python 2 Python 3

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

Hashes for antidote-0.1.0.tar.gz
Algorithm Hash digest
SHA256 68e14696aa9206912bddde51cc8ef9c72d8093e2efc42b457d074bc97e0c4a08
MD5 722e044841b57f2fdd9d8874017de996
BLAKE2b-256 cfcea8142e14213a9a005b2e3b85fe6f1d0758be652b2bae2d31445f72d186f4

See more details on using hashes here.

Provenance

File details

Details for the file antidote-0.1.0-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for antidote-0.1.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 cd615b52899624af0177782d7cf69f6029a0b0c9eba13c29d57a5956412a3f79
MD5 a3025fba0d4edbe6e972deee588c4df8
BLAKE2b-256 ffd25cbc27cd872191dda529b1846f54ec771b0795b4714c259ab84ed43e45e5

See more details on using hashes here.

Provenance

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