Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/fixed/tumbling-toucan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Typed JSON payload conversion no longer truncates a float to an `int` when the type hint is a union of `int` and `float`, such as `int | float`.
4 changes: 4 additions & 0 deletions temporalio/converter/_payload_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,10 @@ def value_to_type(

# Union
if is_union:
# The int conversion accepts a float and truncates it, so give a float
# to a float member before trying an earlier int member
if isinstance(value, float) and float in type_args:
return value_to_type(float, value, custom_converters)
# Try each one. Note, Optional is just a union w/ none.
for arg in type_args:
try:
Expand Down
5 changes: 5 additions & 0 deletions tests/test_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,11 @@ def fail(hint: Any, value: Any) -> None:
fail(int | None, "1")
ok(MyDataClass | NestedDataClass, MyDataClass("foo", 5, SerializableEnum.FOO))
ok(MyDataClass | NestedDataClass, NestedDataClass("foo"))
# An earlier int member must not truncate a float
ok(int | float, 5)
ok(int | float, 5.5)
ok(int | float | None, 5.5)
ok(list[int | float], [5, 5.5])

# NewType
ok(NewIntType, 5)
Expand Down
Loading