diff --git a/planning/releases/2.21.0.md b/planning/releases/2.21.0.md new file mode 100644 index 0000000..29514da --- /dev/null +++ b/planning/releases/2.21.0.md @@ -0,0 +1,21 @@ +# modern-di 2.21.0 — `ContextProvider.context_type` + +Purely additive. One newly-public attribute; the contract of existing code is unchanged. + +## Feature + +- **`ContextProvider.context_type`** is now a public attribute — the type the provider supplies and the key its value is set under in `context`. It was stored privately (`_context_type`) with no accessor. + +Implemented as a plain public slot, matching its sibling `bound_type` (both derive from the same constructor argument) and the base provider's public `scope` / `bound_type`. Properties in the providers are reserved for *derived* values (`display_name`); `context_type` is stored config, so it is a plain attribute. + +## Why + +Framework integrations build a connection → scope → context-key mapping. Without a public `context_type` they re-state, in an `isinstance` ladder, the very type they already passed into the provider — so the connection-kind knowledge is split across two places. Exposing `context_type` lets an integration drive that dispatch off the provider objects themselves, single-sourcing the mapping. + +## Downstream + +No action required. Integrations that want to single-source their connection-kind dispatch (the `modern-di-fastapi` refactor, and the same pattern in `modern-di-litestar` / `modern-di-faststream` / `modern-di-typer`) can read `provider.context_type` and bump their floor to `modern-di>=2.21.0`. Nothing breaks for consumers that don't. + +## Internals + +- 100% line coverage maintained across Python 3.10–3.14; `ruff` and `ty` clean.