Skip to content

Commit 4dc9f1b

Browse files
committed
fixed bug in edge case of using Union with dict
1 parent e259ca9 commit 4dc9f1b

File tree

3 files changed

+44
-6
lines changed

3 files changed

+44
-6
lines changed

osbot_utils/type_safe/type_safe_core/steps/Type_Safe__Step__Init.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import ForwardRef
1+
from typing import ForwardRef, Union
22
from osbot_utils.type_safe.Type_Safe__Primitive import Type_Safe__Primitive
33
from osbot_utils.type_safe.type_safe_core.collections.Type_Safe__Dict import Type_Safe__Dict
44
from osbot_utils.type_safe.type_safe_core.collections.Type_Safe__List import Type_Safe__List
@@ -103,13 +103,16 @@ def convert_value_to_type_safe_objects(self, __self, key, value):
103103
else:
104104

105105
origin = type_safe_annotations.get_origin(annotation)
106+
if origin is Union:
107+
return value
108+
106109
# If the value is an empty container, create proper type-safe container
107110
if ((isinstance(value, list ) and len(value) == 0) or
108111
(isinstance(value, dict ) and len(value) == 0) or
109112
(isinstance(value, set ) and len(value) == 0) or
110113
(isinstance(value, tuple) and len(value) == 0)):
111114
value = type_safe_step_default_value.default_value(__self.__class__, annotation) # Use default_value to create the proper type-safe container
112-
# Handle non-empty list
115+
113116
elif origin is list and isinstance(value, list):
114117
args = get_args(annotation)
115118
if args: # Only create Type_Safe__List if we have type info

tests/unit/type_safe/type_safe_core/_bugs/test_Type_Safe__bugs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
class test_Type_Safe__bugs(TestCase):
77

88

9+
910
def test__bug__property_descriptor_handling__doesnt_enforce_type_safety(self):
1011

1112
class Test_Class(Type_Safe):

tests/unit/type_safe/type_safe_core/_regression/test_Type_Safe__regression.py

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@
3232
class Node_Value(Type_Safe):
3333
value: int
3434

35+
class Base__Type(Type_Safe):
36+
ref_type: Type['Base__Type']
37+
38+
class Type__With__Forward__Ref(Base__Type):
39+
pass
40+
3541
class test_Type_Safe__regression(TestCase):
3642

3743
def test__regression__type_safe_step_init__issue_with_Dict_with_not_types(self):
@@ -1603,9 +1609,37 @@ class Cache_Entry_H(Type_Safe):
16031609
an_guid : Random_Guid # as soon as we add the Random_Guid
16041610

16051611
assert Cache_Entry_H().entry_id != Cache_Entry_H().entry_id # it works again
1612+
def test__regression__empty_dict__assigns_to_none(self):
1613+
class Schema__Cache__Data__Store__Request(Type_Safe):
1614+
data : Union[str, dict, bytes] = None
16061615

1607-
class Base__Type(Type_Safe):
1608-
ref_type: Type['Base__Type']
1616+
request_1 = Schema__Cache__Data__Store__Request()
1617+
assert request_1.data is None
16091618

1610-
class Type__With__Forward__Ref(Base__Type):
1611-
pass
1619+
request_2 = Schema__Cache__Data__Store__Request(data=None)
1620+
assert request_2.data is None
1621+
1622+
request_3 = Schema__Cache__Data__Store__Request(data={})
1623+
#assert request_3.data is None # BUG
1624+
assert request_3.data == {}
1625+
1626+
request_3 = Schema__Cache__Data__Store__Request(data={'a':42})
1627+
assert request_3.data == {'a':42 }
1628+
1629+
class An_Class_1(Type_Safe):
1630+
data : dict = None
1631+
1632+
class An_Class_2(Type_Safe):
1633+
data : Union[str, dict, bytes] = None
1634+
1635+
class An_Class_3(Type_Safe):
1636+
data : Union[str, Dict, bytes] = None
1637+
1638+
assert An_Class_1( ).data is None
1639+
assert An_Class_2( ).data is None
1640+
1641+
assert An_Class_1(data={}).data == {}
1642+
#assert An_Class_2(data={}).data is None # BUG
1643+
#assert An_Class_3(data={}).data is None # BUG
1644+
assert An_Class_2(data={}).data == {}
1645+
assert An_Class_3(data={}).data == {}

0 commit comments

Comments
 (0)