Skip to main content

NestDI

NestDI is a lightweight and powerful Dependency Injection (DI) container for Python, heavily inspired by the architecture of NestJS. It allows you to organize your code into modules, making your applications easier to maintain, test, and scale.

🚀 Features

  • Decorator-based: Use @Module(), @Injectable(), and @Controller() to define your structure.
  • Scope Management: Support for SINGLETON, TRANSIENT, and REQUEST scopes.
  • Automatic Injection: Automatic dependency resolution through type hints in constructors.
  • Module System: Encapsulation and reuse of logic through imports and exports.
  • Flexible Providers: Support for classes, constant values, and factories.
  • Circular Dependency Detection: Throws clear exceptions when cycles are detected.
  • Strongly Typed: Full support for MyPy and Pyright with .typed.

📦 Installation

Since this project uses PDM, you can install it via:

pdm add nestdi

Or via pip (if published):

pip install nestdi

🛠️ Usage Guide

1. Defining Providers

Mark your classes with @Injectable() so NestDI can instantiate and inject them.

from nestdi import Injectable

@Injectable()
class LoggingService:
    def log(self, message: str):
        print(f"[LOG]: {message}")

@Injectable()
class UserService:
    def __init__(self, logger: LoggingService):
        self.logger = logger

    def get_user(self):
        self.logger.log("Fetching user...")
        return {"id": 1, "name": "John Doe"}

2. Creating Modules

Modules organize related components.

from nestdi import Module

@Module(
    providers=[LoggingService, UserService],
    exports=[UserService] # Export so other modules can use it
)
class UserModule:
    pass

3. Controllers and Root Container

Controllers are entry points for your logic.

from nestdi import Controller, Module

@Controller()
class UserController:
    def __init__(self, user_service: UserService):
        self.user_service = user_service

    def detail(self):
        return self.user_service.get_user()

@Module(
    imports=[UserModule],
    controllers=[UserController]
)
class AppModule:
    pass

4. Initialization and Usage

from nestdi import ModuleClass

# The @Module decorator returns a ModuleClass instance
app: ModuleClass = AppModule

# Getting the resolved controller
user_controller = app.get(UserController)
print(user_controller.detail())

🌍 Global Modules

If you want a module's providers to be available throughout the application without needing to import it in every module, use the @Global() decorator.

from nestdi import Module, Global, Injectable

@Injectable()
class GlobalService:
    pass

@Global()
@Module(
    providers=[GlobalService],
    exports=[GlobalService]
)
class CommonModule:
    pass

📐 Provider Scopes

You can define how instances are created:

  • ProviderScope.SINGLETON (Default): A single instance is created and shared across the entire application.
  • ProviderScope.TRANSIENT: A new instance is created every time the provider is requested.
  • ProviderScope.REQUEST: A new instance is created for each "request" (useful in web contexts).
from nestdi import Injectable, ProviderScope

@Injectable(scope=ProviderScope.TRANSIENT)
class GeneratorService:
    pass

🏭 Factory Providers

from nestdi import Provider, Module

def connection_factory(config_service: ConfigService):
    return DatabaseConnection(config_service.db_url)

@Module(
    providers=[
        Provider(
            provide="DATABASE_CONNECTION",
            use_factory=connection_factory,
            inject=[ConfigService]
        )
    ]
)
class DatabaseModule:
    pass

📝 License

This project is licensed under the MIT License.

Metadata

Release files for nestdi 0.2.0

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

Source distribution (sdist)

Source distribution for nestdi 0.2.0
File Size Uploaded
nestdi-0.2.0.tar.gz 4.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nestdi 0.2.0
File Interpreter ABI Platform
nestdi-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 9.8 kB

Release files / nestdi-0.2.0.tar.gz

Download URL nestdi-0.2.0.tar.gz
Size 4.6 kB
Tags Source
SHA-256 checksum
How to use checksums
1e92fbe5d265937b1694a2a53399ee8dcc8fe0c5ec57bbb7a8ec50559af78490
BLAKE2b-256 checksum
How to use checksums
b261a57f46f0cbccb02b40eb076e6651da710fd310cbc6899dfc8f762818276b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via pdm/2.25.5 CPython/3.12.2 Linux/6.6.87.2-microsoft-standard-WSL2

Release files / nestdi-0.2.0-py3-none-any.whl

Download URL nestdi-0.2.0-py3-none-any.whl
Size 5.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
45517ff0c906fbdf35547df02ac622453e46f90291c50a7744b323f22dccacf8
BLAKE2b-256 checksum
How to use checksums
e073b35d97c1c90a6b06dc991f8d576e9c109b6f3471836ac81142a3590372e6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via pdm/2.25.5 CPython/3.12.2 Linux/6.6.87.2-microsoft-standard-WSL2

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

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