Skip to main content

A simple and efficient Python library for handling dependency injection.

Project description

haldi logo

haldi

Async-first dependency injection container for Python. It supports transient, scoped, and singleton lifetimes, resolves constructor (or callable) dependencies via type annotations, and can manage async context managers during resolution.

Requires Python 3.10 or newer.

Features

  • Async resolve() and get_executor() APIs
  • Service lifetimes: transient, scoped, singleton
  • Multiple registrations per interface (resolve returns a list)
  • Ordered union resolution for typing.Union[...], A | B, and Optional[T]
  • Optional lifetime-compatibility warning (singleton depending on scoped)
  • Async context manager support for factories

Installation

pip install haldi

Haldi now targets Python 3.10+.

Quick start

from haldi import Container

class Repo:
	...

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

container = Container()
container.add_transient(Repo)
container.add_scoped(Service)

# Resolve inside an async context
service = await container.get(Service)

Service lifetimes

  • Transient: a new instance every time.
  • Scoped: one instance per scope. Use create_scope() or scoped().
  • Singleton: one instance for the container lifetime.
container = Container()
container.add_transient(Repo)
container.add_scoped(Service)
container.add_singleton(Config)

scope = container.create_scope()
svc_a = await scope.get(Service)
svc_b = await scope.get(Service)
assert svc_a is svc_b

Multiple implementations

Register multiple providers for the same interface and resolve() returns a list.

class Interface:
	...

class ImplA(Interface):
	...

class ImplB(Interface):
	...

container.add_transient(Interface, ImplA)
container.add_transient(Interface, ImplB)

instances = await container.resolve(Interface)

Union annotations

Union-typed dependencies are resolved in declaration order. The first branch that can be resolved wins.

class Cache:
	...

class Repository:
	...

class Service:
	def __init__(self, dep: Cache | Repository | None):
		self.dep = dep

If Cache is registered, it will be injected. If not, Haldi tries Repository. If neither is registered, the final None branch is used.

Factory registration

Factories can be callables (sync or async). Return annotations are required unless using a lambda.

async def build_client() -> Client:
	return Client()

container.add_singleton(Client, build_client)

Scoped context helper

Use scoped() to automatically close async context managers created during resolution.

async with container.scoped() as scope:
	service = await scope.get(Service)

Warnings

If a singleton depends on a scoped service, a UserWarning is emitted because the scoped instance would be captured for the lifetime of the singleton.

API overview

  • Container.add_transient(type, concrete_type=None)
  • Container.add_scoped(type, concrete_type=None)
  • Container.add_singleton(type, concrete_type=None)
  • await Container.resolve(type, strict=True)
  • await Container.get(type)
  • await Container.try_get(type)
  • await Container.get_executor(callable, strict=True)
  • Container.create_scope()
  • Container.scoped()

Development

pip install -e .
pytest

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

haldi-0.7.tar.gz (9.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

haldi-0.7-py3-none-any.whl (10.1 kB view details)

Uploaded Python 3

File details

Details for the file haldi-0.7.tar.gz.

File metadata

  • Download URL: haldi-0.7.tar.gz
  • Upload date:
  • Size: 9.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for haldi-0.7.tar.gz
Algorithm Hash digest
SHA256 a5c4a2e5f19f43ce59a9acc11ca009cd6191f709a5250d05988217bceee1aff6
MD5 cc10000c654b4fe553337a6706691383
BLAKE2b-256 102fff4625ded2b4ef943e80d65733b324b890951c8fa60f063c712a89f987ea

See more details on using hashes here.

File details

Details for the file haldi-0.7-py3-none-any.whl.

File metadata

  • Download URL: haldi-0.7-py3-none-any.whl
  • Upload date:
  • Size: 10.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for haldi-0.7-py3-none-any.whl
Algorithm Hash digest
SHA256 f3a3c2827a7ebb0a62ba306850d08d761ba9e55f779da4cb476d2d190441c992
MD5 0fc990ac0d4cb29cdb75848ec9cb4ae9
BLAKE2b-256 67fae29ea08e1425299c82216307cb8a8968ff1c8b8c48c0789b46d5d0cfb3e6

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