Commit 650206f
Free-threaded Python (nogil) support (#153)
* docs(planning): spec free-threaded Python (nogil) support
orjson is the sole blocker for free-threaded CPython: no ft wheels and its
build refuses ft (verified on 3.14t). Make orjson an opt-in extra with a
stdlib-json fallback so core + pure extras install and test on ft; add a
3.13t/3.14t CI leg and a free-threading capability page. otl-grpc and
pyroscope remain ecosystem-blocked (deferred with revisit triggers).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore: git-ignore .superpowers scratch dir
Ephemeral plans and subagent-driven-development scratch live here per the
planning convention; keep them out of version control.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat: make orjson an opt-in extra with a stdlib-json fallback
orjson ships no free-threaded wheels and its build refuses ft, yet it was a
mandatory core dep used only by the logging serializer. Move it to an opt-in
`orjson` extra and fall back to the stdlib json accelerator when absent, so
core and the pure extras install on free-threaded CPython. GIL-build output is
byte-identical when orjson is present.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: prove free-threaded support on 3.13t/3.14t via a smoke leg
Add a standalone ft smoke script (bootstrap + serializer fallback) and a CI
matrix leg installing the ft-ready extras. conftest.py hard-imports
opentelemetry, so the ft leg runs the script, not the coverage suite.
orjson/otl/pyroscope are excluded as planned. fastmcp is also excluded: it
transitively pulls in opentelemetry-api, which crashes import_checker.py's
find_spec calls once opentelemetry-instrumentation isn't also present.
litestar is excluded because msgspec gates Py_GIL_DISABLED support to
Python 3.14+, so it fails to build on the 3.13t leg (the CI job shares one
install step across the {3.13t, 3.14t} matrix). Both gaps are tracked in
planning/deferred.md. Also adds a scripts/*.py per-file INP001 ignore since
the smoke script is a standalone entry point, not an importable package.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: guard import_checker and OTel exporter import against a partial opentelemetry stack
find_spec on a dotted name imports its parent first, so
find_spec("opentelemetry.instrumentation.fastapi") raised ModuleNotFoundError
(crashing import lite_bootstrap) when opentelemetry-api was installed without
opentelemetry-instrumentation. Guard both dotted checks with a
_safe_find_spec helper.
Separately, opentelemetry_instrument.py unconditionally imported the grpc
otlp exporter under the coarse is_opentelemetry_installed guard, which only
means opentelemetry-api resolves, not that the exporter package is present.
Give it its own is_otlp_grpc_exporter_installed guard, at both the import and
the bootstrap() use site, so an endpoint configured without the exporter
installed no longer crashes.
Both bugs surface for any environment with opentelemetry-api installed but
not the rest of the stack (e.g. lite-bootstrap[fastmcp], which pulls bare
opentelemetry-api transitively) - not ft-specific, though ft is what
surfaced them.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: split the free-threaded leg's install per Python version, add litestar to 3.14t
msgspec still gates Py_GIL_DISABLED to 3.14+, so litestar can't install on
3.13t; move from one shared install step to a per-version extras matrix so
litestar/litestar-metrics can run on 3.14t while 3.13t stays without them.
fastmcp/fastmcp-metrics stay off both legs: cffi (pulled in via fastmcp ->
cryptography) gates free-threaded 3.13 upstream, and on 3.14t a remaining
opentelemetry-sdk-vs-opentelemetry-api activation gap (found while verifying
the previous commit's exporter fix) still crashes import lite_bootstrap with
fastmcp installed. Update planning/deferred.md with the corrected picture for
both fastmcp and litestar.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs: promote free-threading support (capability page, matrix, invariant)
Add architecture/free-threading.md with the support matrix reconciled to what
Tasks 1-2b actually shipped: litestar lands on 3.14t only (msgspec's ft gate),
fastmcp stays unsupported on both legs. Update the README dependency claim,
record the single-threaded-init invariant in bootstrappers.md, index the new
page in CLAUDE.md, and add the 1.3.0 release note.
Promote the is_otlp_grpc_exporter_installed guard into instruments.md,
including the silent-OTLP-skip trade-off it leaves open, and fold that into a
cohesive "OTel-stack dependency model" entry in deferred.md alongside the
existing fastmcp entry. Finalize the change file's summary to match the
shipped extra set and the two import-safety bug fixes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs: correct free-threading matrix note and reconcile change-file body
Drop the httptools claim (bare fastapi/faststream don't depend on it) and
update the change file's §2/§3 to the shipped ft CI leg (per-version smoke
script, not just test) and full blocked-extras list, plus the two import-safety
bug fixes found during verification.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs: fix remaining stale ft-leg claims in change-file body
The Summary and Testing sections still said "two extras" blocked and "just
test" on the ft leg; align them with the shipped per-version smoke-script leg
and full blocked-extras list.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs: drop the misplaced import-safety section from free-threading.md
Those two fixes are not ft-specific (they hit any partial-opentelemetry
environment on regular Python); their home is instruments.md and the change
file, not the free-threading capability page. The one ft-relevant fact — the
sdk-vs-api gap blocking fastmcp on 3.14t — already lives in the matrix row.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(faststream): give middleware protocols a __call__ so they satisfy BrokerMiddleware
A newer ty flagged that FastStreamTelemetryMiddlewareProtocol /
FastStreamPrometheusMiddlewareProtocol declared only __init__, so a constructed
instance was not assignable to faststream's BrokerMiddleware[Any, Any] at
broker.add_middleware(). Declare the builder __call__ (loosely typed as Any to
stay decoupled from faststream internals). Pre-existing gap, surfaced by tool drift.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent 7c2e22f commit 650206f
21 files changed
Lines changed: 673 additions & 21 deletions
File tree
- .github/workflows
- architecture
- lite_bootstrap
- bootstrappers
- instruments
- planning
- changes
- decisions
- releases
- scripts
- tests
- instruments
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
65 | 65 | | |
66 | 66 | | |
67 | 67 | | |
| 68 | + | |
68 | 69 | | |
69 | 70 | | |
70 | 71 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
68 | 68 | | |
69 | 69 | | |
70 | 70 | | |
71 | | - | |
| 71 | + | |
72 | 72 | | |
73 | 73 | | |
74 | 74 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
87 | 87 | | |
88 | 88 | | |
89 | 89 | | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
90 | 98 | | |
91 | 99 | | |
92 | 100 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
56 | 85 | | |
57 | 86 | | |
58 | 87 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
46 | 51 | | |
47 | 52 | | |
48 | 53 | | |
| |||
55 | 60 | | |
56 | 61 | | |
57 | 62 | | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
58 | 66 | | |
59 | 67 | | |
60 | 68 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
4 | 17 | | |
5 | 18 | | |
6 | 19 | | |
| |||
9 | 22 | | |
10 | 23 | | |
11 | 24 | | |
12 | | - | |
13 | | - | |
| 25 | + | |
| 26 | + | |
14 | 27 | | |
15 | 28 | | |
16 | | - | |
| 29 | + | |
17 | 30 | | |
| 31 | + | |
18 | 32 | | |
19 | 33 | | |
| 34 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
7 | | - | |
8 | | - | |
9 | 8 | | |
10 | 9 | | |
11 | 10 | | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
12 | 15 | | |
13 | 16 | | |
14 | 17 | | |
| |||
31 | 34 | | |
32 | 35 | | |
33 | 36 | | |
34 | | - | |
| 37 | + | |
35 | 38 | | |
36 | 39 | | |
37 | 40 | | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
38 | 53 | | |
39 | 54 | | |
40 | 55 | | |
| |||
68 | 83 | | |
69 | 84 | | |
70 | 85 | | |
71 | | - | |
72 | | - | |
| 86 | + | |
| 87 | + | |
73 | 88 | | |
74 | 89 | | |
75 | 90 | | |
| |||
0 commit comments