From caffdb3e28099b15d509a68598c3dece5cfda07a Mon Sep 17 00:00:00 2001 From: "Jiayi(Jane) Wu" Date: Fri, 4 Aug 2023 11:15:19 -0500 Subject: [PATCH 1/8] fix problem with List and Dict & add support for Literal --- types2json/main.py | 11 +- types2json/tests/type_test.py | 282 ++++++++++++++++++++++++++++++++++ 2 files changed, 291 insertions(+), 2 deletions(-) create mode 100644 types2json/tests/type_test.py diff --git a/types2json/main.py b/types2json/main.py index 440522c..8f33a42 100644 --- a/types2json/main.py +++ b/types2json/main.py @@ -6,6 +6,7 @@ ClassVar, Dict, List, + Literal, Type, Union, get_args, @@ -27,6 +28,7 @@ class AttributeType(str, Enum): TUPLE = "TUPLE" OBJECT = "OBJECT" ENUM = "ENUM" + LITERAL = "LITERAL" UNKNOWN = "UNKNOWN" @@ -96,13 +98,13 @@ def _is_a_type(annotation: Any, type_) -> bool: if get_origin(annotation) is Union: return any(_is_a_type(arg, type_) for arg in get_args(annotation)) - if type_ is Enum: + if type_ is Enum and isinstance(annotation, type): return issubclass(annotation, Enum) return False -def _parse_param_type(annotation: Any) -> AttributeType: +def _parse_param_type(annotation: Any) -> AttributeType: # noqa """Parse the type of a parameter.""" if annotation is inspect.Parameter.empty: return AttributeType.UNKNOWN @@ -122,6 +124,8 @@ def _parse_param_type(annotation: Any) -> AttributeType: return AttributeType.OBJECT if _is_a_type(annotation, Enum): return AttributeType.ENUM + if _is_a_type(annotation, Literal): + return AttributeType.LITERAL return AttributeType.UNKNOWN @@ -135,6 +139,9 @@ def _get_choices(annotation: Any) -> List[Any]: if _is_a_type(annotation, bool): return [True, False] + if _is_a_type(annotation, Literal): + return annotation.__args__ + return [] diff --git a/types2json/tests/type_test.py b/types2json/tests/type_test.py new file mode 100644 index 0000000..a07f028 --- /dev/null +++ b/types2json/tests/type_test.py @@ -0,0 +1,282 @@ +from typing import ( + Dict, + List, + Literal, + Union, +) + +from types2json.main import AttributeMeta, AttributeType, get_class_init_params + + +class TestObject(object): + def __eq__(self, other): + if isinstance(other, TestObject): + return True + return False + + def __hash__(self): + return 42 + + +class TestClassAll: + def __init__( + self, + str: str, + int: int, + flt: float, + bool: bool, + obj: dict, + unknown: TestObject, + tup: tuple, + lst: list, + union: Union[str, int], + enum: AttributeType, + literal: Literal["a", "b"], + str_val: str = "string", + int_val: int = 0, + flt_val: float = 0.0, + bool_val: bool = True, + obj_val: Dict = None, + unknown_val: TestObject = None, + tup_val: tuple = (1, "hello"), + lst_val: List[int] = None, + union_val: Union[str, int] = "string", + enum_val: AttributeType = AttributeType.ENUM, + literal_val: Literal["a", "b"] = "a", + ) -> None: + self.str = str + + +class TestClassStr: + def __init__( + self, + name: str, + text: str = "text", + ) -> None: + self.name = name + self.text = text + + +def test_all_cls(): + # String with and without default value + str_param = get_class_init_params(TestClassStr) + str_param_asr = { + "name": AttributeMeta( + name="name", + value=None, + type=AttributeType.STRING, + choices=[], + required=True, + ), + "text": AttributeMeta( + name="text", + value="text", + type=AttributeType.STRING, + choices=[], + required=False, + ), + } + + # include all implemented types with/without default value + all_param = get_class_init_params(TestClassAll) + all_param_asr = { + "str": AttributeMeta( + name="str", + value=None, + type=AttributeType.STRING, + choices=[], + required=True, + ), + "int": AttributeMeta( + name="int", + value=None, + type=AttributeType.INTEGER, + choices=[], + required=True, + ), + "flt": AttributeMeta( + name="flt", + value=None, + type=AttributeType.FLOAT, + choices=[], + required=True, + ), + "bool": AttributeMeta( + name="bool", + value=None, + type=AttributeType.BOOLEAN, + choices=[True, False], + required=True, + ), + "obj": AttributeMeta( + name="obj", + value=None, + type=AttributeType.OBJECT, + choices=[], + required=True, + ), + "unknown": AttributeMeta( + name="unknown", + value=None, + type=AttributeType.UNKNOWN, + choices=[], + required=True, + ), + "tup": AttributeMeta( + name="tup", + value=None, + type=AttributeType.TUPLE, + choices=[], + required=True, + ), + "lst": AttributeMeta( + name="lst", + value=None, + type=AttributeType.ARRAY, + choices=[], + required=True, + ), + "union": AttributeMeta( + name="union", + value=None, + type=AttributeType.STRING, + choices=[], + required=True, + ), + "enum": AttributeMeta( + name="enum", + value=None, + type=AttributeType.ENUM, + choices=[ + "STRING", + "INTEGER", + "FLOAT", + "BOOLEAN", + "ARRAY", + "TUPLE", + "OBJECT", + "ENUM", + "LITERAL", + "UNKNOWN", + ], + required=True, + ), + "literal": AttributeMeta( + name="literal", + value=None, + type=AttributeType.LITERAL, + choices=["a", "b"], + required=True, + ), + "str_val": AttributeMeta( + name="str_val", + value="string", + type=AttributeType.STRING, + choices=[], + required=False, + ), + "int_val": AttributeMeta( + name="int_val", + value=0, + type=AttributeType.INTEGER, + choices=[], + required=False, + ), + "flt_val": AttributeMeta( + name="flt_val", + value=0.0, + type=AttributeType.FLOAT, + choices=[], + required=False, + ), + "bool_val": AttributeMeta( + name="bool_val", + value=True, + type=AttributeType.BOOLEAN, + choices=[True, False], + required=False, + ), + "obj_val": AttributeMeta( + name="obj_val", + value={"dict": "val"}, + type=AttributeType.OBJECT, + choices=[], + required=False, + ), + "unknown_val": AttributeMeta( + name="unknown_val", + value=TestObject(), + type=AttributeType.UNKNOWN, + choices=[], + required=False, + ), + "tup_val": AttributeMeta( + name="tup_val", + value=(1, "hello"), + type=AttributeType.TUPLE, + choices=[], + required=False, + ), + "lst_val": AttributeMeta( + name="lst_val", + value=[1, 2, 3], + type=AttributeType.ARRAY, + choices=[], + required=False, + ), + "union_val": AttributeMeta( + name="union_val", + value="string", + type=AttributeType.STRING, + choices=[], + required=False, + ), + "enum_val": AttributeMeta( + name="enum_val", + value=AttributeType.ENUM, + type=AttributeType.ENUM, + choices=[ + "STRING", + "INTEGER", + "FLOAT", + "BOOLEAN", + "ARRAY", + "TUPLE", + "OBJECT", + "ENUM", + "LITERAL", + "UNKNOWN", + ], + required=False, + ), + "literal_val": AttributeMeta( + name="literal_val", + value="a", + type=AttributeType.LITERAL, + choices=["a", "b"], + required=False, + ), + } + + assert ( + str_param == str_param_asr + ), f"Expected {str_param_asr},\n but got {str_param}" + assert ( + all_param == all_param_asr + ), f"Expected {all_param_asr},\n but got {all_param}" + + +# ---- testing mmlapipe nodes ---- +# from chimerapy.pipelines.yolov8.multi_vid_pose import YoloV8Node +# from chimerapy.pipelines.yolov8.multi_save import MultiSaveNode + +# def test_nodes(): +# # yolo node +# yolo_param = get_class_init_params(YoloV8Node) +# yolo_param_asr = {} +# print("\n".join(str(param.model_dump()) for _, param in yolo_param.items())) + +# # save node +# save_param = get_class_init_params(MultiSaveNode) +# save_param_asr = {} +# print("\n".join(str(param.model_dump()) for _, param in save_param.items())) From 2ec1a4155299b3f06a93f6e8883c8d21b690a36f Mon Sep 17 00:00:00 2001 From: "Jiayi(Jane) Wu" Date: Fri, 4 Aug 2023 11:19:48 -0500 Subject: [PATCH 2/8] fix problem with List and Dict & add support for Literal --- types2json/tests/type_test.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/types2json/tests/type_test.py b/types2json/tests/type_test.py index a07f028..6feb321 100644 --- a/types2json/tests/type_test.py +++ b/types2json/tests/type_test.py @@ -7,6 +7,10 @@ from types2json.main import AttributeMeta, AttributeType, get_class_init_params +""" +A dummy test object +""" + class TestObject(object): def __eq__(self, other): @@ -18,6 +22,12 @@ def __hash__(self): return 42 +""" +A dummy test class for all currently supported types +both with/without default values +""" + + class TestClassAll: def __init__( self, @@ -47,6 +57,11 @@ def __init__( self.str = str +""" +A dummy test class for string parameters +""" + + class TestClassStr: def __init__( self, @@ -57,6 +72,12 @@ def __init__( self.text = text +""" +Simple test with dummy test classes +Hardcoded the expected result +""" + + def test_all_cls(): # String with and without default value str_param = get_class_init_params(TestClassStr) From 6970736a9a3d874d232ffbca0662b0964af14017 Mon Sep 17 00:00:00 2001 From: "Jiayi(Jane) Wu" Date: Fri, 4 Aug 2023 11:42:48 -0500 Subject: [PATCH 3/8] fix minor error with type_test --- types2json/tests/type_test.py | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/types2json/tests/type_test.py b/types2json/tests/type_test.py index 6feb321..85dfa72 100644 --- a/types2json/tests/type_test.py +++ b/types2json/tests/type_test.py @@ -46,10 +46,10 @@ def __init__( int_val: int = 0, flt_val: float = 0.0, bool_val: bool = True, - obj_val: Dict = None, + obj_val: Dict = {"dict": "val"}, # noqa: B006 unknown_val: TestObject = None, tup_val: tuple = (1, "hello"), - lst_val: List[int] = None, + lst_val: List[int] = [1, 2, 3], # noqa: B006 union_val: Union[str, int] = "string", enum_val: AttributeType = AttributeType.ENUM, literal_val: Literal["a", "b"] = "a", @@ -226,7 +226,7 @@ def test_all_cls(): ), "unknown_val": AttributeMeta( name="unknown_val", - value=TestObject(), + value=None, type=AttributeType.UNKNOWN, choices=[], required=False, @@ -285,19 +285,3 @@ def test_all_cls(): assert ( all_param == all_param_asr ), f"Expected {all_param_asr},\n but got {all_param}" - - -# ---- testing mmlapipe nodes ---- -# from chimerapy.pipelines.yolov8.multi_vid_pose import YoloV8Node -# from chimerapy.pipelines.yolov8.multi_save import MultiSaveNode - -# def test_nodes(): -# # yolo node -# yolo_param = get_class_init_params(YoloV8Node) -# yolo_param_asr = {} -# print("\n".join(str(param.model_dump()) for _, param in yolo_param.items())) - -# # save node -# save_param = get_class_init_params(MultiSaveNode) -# save_param_asr = {} -# print("\n".join(str(param.model_dump()) for _, param in save_param.items())) From 704c344b084fa2d16aa48f5289f119f7e4590fbd Mon Sep 17 00:00:00 2001 From: "Jiayi(Jane) Wu" Date: Tue, 5 Sep 2023 00:59:11 -0500 Subject: [PATCH 4/8] added tests for nested structures --- types2json/tests/type_test.py | 101 +++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 3 deletions(-) diff --git a/types2json/tests/type_test.py b/types2json/tests/type_test.py index 85dfa72..6c53b21 100644 --- a/types2json/tests/type_test.py +++ b/types2json/tests/type_test.py @@ -54,7 +54,7 @@ def __init__( enum_val: AttributeType = AttributeType.ENUM, literal_val: Literal["a", "b"] = "a", ) -> None: - self.str = str + pass """ @@ -68,8 +68,31 @@ def __init__( name: str, text: str = "text", ) -> None: - self.name = name - self.text = text + pass + + +""" +A dummy test class for nested types +with/without default values +""" + + +class TestNested: + def __init__( + self, + tuple: tuple[tuple[int, str], tuple[float, bool]], + lst: List[List[int]], + union: Union[int, Union[str, float]], + dict: Dict[str, Dict[int, float]], + tuple_val: tuple[tuple[int, str], tuple[float, bool]] = ( + (0, "string"), + (0.0, False), + ), + lst_val: List[List[int]] = [[1, 2, 3], [4, 5, 6]], # noqa: B006 + union_val: Union[int, Union[str, float]] = "string", + dict_val: Dict[str, Dict[int, float]] = {"key": {0: 0.0}}, # noqa: B006 + ) -> None: + pass """ @@ -285,3 +308,75 @@ def test_all_cls(): assert ( all_param == all_param_asr ), f"Expected {all_param_asr},\n but got {all_param}" + + +""" +Testing embedded items +""" + + +def test_nested(): + # nested types with & wihtout value + nested_param = get_class_init_params(TestNested) + nested_param_asr = { + "tuple": AttributeMeta( + name="tuple", + value=None, + type=AttributeType.TUPLE, + choices=[], + required=True, + ), + "lst": AttributeMeta( + name="lst", + value=None, + type=AttributeType.ARRAY, + choices=[], + required=True, + ), + "union": AttributeMeta( + name="union", + value=None, + type=AttributeType.STRING, + choices=[], + required=True, + ), + "dict": AttributeMeta( + name="dict", + value=None, + type=AttributeType.OBJECT, + choices=[], + required=True, + ), + "tuple_val": AttributeMeta( + name="tuple_val", + value=((0, "string"), (0.0, False)), + type=AttributeType.TUPLE, + choices=[], + required=False, + ), + "lst_val": AttributeMeta( + name="lst_val", + value=[[1, 2, 3], [4, 5, 6]], + type=AttributeType.ARRAY, + choices=[], + required=False, + ), + "union_val": AttributeMeta( + name="union_val", + value="string", + type=AttributeType.STRING, + choices=[], + required=False, + ), + "dict_val": AttributeMeta( + name="dict_val", + value={"key": {0: 0.0}}, + type=AttributeType.OBJECT, + choices=[], + required=False, + ), + } + + assert ( + nested_param == nested_param_asr + ), f"Expected {nested_param_asr},\n but got {nested_param}" From d84275dea28df48da19e9ee28355df609ae59a17 Mon Sep 17 00:00:00 2001 From: "Jiayi(Jane) Wu" Date: Tue, 5 Sep 2023 10:16:45 -0500 Subject: [PATCH 5/8] add test for subclass --- types2json/tests/type_test.py | 85 ++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 2 deletions(-) diff --git a/types2json/tests/type_test.py b/types2json/tests/type_test.py index 6c53b21..de6bc91 100644 --- a/types2json/tests/type_test.py +++ b/types2json/tests/type_test.py @@ -71,13 +71,36 @@ def __init__( pass +""" +A dummy class that inherits from another class +""" + + +class TestSubClass(TestClassStr): + def __init__( + self, + subname: str, + subtext: str = "subtext", + ) -> None: + pass + + +class TestSubSubClass(TestSubClass): + def __init__( + self, + subsubname: str, + subsubtext: str = "subsubtext", + ) -> None: + pass + + """ A dummy test class for nested types with/without default values """ -class TestNested: +class TestClassNested: def __init__( self, tuple: tuple[tuple[int, str], tuple[float, bool]], @@ -317,7 +340,7 @@ def test_all_cls(): def test_nested(): # nested types with & wihtout value - nested_param = get_class_init_params(TestNested) + nested_param = get_class_init_params(TestClassNested) nested_param_asr = { "tuple": AttributeMeta( name="tuple", @@ -380,3 +403,61 @@ def test_nested(): assert ( nested_param == nested_param_asr ), f"Expected {nested_param_asr},\n but got {nested_param}" + + +""" +Testing subclass +""" + + +def test_subclass(): + # getting params from subclass + sub_param = get_class_init_params(TestSubSubClass) + sub_param_asr = { + "name": AttributeMeta( + name="name", + value=None, + type=AttributeType.STRING, + choices=[], + required=True, + ), + "text": AttributeMeta( + name="text", + value="text", + type=AttributeType.STRING, + choices=[], + required=False, + ), + "subname": AttributeMeta( + name="subname", + value=None, + type=AttributeType.STRING, + choices=[], + required=True, + ), + "subtext": AttributeMeta( + name="subtext", + value="subtext", + type=AttributeType.STRING, + choices=[], + required=False, + ), + "subsubname": AttributeMeta( + name="subsubname", + value=None, + type=AttributeType.STRING, + choices=[], + required=True, + ), + "subsubtext": AttributeMeta( + name="subsubtext", + value="subsubtext", + type=AttributeType.STRING, + choices=[], + required=False, + ), + } + + assert ( + sub_param == sub_param_asr + ), f"Expected {sub_param_asr},\n but got {sub_param}" From 33de6703bb9ffa4bdee841c2920b4a8f67607d4b Mon Sep 17 00:00:00 2001 From: "Jiayi(Jane) Wu" Date: Tue, 5 Sep 2023 15:47:39 -0500 Subject: [PATCH 6/8] added test for nested Enum --- types2json/tests/type_test.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/types2json/tests/type_test.py b/types2json/tests/type_test.py index de6bc91..64f1d67 100644 --- a/types2json/tests/type_test.py +++ b/types2json/tests/type_test.py @@ -1,3 +1,4 @@ +from enum import Enum from typing import ( Dict, List, @@ -22,6 +23,16 @@ def __hash__(self): return 42 +""" +A nested Enum Class +""" + + +class NestedEnum(Enum): + NESTED = "NESTED" + TYPE = AttributeType + + """ A dummy test class for all currently supported types both with/without default values @@ -107,6 +118,7 @@ def __init__( lst: List[List[int]], union: Union[int, Union[str, float]], dict: Dict[str, Dict[int, float]], + enum: NestedEnum, tuple_val: tuple[tuple[int, str], tuple[float, bool]] = ( (0, "string"), (0.0, False), @@ -114,6 +126,7 @@ def __init__( lst_val: List[List[int]] = [[1, 2, 3], [4, 5, 6]], # noqa: B006 union_val: Union[int, Union[str, float]] = "string", dict_val: Dict[str, Dict[int, float]] = {"key": {0: 0.0}}, # noqa: B006 + enum_val: NestedEnum = NestedEnum.TYPE.value.STRING, ) -> None: pass @@ -370,6 +383,13 @@ def test_nested(): choices=[], required=True, ), + "enum": AttributeMeta( + name="enum", + value=None, + type=AttributeType.ENUM, + choices=["NESTED", AttributeType], + required=True, + ), "tuple_val": AttributeMeta( name="tuple_val", value=((0, "string"), (0.0, False)), @@ -398,6 +418,13 @@ def test_nested(): choices=[], required=False, ), + "enum_val": AttributeMeta( + name="enum_val", + value=AttributeType.STRING, + type=AttributeType.ENUM, + choices=["NESTED", AttributeType], + required=False, + ), } assert ( From 1608bc918510c825ec203ef9614dd0cc39c4ceca Mon Sep 17 00:00:00 2001 From: "Jiayi(Jane) Wu" Date: Tue, 5 Sep 2023 15:56:34 -0500 Subject: [PATCH 7/8] added test for nested optional --- types2json/tests/type_test.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/types2json/tests/type_test.py b/types2json/tests/type_test.py index 64f1d67..9ee4592 100644 --- a/types2json/tests/type_test.py +++ b/types2json/tests/type_test.py @@ -1,10 +1,5 @@ from enum import Enum -from typing import ( - Dict, - List, - Literal, - Union, -) +from typing import Dict, List, Literal, Optional, Union from types2json.main import AttributeMeta, AttributeType, get_class_init_params @@ -119,6 +114,7 @@ def __init__( union: Union[int, Union[str, float]], dict: Dict[str, Dict[int, float]], enum: NestedEnum, + option: Optional[Optional[int]], tuple_val: tuple[tuple[int, str], tuple[float, bool]] = ( (0, "string"), (0.0, False), @@ -127,6 +123,7 @@ def __init__( union_val: Union[int, Union[str, float]] = "string", dict_val: Dict[str, Dict[int, float]] = {"key": {0: 0.0}}, # noqa: B006 enum_val: NestedEnum = NestedEnum.TYPE.value.STRING, + option_val: Optional[Optional[int]] = 0, ) -> None: pass @@ -390,6 +387,13 @@ def test_nested(): choices=["NESTED", AttributeType], required=True, ), + "option": AttributeMeta( + name="option", + value=None, + type=AttributeType.INTEGER, + choices=[], + required=True, + ), "tuple_val": AttributeMeta( name="tuple_val", value=((0, "string"), (0.0, False)), @@ -425,6 +429,13 @@ def test_nested(): choices=["NESTED", AttributeType], required=False, ), + "option_val": AttributeMeta( + name="option_val", + value=0, + type=AttributeType.INTEGER, + choices=[], + required=False, + ), } assert ( From 08eb7326829b809c2191f589400c10ddfd8f1017 Mon Sep 17 00:00:00 2001 From: Umesh Date: Tue, 5 Sep 2023 21:24:41 -0500 Subject: [PATCH 8/8] Refactor tests --- types2json/tests/classes.py | 128 +++++++ types2json/tests/test_types2json.py | 377 ++++++++++++++++++++- types2json/tests/type_test.py | 501 ---------------------------- 3 files changed, 504 insertions(+), 502 deletions(-) create mode 100644 types2json/tests/classes.py delete mode 100644 types2json/tests/type_test.py diff --git a/types2json/tests/classes.py b/types2json/tests/classes.py new file mode 100644 index 0000000..9f87afd --- /dev/null +++ b/types2json/tests/classes.py @@ -0,0 +1,128 @@ +from enum import Enum +from typing import Dict, List, Literal, Optional, Union + +from types2json import AttributeType + +""" +A dummy test object +""" + + +class Object(object): + def __eq__(self, other): + if isinstance(other, Object): + return True + return False + + def __hash__(self): + return 42 + + +""" +A nested Enum Class +""" + + +class NestedEnum(Enum): + NESTED = "NESTED" + TYPE = AttributeType + + +""" +A dummy test class for all currently supported types +both with/without default values +""" + + +class ClassAll: + def __init__( + self, + str: str, + int: int, + flt: float, + bool: bool, + obj: dict, + unknown: Object, + tup: tuple, + lst: list, + union: Union[str, int], + enum: AttributeType, + literal: Literal["a", "b"], + str_val: str = "string", + int_val: int = 0, + flt_val: float = 0.0, + bool_val: bool = True, + obj_val: Dict = {"dict": "val"}, # noqa: B006 + unknown_val: Object = None, + tup_val: tuple = (1, "hello"), + lst_val: List[int] = [1, 2, 3], # noqa: B006 + union_val: Union[str, int] = "string", + enum_val: AttributeType = AttributeType.ENUM, + literal_val: Literal["a", "b"] = "a", + ) -> None: + pass + + +""" +A dummy test class for string parameters +""" + + +class ClassStr: + def __init__( + self, + name: str, + text: str = "text", + ) -> None: + pass + + +""" +A dummy class that inherits from another class +""" + + +class SubClass(ClassStr): + def __init__( + self, + subname: str, + subtext: str = "subtext", + ) -> None: + pass + + +class SubSubClass(SubClass): + def __init__( + self, + subsubname: str, + subsubtext: str = "subsubtext", + ) -> None: + pass + + +""" +A dummy test class for nested types +with/without default values +""" + + +class ClassNested: + def __init__( + self, + tuple: tuple[tuple[int, str], tuple[float, bool]], + lst: List[List[int]], + union: Union[int, Union[str, float]], + dict: Dict[str, Dict[int, float]], + enum: NestedEnum, + option: Optional[Optional[int]], + tuple_val: tuple[tuple[int, str], tuple[float, bool]] = ( + (0, "string"), + (0.0, False), + ), + lst_val: List[List[int]] = [[1, 2, 3], [4, 5, 6]], # noqa: B006 + union_val: Union[int, Union[str, float]] = "string", + dict_val: Dict[str, Dict[int, float]] = {"key": {0: 0.0}}, # noqa: B006 + enum_val: NestedEnum = NestedEnum.TYPE.value.STRING, + option_val: Optional[Optional[int]] = 0, + ) -> None: + pass diff --git a/types2json/tests/test_types2json.py b/types2json/tests/test_types2json.py index bfa73d0..b98ab39 100644 --- a/types2json/tests/test_types2json.py +++ b/types2json/tests/test_types2json.py @@ -1,5 +1,11 @@ -from types2json import AttributeMeta +from types2json import AttributeMeta, AttributeType, get_class_init_params from types2json.tests.base_test import BaseTest +from types2json.tests.classes import ( + ClassAll, + ClassNested, + ClassStr, + SubSubClass, +) class TestModelClasses(BaseTest): @@ -15,3 +21,372 @@ def test_attribute_meta(self): assert meta.value == "value1" assert meta.choices == [] assert meta.required + + +class TestAttributeParser(BaseTest): + """ + Simple test with dummy test classes + Hardcoded the expected result + """ + + def test_all_cls(self): + # String with and without default value + str_param = get_class_init_params(ClassStr) + str_param_asr = { + "name": AttributeMeta( + name="name", + value=None, + type=AttributeType.STRING, + choices=[], + required=True, + ), + "text": AttributeMeta( + name="text", + value="text", + type=AttributeType.STRING, + choices=[], + required=False, + ), + } + + # include all implemented types with/without default value + all_param = get_class_init_params(ClassAll) + all_param_asr = { + "str": AttributeMeta( + name="str", + value=None, + type=AttributeType.STRING, + choices=[], + required=True, + ), + "int": AttributeMeta( + name="int", + value=None, + type=AttributeType.INTEGER, + choices=[], + required=True, + ), + "flt": AttributeMeta( + name="flt", + value=None, + type=AttributeType.FLOAT, + choices=[], + required=True, + ), + "bool": AttributeMeta( + name="bool", + value=None, + type=AttributeType.BOOLEAN, + choices=[True, False], + required=True, + ), + "obj": AttributeMeta( + name="obj", + value=None, + type=AttributeType.OBJECT, + choices=[], + required=True, + ), + "unknown": AttributeMeta( + name="unknown", + value=None, + type=AttributeType.UNKNOWN, + choices=[], + required=True, + ), + "tup": AttributeMeta( + name="tup", + value=None, + type=AttributeType.TUPLE, + choices=[], + required=True, + ), + "lst": AttributeMeta( + name="lst", + value=None, + type=AttributeType.ARRAY, + choices=[], + required=True, + ), + "union": AttributeMeta( + name="union", + value=None, + type=AttributeType.STRING, + choices=[], + required=True, + ), + "enum": AttributeMeta( + name="enum", + value=None, + type=AttributeType.ENUM, + choices=[ + "STRING", + "INTEGER", + "FLOAT", + "BOOLEAN", + "ARRAY", + "TUPLE", + "OBJECT", + "ENUM", + "LITERAL", + "UNKNOWN", + ], + required=True, + ), + "literal": AttributeMeta( + name="literal", + value=None, + type=AttributeType.LITERAL, + choices=["a", "b"], + required=True, + ), + "str_val": AttributeMeta( + name="str_val", + value="string", + type=AttributeType.STRING, + choices=[], + required=False, + ), + "int_val": AttributeMeta( + name="int_val", + value=0, + type=AttributeType.INTEGER, + choices=[], + required=False, + ), + "flt_val": AttributeMeta( + name="flt_val", + value=0.0, + type=AttributeType.FLOAT, + choices=[], + required=False, + ), + "bool_val": AttributeMeta( + name="bool_val", + value=True, + type=AttributeType.BOOLEAN, + choices=[True, False], + required=False, + ), + "obj_val": AttributeMeta( + name="obj_val", + value={"dict": "val"}, + type=AttributeType.OBJECT, + choices=[], + required=False, + ), + "unknown_val": AttributeMeta( + name="unknown_val", + value=None, + type=AttributeType.UNKNOWN, + choices=[], + required=False, + ), + "tup_val": AttributeMeta( + name="tup_val", + value=(1, "hello"), + type=AttributeType.TUPLE, + choices=[], + required=False, + ), + "lst_val": AttributeMeta( + name="lst_val", + value=[1, 2, 3], + type=AttributeType.ARRAY, + choices=[], + required=False, + ), + "union_val": AttributeMeta( + name="union_val", + value="string", + type=AttributeType.STRING, + choices=[], + required=False, + ), + "enum_val": AttributeMeta( + name="enum_val", + value=AttributeType.ENUM, + type=AttributeType.ENUM, + choices=[ + "STRING", + "INTEGER", + "FLOAT", + "BOOLEAN", + "ARRAY", + "TUPLE", + "OBJECT", + "ENUM", + "LITERAL", + "UNKNOWN", + ], + required=False, + ), + "literal_val": AttributeMeta( + name="literal_val", + value="a", + type=AttributeType.LITERAL, + choices=["a", "b"], + required=False, + ), + } + + assert ( + str_param == str_param_asr + ), f"Expected {str_param_asr},\n but got {str_param}" + assert ( + all_param == all_param_asr + ), f"Expected {all_param_asr},\n but got {all_param}" + + """ + Testing embedded items + """ + + def test_nested(self): + # nested types with & wihtout value + nested_param = get_class_init_params(ClassNested) + nested_param_asr = { + "tuple": AttributeMeta( + name="tuple", + value=None, + type=AttributeType.TUPLE, + choices=[], + required=True, + ), + "lst": AttributeMeta( + name="lst", + value=None, + type=AttributeType.ARRAY, + choices=[], + required=True, + ), + "union": AttributeMeta( + name="union", + value=None, + type=AttributeType.STRING, + choices=[], + required=True, + ), + "dict": AttributeMeta( + name="dict", + value=None, + type=AttributeType.OBJECT, + choices=[], + required=True, + ), + "enum": AttributeMeta( + name="enum", + value=None, + type=AttributeType.ENUM, + choices=["NESTED", AttributeType], + required=True, + ), + "option": AttributeMeta( + name="option", + value=None, + type=AttributeType.INTEGER, + choices=[], + required=True, + ), + "tuple_val": AttributeMeta( + name="tuple_val", + value=((0, "string"), (0.0, False)), + type=AttributeType.TUPLE, + choices=[], + required=False, + ), + "lst_val": AttributeMeta( + name="lst_val", + value=[[1, 2, 3], [4, 5, 6]], + type=AttributeType.ARRAY, + choices=[], + required=False, + ), + "union_val": AttributeMeta( + name="union_val", + value="string", + type=AttributeType.STRING, + choices=[], + required=False, + ), + "dict_val": AttributeMeta( + name="dict_val", + value={"key": {0: 0.0}}, + type=AttributeType.OBJECT, + choices=[], + required=False, + ), + "enum_val": AttributeMeta( + name="enum_val", + value=AttributeType.STRING, + type=AttributeType.ENUM, + choices=["NESTED", AttributeType], + required=False, + ), + "option_val": AttributeMeta( + name="option_val", + value=0, + type=AttributeType.INTEGER, + choices=[], + required=False, + ), + } + + assert ( + nested_param == nested_param_asr + ), f"Expected {nested_param_asr},\n but got {nested_param}" + + """ + Testing subclass + """ + + def test_subclass(self): + # getting params from subclass + sub_param = get_class_init_params(SubSubClass) + sub_param_asr = { + "name": AttributeMeta( + name="name", + value=None, + type=AttributeType.STRING, + choices=[], + required=True, + ), + "text": AttributeMeta( + name="text", + value="text", + type=AttributeType.STRING, + choices=[], + required=False, + ), + "subname": AttributeMeta( + name="subname", + value=None, + type=AttributeType.STRING, + choices=[], + required=True, + ), + "subtext": AttributeMeta( + name="subtext", + value="subtext", + type=AttributeType.STRING, + choices=[], + required=False, + ), + "subsubname": AttributeMeta( + name="subsubname", + value=None, + type=AttributeType.STRING, + choices=[], + required=True, + ), + "subsubtext": AttributeMeta( + name="subsubtext", + value="subsubtext", + type=AttributeType.STRING, + choices=[], + required=False, + ), + } + + assert ( + sub_param == sub_param_asr + ), f"Expected {sub_param_asr},\n but got {sub_param}" diff --git a/types2json/tests/type_test.py b/types2json/tests/type_test.py deleted file mode 100644 index 9ee4592..0000000 --- a/types2json/tests/type_test.py +++ /dev/null @@ -1,501 +0,0 @@ -from enum import Enum -from typing import Dict, List, Literal, Optional, Union - -from types2json.main import AttributeMeta, AttributeType, get_class_init_params - -""" -A dummy test object -""" - - -class TestObject(object): - def __eq__(self, other): - if isinstance(other, TestObject): - return True - return False - - def __hash__(self): - return 42 - - -""" -A nested Enum Class -""" - - -class NestedEnum(Enum): - NESTED = "NESTED" - TYPE = AttributeType - - -""" -A dummy test class for all currently supported types -both with/without default values -""" - - -class TestClassAll: - def __init__( - self, - str: str, - int: int, - flt: float, - bool: bool, - obj: dict, - unknown: TestObject, - tup: tuple, - lst: list, - union: Union[str, int], - enum: AttributeType, - literal: Literal["a", "b"], - str_val: str = "string", - int_val: int = 0, - flt_val: float = 0.0, - bool_val: bool = True, - obj_val: Dict = {"dict": "val"}, # noqa: B006 - unknown_val: TestObject = None, - tup_val: tuple = (1, "hello"), - lst_val: List[int] = [1, 2, 3], # noqa: B006 - union_val: Union[str, int] = "string", - enum_val: AttributeType = AttributeType.ENUM, - literal_val: Literal["a", "b"] = "a", - ) -> None: - pass - - -""" -A dummy test class for string parameters -""" - - -class TestClassStr: - def __init__( - self, - name: str, - text: str = "text", - ) -> None: - pass - - -""" -A dummy class that inherits from another class -""" - - -class TestSubClass(TestClassStr): - def __init__( - self, - subname: str, - subtext: str = "subtext", - ) -> None: - pass - - -class TestSubSubClass(TestSubClass): - def __init__( - self, - subsubname: str, - subsubtext: str = "subsubtext", - ) -> None: - pass - - -""" -A dummy test class for nested types -with/without default values -""" - - -class TestClassNested: - def __init__( - self, - tuple: tuple[tuple[int, str], tuple[float, bool]], - lst: List[List[int]], - union: Union[int, Union[str, float]], - dict: Dict[str, Dict[int, float]], - enum: NestedEnum, - option: Optional[Optional[int]], - tuple_val: tuple[tuple[int, str], tuple[float, bool]] = ( - (0, "string"), - (0.0, False), - ), - lst_val: List[List[int]] = [[1, 2, 3], [4, 5, 6]], # noqa: B006 - union_val: Union[int, Union[str, float]] = "string", - dict_val: Dict[str, Dict[int, float]] = {"key": {0: 0.0}}, # noqa: B006 - enum_val: NestedEnum = NestedEnum.TYPE.value.STRING, - option_val: Optional[Optional[int]] = 0, - ) -> None: - pass - - -""" -Simple test with dummy test classes -Hardcoded the expected result -""" - - -def test_all_cls(): - # String with and without default value - str_param = get_class_init_params(TestClassStr) - str_param_asr = { - "name": AttributeMeta( - name="name", - value=None, - type=AttributeType.STRING, - choices=[], - required=True, - ), - "text": AttributeMeta( - name="text", - value="text", - type=AttributeType.STRING, - choices=[], - required=False, - ), - } - - # include all implemented types with/without default value - all_param = get_class_init_params(TestClassAll) - all_param_asr = { - "str": AttributeMeta( - name="str", - value=None, - type=AttributeType.STRING, - choices=[], - required=True, - ), - "int": AttributeMeta( - name="int", - value=None, - type=AttributeType.INTEGER, - choices=[], - required=True, - ), - "flt": AttributeMeta( - name="flt", - value=None, - type=AttributeType.FLOAT, - choices=[], - required=True, - ), - "bool": AttributeMeta( - name="bool", - value=None, - type=AttributeType.BOOLEAN, - choices=[True, False], - required=True, - ), - "obj": AttributeMeta( - name="obj", - value=None, - type=AttributeType.OBJECT, - choices=[], - required=True, - ), - "unknown": AttributeMeta( - name="unknown", - value=None, - type=AttributeType.UNKNOWN, - choices=[], - required=True, - ), - "tup": AttributeMeta( - name="tup", - value=None, - type=AttributeType.TUPLE, - choices=[], - required=True, - ), - "lst": AttributeMeta( - name="lst", - value=None, - type=AttributeType.ARRAY, - choices=[], - required=True, - ), - "union": AttributeMeta( - name="union", - value=None, - type=AttributeType.STRING, - choices=[], - required=True, - ), - "enum": AttributeMeta( - name="enum", - value=None, - type=AttributeType.ENUM, - choices=[ - "STRING", - "INTEGER", - "FLOAT", - "BOOLEAN", - "ARRAY", - "TUPLE", - "OBJECT", - "ENUM", - "LITERAL", - "UNKNOWN", - ], - required=True, - ), - "literal": AttributeMeta( - name="literal", - value=None, - type=AttributeType.LITERAL, - choices=["a", "b"], - required=True, - ), - "str_val": AttributeMeta( - name="str_val", - value="string", - type=AttributeType.STRING, - choices=[], - required=False, - ), - "int_val": AttributeMeta( - name="int_val", - value=0, - type=AttributeType.INTEGER, - choices=[], - required=False, - ), - "flt_val": AttributeMeta( - name="flt_val", - value=0.0, - type=AttributeType.FLOAT, - choices=[], - required=False, - ), - "bool_val": AttributeMeta( - name="bool_val", - value=True, - type=AttributeType.BOOLEAN, - choices=[True, False], - required=False, - ), - "obj_val": AttributeMeta( - name="obj_val", - value={"dict": "val"}, - type=AttributeType.OBJECT, - choices=[], - required=False, - ), - "unknown_val": AttributeMeta( - name="unknown_val", - value=None, - type=AttributeType.UNKNOWN, - choices=[], - required=False, - ), - "tup_val": AttributeMeta( - name="tup_val", - value=(1, "hello"), - type=AttributeType.TUPLE, - choices=[], - required=False, - ), - "lst_val": AttributeMeta( - name="lst_val", - value=[1, 2, 3], - type=AttributeType.ARRAY, - choices=[], - required=False, - ), - "union_val": AttributeMeta( - name="union_val", - value="string", - type=AttributeType.STRING, - choices=[], - required=False, - ), - "enum_val": AttributeMeta( - name="enum_val", - value=AttributeType.ENUM, - type=AttributeType.ENUM, - choices=[ - "STRING", - "INTEGER", - "FLOAT", - "BOOLEAN", - "ARRAY", - "TUPLE", - "OBJECT", - "ENUM", - "LITERAL", - "UNKNOWN", - ], - required=False, - ), - "literal_val": AttributeMeta( - name="literal_val", - value="a", - type=AttributeType.LITERAL, - choices=["a", "b"], - required=False, - ), - } - - assert ( - str_param == str_param_asr - ), f"Expected {str_param_asr},\n but got {str_param}" - assert ( - all_param == all_param_asr - ), f"Expected {all_param_asr},\n but got {all_param}" - - -""" -Testing embedded items -""" - - -def test_nested(): - # nested types with & wihtout value - nested_param = get_class_init_params(TestClassNested) - nested_param_asr = { - "tuple": AttributeMeta( - name="tuple", - value=None, - type=AttributeType.TUPLE, - choices=[], - required=True, - ), - "lst": AttributeMeta( - name="lst", - value=None, - type=AttributeType.ARRAY, - choices=[], - required=True, - ), - "union": AttributeMeta( - name="union", - value=None, - type=AttributeType.STRING, - choices=[], - required=True, - ), - "dict": AttributeMeta( - name="dict", - value=None, - type=AttributeType.OBJECT, - choices=[], - required=True, - ), - "enum": AttributeMeta( - name="enum", - value=None, - type=AttributeType.ENUM, - choices=["NESTED", AttributeType], - required=True, - ), - "option": AttributeMeta( - name="option", - value=None, - type=AttributeType.INTEGER, - choices=[], - required=True, - ), - "tuple_val": AttributeMeta( - name="tuple_val", - value=((0, "string"), (0.0, False)), - type=AttributeType.TUPLE, - choices=[], - required=False, - ), - "lst_val": AttributeMeta( - name="lst_val", - value=[[1, 2, 3], [4, 5, 6]], - type=AttributeType.ARRAY, - choices=[], - required=False, - ), - "union_val": AttributeMeta( - name="union_val", - value="string", - type=AttributeType.STRING, - choices=[], - required=False, - ), - "dict_val": AttributeMeta( - name="dict_val", - value={"key": {0: 0.0}}, - type=AttributeType.OBJECT, - choices=[], - required=False, - ), - "enum_val": AttributeMeta( - name="enum_val", - value=AttributeType.STRING, - type=AttributeType.ENUM, - choices=["NESTED", AttributeType], - required=False, - ), - "option_val": AttributeMeta( - name="option_val", - value=0, - type=AttributeType.INTEGER, - choices=[], - required=False, - ), - } - - assert ( - nested_param == nested_param_asr - ), f"Expected {nested_param_asr},\n but got {nested_param}" - - -""" -Testing subclass -""" - - -def test_subclass(): - # getting params from subclass - sub_param = get_class_init_params(TestSubSubClass) - sub_param_asr = { - "name": AttributeMeta( - name="name", - value=None, - type=AttributeType.STRING, - choices=[], - required=True, - ), - "text": AttributeMeta( - name="text", - value="text", - type=AttributeType.STRING, - choices=[], - required=False, - ), - "subname": AttributeMeta( - name="subname", - value=None, - type=AttributeType.STRING, - choices=[], - required=True, - ), - "subtext": AttributeMeta( - name="subtext", - value="subtext", - type=AttributeType.STRING, - choices=[], - required=False, - ), - "subsubname": AttributeMeta( - name="subsubname", - value=None, - type=AttributeType.STRING, - choices=[], - required=True, - ), - "subsubtext": AttributeMeta( - name="subsubtext", - value="subsubtext", - type=AttributeType.STRING, - choices=[], - required=False, - ), - } - - assert ( - sub_param == sub_param_asr - ), f"Expected {sub_param_asr},\n but got {sub_param}"