Skip to content

Commit 57344be

Browse files
Callum027Callum Dickinson
andauthored
Fix more Python 3.10+ union type parsing issues (#14)
* Fix parsing Python 3.10+ type hints when encoding search filters. * Fix parsing Python 3.10+ type hints when decoding record values. * Add missing release note for fixing parsing Python 3.10+ type hints when evaluating model refs. Co-authored-by: Callum Dickinson <[email protected]>
1 parent 33e5d51 commit 57344be

File tree

4 files changed

+19
-11
lines changed

4 files changed

+19
-11
lines changed

changelog.d/12.fixed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix parsing Python 3.10+ union type hints when evaluating model refs

changelog.d/14.fixed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix parsing Python 3.10+ union type hints when encoding search filters, and decoding record values

openstack_odooclient/base/record.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -395,10 +395,9 @@ def _getattr_model_ref(
395395
attr_type_origin = get_type_origin(attr_type)
396396
if attr_type_origin is Union or attr_type_origin is UnionType:
397397
unsupported_union = (
398-
"Only unions of the format Optional[T], "
399-
"Union[T, type(None)] or Union[T, Literal[False]] "
400-
"are supported for singular model refs, "
401-
f"found type hint: {attr_type}"
398+
"Only unions of the format 'T | None' "
399+
"or 'T | Literal[False]' are supported for singular "
400+
f"model refs, found type hint: {attr_type}"
402401
)
403402
union_types = set(get_type_args(attr_type))
404403
if len(union_types) > 2: # noqa: PLR2004
@@ -465,7 +464,7 @@ def _decode_value(cls, type_hint: Any, value: Any) -> Any:
465464
# Not suitable for handling complicated union structures.
466465
# TODO(callumdickinson): Find a way to handle complicated
467466
# union structures more smartly.
468-
if value_type is Union:
467+
if value_type is Union or value_type is UnionType:
469468
attr_union_types = get_type_args(type_hint)
470469
if len(attr_union_types) == 2: # noqa: PLR2004
471470
# T | None

openstack_odooclient/base/record_manager.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import builtins
1919

2020
from datetime import date, datetime
21-
from types import MappingProxyType
21+
from types import MappingProxyType, UnionType
2222
from typing import (
2323
TYPE_CHECKING,
2424
Annotated,
@@ -961,25 +961,32 @@ def _encode_value(self, type_hint: Any, value: Any) -> Any:
961961
return value
962962
# For every other field type, parse the possible value types
963963
# from the type hint.
964+
# First, remove Annotated to get the actual attribute type.
964965
type_hint_origin = get_type_origin(type_hint) or type_hint
965966
attr_type = (
966967
get_type_args(type_hint)[0]
967968
if type_hint_origin is Annotated
968-
else type_hint_origin
969+
else type_hint
969970
)
971+
# Next, get a list of allowed values types from the attribute type.
972+
# If there is only one, create a list containing only that type.
970973
attr_type_origin = get_type_origin(attr_type) or attr_type
971974
value_types = (
972975
get_type_args(attr_type)
973-
if attr_type_origin is Union
974-
else [attr_type_origin]
976+
if attr_type_origin is Union or attr_type_origin is UnionType
977+
else [attr_type]
975978
)
976979
# Recursively handle the types that need to be serialised.
977980
for value_type in value_types:
981+
value_type_origin = get_type_origin(value_type) or value_type
978982
if value_type is date and isinstance(value, date):
979983
return value.strftime(DEFAULT_SERVER_DATE_FORMAT)
980984
if value_type is datetime and isinstance(value, datetime):
981985
return value.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
982-
if value_type is list and isinstance(value, (list, set, tuple)):
983-
v_type = get_type_args(type_hint)[0]
986+
if value_type_origin is list and isinstance(
987+
value,
988+
(list, set, tuple),
989+
):
990+
v_type = get_type_args(value_type)[0]
984991
return [self._encode_value(v_type, v) for v in value]
985992
return value

0 commit comments

Comments
 (0)