Skip to content

chore(deps): adapt to faststream 0.7.6 and raise its floor - #182

Merged
lesnik512 merged 1 commit into
mainfrom
chore/update-deps
Sep 20, 2026
Merged

lesnik512 merged 1 commit into
mainfrom
chore/update-deps

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Dependency refresh. uv.lock is gitignored, so the baseline is a local lock; against the live index
only these moved:

package old new
faststream 0.7.5 0.7.6
fast-depends 3.0.8 3.0.9
sqlalchemy 2.0.53 2.0.54
ty 0.0.81 0.0.82
ruff 0.16.7 0.16.8
eof-fixer 0.4.2 0.4.3
idna 3.19 3.20

fastapi stays at 0.139.2 under the existing <0.140 cap; lifting it is untested here.

faststream 0.7.6 accounted for all of it: 5 test failures and 15 ty diagnostics.

Upstream changes and the adaptations

The ASGI try-it-out registry monkeypatch is gone. 0.7.6 replaced the private
_get_broker_registry with a TestBroker.__init_subclass__(broker=...) hook, so TestOutboxBroker
declares broker=OutboxBroker and the 29-line try/except in __init__.py is deleted. Net removal,
and one fewer reach into a private symbol.

SubscriberSpec / PublisherSpec gained a required address, and channel_labels became
abstract.
Both implemented. The subscriber keeps its single comma-joined channel rather than
splitting one per queue the way the built-in brokers now do; that is a document-shape decision
rather than a dependency one, written up with a verified blast radius in #181.

__aiter__ is a plain def upstream again (declaring it async typed it as a coroutine, which
async for rejects). Shape matched; the unsupported-peek behaviour is unchanged.

dependencies narrowed from Iterable to Sequence across upstream's signatures. Followed at
the four sites in broker.py, router.py (x2), registrator.py.

publisher.mock now raises SetupError outside a test broker instead of answering with a reset
mock. That exposed a vacuous assertion: test_relay_dual_fire_guard_through_worker_loop_leaves_row_and_logs
called assert_not_called() after leaving the TestKafkaBroker context, where the mock had already
been cleared, so it could not fail. Moved inside the context, it tests something.

Four ty: ignore suppressions became redundant and are removed with their comments.

The floor was wrong

TestBroker did not accept the broker= kwarg before 0.7.6, so on 0.7.5 import faststream_outbox
now fails at import:

TypeError: TestOutboxBroker.__init_subclass__() takes no keyword arguments

Verified by installing the package against faststream==0.7.5. SubscriberSpec/PublisherSpec
also lack address there. The floor moves 0.7.1 -> 0.7.6 in both the runtime dependency and the
dev group. Nothing in CI resolves at the lower bound, which is why the old floor went stale without
anyone noticing; worth a UV_RESOLUTION=lowest-direct job, but that is not in this PR.

Compatibility

Runtime behaviour is unchanged for anyone already on faststream 0.7.6. Three things are worth
calling out:

  • Installs on faststream < 0.7.6 are now refused by the resolver rather than failing at import.
    That is the point of the floor bump, and it is a real narrowing for anyone pinning 0.7.1-0.7.5,
    though such an install is already broken by 0.7.6's own API removals.
  • dependencies= no longer type-checks for a non-Sequence iterable (a generator, a set).
    Runtime is unaffected, there is no isinstance check; only type checkers will complain. Matches
    what upstream did to the same kwarg.
  • The generated AsyncAPI document gains an address on every channel. Additive: 0.7.5's
    SubscriberSpec/PublisherSpec had no such field. Real queue names everywhere except a
    multi-queue subscriber, which gets the comma-joined string until AsyncAPI: emit one channel per queue, not one comma-joined channel per subscriber #181 lands.

__aiter__ switching from async def to def is not a break in practice: it raised
NotImplementedError before and raises it now, just from the call rather than the await, so
await sub.__aiter__() still behaves identically.

Verification

Run locally against Postgres 17 via compose, so test_integration.py was not skipped.

  • eof-fixer --check, ruff format --check, ruff check --no-fix, ty check all clean
  • 623 passed, coverage 100.00% (gate holds)
  • mkdocs build --strict clean
  • python -m benchmarks check: gate OK

faststream 0.7.6 replaced the private ASGI try-it-out registry with a
`TestBroker.__init_subclass__(broker=...)` hook, made `SubscriberSpec` /
`PublisherSpec` carry a required `address`, made `channel_labels` abstract,
narrowed `dependencies` to `Sequence`, and turned `__aiter__` back into a
plain `def`.

The registry monkeypatch goes away entirely in favour of the declarative
hook, which also drops a reach into a private symbol. `TestBroker` did not
accept the `broker=` kwarg before 0.7.6, so `import faststream_outbox` now
fails outright on 0.7.5; the floor moves from 0.7.1 to 0.7.6 to say so.
Nothing in CI resolves at the lower bound, which is why the previous floor
went stale unnoticed.

`publisher.mock` now raises `SetupError` outside a test broker rather than
answering with a reset mock, which exposed a vacuous assertion in the relay
dual-fire test: it checked `assert_not_called()` after leaving the
`TestKafkaBroker` context, where the mock had already been cleared. Moved
inside, it tests something.

The subscriber keeps its single comma-joined AsyncAPI channel rather than
splitting one per queue the way the built-in brokers now do. That is a
document-shape decision, not a dependency one: #181.
@github-actions

Copy link
Copy Markdown

Benchmark gate

✅ gate passed

scenario msg/s delete/msg WALrec/msg WALB/msg fpi upd del dead_tup
consumer/w1/b10 1108 1.000 6.81 909 242 5000 5000 10000
consumer/w1/b100 896 1.000 6.88 917 243 5000 5000 10000
consumer/w2/b10 1383 1.000 6.79 958 242 5000 5000 10000
consumer/w2/b100 1678 1.000 6.73 955 243 5000 5000 10000
consumer/w4/b10 1303 1.000 6.74 962 261 5000 5000 10000
consumer/w4/b100 2011 1.000 6.86 1033 244 5000 5000 10000
consumer/w1/b100/tfbs100 8260 0.010 6.07 1116 243 5000 5000 10000
producer/w1/b100 2942 0.000 3.04 584 0 0 0 0

Gated (fails the build): delete_calls + tuple counters (upd/del/ins) + the producer's insert_calls, exact; select_calls within +2; wal_records within a 10% band. msg/s, WAL bytes and total calls are informational (timing/FPI noise).

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.

1 participant