Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions planning/releases/2.2.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# modern-di-aiogram 2.2.0 — adopt the modern-di integration kit

Maintenance release. **No public API change** — `FromDI`, `inject` (both
`modern_di_aiogram` and `modern_di_aiogram.dialog`), `setup_di`,
`fetch_di_container`, and the two connection providers keep their signatures
and behavior. Swaps this package's hand-rolled connection-scope lifecycle
and marker resolution for the shared primitives in
[`modern_di.integrations`](https://github.com/modern-python/modern-di/blob/main/architecture/integration-kit.md),
shipped in
[modern-di 2.28.0](https://github.com/modern-python/modern-di/releases/tag/2.28.0).
Twelfth of 13 planned adapter conversions across the `modern-di` ecosystem
(after
[`modern-di-starlette` 2.2.0](https://github.com/modern-python/modern-di-starlette/releases/tag/2.2.0),
[`modern-di-fastapi` 2.10.0](https://github.com/modern-python/modern-di-fastapi/releases/tag/2.10.0),
[`modern-di-litestar` 2.13.0](https://github.com/modern-python/modern-di-litestar/releases/tag/2.13.0),
[`modern-di-aiohttp` 2.2.0](https://github.com/modern-python/modern-di-aiohttp/releases/tag/2.2.0),
[`modern-di-flask` 2.1.0](https://github.com/modern-python/modern-di-flask/releases/tag/2.1.0),
[`modern-di-faststream` 2.10.0](https://github.com/modern-python/modern-di-faststream/releases/tag/2.10.0),
[`modern-di-typer` 2.3.0](https://github.com/modern-python/modern-di-typer/releases/tag/2.3.0),
[`modern-di-grpc` 2.1.0](https://github.com/modern-python/modern-di-grpc/releases/tag/2.1.0),
[`modern-di-celery` 2.1.0](https://github.com/modern-python/modern-di-celery/releases/tag/2.1.0),
[`modern-di-arq` 2.1.0](https://github.com/modern-python/modern-di-arq/releases/tag/2.1.0),
and
[`modern-di-taskiq` 2.1.0](https://github.com/modern-python/modern-di-taskiq/releases/tag/2.1.0)).

aiogram is the kit's documented **Layer-1 outlier**: its per-update child
container's context is a hand-written multi-provider merge with a hardcoded
scope (`{Update: event, TelegramObject: event.event}`, two aiogram types
from one event) that no single-provider `bind()` can derive — so that
literal is kept, and **no `bind`/`classify_connection` is introduced**. Only
the container lifecycle and the marker/resolution seam adopt the kit.

## Internal refactors

- **`_DiMiddleware` now opens/closes the per-update child through
`Container`'s own `async with`** (replacing the manual `try`/`finally:
await child.close_async()`). The multi-provider `context={...}` literal and
both `ContextProvider` registrations are unchanged.
- **`_FromDI` is gone; `FromDI = integrations.from_di`.** `_parse_inject_params`
is deleted; `inject` composes `integrations.parse_markers`/
`integrations.resolve_markers`.
- **The `__modern_di_injected__` double-wrap guard is now
`integrations.is_injected`/`integrations.mark_injected`** (same underlying
attribute — used in `inject` and `auto_inject`'s `_inject_router`).
- **`modern_di_aiogram.dialog`** (the aiogram-dialog `inject`, which shares
the marker) converts its `parse_markers`/`resolve_markers` usage in the
same change.
- The `inject` signature-rewrite machinery (the deliberate non-use of
`functools.wraps`, driven by aiogram's `__wrapped__` unwrapping) and
`dialog.py`'s `_container_from_call` call-shape lookup are aiogram-specific
glue, kept exactly as-is.
- Dead imports removed (`dataclasses`, the `T_co` TypeVar).
- `architecture/dependency-injection.md` promoted to describe the new
internals.

## Packaging

- Bumps the `modern-di` floor to `>=2.28,<3`.

## Downstream

No action needed — the public API (`FromDI`, `inject`, `setup_di`,
`fetch_di_container`, `aiogram_update_provider`, `aiogram_event_provider`,
and `modern_di_aiogram.dialog.inject`) is unchanged. Upgrading only requires
`modern-di>=2.28.0`.

## Internals

- 100% line coverage; `ruff`, `ty` clean across Python 3.10–3.14. Tests use
a fake-token `Bot` and `aiogram_dialog.test_tools` (no external service).
- Built via `subagent-driven-development`: 5 planned tasks, each with an
independent spec+quality review; a whole-branch review before merge that
verified no `bind`/`classify_connection` was introduced, the `async with`
preserves the old close semantics on both the normal and handler-error
paths, and the double-wrap guard round-trips through the same
`__modern_di_injected__` attribute.