Skip to content

fix(pydantic): accept union type objects for stream_type hints#617

Open
majiayu000 wants to merge 1 commit intoapache:mainfrom
majiayu000:fix-stream-type-union
Open

fix(pydantic): accept union type objects for stream_type hints#617
majiayu000 wants to merge 1 commit intoapache:mainfrom
majiayu000:fix-stream-type-union

Conversation

@majiayu000
Copy link
Copy Markdown
Contributor

@majiayu000 majiayu000 commented Dec 31, 2025

Summary

  • treat union type objects as valid stream_type values for pydantic streaming actions
  • keep runtime behavior unchanged while relaxing type hints for union-type streams

Testing

  • not run (type-hint only change)

Comment thread burr/core/action.py
Comment on lines +70 to +75
if typing.TYPE_CHECKING:
StreamingPydanticType = Any
else:
StreamingPydanticType = Union[Type["BaseModel"], Type[dict]]
if UnionType is not None:
StreamingPydanticType = Union[Type["BaseModel"], Type[dict], UnionType]
Copy link
Copy Markdown
Contributor

@skrawcz skrawcz Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doing Any for typing checking will of course work and is cheating...

I think we shouldn't have a typing.TYPE_CHECKING part here, and instead I think the fix is line 74 + 75.

note I had to do this stream_type: Union[Type["BaseModel"], Type[dict], type, "types.UnionType"], for my pyright in the IDE to not complain -- i.e. the quotes part.

@majiayu000
Copy link
Copy Markdown
Contributor Author

Thanks for the review! I've updated the code according to your suggestion:

  • Removed the TYPE_CHECKING + Any approach
  • Added "types.UnionType" (with quotes) to the Union type hints

The type definitions are now:

# burr/integrations/pydantic.py
PartialType = Union[Type[pydantic.BaseModel], Type[dict], type, "types.UnionType"]

# burr/core/action.py  
stream_type: Union[Type["BaseModel"], Type[dict], type, "types.UnionType"]

This should satisfy pyright while properly accepting union type objects like str | int for the stream_type parameter.

@andreahlert andreahlert added kind/bug Something is broken area/streaming Streaming actions, parallel streams area/typing Mypy, type hints, pydantic labels Mar 30, 2026
@github-actions github-actions Bot added the pr/stale No activity for 14+ days after review label Apr 20, 2026
@github-actions
Copy link
Copy Markdown

This PR has been inactive for 20 days after receiving review feedback.
Converting to draft.

Please mark it as ready for review when you have addressed the comments.
If no activity occurs within 90 days, it will be closed automatically.

Copy link
Copy Markdown
Contributor

@skrawcz skrawcz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tackling this! The union type support for stream_type is a needed fix for issue #607, and the runtime behavior is correct.

The TYPE_CHECKING = Any approach disables type checking entirely — it accepts stream_type="hello" without complaint. I'd recommend replacing both TYPE_CHECKING blocks with a sys.version_info >= (3, 10) guard, which pyright understands natively:

if sys.version_info >= (3, 10):
    StreamingPydanticType = Union[Type[BaseModel], Type[dict], types.UnionType]
else:
    StreamingPydanticType = Union[Type[BaseModel], Type[dict]]

This correctly narrows the type on 3.10+ while falling back gracefully on 3.9. I validated this with pyright against all the expected cases (union types, single types, dict, and invalid inputs).

Comment thread burr/core/action.py
else:
StreamingPydanticType = Union[Type["BaseModel"], Type[dict]]
if UnionType is not None:
StreamingPydanticType = Union[Type["BaseModel"], Type[dict], UnionType]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TYPE_CHECKING = Any pattern effectively disables the type checker for stream_type. Replace with:

if sys.version_info >= (3, 10):
    StreamingPydanticType = Union[Type["BaseModel"], Type[dict], types.UnionType]
else:
    StreamingPydanticType = Union[Type["BaseModel"], Type[dict]]

sys is already imported in this file. Pyright natively narrows on sys.version_info checks.

else:
PartialType = Union[Type[pydantic.BaseModel], Type[dict]]
if UnionType is not None:
PartialType = Union[Type[pydantic.BaseModel], Type[dict], UnionType]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue — replace the TYPE_CHECKING = Any pattern with the sys.version_info guard for PartialType.

@@ -22,6 +22,7 @@
import types
import typing
from typing import (
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the Any import can be removed if switching to the sys.version_info approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/streaming Streaming actions, parallel streams area/typing Mypy, type hints, pydantic kind/bug Something is broken pr/stale No activity for 14+ days after review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants