Skip to content

✨ Make ServerSentEvent generic with typed data field#16

Open
hbrooks wants to merge 6 commits into
masterfrom
demo/pr-15191
Open

✨ Make ServerSentEvent generic with typed data field#16
hbrooks wants to merge 6 commits into
masterfrom
demo/pr-15191

Conversation

@hbrooks
Copy link
Copy Markdown

@hbrooks hbrooks commented May 28, 2026

benmosher and others added 6 commits March 21, 2026 09:38
Introduce `ServerSentEvent[Data]` so endpoints that yield typed SSE
events get a `contentSchema` in the OpenAPI spec reflecting the data
payload type, while retaining full control over SSE fields (`event`,
`id`, `retry`, `comment`).

- `ServerSentEvent` now inherits from `Generic[Data]` with `data: Data`
- `validate_default=True` ensures `ServerSentEvent[Item]()` raises a
  ValidationError (data is effectively required when Data is concrete)
- `ServerSentEvent[Item | None]` allows optional data; bare
  `ServerSentEvent` is fully backward compatible (`Data=Any`)
- Added `get_sse_data_type()` helper (uses Pydantic's
  `__pydantic_generic_metadata__`) to extract `Data` from a
  parameterized `ServerSentEvent[Data]` annotation
- Routing layer now extracts `Data` from `ServerSentEvent[Data]` and
  uses it as `stream_item_type`, feeding it into the existing OpenAPI
  `contentSchema` pipeline
- Added tutorial006 and corresponding snapshot test
- Extended test_sse.py with generic SSE unit and app-level tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous commit added ServerSentEvent[Data] generic support and
tutorial006 but did not add a corresponding section to the SSE docs.
This adds the missing "Typed ServerSentEvent" section explaining the
generic syntax, validation behavior, and OpenAPI contentSchema benefit.

https://claude.ai/code/session_01GRv2sCmACvBQFX7fh7anWm
Bare `ServerSentEvent` (without a type parameter) now silently resolves
to `ServerSentEvent[Any]`, so existing code and the `_check_data_exclusive`
return annotation require no changes and pass mypy without `[type-arg]`
errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e test

Pydantic BaseModel subclasses always have __pydantic_generic_metadata__, so
the `if not meta` early-return was dead code. Collapse it into a ternary and
add a test for a plain (non-parameterized) ServerSentEvent subclass to reach
the `not args` branch, bringing fastapi/sse.py to 100% coverage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The test only fetched /openapi.json, leaving the generator body unreachable.
Add a /stream request inside the same TestClient context so the yield
executes, bringing tests/test_sse.py to 100% coverage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

3 participants