All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
AutowiredDjangoConfig— a project-wide AppConfig driven by asettings.DJANGO_AUTOWIREDdict. Brings Spring Boot–style auto-discovery to Django: oneINSTALLED_APPSentry plus a config dict bootstraps DI for every domain app, no per-appapps.pyconfig required. SupportsPACKAGES(explicit list),AUTODISCOVER_PREFIX(filterINSTALLED_APPSby prefix),AUTODISCOVER_SUBPACKAGE(e.g."adapters"for partial adoption),EXTRA_MODULESas dotted"module:attr"strings, and aSTRICTflag for fail-fast scanning.examples/django_autodiscover_demo/— Spring Boot–style Django demo with multiple bounded contexts, cross-app DI, and a@providesfeature flag.strictparameter oncontainer.initialize()andscan_packages()— when True, broken sub-modules raise instead of logging a warning.
@providesdecorator for conditional/factory-based bindings. Use when the concrete implementation of an interface must be chosen at runtime (feature flags, environment, etc.). Factories support dependency injection via annotated parameters and respectScope.SINGLETON,TRANSIENT, andTHREADfor invocation frequency. Factories are evaluated eagerly atcontainer.initialize(); failures raise the newProviderResolutionError.ProviderResolutionErrorexception type for@providesfactory failures.- All three example apps (Django, FastAPI, Flask) now demo
@providesvia aGREETER_FORMATTER_STYLEenv var that swaps the name formatter at boot.
- Lowered minimum Python version to 3.12 (was 3.13).
container.reset()and the testing fixtures (autowired_container,build_container,container_context) no longer clear the registry. Python caches imported modules, so clearing the registry between tests would strip registrations whose modules were already imported — the nextscan_packages()call would then be a no-op and resolution would fail. Registrations now persist for the process lifetime; usecontainer.override()for per-test binding changes.InjectorBackend.override()now rebuilds the injector from scratch with the overrides baked in, instead of creating a child injector. The child injector approach did not affect transitive dependencies of parent-owned singletons, so overrides silently had no effect on deeper graphs.
examples/django_demo/,examples/fastapi_demo/,examples/flask_demo/— minimal projects demonstrating ports/adapters,@injectable, framework integration, and the three testing patterns (pure unit, full wiring, override).django_autowired.inspectmodule withBindingReport,report(), and renderers fortable,tree,json, andmermaidoutput.python -m django_autowired inspectCLI that scans packages and prints a report of registered@injectablebindings without requiring a running container. Supports--formatand--exclude.@injectabledecorator with optionalbind_toandscope.Scopeenum:SINGLETON,TRANSIENT,THREAD.- Thread-safe
_Registrythat detects duplicate interface bindings at decoration time. scan_packages(*paths, exclude_patterns=...)with built-in skips formigrations,tests,test,conftest,factories,fixtures.- Global container lifecycle:
initialize,get,override,reset,is_initialized. - Backend adapters:
InjectorBackend(priority) — auto-applies@injectto annotated constructors.LagomBackend— dict-based overrides to work around immutable definitions.WireupBackend—create_sync_container+injectabledecorator composition.Scope.THREADfalls back toSINGLETON.DishkaBackend— dynamicProvidersynthesis with rebuild-on-override.
- Integrations:
AutowiredAppConfigfor Django.autowired_lifespan+Providefor FastAPI.Autowiredextension +inject_depfor Flask.
- Testing utilities:
autowired_containerfixture,build_containerfactory,container_context,InMemoryOverrideModule. - Typed exceptions:
AutowiredError,ContainerNotInitializedError,ContainerAlreadyInitializedError,DuplicateBindingError,BackendNotInstalledError,UnresolvableTypeError.