diff --git a/jedi/evaluate/names.py b/jedi/evaluate/names.py index ce27c0f6..e1fd83cc 100644 --- a/jedi/evaluate/names.py +++ b/jedi/evaluate/names.py @@ -184,12 +184,19 @@ class ParamName(ParamNameInterface, AbstractTreeName): return Parameter.VAR_KEYWORD parent = tree_param.parent + param_appeared = False for p in parent.children: - if p.type == 'param': - if p.star_count: + if param_appeared: + if p == '/': + return Parameter.POSITIONAL_ONLY + else: + if p == '*': return Parameter.KEYWORD_ONLY - if p == tree_param: - break + if p.type == 'param': + if p.star_count: + return Parameter.KEYWORD_ONLY + if p == tree_param: + param_appeared = True return Parameter.POSITIONAL_OR_KEYWORD def to_string(self): diff --git a/jedi/evaluate/signature.py b/jedi/evaluate/signature.py index f6845b06..e0efab09 100644 --- a/jedi/evaluate/signature.py +++ b/jedi/evaluate/signature.py @@ -25,8 +25,10 @@ class AbstractSignature(object): yield '/' is_positional = False - if kind == Parameter.KEYWORD_ONLY and not is_kw_only: - yield '*,' + if kind == Parameter.VAR_POSITIONAL: + is_kw_only = True + elif kind == Parameter.KEYWORD_ONLY and not is_kw_only: + yield '*' is_kw_only = True yield n.to_string() diff --git a/test/test_evaluate/test_signature.py b/test/test_evaluate/test_signature.py index e845541b..e1f16aa7 100644 --- a/test/test_evaluate/test_signature.py +++ b/test/test_evaluate/test_signature.py @@ -32,3 +32,21 @@ def test_compiled_signature(Script, environment, code, sig, names, op, version): signature, = compiled.get_signatures() assert signature.to_string() == sig assert [n.string_name for n in signature.get_param_names()] == names + + +@pytest.mark.parametrize( + 'code, expected', [ + ('def f(a, * args, x): pass\n f(', 'f(a, *args, x)'), + ('def f(a, *, x): pass\n f(', 'f(a, *, x)'), + ('def f(*, x= 3,**kwargs): pass\n f(', 'f(*, x=3, **kwargs)'), + ('def f(x,/,y,* ,z): pass\n f(', 'f(x, /, y, *, z)'), + ('def f(a, /, *, x=3, **kwargs): pass\n f(', 'f(a, /, *, x=3, **kwargs)'), + ] +) +def test_tree_signature(Script, environment, code, expected): + # Only test this in the latest version, because of / + if environment.version_info < (3, 8): + pytest.skip() + + sig, = Script(code).call_signatures() + assert expected == sig._signature.to_string()