Skip to content

Commit 8abd972

Browse files
committed
fixed edge case with @type_safe decorator and Dict use
1 parent c505167 commit 8abd972

File tree

3 files changed

+60
-4
lines changed

3 files changed

+60
-4
lines changed

osbot_utils/type_safe/type_safe_core/methods/Type_Safe__Method.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,13 @@ def validate_direct_type(self, param_name: str, param_value: Any, expected_type:
235235
if origin in (dict, Dict): # Special handling for Dict
236236
if not isinstance(param_value, dict):
237237
raise ValueError(f"Parameter '{param_name}' expected dict but got {type(param_value)}")
238-
key_type, value_type = get_args(expected_type)
238+
239+
type_args = get_args(expected_type)
240+
if not type_args: # Dict without parameters (e.g., Dict instead of Dict[str, int])
241+
return True # Accept any dict without validating keys/values
242+
243+
key_type, value_type = type_args
244+
239245
if value_type is Any: # if value type is Any, we don't need to do any checks since they will all match
240246
return True
241247
for k, v in param_value.items():

tests/unit/testing/test__.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
from unittest import TestCase
2-
from osbot_utils.testing.__ import __, __SKIP__, __MISSING__
1+
from unittest import TestCase
2+
from osbot_utils.testing.__ import __, __SKIP__, __MISSING__
3+
from osbot_utils.testing.__helpers import obj
34

45

56
class test__(TestCase):
@@ -290,4 +291,11 @@ def test__real_world_example__api_response_validation(self):
290291
)
291292

292293
assert api_response == expected_structure # Structure valid
293-
assert api_response.json.contains(__(meta=__(total=2))) # Specific check
294+
assert api_response.json.contains(__(meta=__(total=2))) # Specific check
295+
296+
297+
def test__regression__osbot_utils__obj__doesnt_handle_reserved_keywords(self):
298+
an_json = {"tag" : "p",
299+
"class" : "title"}
300+
301+
assert obj(an_json) == __(tag='p', _class='title') # FIXED : BUG :this doesn't compile

tests/unit/type_safe/type_safe_core/decorators/test__decorator__type_safe__regression.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,48 @@
1212

1313
class test_decorator__type_safe__regression(TestCase):
1414

15+
def test__regression__type_safe__method__failed_with_dict(self):
16+
@type_safe
17+
def an_method_1(html_dict: Dict): pass
18+
19+
@type_safe
20+
def an_method_2(self, html_dict: Dict): pass
21+
22+
@type_safe
23+
def an_method_3(html_dict: dict): pass
24+
25+
@type_safe
26+
def an_method_4(self, html_dict: dict): pass
27+
28+
an_dict_1 = {}
29+
an_dict_2 = dict()
30+
31+
# BUG: with Dict fails
32+
# error_message = "not enough values to unpack (expected 2, got 0)"
33+
# with pytest.raises(ValueError, match=re.escape(error_message)):
34+
# an_method_1({}) # BUG
35+
#
36+
# with pytest.raises(ValueError, match=re.escape(error_message)):
37+
# an_method_2(None, {}) # BUG
38+
#
39+
# with pytest.raises(ValueError, match=re.escape(error_message)):
40+
# an_method_2(None, an_dict_1) # BUG
41+
42+
43+
an_method_1({}) # FIXED: BUG
44+
an_method_2(None, {}) # FIXED: BUG
45+
an_method_2(None, an_dict_1) # FIXED: BUG
46+
47+
# with dict it works
48+
an_method_3({}) # works with an_method_3(html_dict: dict)
49+
an_method_3(an_dict_1) # works with an_method_3(html_dict: dict)
50+
an_method_3(an_dict_2) # works with an_method_3(html_dict: dict)
51+
an_method_4(None, {}) # works with an_method_4(self, html_dict: dict)
52+
an_method_4(None, an_dict_1) # works with an_method_4(self, html_dict: dict)
53+
an_method_4(None, an_dict_2) # works with an_method_4(self, html_dict: dict)
54+
55+
56+
1557
def test__regression__enum_doesnt_convert_str(self):
1658
class An_Enum(str, Enum):
1759
VALUE_A = 'value_a'

0 commit comments

Comments
 (0)