Skip to main content

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python_pydit-1.0.1.tar.gz (11.6 kB view details)

Uploaded Source

Built Distribution

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

python_pydit-1.0.1-py3-none-any.whl (16.7 kB view details)

Uploaded Python 3

File details

Details for the file python_pydit-1.0.1.tar.gz.

File metadata

  • Download URL: python_pydit-1.0.1.tar.gz
  • Upload date:
  • Size: 11.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.5 CPython/3.12.3 Linux/6.14.0-37-generic

File hashes

Hashes for python_pydit-1.0.1.tar.gz
Algorithm Hash digest
SHA256 0f3b16e52892e82e3e8d06b47978d9da94a98a225c9759206747ba6b8319373e
MD5 817cf3d1c829b2d8fd7a4877c4dcfdf5
BLAKE2b-256 8c5de0af965d6df24b093c43af206a1eacd8c945ac6048f52a1ecf0c9a88c907

See more details on using hashes here.

File details

Details for the file python_pydit-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: python_pydit-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 16.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.5 CPython/3.12.3 Linux/6.14.0-37-generic

File hashes

Hashes for python_pydit-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0b1aa1607b4575e9aa23dcfbe1b89493b124777b657b6eb16724ad1cba8a85ea
MD5 9d90d1d9fe64ef8a36c5b144eec96ed6
BLAKE2b-256 22093568e50362f70f7afde23f0e46cb91c3de0a48b6b281bb10fc12c937d836

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