Skip to main content

A minimal dependency injection framework for Python with zero dependencies. Features type-hints support, singleton caching, and both type and string-based identifiers.

Project description

mindi

A lightweight dependency injection framework for Python.

  • Zero external dependencies
  • Type hint support
  • Automatic singleton instance caching
  • Support for both type and string identifiers
  • Dependency cycle detection
  • Dependency graph verification
  • Support for dataclasses and named tuples

Quick Start

Installation:

python3 -m pip install mindi

A simple example to get you started:

from mindi import Container

di = Container()

@di.bind
class Database:
    def query(self):
        return "data from database"

@di.wire
def main(db: Database = di.use(Database)):
    print(db.query())

main()  # Prints: "data from database"

Examples

Binding Providers

Bind your providers in multiple ways:

# Simple class binding
@di.bind
class Service:
    pass

# With constructor arguments
@di.bind(url="localhost")
class Database:
    def __init__(self, url):
        self.url = url

# Using string identifiers
di.bind("dev_db", Database, url="dev-host")
di.bind("prod_db", Database, url="prod-host") 

# Using factory functions
di.bind("config", lambda: {"api_key": "secret"})

Dependency Injection

It automatically resolves dependencies marked with di.use():

# Constructor injection
@di.bind
class Service:
    # @di.wire  <== This line is not needed, this is handled by @di.bind
    def __init__(self, db: Database = di.use(Database)):
        self.db = db

# Function injection by type
@di.wire
def handle_request(service: Service = di.use(Service)):
    return service.db.query()

# Function injection by string identifier
di.bind("dev_db", Database)
@di.wire
def handle_dev_request(db = di.use("dev_db")):
    return db.query()

String Identifiers

from mindi import Container
from mindi.core import identifier

di = Container()

class Foo:
    pass

# These binding examples are equivalent:
di.bind(Foo)
di.bind(Foo, Foo)
di.bind(Foo, lambda: Foo())
di.bind(identifier(Foo), Foo)
di.bind(f"{Foo.__module__}.{Foo.__qualname__}", Foo)

Working with Dataclasses

from dataclasses import dataclass, field

@dataclass
class Config:
    api_key: str
    timeout: int = field(default=30)
    database: Database = di.use(Database)

di.bind("config", Config, api_key="secret")

@di.wire
def process(config: Config = di.use("config")):
    print(f"Using API key: {config.api_key}")
    print(f"Database: {config.database.url}")

Wiring Classes and Binding Functions

You can wire both functions and classes:

di.bind("value", lambda: 123)

@di.bind
class Service:
    def __init__(self, value: int = di.use("value")):
        self.value = value

# Create a wired service factory
@di.bind
def WiredService():
    return di.wire(Service)()

@di.wire
def get_value(service: Service = di.use(WiredService)):
    return service.value  # Returns 123

Rebinding for Tests

Dependency overriding for tests:

# Enable rebinding
di = Container(rebind=True)

class MockDatabase:
    def query(self):
        return "test data"

# Override production database with mock
di.bind(Database, lambda: MockDatabase())

Dependency Verification

Verify your dependency graph:

# Verify all dependencies
di.instantiate()

# Verify specific service
db = di.instantiate("db")

The framework will detect and report circular dependencies with clear error messages.

License

MIT License

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

mindi-0.1.0.tar.gz (3.7 kB view details)

Uploaded Source

Built Distribution

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

mindi-0.1.0-py3-none-any.whl (4.2 kB view details)

Uploaded Python 3

File details

Details for the file mindi-0.1.0.tar.gz.

File metadata

  • Download URL: mindi-0.1.0.tar.gz
  • Upload date:
  • Size: 3.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.12.4

File hashes

Hashes for mindi-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3e8ea6ff3543c988633bcf458b9bbb913c551da90dddfcf4310c7631731f61a5
MD5 386b8ba5d1abc7be86f6904c3f308a3c
BLAKE2b-256 d81ae3cfc8c3e529526bb8f506e0233ee8a824306efd1a7b5ad5c759b925aba5

See more details on using hashes here.

File details

Details for the file mindi-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: mindi-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 4.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.12.4

File hashes

Hashes for mindi-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8b07d1dc355ca910974eb29671bc689d5e85b21bda08c52100cd444599ef536a
MD5 43830547e7280b962f95d4c43d08a56f
BLAKE2b-256 f6ac7f022747be6c20d9b3a425a54b1dda583b923181525c7508504051fd0174

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