Skip to main content

Easy-DI: Lightweight Dependency Injection for Python 🚀🚀🚀

Introduction 🎯🔧📌

Easy-DI is a simple yet powerful Python library for dependency injection. It helps you manage dependencies efficiently, promoting modular, reusable, and testable code. With Easy-DI, you can dynamically register and inject dependencies using decorators, making dependency management seamless. ✅✅✅

Key Features ✨🔥💡

  • Decorator-based dependency injection for clean and intuitive code
  • Dynamic registration and unregistration of dependencies
  • Support for various dependency types: functions, classes, objects, and more
  • Strict enforcement of string-based dependency IDs
  • Grouped dependency injection for better organization
  • Supports wildcard injection (group.*) to inject all dependencies from a group as separate elements
  • Supports bulk unregistration using wildcard patterns (e.g., *, group.*)
  • Full compatibility with Python's type hints for type safety

Installation 💻📦⚙️

Easy-DI has no external dependencies. You can install it using your preferred package manager:

Using pip 🐍📌✅

pip install di-easy

Using Poetry 🎼📌✅

poetry add di-easy

Using uv ⚡📌✅

uv pip install di-easy

or

uv add di-easy

Usage Guide 📝🚀🔍

Basic Dependency Injection 🏗️🔄🎯

from easy_di import BaseInjector

# Define a class to be used as a dependency
class Service:
    def process(self, arg):
        return f"Processed: {arg}"

# Register an instance of the class as a dependency
BaseInjector.register("service", Service())  # IDs must be strings

# Define a function with dependency injection
@BaseInjector("service")
def my_function(deps, arg):
    return deps["service"].process(arg)

print(my_function("Hello"))  # Output: "Processed: Hello"

✅ In BaseInjector, dependencies can be registered before or after the function is defined, but must be registered before the function is first called.

Grouped Dependency Injection 🎯🔗📌

from easy_di import GroupInjector

# Register a dependency group with multiple dependencies
GroupInjector.register_dependency_group("services", logger=lambda msg: f"Log: {msg}", config={"debug": True})

# Define a function with grouped injection
@GroupInjector("services.logger", "services.config")
def log_message(deps, message):
    return f"{deps['services.logger'](message)} | Debug: {deps['services.config']['debug']}"

print(log_message("An event occurred"))  # Output: "Log: An event occurred | Debug: True"

✅ In GroupInjector, dependencies can also be registered before or after the function definition, but must be registered before its first invocation. When registering a dependency into a group, ensure that the group is registered first (unless you set if_group_not_exists="create").

Wildcard Group Injection (group.*) 🎯✨🔧

You can inject all dependencies from a group using the group.* pattern. Each dependency in the group will be added as a separate element in deps.

from easy_di import GroupInjector

# Register a dependency group with multiple dependencies
GroupInjector.register_dependency_group("config", host="localhost", port=8080, debug=True)

# Inject all elements of the group as separate entries in `deps`
@GroupInjector("config.*")
def app_settings(deps):
    return f"Host: {deps['config.host']}, Port: {deps['config.port']}, Debug: {deps['config.debug']}"

print(app_settings())  # Output: "Host: localhost, Port: 8080, Debug: True"

Bulk Unregistration with Wildcards ❌🧹🚫

You can unregister multiple dependencies at once using wildcard patterns:

from easy_di import BaseInjector, GroupInjector

BaseInjector.unregister("*")  # Unregister all dependencies in BaseInjector
GroupInjector.unregister_dependency("test.*")  # Unregister all dependencies in group "test"
GroupInjector.unregister_dependency_group("*")  # Unregister all dependency groups and their dependencies

API Reference 📚🔍🛠️

BaseInjector ⚙️🔄📌

BaseInjector(dependency_id: str)

Decorator that injects a registered dependency into a function.

BaseInjector.register(dependency_id: str, dependency: Any) -> None

Registers a dependency using a string ID.

BaseInjector.unregister(dependency_id: str) -> None

Unregisters a dependency by its ID. Supports "*" to unregister all.


GroupInjector 🔗⚙️📌

GroupInjector(dependency_id: str, *, group_deps: bool = False)

Decorator that injects dependencies from a registered group.

group_deps: If true, group the dependencies into named collections in format {group_id: {dependency_id: dependency}}.

GroupInjector.register_dependency_group(group_id: str, **dependencies: Any) -> None

Registers a dependency group containing multiple dependencies.

GroupInjector.register_dependency(dependency_id: str, dependency: Any, group_id: Optional[str] = None, *, if_group_not_exists: Literal["error", "create"] = "error") -> None

Registers a dependency inside an existing group.

if_group_not_exists: What to do when the group is not registered. Use "error" to raise an exception or "create" to automatically create the group.

GroupInjector.unregister_dependency(dependency_id: str, group_id: Optional[str] = None) -> None

Unregisters a specific dependency from a group. Supports wildcards (e.g., "group.*").

GroupInjector.unregister_dependency_group(group_id: str) -> None

Unregisters an entire dependency group. Supports "*" to unregister all groups.

Development & Configuration 🛠️💡🔧

Easy-DI follows PEP8 guidelines and enforces strict type checking with MyPy. The following tools are used in development:

  • coverage (test coverage analysis)
  • isort (import sorting)
  • mypy (static type checking)
  • ruff (linting and code formatting)

License 📜✅🔓

Easy-DI is released under the MIT License.

Contributing 🤝📢📌

Contributions are welcome! Feel free to open issues or submit pull requests.

Support & Contact 📩💬📌

For questions or support, please open an issue in the repository.

Metadata

Release files for di-easy 1.1.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 di-easy 1.1.0
File Size Uploaded
di_easy-1.1.0.tar.gz 7.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for di-easy 1.1.0
File Interpreter ABI Platform
di_easy-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 17.0 kB

Release files / di_easy-1.1.0.tar.gz

Download URL di_easy-1.1.0.tar.gz
Size 7.7 kB
Tags Source
SHA-256 checksum
How to use checksums
48365ccd1d49335d2c10fbad9917ad8bf343ca9616aeb03cda3ac9765bc88ed4
BLAKE2b-256 checksum
How to use checksums
45adf186da5c405c597cb9beaa024558b979cbed27c2b8317a4b548fbc56c508
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.3

Release files / di_easy-1.1.0-py3-none-any.whl

Download URL di_easy-1.1.0-py3-none-any.whl
Size 9.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4406f768acbaa1c20434cad36c13d1d8dc31c71a179c2db6d21335f73616f67f
BLAKE2b-256 checksum
How to use checksums
fdc05bfe89c8e93c31b07cf59292e31cbff3fc2671402c22a7f4cd524050b125
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

1.0.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