Skip to content
bocejo5Public

About

A lightweight, implicit Dependency Injection and Inversion of Control (IoC) container for Python

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

6 Commits

Folders and files

Repository files navigation

inject-x

Dependency injection for Python with automatic class discovery.

Built on top of injector, inject-x adds auto-loading from a folder and retrieval of all instances by base type — removing the need to manually register every class.

Installation

pip install inject-x

Requirements: Python >= 3.11.5, injector >= 0.22.0

Quick start

from injectx import Injector, Presentation, Service, Repository, Config

# Load and register all eligible classes from a folder (recursive)
inj = Injector().register_all_from_folder("myapp/")

# Retrieve a specific instance
my_service = inj.get(MyService)

# Retrieve all registered instances of a base type
presentations = inj.get_all_by_type(Presentation)

Base classes

Annotate your classes by inheriting from one of the four base types:

Class Intended use
Presentation Controllers, API handlers, CLI entry points
Service Business logic
Repository Data access (DB, external APIs)
Config Configuration objects

Only classes that inherit from one of these will be picked up by register_all_from_folder. Classes that don't inherit from any of them (like plain helpers) are ignored.

API

Injector(folder_path_to_register="")

Creates a new injector. Optionally accepts a folder path to auto-register on construction.

inj = Injector("myapp/")
# equivalent to:
inj = Injector().register_all_from_folder("myapp/")

register_all_from_folder(folder: str) -> Injector

Recursively walks folder, imports every .py file (skipping __init__.py), and registers all classes that inherit from Presentation, Service, Repository, or Config as singletons.

  • Returns self for chaining.
  • Modules are loaded with their full dotted name (e.g. myapp.services.user_service), consistent with normal Python imports — so injector.get(MyService) and from myapp.services.user_service import MyService refer to the exact same class object.
  • Calling register_all_from_folder (or register) twice with the same class is a no-op.
inj = (
    Injector()
    .register_all_from_folder("myapp/services/")
    .register_all_from_folder("myapp/repositories/")
)

register(cls) -> None

Manually registers a single class as a singleton. Useful when auto-discovery is not needed.

inj = Injector()
inj.register(MyService)

get(cls) -> instance

Returns the singleton instance for the given class.

svc = inj.get(MyService)

get_all_by_type(base_class) -> list

Returns the singleton instances of all registered classes that are subclasses of base_class, traversing the full inheritance hierarchy recursively.

from injectx import Injector, Presentation

class Handler(Presentation): ...
class SpecialHandler(Handler): ...

inj = Injector()
inj.register(Handler)
inj.register(SpecialHandler)

inj.get_all_by_type(Presentation)  # [<Handler>, <SpecialHandler>]

Example project layout

myapp/
├── presentation/
│   └── user_controller.py   # class UserController(Presentation): ...
├── services/
│   └── user_service.py      # class UserService(Service): ...
└── repositories/
    └── user_repo.py         # class UserRepo(Repository): ...
from injectx import Injector, Service

inj = Injector().register_all_from_folder("myapp/")

# All services, regardless of nesting depth
services = inj.get_all_by_type(Service)

Running tests

pip install pytest
pytest tests/

Build & publish

bumpver update --patch   # or --minor / --major
python -m build
twine upload dist/*

License

MIT — Colageo Mirko mirko.colageo@gmail.com

About

A lightweight, implicit Dependency Injection and Inversion of Control (IoC) container for Python

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages