Skip to content

Commit 02a13cb

Browse files
lesnik512claude
andauthored
docs(release): 2.27.0 notes — positional subjects, group scope, CM override, anchors (#292)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent dd68cf9 commit 02a13cb

1 file changed

Lines changed: 75 additions & 0 deletions

File tree

‎planning/releases/2.27.0.md‎

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# modern-di 2.27.0 — shorter registrations, self-resetting overrides, anchored errors
2+
3+
Back-compatible: no behavior flips, no new warnings. Four features from the
4+
3.0 UX research land together — the registration line gets shorter twice,
5+
test overrides clean up after themselves, and error messages now point at
6+
the source line that declared the failing provider.
7+
8+
## Feature
9+
10+
- **Positional subject arguments (API-5).** `Factory`, `ContextProvider`,
11+
and `Alias` accept their subject as the first positional argument —
12+
`providers.Factory(UserRepository)`,
13+
`providers.ContextProvider(HttpRequest)`, `providers.Alias(Concrete)`.
14+
The keyword spellings (`creator=`, `context_type=`, `source_type=`)
15+
remain first-class; nothing is deprecated. Docs teach the positional
16+
form throughout.
17+
- **Group-level default scope (API-4).** A `Group` subclass may declare its
18+
members' default scope:
19+
20+
```python
21+
class RequestGroup(Group, scope=Scope.REQUEST):
22+
repo = providers.Factory(UserRepository) # takes REQUEST
23+
audit = providers.Factory(AuditLog, scope=Scope.APP) # explicit wins
24+
```
25+
26+
Priority: explicit `scope=` > the group's kwarg (inherited via MRO;
27+
a subclass's kwarg applies to providers declared in its own body) >
28+
`Scope.APP`. `Alias` never participates (its scope derives from its
29+
source). A scope-defaulted provider shared by two groups with different
30+
defaults raises the new `GroupScopeConflictError` at class creation —
31+
import order never decides a provider's scope.
32+
- **Context-manager override (INT-4).** `container.override(provider, obj)`
33+
still applies immediately and now returns an `OverrideHandle`:
34+
35+
```python
36+
with container.override(MyGroup.api_client, mock_client) as client:
37+
... # resolution returns mock_client
38+
# prior override state restored here — even on exception
39+
```
40+
41+
Exit restores the snapshot taken at the call (a previously stacked
42+
override, or none); nested overrides of the same provider unwind in
43+
order. Imperative `override()`/`reset_override()` callers are unaffected.
44+
- **Definition-site anchors on error paths (ERR-6).** Breadcrumb lines and
45+
cycle hops now end with the creator's declaration site:
46+
47+
```
48+
Cannot resolve dependency chain:
49+
REQUEST UserService (app.services:17)
50+
APP └─> SessionFactory (app.db:42)
51+
```
52+
53+
Captured lazily on the error path only (zero import/resolution cost),
54+
memoized, with silent fallback for callables without source. Cycle
55+
errors expose the parallel `.cycle_locations`; `.cycle_path` stays bare
56+
type names.
57+
58+
## Downstream
59+
60+
- **Tests asserting exact error messages** will break on the new trailing
61+
`(module:line)` anchors in breadcrumb and cycle lines. As with 2.24.0
62+
and 2.26.0: prefer `pytest.raises(..., match=...)` with a substring —
63+
anchors are trailing additions, so substring matches survive.
64+
- `Container.override` now returns an `OverrideHandle` instead of `None` —
65+
invisible to callers that ignore the return value.
66+
- New exception: `GroupScopeConflictError` (a `RegistrationError`), with
67+
its [troubleshooting page](https://modern-di.modern-python.org/troubleshooting/group-scope-conflict-error/).
68+
- No floor bumps required.
69+
70+
## Internals
71+
72+
- The eager warm-up capability (API-8/INT-3, `init_cache()`-style) is
73+
explicitly deferred with a revisit trigger recorded in planning.
74+
- 100% line coverage maintained across Python 3.10–3.14; `ruff` and `ty`
75+
clean; docs built under `mkdocs --strict` in CI.

0 commit comments

Comments
 (0)