Skip to main content

Python dependency injection library

Project description

pythondi

license pypi pyversions badge


pythondi is a lightweight dependency injection library for python

Installation

pip3 install pythondi

Usage

Binding classes and configure

from pythondi import Provider, configure, configure_after_clear


# Init provider
provider = Provider()

# Bind `Impl` class to `Interface` class
provider.bind(Repo, SQLRepo)

# Inject with configure
configure(provider=provider)

# Or if you want to fresh inject, use `configure_after_clear`
configure_after_clear(provider=provider)

Import inject

from pythondi import inject

Add type annotations that you want to inject dependencies

class Usecase:
    def __init__(self, repo: Repo):
        self.repo = repo

Add decorator

class Usecase:
    @inject()
    def __init__(self, repo: Repo):
        self.repo = repo

Initialize class with no arguments

usecase = Usecase()

Or, you can also inject manually through decorator arguments

class Usecase:
    @inject(repo=SQLRepo)
    def __init__(self, repo):
        self.repo = repo

In this case, do not have to configure providers and type annotation.

Note

At the moment of inject, class is automatically initialized.

So you don't have to initialize your class inside of code.

Yes:

@inject()
def __init__(self, repo: Repo):
    self.repo = repo

No:

@inject()
def __init__(self, repo: Repo):
    self.repo = repo()

General example

import abc

from pythondi import Provider, configure, configure_after_clear, inject


class Repo:
    """Interface class"""
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def get(self):
        pass


class SQLRepo(Repo):
    """Impl class"""
    def get(self):
        print('SQLRepo')


class Usecase:
    @inject()
    def __init__(self, repo: Repo):
        self.repo = repo


if __name__ == '__main__':
    # Init provider
    provider = Provider()

    # Bind `Impl` class to `Interface` class
    provider.bind(Repo, SQLRepo)

    # Inject with configure
    configure(provider=provider)

    # Or if you want to fresh injection, use `configure_after_clear`
    configure_after_clear(provider=provider)

    # Init class without arguments
    u = Usecase()

Flask example

from flask import Flask, Blueprint, jsonify

from pythondi import Provider, configure, inject
from .repo import Repo, SQLRepo

bp = Blueprint('home', __name__)


@bp.route('/')
def home():
    usecase = Usecase()
    usecase.repo.get()
    return jsonify({'hello': 'world'})


class Usecase:
    @inject()
    def __init__(self, repo: Repo):
        self.repo = repo


def create_app():
    provider = Provider()
    provider.bind(Repo, SQLRepo)
    configure(provider=provider)
    app = Flask(__name__)
    app.register_blueprint(bp)
    return app


if __name__ == '__main__':
    app = create_app()
    app.run(debug=True)

Sanic example

import abc

from sanic import Sanic, Blueprint
from sanic.response import json
from pythondi import Provider, configure, inject


class Repo:
    """Interface class"""
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def get(self):
        pass


class SQLRepo(Repo):
    """Impl class"""
    def __init__(self):
        pass

    def get(self):
        print('SQLRepo')


bp = Blueprint('home', url_prefix='/')


@bp.route('/')
async def home(request):
    usecase = Usecase()
    usecase.repo.get()
    return json({'hello': 'world'})


class Usecase:
    @inject()
    def __init__(self, repo: Repo):
        self.repo = repo


def create_app():
    provider = Provider()
    provider.bind(Repo, SQLRepo)
    configure(provider=provider)
    app = Sanic(__name__)
    app.blueprint(bp)
    return app


if __name__ == '__main__':
    app = create_app()
    app.run(debug=True)

Django example

"""
In case of django, just put the initializing code inside of django startup

You can use project folder's __init__.py or urls.py
"""

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

pythondi-1.1.0.tar.gz (4.3 kB view details)

Uploaded Source

File details

Details for the file pythondi-1.1.0.tar.gz.

File metadata

  • Download URL: pythondi-1.1.0.tar.gz
  • Upload date:
  • Size: 4.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/2.0.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.0.1 requests-toolbelt/0.9.1 tqdm/4.38.0 CPython/3.7.4

File hashes

Hashes for pythondi-1.1.0.tar.gz
Algorithm Hash digest
SHA256 e1d4f0f7fc835e9be69563780717ee20ab3a2dc888052a89ff834f4f06f7a3ee
MD5 66b647143c7bdcfe7eb4e07a83b406b3
BLAKE2b-256 2a662b2fd5f133a036f486a4d972a008e567a769cc16b50fe90d6610999caa35

See more details on using hashes here.

Supported by

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