Metadata-Version: 2.4
Name: django-autowired
Version: 0.4.0
Summary: Spring Boot-style @injectable autowiring for Python — zero manual wiring, any DI backend.
Project-URL: Homepage, https://github.com/tylersuehr7/django-autowired
Project-URL: Documentation, https://tylersuehr7.github.io/django-autowired
Project-URL: Repository, https://github.com/tylersuehr7/django-autowired
Project-URL: Issues, https://github.com/tylersuehr7/django-autowired/issues
Project-URL: Changelog, https://github.com/tylersuehr7/django-autowired/blob/main/CHANGELOG.md
Author-email: "Tyler R. Suehr" <tyler@vitablehealth.com>
License: MIT
License-File: LICENSE
Keywords: autowiring,dependency-injection,django,fastapi,flask,injector
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: Django
Classifier: Framework :: Django :: 4.2
Classifier: Framework :: Django :: 5.0
Classifier: Framework :: Django :: 5.1
Classifier: Framework :: FastAPI
Classifier: Framework :: Flask
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.12
Provides-Extra: dev
Requires-Dist: anyio>=4.0; extra == 'dev'
Requires-Dist: dishka>=0.14; extra == 'dev'
Requires-Dist: django>=4.2; extra == 'dev'
Requires-Dist: fastapi>=0.110; extra == 'dev'
Requires-Dist: flask>=3.0; extra == 'dev'
Requires-Dist: injector>=0.21; extra == 'dev'
Requires-Dist: lagom>=2.6; extra == 'dev'
Requires-Dist: mkdocs-material<9.7,>=9.6; extra == 'dev'
Requires-Dist: mkdocs>=1.5; extra == 'dev'
Requires-Dist: mkdocstrings[python]>=0.24; extra == 'dev'
Requires-Dist: mypy>=1.9; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Requires-Dist: wireup>=0.14; extra == 'dev'
Provides-Extra: dishka
Requires-Dist: dishka>=0.14; extra == 'dishka'
Provides-Extra: django
Requires-Dist: django>=4.2; extra == 'django'
Provides-Extra: fastapi
Requires-Dist: anyio>=4.0; extra == 'fastapi'
Requires-Dist: fastapi>=0.110; extra == 'fastapi'
Provides-Extra: flask
Requires-Dist: flask>=3.0; extra == 'flask'
Provides-Extra: injector
Requires-Dist: injector>=0.21; extra == 'injector'
Provides-Extra: lagom
Requires-Dist: lagom>=2.6; extra == 'lagom'
Provides-Extra: testing
Requires-Dist: pytest-asyncio>=0.23; extra == 'testing'
Requires-Dist: pytest>=8.0; extra == 'testing'
Provides-Extra: wireup
Requires-Dist: wireup>=0.14; extra == 'wireup'
Description-Content-Type: text/markdown

# django-autowired

> Spring Boot-style `@injectable` autowiring for Python. Any DI backend. Zero manual wiring.

[![PyPI version](https://img.shields.io/pypi/v/django-autowired.svg)](https://pypi.org/project/django-autowired/)
[![Python versions](https://img.shields.io/pypi/pyversions/django-autowired.svg)](https://pypi.org/project/django-autowired/)
[![License](https://img.shields.io/pypi/l/django-autowired.svg)](https://github.com/tylersuehr7/django-autowired/blob/main/LICENSE)
[![CI](https://github.com/tylersuehr7/django-autowired/actions/workflows/ci.yml/badge.svg)](https://github.com/tylersuehr7/django-autowired/actions/workflows/ci.yml)

## Why

In large Django / FastAPI / Flask codebases, hand-rolling `injector.Module` subclasses
with `binder.bind(IRepository, to=SqlRepository)` calls does not scale. It's boilerplate,
it's easy to forget, and every new service becomes a coordination problem.

`django-autowired` brings the Spring Boot ergonomic to Python: decorate a class with
`@injectable`, point an `AppConfig` (or FastAPI lifespan, or Flask extension) at the
packages to scan, and the rest happens at boot.

## Features

| | |
| --- | --- |
| **Zero wiring** | No `Module` subclasses, no `binder.bind()` calls. Just `@injectable`. |
| **Backend-agnostic** | Works with `injector`, `lagom`, `wireup`, or `dishka`. Swap with one line. |
| **Framework-agnostic core** | Django, FastAPI, Flask, or plain Python — all first-class. |
| **Fail loud at boot** | Duplicate bindings, missing backends, and unresolvable types raise typed errors. |
| **Test-friendly** | Pytest fixtures, overrides, and a context manager ship with the library. |
| **Thread-safe registry** | Concurrent registration is safe by construction. |
| **Introspection** | `python -m django_autowired inspect` prints your DI graph as a table, tree, JSON, or Mermaid diagram. |

## Quickstart (Django)

```python
# myapp/apps.py
from django_autowired.integrations.django import AutowiredAppConfig

class MyAppConfig(AutowiredAppConfig):
    name = "myapp"
    autowired_packages = ["myapp.services", "myapp.adapters"]

# myapp/services.py
from django_autowired import injectable

@injectable()
class GreetingService:
    def greet(self) -> str:
        return "hello"

# myapp/views.py
from django_autowired import container
from myapp.services import GreetingService

def index(request):
    svc = container.get(GreetingService)
    return HttpResponse(svc.greet())
```

That's it. No modules. No binder. No manual wiring.

## Backend support

| Backend  | Status | Priority | Notes |
| -------- | ------ | -------- | ----- |
| `injector` | ✅ | **default** | Most complete. Thread scope supported. |
| `lagom` | ✅ |  | Auto-resolves concretes from type hints. |
| `wireup` | ✅ |  | Thread scope falls back to singleton. |
| `dishka` | ✅ |  | Rebuild-on-override semantics. |

Install the backend you want:

```bash
pip install "django-autowired[injector]"   # default
pip install "django-autowired[lagom]"
pip install "django-autowired[wireup]"
pip install "django-autowired[dishka]"
```

## Framework support

| Framework | Status | Priority |
| --------- | ------ | -------- |
| Django | ✅ | **priority** |
| FastAPI | ✅ | |
| Flask | ✅ | |
| Plain Python | ✅ | |

## Installation

```bash
pip install django-autowired                       # core only (no backend)
pip install "django-autowired[injector]"           # default backend
pip install "django-autowired[django,injector]"    # Django + injector
pip install "django-autowired[fastapi,injector]"   # FastAPI + injector
pip install "django-autowired[flask,injector]"     # Flask + injector
pip install "django-autowired[dev]"                # everything + test/lint/docs
```

Or with `uv`:

```bash
uv add "django-autowired[django,injector]"
```

## Documentation

Full docs at **[tylersuehr7.github.io/django-autowired](https://tylersuehr7.github.io/django-autowired)**.

- [Quickstart](https://tylersuehr7.github.io/django-autowired)
- [`@injectable` guide](https://tylersuehr7.github.io/django-autowired/guide/injectable)
- [Scopes](https://tylersuehr7.github.io/django-autowired/guide/scopes)
- [Django integration](https://tylersuehr7.github.io/django-autowired/integrations/django)
- [FastAPI integration](https://tylersuehr7.github.io/django-autowired/integrations/fastapi)
- [Flask integration](https://tylersuehr7.github.io/django-autowired/integrations/flask)
- [Testing guide](https://tylersuehr7.github.io/django-autowired/guide/testing)

## License

MIT © 2026 Tyler R. Suehr
