Skip to main content

Meta DI - A DI Container for Python using meta-programming (source generation)

This is a DI Container for Python using meta-programming (source generation). Since we know the dependencies and their lifecycles when generating the source code, we can optimize the generated code to avoid unnecessary lookups and function calls, achieving very good performance.

Installation

pip install meta-di

Quickstart

from meta_di import ContainerBuilder

class Config:
    USER: str = "admin"
    PASSWORD: str = "admin"

class AuthServiceProto:
    def authenticate(self, user: str, password: str) -> bool:
        """Returns true if user/password is valid"""
        ...

class FakeAuthService(AuthServiceProto):
    def __init__(self, config: Config):
        self._config = config

    def authenticate(self, user: str, password: str) -> bool:
        if self._config.USER == user and self._config.PASSWORD == password:
            return True
        return False

builder = ContainerBuilder()

# We register AuthServiceProto with transient, meaning that a new instance will be created every time it is requested
# We also specify that the provider for AuthServiceProto is FakeAuthService
builder.add_transient(AuthServiceProto, FakeAuthService)

# FakeAuthService has a dependency on Config, so we must register it as well
# We register Config as a singleton, meaning that the same instance will be returned every time it is requested
builder.add_singleton(Config)

# We build the container
container = builder.build()

# We can now request AuthServiceProto from the container
# The container will create a new instance of FakeAuthService and inject it with the singleton instance of Config
auth_service = container.get(AuthServiceProto)
auth_service2 = container.get(AuthServiceProto)

assert isinstance(auth_service, FakeAuthService)
assert auth_service is not auth_service2 # Auth service is transient, so we get a new instance every time
assert auth_service._config is auth_service2._config # Config is singleton, so we get the same instance every time
assert auth_service.authenticate("admin", "admin") is True

Other features

Scoped lifetime

from meta_di import ContainerBuilder

class Service:
    pass

container = ContainerBuilder().add_scoped(Service).build()

with container as scoped_container:
    service1 = scoped_container.get(Service)
    service2 = scoped_container.get(Service)
    # Scoped lifetime, so we get the same instance within the scope
    assert service1 is service2 

# Alterntively, we can create a scope with create_scope()
scoped_container = container.create_scope()
service3 = scoped_container.get(Service)
service4 = scoped_container.get(Service)

# Scoped lifetime, so we get the same instance within the scope
assert service3 is service4
# Different scopes, so we get different instances
assert service1 is not service3

Function providers

from meta_di import ContainerBuilder, ContainerProto

class Dependency:
    pass

class Service:
    def __init__(self, dependency: Dependency, value: str):
        self.dependency = dependency
        self.value = value

# We can use this function to provide Service
# container will be injected by the container (as itself)
def service_provider(container: ContainerProto):
    return Service(
        dependency=container.get(Dependency),
        value="from function provider",
    )

# Alternatively, we could write the function this way
# Dependency will be injected by the container
def service_provider(dependency: Dependency):
    return Service(
        dependency=dependency,
        value="from function provider",
    )

container = ContainerBuilder().add_transient(Dependency).add_transient(Service, service_provider).build()
assert container.get(Service).value == "from function provider"

Building Container class or getting the generated source code

from meta_di import ContainerBuilder

class Service:
    pass

builder = ContainerBuilder().add_singleton(Service)

# This will return the generated source code for the Container class
# You can use this to inspect the generated code or save it to a file
source_code = builder.get_code()

# This will generate the Container class and return it
ContainerClass = builder.build_class()
# You can use this class to create any number of container instances
container = ContainerClass()
container2 = ContainerClass()

# NOTE, each container instance will have its own singleton instances
assert container.get(Service) is not container2.get(Service)

Release files for meta-di 0.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for meta-di 0.0.1
File Size Uploaded
meta_di-0.0.1.tar.gz 4.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for meta-di 0.0.1
File Interpreter ABI Platform
meta_di-0.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 14.6 kB

Release files / meta_di-0.0.1.tar.gz

Download URL meta_di-0.0.1.tar.gz
Size 4.3 kB
Tags Source
SHA-256 checksum
How to use checksums
12e5a2cb2b79cb23b625908304b3a511c7f5757efe648a00cb0523b89a18663c
BLAKE2b-256 checksum
How to use checksums
d6cd2b3ad7e623dbc45cd82391f63ed5d0d19d0e2ba6271484cfe004b018574e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-httpx/0.24.1

Release files / meta_di-0.0.1-py3-none-any.whl

Download URL meta_di-0.0.1-py3-none-any.whl
Size 10.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
77b4efbb07d3583d9cec03b632d9d3f9b6d7ee37596cd4f4cd3c0351ec325c62
BLAKE2b-256 checksum
How to use checksums
444ab508531a7d70d2e3da41d9dab7146523d89e1cc26ce232a1c32c52a88812
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-httpx/0.24.1

Release history Release notifications | RSS feed

This release

0.0.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page