A python dependency injection lib
Project description
PyDIT (Python Dependency Injection with Typing)
Description
With PyDit you can use ABC and Protocol to make interfaces and use the power of Dependency Inversion Principle.
PyDit allow your code to depend only abstract things, not the real implementation.
Install
With poetry
poetry add python-pydit
With pip
pip install python-pydit
Usage
Create the PyDit instance:
app/configs/di.py
from pydit import PyDit
pydit = PyDit()
Import the pydit instance and register your project's dependencies:
app/configs/dependencies.py
from typing import Any
from app.configs.di import pydit
from app.adapters.repositories.sqlalchemy.user_repository import SqlalchemyUserRepository
from app.configs.database import get_db_config
def setup_dependencies():
"""
This is only a suggestion, you're free to configure it like you want
"""
dependencies: list[dict[str, Any]] = [
{
"dependency": SqlalchemyUserRepository,
"token": "sqlalchemy_user_repository"
},
{
"dependency": get_db_config,
"token": "database_config",
},
{
"dependency": "HELLO WORLD",
"token": "test"
}
]
for dependency in dependencies:
pydit.add_dependency(dependency["dependency"], dependency.get("token"))
Call the setup_dependencies in the main file
app/main.py
from app.config.di import setup_dependencies()
setup_dependencies()
Injecting dependencies
Inject by property
Pydit supports python's @property decorator.
app/domain/user/services/create.py
from typing import cast, Any
from app.configs.di import pydit
# This class can be a Protocol or a clas that inherits from ABC
from app.adapters.repositories.interfaces.user_repositgory import IUserRepository
class CreateUserService:
@pydit.inject()
def user_repository(self) -> IUserRepository:
return cast(IUserRepository, None)
@pydit.inject(token="test")
def other_property(self) -> str:
return ""
def execute(self, data: dict[str, Any]):
self.user_repository.create(data)
# Prints HELLO WORLD
print(self.other_property)
How you can see, we're depending on the intarface IUserRepository, not the real SqlalchemyUserRepository implementation.
Inject dependencies by constuctor
PyDIT needs that each parameter of class/function have default value to be resolved
app/domain/user/services/create.py
from pydit import FunctionInject
from app.adapters.repositories.interfaces.user_repositgory import IUserRepository
class CreateUserService:
def __init__(
self,
user_repository: IUserRepository = FunctionInject(),
other_property: str = FunctionInject(token="test")
):
self.user_repository = user_repository
def execute(self, data):
self.user_repository.create(data)
# Prints HELLO WORLD
print(other_property)
Inject dependencies by function
PyDIT can handle user defined functions too.
app/domain/user/services/create.py
from typing import Any
from pydit import FunctionInject
from app.adapters.repositories.interfaces.user_repositgory import IUserRepository
def create_user(user_data: dict[str, Any], repository: IUserRepository = FunctionInject()):
repository.create(user_data)
app/config/dependencies.py
from app.configs.di import pydit
from app.domain.user.services.create import create_user
def setup_dependencies():
pydit.add_dependency(create_user, "create_user")
app/routers/v1/user.py
from fastapi import APIRouter
from app.configs.di import pydit
from app.domain.user.dto.create import CreateUserDTO
router = APIRouter(prefix="/users", tags=["Users"])
@router.post("")
def create(data: CreateUserDTO):
create_service = pydit.get_value(token="create_user")
create_service(data.dict())
return "OK"
Singleton
To use singleton approach, pass true to singleton parameter in inject fn.
from typing import cast, Any
from app.configs.di import pydit
# This class can be a Protocol or a clas that inherits from ABC
from app.adapters.repositories.interfaces.user_repositgory import IUserRepository
class CreateUserService:
@pydit.inject(singleton=True)
def user_repository(self) -> IUserRepository:
return cast(IUserRepository, None)
@pydit.inject(token="test")
def other_property(self) -> str:
return ""
def execute(self, data: dict[str, Any]):
self.user_repository.create(data)
# Prints HELLO WORLD
print(self.other_property)
Features:
- Inject values based on type signature
- Inject values based on inheritance
- Inject values via token
- Resolves function dependencies, calling and injecting the call result
- Singleton support
- Inject values in function calls or class constructor
__init__based on the arguments' signatures - Add support for kwargs when inject values in functions
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file python_pydit-1.0.2.tar.gz.
File metadata
- Download URL: python_pydit-1.0.2.tar.gz
- Upload date:
- Size: 12.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.5 CPython/3.12.3 Linux/6.17.0-14-generic
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3db007fcf18854452cc973583ccb53584ec392545016fff41986d4ebfa2b943f
|
|
| MD5 |
38f3ccd06955281e54e111300b1e5653
|
|
| BLAKE2b-256 |
649930113c50a65742c2273d38fea1c4f3d7360e25f2769299b34434e9321a67
|
File details
Details for the file python_pydit-1.0.2-py3-none-any.whl.
File metadata
- Download URL: python_pydit-1.0.2-py3-none-any.whl
- Upload date:
- Size: 17.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.5 CPython/3.12.3 Linux/6.17.0-14-generic
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aba395974969163e533e6e430ea0d25571ced07987b312297a822a4c973b9194
|
|
| MD5 |
f6e15767a8ea316f065779e87a8a4ab8
|
|
| BLAKE2b-256 |
7a7e281ece458830f341d06cc268d59109c190727b09f9aa06dcc81a18a03fbc
|