Skip to main content

Type-based dependency-injection

Project description

logo

Build Status (License MIT 1.0)

enterprython

Python library providing type-based dependency-injection

Table of contents

Introduction

If you plan to develop SOLID/domain-driven (i.e., enterprisey) software, you probably want to apply dependency injection on your class constructors, and use a library doing the lookup for you based on static type annotations, instead of configuring the object graph manually.

enterprython provides exactly that.

from enterprython import assemble, component


@component()
class Service:
    def __init__(self) -> None:
        self._greeting: str = "Hello"

    def greet(self, name: str) -> str:
        return f"{self._greeting}, {name}!"


class Client:
    def __init__(self, service: Service) -> None:
        self._service = service

    def run(self) -> None:
        print(self._service.greet("World"))


assemble(Client).run()

Output:

Hello, World!

Features

Abstract base classes

A client may depend on an abstract base class. Enterprython will inject the matching implementation.

from abc import ABC
from enterprython import assemble, component

class ServiceInterface(ABC):
    ...

@component()
class ServiceImpl(ServiceInterface):
    ...

class Client:
    def __init__(self, services: ServiceInterface) -> None:
        ...

assemble(Client)

One singleton instance of ServiceImpl is created and injected into Client.

Factories

Annotating a function with @component() is registered as a factory for its return type.

from enterprython import assemble, component

class Service:
    ...

@component()
def service_factory() -> Service:
    return Service()

class Client:
    def __init__(self, service: Service) -> None:
        ...

assemble(Client)

service_factory is used to create the Service instance for calling the constructor of Client.

Non-singleton services

If a service is annotated with @component(singleton=False) a new instance of it is created with every injection.

@component(singleton=False)
class Service:
    ...

class Client:
    def __init__(self, service: Service) -> None:
        ...

Service lists

A client may depend on a list of implementations of a service interface.

from abc import ABC
from typing import List
from enterprython import assemble, component

class ServiceInterface(ABC):
    pass

@component()
class ServiceA(ServiceInterface):
    ...

@component()
class ServiceB(ServiceInterface):
    ...

class Client:
    def __init__(self, services: List[ServiceInterface]) -> None:
        ...

assemble(Client)

[ServiceA(), ServiceB()] is injected into Client.

Mixing managed and manual injection

One part of a client's dependencies might be injected manually, the rest automatically.

from enterprython import assemble, component

@component()
class ServiceA:
    ...

class ServiceB:
    ...

class Client:
    def __init__(self, service_a: ServiceA, service_b: ServiceB) -> None:
        ...

assemble(Client, service_b=ServiceB())

service_a comes from the DI container, service_b from user code.

If ServiceB also has a @component() annotation, the manually provided object is preferred.

Free functions as clients

Since class constructors are fundamentally just normal functions, we can inject dependencies into free functions too.

from enterprython import assemble, component

@component()
class Service:
    ...

def client(service: Service) -> None:
    ...

assemble(client)

A singleton instance of Service is created and used to call client.

Requirements and Installation

You need Python 3.6.5 or higher.

python3 -m pip install enterprython

Or, if you like to use latest version from this repository:

git clone https://github.com/Dobiasd/enterprython
cd enterprython
python3 -m pip install .

License

Distributed under the MIT License. (See accompanying file LICENSE or at https://opensource.org/licenses/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

enterprython-0.4.3.tar.gz (8.2 kB view details)

Uploaded Source

Built Distribution

enterprython-0.4.3-py3-none-any.whl (8.0 kB view details)

Uploaded Python 3

File details

Details for the file enterprython-0.4.3.tar.gz.

File metadata

  • Download URL: enterprython-0.4.3.tar.gz
  • Upload date:
  • Size: 8.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.18.4 setuptools/40.0.0 requests-toolbelt/0.8.0 tqdm/4.24.0 CPython/3.6.6

File hashes

Hashes for enterprython-0.4.3.tar.gz
Algorithm Hash digest
SHA256 3728d10e7b04a18c962debef76e4fefff49b4a0898e229fc78a7daa47fca6fe0
MD5 3c4c109284911028cd532f0acb4ab207
BLAKE2b-256 c9d402b8a7020f94d4f766e7245e08b09f34b0ff2d5b07550e4c493637fce9c0

See more details on using hashes here.

File details

Details for the file enterprython-0.4.3-py3-none-any.whl.

File metadata

  • Download URL: enterprython-0.4.3-py3-none-any.whl
  • Upload date:
  • Size: 8.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.18.4 setuptools/40.0.0 requests-toolbelt/0.8.0 tqdm/4.24.0 CPython/3.6.6

File hashes

Hashes for enterprython-0.4.3-py3-none-any.whl
Algorithm Hash digest
SHA256 43036c2a13a828693167264956410c3420a0e208a6191aa1a523efbd1d9a7de1
MD5 e0367ad20255fbe1f2f1e5753bcc0d81
BLAKE2b-256 af742956ec69794a6db70ff9c97139879f9b3c07680798e8267fb486c5b5d288

See more details on using hashes here.

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