From 703b747a314e3f54606d13574caab16d07364e21 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Tue, 23 Jul 2019 23:56:30 +0200 Subject: [PATCH] Deal with annotation on *args and **kwargs correctly, fixes #980 --- jedi/evaluate/gradual/annotation.py | 21 +++++++++++++++++++++ test/completion/pep0484_basic.py | 16 ++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/jedi/evaluate/gradual/annotation.py b/jedi/evaluate/gradual/annotation.py index 27f6c00f..c0145129 100644 --- a/jedi/evaluate/gradual/annotation.py +++ b/jedi/evaluate/gradual/annotation.py @@ -14,7 +14,9 @@ from jedi.evaluate.cache import evaluator_method_cache from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS from jedi.evaluate.gradual.typing import TypeVar, LazyGenericClass, \ AbstractAnnotatedClass +from jedi.evaluate.gradual.typing import GenericClass from jedi.evaluate.helpers import is_string +from jedi.evaluate.compiled import builtin_from_name from jedi import debug from jedi import parser_utils @@ -106,6 +108,25 @@ def _split_comment_param_declaration(decl_text): @evaluator_method_cache() def infer_param(execution_context, param): + contexts = _infer_param(execution_context, param) + evaluator = execution_context.evaluator + if param.star_count == 1: + tuple_ = builtin_from_name(evaluator, 'tuple') + return ContextSet([GenericClass( + tuple_, + generics=(contexts,), + ) for c in contexts]) + elif param.star_count == 2: + dct = builtin_from_name(evaluator, 'dict') + return ContextSet([GenericClass( + dct, + generics=(ContextSet([builtin_from_name(evaluator, 'str')]), contexts), + ) for c in contexts]) + pass + return contexts + + +def _infer_param(execution_context, param): """ Infers the type of a function parameter, using type annotations. """ diff --git a/test/completion/pep0484_basic.py b/test/completion/pep0484_basic.py index 64b69dc1..aef5437c 100644 --- a/test/completion/pep0484_basic.py +++ b/test/completion/pep0484_basic.py @@ -165,3 +165,19 @@ def keyword_only(a: str, *, b: str): a.startswi #? ['startswith'] b.startswi + + +def argskwargs(*args: int, **kwargs: float): + """ + This might be a bit confusing, but is part of the standard. + args is changed to Tuple[int] in this case and kwargs to Dict[str, float], + which makes sense if you think about it a bit. + """ + #? tuple() + args + #? int() + args[0] + #? str() + next(iter(kwargs.keys())) + #? float() + kwargs['']