From 24db05841b155b70125f300c97c3418b311a16db Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 2 Aug 2019 10:23:52 +0200 Subject: [PATCH] Add a execute_annotation option to infer_annotation --- jedi/api/classes.py | 8 ++++++-- jedi/evaluate/names.py | 7 +++++-- test/test_api/test_signatures.py | 24 +++++++++++++++--------- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/jedi/api/classes.py b/jedi/api/classes.py index c5026b65..56994831 100644 --- a/jedi/api/classes.py +++ b/jedi/api/classes.py @@ -664,9 +664,13 @@ class ParamDefinition(Definition): def infer_default(self): return [Definition(self._evaluator, d.name) for d in self._name.infer_default()] - def infer_annotation(self): + def infer_annotation(self, **kwargs): + """ + :param execute_annotation: If False, the values are not executed and + you get classes instead of instances. + """ return [Definition(self._evaluator, d.name) - for d in self._name.infer_annotation().execute_annotation()] + for d in self._name.infer_annotation(**kwargs)] def to_string(self): return self._name.to_string() diff --git a/jedi/evaluate/names.py b/jedi/evaluate/names.py index 86537d10..bf891e82 100644 --- a/jedi/evaluate/names.py +++ b/jedi/evaluate/names.py @@ -220,11 +220,14 @@ class ParamName(BaseTreeParamName): def annotation_node(self): return self._get_param_node().annotation - def infer_annotation(self): + def infer_annotation(self, execute_annotation=True): node = self.annotation_node if node is None: return NO_CONTEXTS - return self.parent_context.parent_context.eval_node(node) + contexts = self.parent_context.parent_context.eval_node(node) + if execute_annotation: + contexts = contexts.execute_annotation() + return contexts def infer_default(self): node = self.default_node diff --git a/test/test_api/test_signatures.py b/test/test_api/test_signatures.py index 23954369..2f1936d8 100644 --- a/test/test_api/test_signatures.py +++ b/test/test_api/test_signatures.py @@ -1,21 +1,27 @@ import pytest +_tuple_code = 'from typing import Tuple\ndef f(x: Tuple[int]): ...\nf' + @pytest.mark.parametrize( - 'code, expected_params', [ - ('def f(x: 1, y): ...\nf', [None, None]), - ('def f(x: int): ...\nf', ['instance int']), - ('from typing import List\ndef f(x: List[int]): ...\nf', ['instance list']), - ('from typing import Tuple\ndef f(x: Tuple[int]): ...\nf', ['Tuple: _SpecialForm = ...']), - ('x=str\ndef f(p: x): ...\nx=int\nf', ['instance int']), + 'code, expected_params, execute_annotation', [ + ('def f(x: 1, y): ...\nf', [None, None], True), + ('def f(x: 1, y): ...\nf', ['instance int', None], False), + ('def f(x: int): ...\nf', ['instance int'], True), + ('from typing import List\ndef f(x: List[int]): ...\nf', ['instance list'], True), + ('from typing import List\ndef f(x: List[int]): ...\nf', ['class list'], False), + (_tuple_code, ['Tuple: _SpecialForm = ...'], True), + (_tuple_code, ['Tuple: _SpecialForm = ...'], False), + ('x=str\ndef f(p: x): ...\nx=int\nf', ['instance int'], True), ] ) -def test_param_annotation(Script, code, expected_params): +def test_param_annotation(Script, code, expected_params, execute_annotation): func, = Script(code).goto_assignments() sig, = func.get_signatures() for p, expected in zip(sig.params, expected_params): + annotations = p.infer_annotation(execute_annotation=execute_annotation) if expected is None: - assert not p.infer_annotation() + assert not annotations else: - annotation, = p.infer_annotation() + annotation, = annotations assert annotation.description == expected