diff --git a/jedi/inference/star_args.py b/jedi/inference/star_args.py index ef699dd7..519cde0c 100644 --- a/jedi/inference/star_args.py +++ b/jedi/inference/star_args.py @@ -127,6 +127,7 @@ def process_params(param_names, star_count=3): # default means both * and ** used_names.add(p.string_name) yield p + # First process *args longest_param_names = () found_arg_signature = False found_kwarg_signature = False @@ -172,12 +173,7 @@ def process_params(param_names, star_count=3): # default means both * and ** elif arg_names: yield arg_names[0] - for p in kw_only_names: - if p.string_name in used_names: - continue - yield p - used_names.add(p.string_name) - + # Then process **kwargs for func, arguments in kwarg_callables: for signature in func.get_signatures(): found_kwarg_signature = True @@ -186,8 +182,16 @@ def process_params(param_names, star_count=3): # default means both * and ** arguments, signature.get_param_names(resolve_stars=False) )), star_count=2): - if p.get_kind() != Parameter.KEYWORD_ONLY or not kwarg_names: - yield p + if p.get_kind() == Parameter.VAR_KEYWORD: + kwarg_names.append(p) + elif p.get_kind() == Parameter.KEYWORD_ONLY: + kw_only_names.append(p) + + for p in kw_only_names: + if p.string_name in used_names: + continue + yield p + used_names.add(p.string_name) if not found_kwarg_signature and original_kwarg_name is not None: yield original_kwarg_name diff --git a/test/test_inference/test_signature.py b/test/test_inference/test_signature.py index 41b7d2c2..efac00d9 100644 --- a/test/test_inference/test_signature.py +++ b/test/test_inference/test_signature.py @@ -123,6 +123,12 @@ def test_tree_signature(Script, environment, code, expected): ('two_redirects(akw, kw)', 'a, c, *args, **kwargs'), ('two_redirects(kw, akw)', 'a, b, *args, c, **kwargs'), + ('two_kwargs_redirects(simple, simple)', '*args, a, b, c'), + ('two_kwargs_redirects(kw, kw)', '*args, a, b, c, **kwargs'), + ('two_kwargs_redirects(simple, kw)', '*args, a, b, c, **kwargs'), + ('two_kwargs_redirects(simple2, two_kwargs_redirects(simple, simple))', + '*args, x, a, b, c'), + ('combined_redirect(simple, simple2)', 'a, b, /, *, x'), ('combined_redirect(simple, simple3)', 'a, b, /, *, a, x: int'), ('combined_redirect(simple2, simple)', 'x, /, *, a, b, c'), @@ -130,6 +136,7 @@ def test_tree_signature(Script, environment, code, expected): ('combined_redirect(simple, kw)', 'a, b, /, *, a, b, c, **kwargs'), ('combined_redirect(kw, simple)', 'a, b, /, *, a, b, c'), + ('combined_redirect(simple, simple2)', 'a, b, /, *, x'), ('combined_lot_of_args(kw, simple4)', '*, b'), ('combined_lot_of_args(simple4, kw)', '*, b, c, **kwargs'), @@ -163,6 +170,8 @@ def test_nested_signatures(Script, environment, combination, expected, skip_pre_ return lambda *args, **kwargs: func(1, *args, **kwargs) def two_redirects(func1, func2): return lambda *args, **kwargs: func1(*args, **kwargs) + func2(1, *args, **kwargs) + def two_kwargs_redirects(func1, func2): + return lambda *args, **kwargs: func1(**kwargs) + func2(1, **kwargs) def combined_redirect(func1, func2): return lambda *args, **kwargs: func1(*args) + func2(**kwargs) def combined_lot_of_args(func1, func2):