feat(http-client-python): generate structured JSONL/SSE streaming - #11594
feat(http-client-python): generate structured JSONL/SSE streaming#11594Libba Lawrence (l0lawrence) wants to merge 2 commits into
Conversation
commit: |
|
All changed packages have been documented.
Show changes
|
Python emitter diffBaseline Diff summary: 129 file(s), +14423 / -76 Rendered diff: inline on the run summary, or the emitter-diff-html artifact. Informational check (eng/emitter-diff); does not block the PR. |
|
You can try these changes here
|
4a36e0a to
d93a175
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds structured streaming support to the TypeSpec Python emitter/generator for the Azure flavor, emitting client methods that return Stream[T] / AsyncStream[T] for JSONL (application/jsonl) and SSE (text/event-stream) responses, using TCGC streaming metadata to drive per-item deserialization and SSE event dispatch. It also vendors a small streaming runtime into generated packages to avoid requiring an unreleased azure.core.streaming dependency.
Changes:
- Emit a
streamingblock in response YAML for structured JSONL/SSE streams (including SSE event/terminal metadata) and preserve it across request overloads. - Generate and write a vendored
_utils/streaming_base.pyruntime (Stream/AsyncStream + JSONL/SSE decoders) when needed, and update response/operation modeling + response handling to returnStream[T]/AsyncStream[T]. - Add emitter-side unit tests for structured-stream detection and update dependency versions to TCGC prereleases that expose
sseMetadata.
Reviewed changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/http-client-python/README.md | Documents structured streaming behavior for Azure flavor and the vendored runtime. |
| packages/http-client-python/package.json | Updates dev dependencies to prereleases and adds an npm overrides entry for compiler version alignment. |
| packages/http-client-python/package-lock.json | Locks new prerelease dependency resolutions used by the emitter/generator tests. |
| packages/http-client-python/generator/pygen/preprocess/init.py | Preserves streaming metadata across generated overload YAML updates. |
| packages/http-client-python/generator/pygen/codegen/templates/streaming_base.py.jinja2 | Adds vendored streaming runtime template (Stream/AsyncStream + JSONL/SSE decoding). |
| packages/http-client-python/generator/pygen/codegen/serializers/general_serializer.py | Adds serializer for the new streaming runtime template. |
| packages/http-client-python/generator/pygen/codegen/serializers/builder_serializer.py | Emits response handling that returns Stream/AsyncStream with per-item deserialization callbacks. |
| packages/http-client-python/generator/pygen/codegen/serializers/init.py | Writes _utils/streaming_base.py when structured streaming is present. |
| packages/http-client-python/generator/pygen/codegen/models/response.py | Models structured stream metadata, stream return annotations, and imports needed for generated operations. |
| packages/http-client-python/generator/pygen/codegen/models/operation.py | Forces stream=True for structured streaming operations and exposes a structured-stream predicate. |
| packages/http-client-python/generator/pygen/codegen/models/code_model.py | Tracks whether any structured streaming exists to decide if vendored runtime must be emitted. |
| packages/http-client-python/emitter/test/streaming.test.ts | Adds emitter unit tests for structured-stream detection and kind inference. |
| packages/http-client-python/emitter/src/http.ts | Emits response streaming YAML using TCGC stream/sse metadata; adds structured stream detection helpers. |
| cspell.yaml | Adds streaming/runtime-related identifiers to the spellchecker dictionary. |
| .chronus/changes/structured-streaming-2026-0-0.md | Changelog entry describing the new Azure-flavor structured streaming support. |
Files not reviewed (1)
- packages/http-client-python/package-lock.json: Generated file
| def iter_events(self, iter_bytes: Iterator[bytes]) -> Iterator[T_co]: | ||
| """Iterate over events from a byte iterator. | ||
|
|
||
| :param iter_bytes: An iterator of byte chunks. | ||
| :type iter_bytes: Iterator[bytes] | ||
| :return: An iterator of decoded data. | ||
| :rtype: Iterator[DecodedType_co] | ||
| """ | ||
| ... | ||
|
|
||
|
|
||
| @runtime_checkable | ||
| class AsyncStreamDecoder(Protocol[T_co]): | ||
| """Protocol for async stream decoders.""" | ||
|
|
||
| # Why this isn't async def: https://mypy.readthedocs.io/en/stable/more_types.html#asynchronous-iterators | ||
| def aiter_events(self, iter_bytes: AsyncIterator[bytes]) -> AsyncIterator[T_co]: | ||
| """Asynchronously iterate over events from a byte iterator. | ||
|
|
||
| :param iter_bytes: An asynchronous iterator of byte chunks. | ||
| :type iter_bytes: AsyncIterator[bytes] | ||
| :return: An asynchronous iterator of decoded data. | ||
| :rtype: AsyncIterator[DecodedType_co] | ||
| """ | ||
| ... |
| async def aiter_lines(iter_bytes: AsyncIterator[bytes]) -> AsyncIterator[str]: | ||
| """Iterate over lines from a byte iterator. | ||
|
|
||
| :param iter_bytes: An iterator of byte chunks. | ||
| :type iter_bytes: Iterator[bytes] | ||
| :rtype: Iterator[str] | ||
| :return: An iterator of lines. | ||
| """ |
d93a175 to
c3924da
Compare
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e57edafe-9764-4b99-a1ae-0efd56e8729e
c3924da to
294b0c5
Compare
|
|
||
| def serialize_init_file(self, clients: list[Client]) -> str: | ||
| template = self.env.get_template("init.py.jinja2") | ||
| expose_streaming_types = ( |
There was a problem hiding this comment.
Instead of doing this and exposing Stream directly since we are going to eventually use azure-core, should we not expose this and instead type the outputs as Iterators that will eventually become an iterator created by azure-core vs gen code vendor?
Summary
Stream[T]/AsyncStream[T]for JSONL (application/jsonl) and SSE (text/event-stream) response streams.streamMetadata/sseMetadatato deserialize JSONL items and dispatch named SSE events to their concrete generated models, including terminal-event handling.Coverage
Notes
This uses the TCGC prerelease containing
sseMetadata. The external Azure mock API streaming test still asserts the previous raw-byte contract and is expected to remain failing until that test is aligned with the type-driven behavior.