Skip to content

feat: declare floors for the last four bare dependencies - #218

Merged
lesnik512 merged 1 commit into
mainfrom
feat/remaining-floors
Sep 15, 2026
Merged

lesnik512 merged 1 commit into
mainfrom
feat/remaining-floors

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Closes #213. The last four bare requirements, swept in one pass.

structlog>=21.3
sentry-sdk>=2.1
orjson>=3.11
pyroscope-io>=0.7.2
structlog>=22.2   # [dependency-groups] dev, see below

How each floor was established

The oracle is the one settled on #213: install the extra, build the bootstrapper, bootstrap(),
exercise the call, teardown(). No test client, so no probe depends on the dev group. Each boundary
below is exact: the release named passes and the one before it fails.

package floor what sets it
structlog 21.3 structlog.stdlib.ProcessorFormatter.remove_processors_meta (logging_instrument.py:158)
sentry-sdk 2.1 sentry_sdk.set_tags, plural (sentry_instrument.py:112)
pyroscope-io 0.7.2 pyroscope.shutdown() (pyroscope_instrument.py:52)
orjson 3.11 no API; first release with cp314 wheels

Two of these want a word on the rationale.

sentry-sdk has two constraints, so the comment names both in the litestar>=2.15 style: 1.0.0 and
1.20.0 fail on TypeError: Unknown option 'max_value_length', and once that clears, 1.45.0 and 2.0.1
fail on AttributeError: module 'sentry_sdk' has no attribute 'set_tags'. 2.1.0 is where both hold.

orjson is the packaging-derived case from the addendum on #213. The library uses only
orjson.dumps(...).decode() and orjson.loads, both original API, so nothing forces a floor by
symbol. What fails is installation: orjson builds from source only with a Rust toolchain, and 3.10.18
and every release below it has no cp314 wheel, so maturin is invoked and fails on the newest
supported interpreter. 3.11.0 is the first with one. pyroscope-io looked like the same shape (0.3.0
ships an sdist with no project.name) but turned out to have a real API boundary above it, so it is
declared on shutdown() instead.

All four pass on 3.10, 3.11, 3.12, 3.13 and 3.14.

structlog splits across the extra and the dev group

Measured both ways: the library needs 21.3.0, the suite needs 22.2.0. The gap is structlog.typing,
which logging_instrument.py:19 imports only under TYPE_CHECKING but tests/conftest.py:11 imports
for real, to annotate LoggingMock.

Guarding the test's import would close the gap mechanically, but [tool.ruff.lint] ignores TCH
repo-wide on the grounds that "imports stay real; TYPE_CHECKING-only imports break runtime
introspection". Rewriting a test to satisfy a floor the library does not have is the wrong trade, so
the suite's floor goes to [dependency-groups] dev, which no downstream service installs.

Composition check

With every direct requirement now floored, --resolution lowest-direct per *-all extra resolves
and imports, which was not possible before this PR:

extra 3.10 3.14
free-all ok ok
fastapi-all ok ok
fastmcp-all ok ok
litestar-all fails ok
faststream-all ok fails

Both failures are in floors that predate this PR, and neither is fixed by it:

  • litestar-all on 3.10: litestar==2.15.0 does import sniffio (litestar/concurrency.py:8)
    without declaring it, and relied on anyio to supply it. anyio==4.14.2 no longer does, so
    import lite_bootstrap raises ModuleNotFoundError: No module named 'sniffio'. The declared
    litestar>=2.15 is false against a current transitive set.
  • faststream-all on 3.14: faststream==0.6.0 pins fast-depends[pydantic]==3.0.8, which pins
    pydantic==2.7.4, whose pydantic-core==2.18.4 has no cp314 wheel and fails to build.

These are the decay #210 describes, found in declarations that were hand-verified when written. They
want their own change, since raising a floor and constraining a transitive are different fixes with
different costs.

Verification

just lint-ci and just test-ci pass. uv.lock is unchanged: every resolved version already sat
above the new floors.

structlog, sentry-sdk, orjson and pyroscope-io were the remaining bare
requirements. Each floor is the lowest release that installs and runs on
every supported interpreter, established by bootstrapping rather than by
running the suite.

structlog splits: the library needs 21.3, the test suite reaches for
structlog.typing and needs 22.2, so the suite's floor goes to the dev
group where downstream services never see it.
@lesnik512
lesnik512 merged commit 12183a4 into main Sep 15, 2026
12 checks passed
@lesnik512
lesnik512 deleted the feat/remaining-floors branch September 15, 2026 16:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Declare a floor for every bare direct dependency

1 participant