From 4bff2cb7ea8d8d3564a58b8f25c4895d4e99137c Mon Sep 17 00:00:00 2001 From: Arsam Date: Mon, 27 Nov 2023 23:11:55 +0100 Subject: [PATCH] Fixed bugs and tests, added qnames for some NamedTypes --- .../api_analyzer/_ast_visitor.py | 14 +++++- .../api_analyzer/_mypy_helpers.py | 4 +- tests/data/test_main/main_test_module.py | 1 + tests/data/test_package/function_module.py | 2 +- tests/data/test_package/infer_types_module.py | 13 +++++- .../__snapshots__/test_main.ambr | 16 +++---- .../__snapshots__/test__get_api.ambr | 46 +++++++++++++------ .../__snapshots__/test_generate_stubs.ambr | 22 ++++++--- 8 files changed, 83 insertions(+), 35 deletions(-) diff --git a/src/safeds_stubgen/api_analyzer/_ast_visitor.py b/src/safeds_stubgen/api_analyzer/_ast_visitor.py index 172f1700..3c046655 100644 --- a/src/safeds_stubgen/api_analyzer/_ast_visitor.py +++ b/src/safeds_stubgen/api_analyzer/_ast_visitor.py @@ -363,7 +363,7 @@ def _mypy_expression_to_sds_type(self, expr: mp_nodes.Expression) -> sds_types.N if expr.name in {"False", "True"}: return sds_types.NamedType(name="bool") else: - return sds_types.NamedType(name=expr.name) + return sds_types.NamedType(name=expr.name, qname=expr.fullname) elif isinstance(expr, mp_nodes.IntExpr): return sds_types.NamedType(name="int") elif isinstance(expr, mp_nodes.FloatExpr): @@ -476,6 +476,18 @@ def _create_result(self, node: mp_nodes.FuncDef, function_id: str) -> list[Resul return results + elif isinstance(ret_type, sds_types.TupleType): + return [ + Result( + id=f"{function_id}/result_{i + 1}", + type=type_, + is_type_inferred=is_type_inferred, + name=f"result_{i + 1}", + docstring=self.docstring_parser.get_result_documentation(node), + ) + for i, type_ in enumerate(ret_type.types) + ] + return [Result( id=f"{function_id}/result_1", type=ret_type, diff --git a/src/safeds_stubgen/api_analyzer/_mypy_helpers.py b/src/safeds_stubgen/api_analyzer/_mypy_helpers.py index 3e9b4186..54a5b61e 100644 --- a/src/safeds_stubgen/api_analyzer/_mypy_helpers.py +++ b/src/safeds_stubgen/api_analyzer/_mypy_helpers.py @@ -79,7 +79,7 @@ def mypy_type_to_abstract_type( mypy_type_to_abstract_type(arg) for arg in mypy_type.args ]) - # Todo Aliasing: Import auflösen + # Todo Aliasing: Import auflösen, wir können wir keinen fullname (qname) bekommen return sds_types.NamedType(name=mypy_type.name) elif isinstance(mypy_type, mp_types.TypeType): # The first parameter of cls methods @@ -119,7 +119,7 @@ def mypy_type_to_abstract_type( return sds_types.DictType(key_type=key_type, value_type=value_type) else: - return sds_types.NamedType(name=type_name) + return sds_types.NamedType(name=type_name, qname=mypy_type.type.fullname) raise ValueError("Unexpected type.") diff --git a/tests/data/test_main/main_test_module.py b/tests/data/test_main/main_test_module.py index 23c7a231..214e6864 100644 --- a/tests/data/test_main/main_test_module.py +++ b/tests/data/test_main/main_test_module.py @@ -15,6 +15,7 @@ ac_alias = AnotherClass +# Todo Frage: Ist bei den Stubs param_2 optional? Wird None als default value unterstützt? # noinspection PyUnusedLocal def global_func(param_1: str = "first param", param_2: ac_alias | None = None) -> ac_alias: """Docstring 1. diff --git a/tests/data/test_package/function_module.py b/tests/data/test_package/function_module.py index 1371ca8d..976e69da 100644 --- a/tests/data/test_package/function_module.py +++ b/tests/data/test_package/function_module.py @@ -39,7 +39,7 @@ def public_no_params_no_result(): ... def params( integer: int, boolean: bool, - float_: 1.2, + float_: float, none: None, string: str, obj: FunctionModuleClassA, diff --git a/tests/data/test_package/infer_types_module.py b/tests/data/test_package/infer_types_module.py index 3a6b0c1e..b3567425 100644 --- a/tests/data/test_package/infer_types_module.py +++ b/tests/data/test_package/infer_types_module.py @@ -1,5 +1,14 @@ +class InferMe: + ... + + class InferMyTypes: - infer_attr = 1 + infer_int = 1 + infer_float = 1.2 + infer_bool = False + infer_str = "String" + infer_none = None + infer_obj = InferMe # Todo Frage: Ist "static attr inferObj: () -> a: InferMe" richtig? def __init__(self, init_param=1): self.init_infer = 3 @@ -33,6 +42,6 @@ def infer_function(infer_param=1, infer_param_2: int = "Something"): for _ in (1, 2): if infer_param_2: - return ModuleClass + return InferMe return int diff --git a/tests/safeds_stubgen/__snapshots__/test_main.ambr b/tests/safeds_stubgen/__snapshots__/test_main.ambr index 15e71567..fce8144d 100644 --- a/tests/safeds_stubgen/__snapshots__/test_main.ambr +++ b/tests/safeds_stubgen/__snapshots__/test_main.ambr @@ -635,7 +635,7 @@ 'type': dict({ 'kind': 'NamedType', 'name': 'AnotherClass', - 'qname': '', + 'qname': 'tests.data.test_main.another_path.another_module.AnotherClass', }), }), dict({ @@ -725,7 +725,7 @@ 'type': '', }), 'id': 'test_main/main_test_module/global_func/param_2', - 'is_optional': True, + 'is_optional': False, 'is_type_inferred': False, 'name': 'param_2', 'type': dict({ @@ -734,7 +734,7 @@ dict({ 'kind': 'NamedType', 'name': 'AnotherClass', - 'qname': '', + 'qname': 'tests.data.test_main.another_path.another_module.AnotherClass', }), dict({ 'kind': 'NamedType', @@ -786,7 +786,7 @@ 'type': dict({ 'kind': 'NamedType', 'name': 'AnotherClass', - 'qname': '', + 'qname': 'tests.data.test_main.another_path.another_module.AnotherClass', }), }), dict({ @@ -803,17 +803,17 @@ dict({ 'kind': 'NamedType', 'name': 'AnotherClass', - 'qname': '', + 'qname': 'tests.data.test_main.another_path.another_module.AnotherClass', }), dict({ 'kind': 'NamedType', 'name': 'AnotherClass', - 'qname': '', + 'qname': 'tests.data.test_main.another_path.another_module.AnotherClass', }), dict({ 'kind': 'NamedType', 'name': 'AnotherClass', - 'qname': '', + 'qname': 'tests.data.test_main.another_path.another_module.AnotherClass', }), ]), }), @@ -829,7 +829,7 @@ 'type': dict({ 'kind': 'NamedType', 'name': 'AnotherClass', - 'qname': '', + 'qname': 'tests.data.test_main.another_path.another_module.AnotherClass', }), }), ]), diff --git a/tests/safeds_stubgen/api_analyzer/__snapshots__/test__get_api.ambr b/tests/safeds_stubgen/api_analyzer/__snapshots__/test__get_api.ambr index f4d2d85e..f016936a 100644 --- a/tests/safeds_stubgen/api_analyzer/__snapshots__/test__get_api.ambr +++ b/tests/safeds_stubgen/api_analyzer/__snapshots__/test__get_api.ambr @@ -197,7 +197,7 @@ dict({ 'kind': 'NamedType', 'name': 'AttributesClassA', - 'qname': '', + 'qname': 'tests.data.test_package.attribute_module.AttributesClassA', }), ]), }), @@ -628,7 +628,7 @@ 'type': dict({ 'kind': 'NamedType', 'name': 'AttributesClassA', - 'qname': '', + 'qname': 'tests.data.test_package.attribute_module.AttributesClassA', }), }), dict({ @@ -1905,7 +1905,12 @@ # name: test_classes_InferMyTypes dict({ 'attributes': list([ - 'test_package/infer_types_module/InferMyTypes/infer_attr', + 'test_package/infer_types_module/InferMyTypes/infer_int', + 'test_package/infer_types_module/InferMyTypes/infer_float', + 'test_package/infer_types_module/InferMyTypes/infer_bool', + 'test_package/infer_types_module/InferMyTypes/infer_str', + 'test_package/infer_types_module/InferMyTypes/infer_none', + 'test_package/infer_types_module/InferMyTypes/infer_obj', 'test_package/infer_types_module/InferMyTypes/init_infer', ]), 'classes': list([ @@ -2124,7 +2129,7 @@ 'type': dict({ 'kind': 'NamedType', 'name': 'A', - 'qname': '', + 'qname': 'tests.data.test_package.variance_module.A', }), 'variance_type': 'CONTRAVARIANT', }), @@ -3425,7 +3430,7 @@ 'type': dict({ 'kind': 'NamedType', 'name': 'FunctionModuleClassA', - 'qname': '', + 'qname': 'tests.data.test_package.function_module.FunctionModuleClassA', }), }), dict({ @@ -4056,6 +4061,7 @@ 'type': dict({ 'kind': 'NamedType', 'name': 'float', + 'qname': '', }), }), dict({ @@ -4069,6 +4075,7 @@ 'type': dict({ 'kind': 'NamedType', 'name': 'int', + 'qname': '', }), }), ]) @@ -4236,27 +4243,32 @@ 'types': list([ dict({ 'kind': 'NamedType', - 'name': 'float', + 'name': 'int', 'qname': '', }), dict({ 'kind': 'NamedType', - 'name': 'ModuleClass', - 'qname': '', + 'name': 'InferMe', + 'qname': 'tests.data.test_package.infer_types_module.InferMe', }), dict({ 'kind': 'NamedType', - 'name': 'int', + 'name': 'None', + 'qname': 'builtins.None', + }), + dict({ + 'kind': 'NamedType', + 'name': 'float', 'qname': '', }), dict({ 'kind': 'NamedType', 'name': 'bool', - 'qname': '', + 'qname': 'builtins.bool', }), dict({ 'kind': 'NamedType', - 'name': 'None', + 'name': 'str', 'qname': '', }), dict({ @@ -4267,12 +4279,12 @@ dict({ 'kind': 'NamedType', 'name': 'InferMyTypes', - 'qname': '', + 'qname': 'tests.data.test_package.infer_types_module.InferMyTypes', }), dict({ 'kind': 'NamedType', - 'name': 'str', - 'qname': '', + 'name': 'int', + 'qname': 'builtins.int', }), ]), }), @@ -4330,7 +4342,7 @@ 'type': dict({ 'kind': 'NamedType', 'name': 'FunctionModuleClassA', - 'qname': '', + 'qname': 'tests.data.test_package.function_module.FunctionModuleClassA', }), }), ]) @@ -4348,6 +4360,7 @@ 'type': dict({ 'kind': 'NamedType', 'name': 'str', + 'qname': '', }), }), dict({ @@ -4361,6 +4374,7 @@ 'type': dict({ 'kind': 'NamedType', 'name': 'int', + 'qname': '', }), }), dict({ @@ -4374,6 +4388,7 @@ 'type': dict({ 'kind': 'NamedType', 'name': 'bool', + 'qname': '', }), }), dict({ @@ -4387,6 +4402,7 @@ 'type': dict({ 'kind': 'NamedType', 'name': 'FunctionModuleClassA', + 'qname': 'tests.data.test_package.function_module.FunctionModuleClassA', }), }), ]) diff --git a/tests/safeds_stubgen/stubs_generator/__snapshots__/test_generate_stubs.ambr b/tests/safeds_stubgen/stubs_generator/__snapshots__/test_generate_stubs.ambr index 4ef3f4d9..21fd1a6c 100644 --- a/tests/safeds_stubgen/stubs_generator/__snapshots__/test_generate_stubs.ambr +++ b/tests/safeds_stubgen/stubs_generator/__snapshots__/test_generate_stubs.ambr @@ -8,8 +8,7 @@ from abc import abstractmethod class AbstractModuleClass { - // TODO Safe-DS does not support tuple types. - @PythonName("abstract_property_method") attr abstractPropertyMethod: Tuple + @PythonName("abstract_property_method") attr abstractPropertyMethod: union // TODO Result type information missing. @Pure @@ -311,7 +310,6 @@ @PythonName("one_result") fun oneResult() -> result1: Int - // TODO Safe-DS does not support tuple types. @Pure @PythonName("multiple_results") fun multipleResults() -> (result1: String, result2: Int, result3: Boolean, result4: FunctionModuleClassA) @@ -394,11 +392,23 @@ @PythonModule("test_package.infer_types_module") package testPackage.inferTypesModule + class InferMe() + class InferMyTypes( @PythonName("init_param") initParam: Int = 1 ) { - @PythonName("infer_attr") - static attr inferAttr: Int + @PythonName("infer_int") + static attr inferInt: Int + @PythonName("infer_float") + static attr inferFloat: Float + @PythonName("infer_bool") + static attr inferBool: Boolean + @PythonName("infer_str") + static attr inferStr: String + @PythonName("infer_none") + static attr inferNone: Nothing? + @PythonName("infer_obj") + static attr inferObj: () -> a: InferMe // TODO Attribute has no type information. @PythonName("init_infer") attr initInfer @@ -408,7 +418,7 @@ static fun inferFunction( @PythonName("infer_param") inferParam: Int = 1, @PythonName("infer_param_2") inferParam2: Int = Something - ) -> (result1: union, result2: union, result3: Float) + ) -> (result1: union, result2: union, result3: Float) } '''