Skip to content

Commit

Permalink
fixed bug in nested Dict with Type in Type_Safe
Browse files Browse the repository at this point in the history
  • Loading branch information
DinisCruz committed Feb 10, 2025
1 parent 936ee78 commit b266cb2
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 4 deletions.
8 changes: 7 additions & 1 deletion osbot_utils/type_safe/steps/Type_Safe__Step__From_Json.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,13 @@ def deserialize_dict__using_key_value_annotations(self, _self, key, value):
new_value = Type_Safe__Dict(expected_key_type=key_class, expected_value_type=value_class)

for dict_key, dict_value in value.items():
if issubclass(key_class, Type_Safe):
key_origin = type_safe_cache.get_origin(key_class)
if key_origin is type:
expected_dict_type = get_args(key_class)[0]
if dict_key != expected_dict_type and not issubclass(dict_key,expected_dict_type):
raise TypeError(f"Expected {expected_dict_type} class for key but got instance: {dict_key}")
new__dict_key = get_args(key_class)[0]
elif issubclass(key_class, Type_Safe):
new__dict_key = self.deserialize_from_dict(key_class(), dict_key)
else:
new__dict_key = key_class(dict_key)
Expand Down
6 changes: 5 additions & 1 deletion tests/unit/type_safe/_bugs/test_Type_Safe__bugs.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import re
import sys
import pytest
from typing import Optional, Union, Dict, Set
from typing import Optional, Union, Dict, Set, Type
from unittest import TestCase

from osbot_utils.helpers.Obj_Id import Obj_Id
from osbot_utils.type_safe.Type_Safe import Type_Safe
from osbot_utils.base_classes.Kwargs_To_Self import Kwargs_To_Self
from osbot_utils.type_safe.Type_Safe__Dict import Type_Safe__Dict
from osbot_utils.type_safe.shared.Type_Safe__Convert import type_safe_convert
from osbot_utils.utils.Dev import pprint


class test_Type_Safe__bugs(TestCase):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@
from unittest import TestCase
from typing import Optional, List, Dict, Union, Any
from enum import Enum, auto

import pytest

from osbot_utils.testing.performance.Performance_Measure__Session import Performance_Measure__Session
from osbot_utils.type_safe.Type_Safe import Type_Safe
from osbot_utils.type_safe.shared.Type_Safe__Cache import type_safe_cache
from osbot_utils.utils.Env import not_in_github_action


class test__perf__Type_Safe__ctor(TestCase):

@classmethod
def setUpClass(cls): # Set up timing thresholds
# import pytest
# pytest.skip("skipping until refactoring of Type_Safe is complete")
if not_in_github_action():
pytest.skip("Only run on GitHub (too unstable locally due to local CPU load)")
cls.time_200_ns = 200
cls.time_300_ns = 300
cls.time_700_ns = 700
Expand Down
36 changes: 36 additions & 0 deletions tests/unit/type_safe/_regression/test_Type_Safe__regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from typing import Optional, Union, List, Dict, get_origin, Type, ForwardRef, Any, Set
from unittest import TestCase
from unittest.mock import patch

from osbot_utils.helpers.Obj_Id import Obj_Id
from osbot_utils.helpers.Timestamp_Now import Timestamp_Now
from osbot_utils.helpers.Guid import Guid
from osbot_utils.helpers.python_compatibility.python_3_8 import Annotated
Expand All @@ -23,6 +25,40 @@

class test_Type_Safe__regression(TestCase):


def test__regression__error_when_using__dict_with_type_as_key(self):
class Node_Value(Type_Safe):
value: int

class Container(Type_Safe):
value_nodes: Dict[Type[Node_Value], Obj_Id]

# Case 1: Using class (should work)
node_type_1 = Node_Value
obj_id_1 = Obj_Id()
#with pytest.raises(TypeError, match=re.escape(expected_error)): # BUG should have worked
container_1 = Container(value_nodes={node_type_1: obj_id_1})

assert container_1.json() == {'value_nodes': { node_type_1: obj_id_1}}


# Case 2: Using instance
node_type_2 = Node_Value()
obj_id_2 = Obj_Id()

expected_error = "Expected <class 'test_Type_Safe__regression.test_Type_Safe__regression.test__regression__error_when_using__dict_with_type_as_key.<locals>.Node_Value'> class for key but got instance: <class 'str'>"
with pytest.raises(TypeError, match=re.escape(expected_error)):
Container(value_nodes={str: obj_id_2}) # BUG should have raised type safety error


# confirm round trip
container = Container(value_nodes={node_type_1: obj_id_1})

serialized = container.json()
deserialized = Container.from_json(serialized)

self.assertEqual(container.value_nodes, deserialized.value_nodes)

def test__regression__roundtrip_set_support(self):
class An_Class(Type_Safe):
an_set_1: set[str]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
from unittest import TestCase
from typing import List, Dict, Any, Union, Optional, Type
from enum import Enum

import pytest

from osbot_utils.testing.performance.Performance_Measure__Session import Performance_Measure__Session
from osbot_utils.type_safe.steps.Type_Safe__Step__Class_Kwargs import type_safe_step_class_kwargs
from osbot_utils.utils.Env import not_in_github_action


class SimpleEnum(Enum): # Test enum for type checking
A = 1
Expand All @@ -16,6 +21,8 @@ class test_perf__Type_Safe__Step__Class_Kwargs(TestCase):

@classmethod
def setUpClass(cls): # Define timing thresholds
if not_in_github_action():
pytest.skip("Only run on GitHub (too unstable locally due to local CPU load)")
cls.assert_enabled = False
cls.session = Performance_Measure__Session(assert_enabled=cls.assert_enabled)
cls.time_100_ns = 100
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

from osbot_utils.testing.performance.Performance_Measure__Session import Performance_Measure__Session
from osbot_utils.type_safe.steps.Type_Safe__Step__Default_Kwargs import type_safe_step_default_kwargs
from osbot_utils.utils.Env import not_in_github_action


class BaseClass: # Base class for inheritance tests
base_str : str = "base"
Expand All @@ -14,6 +16,8 @@ class test_perf__Type_Safe__Step__Default_Kwargs(TestCase):

@classmethod
def setUpClass(cls): # Define timing thresholds
if not_in_github_action():
pytest.skip("Only run on GitHub (too unstable locally due to local CPU load)")
cls.time_100_ns = 100
cls.time_200_ns = 200
cls.time_300_ns = 300
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
from unittest import TestCase
from typing import List, Dict, Any, Union, Optional
from typing import Set, Type, ForwardRef

import pytest

from osbot_utils.testing.performance.Performance_Measure__Session import Performance_Measure__Session
from osbot_utils.type_safe.steps.Type_Safe__Step__Default_Value import type_safe_step_default_value
from osbot_utils.utils.Env import not_in_github_action


class test_perf__Type_Safe__Step__Default_Value(TestCase):

@classmethod
def setUpClass(cls): # Define timing thresholds
if not_in_github_action():
pytest.skip("Only run on GitHub (too unstable locally due to local CPU load)")
cls.time_100_ns = 100
cls.time_200_ns = 200
cls.time_300_ns = 300
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@
from typing import List, Dict, Any, Union, Optional, Type
from enum import Enum
from decimal import Decimal

import pytest

from osbot_utils.testing.performance.Performance_Measure__Session import Performance_Measure__Session
from osbot_utils.type_safe.steps.Type_Safe__Step__From_Json import type_safe_step_from_json
from osbot_utils.type_safe.Type_Safe import Type_Safe
from osbot_utils.helpers.Random_Guid import Random_Guid
from osbot_utils.helpers.Random_Guid_Short import Random_Guid_Short
from osbot_utils.helpers.Safe_Id import Safe_Id
from osbot_utils.helpers.Timestamp_Now import Timestamp_Now
from osbot_utils.utils.Env import not_in_github_action


class StatusEnum(Enum): # Test enum for deserialization
Expand All @@ -28,6 +32,8 @@ class test_perf__Type_Safe__Step__From_Json(TestCase):

@classmethod
def setUpClass(cls): # Define timing thresholds
if not_in_github_action():
pytest.skip("Only run on GitHub (too unstable locally due to local CPU load)")
cls.time_100_ns = 100
cls.time_200_ns = 200
cls.time_500_ns = 500
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
from unittest import TestCase
from typing import List, Dict, Any, Union, Optional, Annotated

import pytest

from osbot_utils.testing.performance.Performance_Measure__Session import Performance_Measure__Session
from osbot_utils.type_safe.steps.Type_Safe__Step__Set_Attr import type_safe_step_set_attr
from osbot_utils.utils.Env import not_in_github_action
from tests.unit.type_safe.steps.test_perf__Type_Safe__Step__Init import MinLengthValidator, StatusEnum


class test_perf__Type_Safe__Step__Set_Attr(TestCase): # Test attribute setting performance

@classmethod
def setUpClass(cls): # Define timing thresholds
if not_in_github_action():
pytest.skip("Only run on GitHub (too unstable locally due to local CPU load)")
cls.time_100_ns = 100
cls.time_200_ns = 200
cls.time_500_ns = 500
Expand Down

0 comments on commit b266cb2

Please sign in to comment.