fix: allow union types (X | Y) for stream_type in streaming_action.pydantic#845
fix: allow union types (X | Y) for stream_type in streaming_action.pydantic#845mirakour wants to merge 3 commits into
Conversation
Add regression tests for union stream type support in Pydantic decorators. These tests ensure compatibility with Python 3.10's union type syntax.
|
Heads up that #813 (opened 2026-06-20) implements the same feature, touching the same two files. Worth the maintainers deciding between them rather than reviewing both in isolation. Having read both, there are two cases this one may not cover. 1. 2. Union members are not validated. Widening #813 handles both by keeping the annotation wide and doing the real check at decoration time: if typing.get_origin(t) is Union: # typing.Union[...]
return all(_is_valid_stream_type(arg) for arg in typing.get_args(t))
_UnionType = getattr(types, "UnionType", None) # X | Y, guarded for 3.9
if _UnionType is not None and isinstance(t, _UnionType):
return all(_is_valid_stream_type(arg) for arg in t.__args__)That also speaks to @elijahbenizzy's question on #607 ("does it actually detect per-instance rather than assume they're all the same?"): recursing into the members is what makes an invalid union fail at decoration time rather than surfacing later during streaming. Not trying to talk down your PR - the smaller diff is appealing and the version guard is careful. But if the two get merged into one, the member validation and the |
Closes #607
What and Why
The
stream_typeparameter in@streaming_action.pydanticandpydantic_streaming_actioncurrently only accepts a single Pydantic model class ordict. Passing a union type (e.g.ModelA | ModelBusing Python 3.10+ syntax) raises aTypeErrorbecausetypes.UnionTypeis not included in thePartialTypealias.This PR fixes that by expanding
PartialTypeto includetypes.UnionTypeon Python 3.10+ using a version guard, and updating thestream_typeannotation inaction.pyaccordingly.Changes
burr/integrations/pydantic.py: Addedimport sysand a version guard soPartialTypeincludestypes.UnionTypeon Python 3.10+burr/core/action.py: Updated thestream_typeannotation instreaming_action.pydantic()fromUnion[Type["BaseModel"], Type[dict]]toUnion[Type["BaseModel"], Type[dict], Any]tests/integrations/test_burr_pydantic.py: Added 3 regression tests guarded with@pytest.mark.skipif(sys.version_info < (3, 10), ...)How I tested this
Added 3 regression tests in
tests/integrations/test_burr_pydantic.py:test_validate_streaming_signature_accepts_union_stream_type— verifies the internal validation function acceptstypes.UnionTypetest_pydantic_streaming_action_accepts_union_stream_type— verifies@pydantic_streaming_actionworks withstream_type=ModelA | ModelBtest_streaming_action_pydantic_decorator_accepts_union_stream_type— same for the@streaming_action.pydanticdecoratorAll tests are skipped automatically on Python < 3.10.
Notes
PartialTypeis preserved for older versionsAnyannotation inaction.pyis intentionally broad to accommodate future union-like types without requiring another version guardChecklist