Skip to main content

Library for easy dependency injection

Project description

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.

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

di_easy-1.1.0.tar.gz (7.7 kB view details)

Uploaded Source

Built Distribution

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

di_easy-1.1.0-py3-none-any.whl (9.2 kB view details)

Uploaded Python 3

File details

Details for the file di_easy-1.1.0.tar.gz.

File metadata

  • Download URL: di_easy-1.1.0.tar.gz
  • Upload date:
  • Size: 7.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.3

File hashes

Hashes for di_easy-1.1.0.tar.gz
Algorithm Hash digest
SHA256 48365ccd1d49335d2c10fbad9917ad8bf343ca9616aeb03cda3ac9765bc88ed4
MD5 a125d147d25ffe5cc19c7ecc7d93c684
BLAKE2b-256 45adf186da5c405c597cb9beaa024558b979cbed27c2b8317a4b548fbc56c508

See more details on using hashes here.

File details

Details for the file di_easy-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: di_easy-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 9.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.3

File hashes

Hashes for di_easy-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4406f768acbaa1c20434cad36c13d1d8dc31c71a179c2db6d21335f73616f67f
MD5 f6e8ec1125e52598c5a722a802dea3c9
BLAKE2b-256 fdc05bfe89c8e93c31b07cf59292e31cbff3fc2671402c22a7f4cd524050b125

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