From f13aa59fb06d59efd7b4e18af5622eb0af421b90 Mon Sep 17 00:00:00 2001 From: Marco Eilers <eilers.marco@googlemail.com> Date: Thu, 15 Feb 2024 23:37:21 +0100 Subject: [PATCH] Proper error message for partially inferred types --- src/nagini_translation/analyzer.py | 10 ++++++++++ src/nagini_translation/lib/typeinfo.py | 3 +++ tests/functional/translation/test_partial_type.py | 12 ++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 tests/functional/translation/test_partial_type.py diff --git a/src/nagini_translation/analyzer.py b/src/nagini_translation/analyzer.py index fe4e054c3..b2326cd98 100644 --- a/src/nagini_translation/analyzer.py +++ b/src/nagini_translation/analyzer.py @@ -1219,6 +1219,16 @@ def convert_type(self, mypy_type, node) -> PythonType: return self._convert_callable_type(mypy_type, node) elif self.types.is_type_alias_type(mypy_type): return self.convert_type(mypy_type.alias.target, node) + elif self.types.is_partial_type(mypy_type): + try: + partial_type = self.convert_type(mypy_type.type, node) + except: + partial_type = None + if partial_type: + msg = f'Type {partial_type.python_class.name} could not be fully inferred (this usually means that a type argument is unknown)' + else: + msg = f'Type could not be fully inferred (this usually means that a type argument is unknown)' + raise InvalidProgramException(node, 'partial.type', message=msg) else: msg = 'Unsupported type: {}'.format(mypy_type.__class__.__name__) raise UnsupportedException(node, desc=msg) diff --git a/src/nagini_translation/lib/typeinfo.py b/src/nagini_translation/lib/typeinfo.py index cf3b107a8..675cd3fe0 100644 --- a/src/nagini_translation/lib/typeinfo.py +++ b/src/nagini_translation/lib/typeinfo.py @@ -432,6 +432,9 @@ def is_type_type(self, type: mypy.types.Type) -> bool: def is_type_alias_type(self, type: mypy.types.Type) -> bool: return isinstance(type, mypy.types.TypeAliasType) + def is_partial_type(self, type: mypy.types.Type) -> bool: + return isinstance(type, mypy.types.PartialType) + def is_any_type_from_error(self, type: mypy.types.Type) -> bool: if isinstance(type, mypy.types.AnyType): if type.type_of_any == mypy.types.TypeOfAny.from_error: diff --git a/tests/functional/translation/test_partial_type.py b/tests/functional/translation/test_partial_type.py new file mode 100644 index 000000000..4e6b10200 --- /dev/null +++ b/tests/functional/translation/test_partial_type.py @@ -0,0 +1,12 @@ +from typing import List + + +def get_odd_collatz(n: int) -> List[int]: + #:: ExpectedOutput(invalid.program:partial.type) + ans, x = [], n + while x != 1: + if x % 2 == 1: + ans.append(x) + x = x // 2 if x % 2 == 0 else x * 3 + 1 + ans.append(1) + return sorted(ans)