Lidi (LIghtweight Dependency Injector)
Lidi is a lightweight dependency injector designed to simplify dependency management in your Python projects.
It provides a simple and intuitive API for binding classes and resolving dependencies.
Installation
You can install Lidi using pip:
pip install lidipy
Usage
Basic Binding
To bind a class to an instance or a callable, you can use the bind()
method of the Lidi
instance:
from lidipy import Lidi
class Parent:
pass
class Child:
pass
lidi = Lidi()
lidi.bind(Parent, Child())
lidi.bind(Parent, Child)
Singleton Binding
If you want to bind a class as a singleton, you can pass the singleton
parameter as True
when calling the bind()
method:
lidi.bind(Parent, Child(), singleton=True)
With singleton binding, the same instance of the class will be returned every time it is resolved.
Resolving Dependencies
To resolve a class and its dependencies, you can use the resolve()
method of the Lidi class:
instance = lidi.resolve(Parent)
If the class was bound as a singleton, the same instance will be returned each time it is resolved.
Deferred Resolution
Lidi also supports deferred resolution using the resolve_defer()
method. This method returns a callable that, when invoked, resolves the class:
deferred_resolve = lidi.resolve_defer(Parent)
instance = deferred_resolve()
Class Attribute Resolution
Class attributes are often services or repositories. Lidi supports resolution of bindings using the resolve_attr
method.
lidi.bind(Parent, Child)
class Repository:
service: Parent = lidi.resolve_attr(Parent)
Handling Missing Bindings
If a binding is missing for a requested type, a BindingMissing
exception will be raised.
You can handle this exception and provide appropriate error handling in your application.
from lidipy import BindingMissing
try:
instance = lidi.resolve(Mother)
except BindingMissing as e:
print(e)
Usage with Dataclasses
Lidi can be used seamlessly with Python's dataclasses. Here's an example of how to use dataclasses with Lidi:
from dataclasses import dataclass
from lidipy import Lidi
lidi = Lidi()
@dataclass(frozen=True)
class Config:
db_url: str
lidi.bind(Config, Config(db_url="example.com:5432"))
@dataclass
class Database:
config: Config = lidi.resolve(Config)
def connect(self):
print(f"Connecting to database at {self.config.db_url}")
lidi.bind(Database, Database)
database = lidi.resolve(Database)
database.connect()
Dynamic binds on runtime
Lidi supports bindings change on runtime, here's an example:
from dataclasses import dataclass, field
from lidipy import Lidi
lidi = Lidi()
@dataclass
class Config:
db_url: str
@dataclass
class Database:
config: Config = field(default_factory=lidi.resolve_defer(Config))
def connect(self):
print(f"Connecting to database at {self.config.db_url}")
lidi.bind(Config, Config(db_url="example.com:5432"))
lidi.bind(Database, Database)
database = lidi.resolve(Database)
database.connect()
lidi.bind(Config, Config(db_url="other-example.com:5432"))
database = lidi.resolve(Database)
database.connect()
Contributing
Contributions are welcome! If you find a bug or want to suggest an improvement, please open an issue or submit a pull request on the GitHub repository.
License
Lidi is licensed under the MIT License.
Feel free to use, modify, and distribute this project as per the terms of the license.