diff --git a/jedi/api/classes.py b/jedi/api/classes.py index d71c15e8..4001a343 100644 --- a/jedi/api/classes.py +++ b/jedi/api/classes.py @@ -530,17 +530,13 @@ class Definition(BaseDefinition): """ typ = self.type tree_name = self._name.tree_name + if typ == 'param': + return typ + ' ' + self._name.to_string() if typ in ('function', 'class', 'module', 'instance') or tree_name is None: if typ == 'function': # For the description we want a short and a pythonic way. typ = 'def' return typ + ' ' + self._name.string_name - elif typ == 'param': - code = search_ancestor(tree_name, 'param').get_code( - include_prefix=False, - include_comma=False - ) - return typ + ' ' + code definition = tree_name.get_definition() or tree_name # Remove the prefix, because that's not what we want for get_code diff --git a/jedi/evaluate/compiled/access.py b/jedi/evaluate/compiled/access.py index b7aa3874..db74d36a 100644 --- a/jedi/evaluate/compiled/access.py +++ b/jedi/evaluate/compiled/access.py @@ -412,7 +412,7 @@ class DirectObjectAccess(object): name=p.name, has_default=p.default is not p.empty, default=self._create_access_path(p.default), - default_string=str(p.default), + default_string=repr(p.default), has_annotation=p.annotation is not p.empty, annotation=self._create_access_path(p.annotation), annotation_string=str(p.default), diff --git a/jedi/evaluate/compiled/context.py b/jedi/evaluate/compiled/context.py index 50b441fc..12e6e727 100644 --- a/jedi/evaluate/compiled/context.py +++ b/jedi/evaluate/compiled/context.py @@ -294,9 +294,7 @@ class CompiledName(AbstractNameDefinition): )]) -class SignatureParamName(AbstractNameDefinition, ParamNameInterface): - api_type = u'param' - +class SignatureParamName(ParamNameInterface, AbstractNameDefinition): def __init__(self, compiled_obj, signature_param): self.parent_context = compiled_obj.parent_context self._signature_param = signature_param @@ -306,7 +304,7 @@ class SignatureParamName(AbstractNameDefinition, ParamNameInterface): return self._signature_param.name def to_string(self): - s = self.string_name + s = self._kind_string() + self.string_name if self._signature_param.has_annotation: s += ': ' + self._signature_param.annotation_string if self._signature_param.has_default: @@ -331,9 +329,7 @@ class SignatureParamName(AbstractNameDefinition, ParamNameInterface): return contexts -class UnresolvableParamName(AbstractNameDefinition, ParamNameInterface): - api_type = u'param' - +class UnresolvableParamName(ParamNameInterface, AbstractNameDefinition): def __init__(self, compiled_obj, name, default): self.parent_context = compiled_obj.parent_context self.string_name = name diff --git a/jedi/evaluate/names.py b/jedi/evaluate/names.py index dc41b829..ce27c0f6 100644 --- a/jedi/evaluate/names.py +++ b/jedi/evaluate/names.py @@ -151,6 +151,16 @@ class TreeNameDefinition(AbstractTreeName): class ParamNameInterface(object): + api_type = u'param' + + def _kind_string(self): + kind = self.get_kind() + if kind == Parameter.VAR_POSITIONAL: # *args + return '*' + if kind == Parameter.VAR_KEYWORD: # **kwargs + return '**' + return '' + def get_kind(self): raise NotImplementedError @@ -158,9 +168,7 @@ class ParamNameInterface(object): raise NotImplementedError -class ParamName(AbstractTreeName, ParamNameInterface): - api_type = u'param' - +class ParamName(ParamNameInterface, AbstractTreeName): def __init__(self, parent_context, tree_name): self.parent_context = parent_context self.tree_name = tree_name @@ -185,7 +193,7 @@ class ParamName(AbstractTreeName, ParamNameInterface): return Parameter.POSITIONAL_OR_KEYWORD def to_string(self): - output = self.string_name + output = self._kind_string() + self.string_name param_node = self._get_param_node() if param_node.annotation is not None: output += ': ' + param_node.annotation.get_code(include_prefix=False) diff --git a/jedi/evaluate/signature.py b/jedi/evaluate/signature.py index 8206c11c..f6845b06 100644 --- a/jedi/evaluate/signature.py +++ b/jedi/evaluate/signature.py @@ -26,7 +26,7 @@ class AbstractSignature(object): is_positional = False if kind == Parameter.KEYWORD_ONLY and not is_kw_only: - yield '*' + yield '*,' is_kw_only = True yield n.to_string() diff --git a/test/test_api/test_call_signatures.py b/test/test_api/test_call_signatures.py index 544efbda..83ca628a 100644 --- a/test/test_api/test_call_signatures.py +++ b/test/test_api/test_call_signatures.py @@ -395,22 +395,22 @@ def test_keyword_argument_index(Script, environment): @pytest.mark.parametrize('code', ['foo', 'instance.foo']) -def test_kwarg_defaults(Script, environment, code): - def foo(kwarg="bla", kwarg1=1): +def test_arg_defaults(Script, environment, code): + def foo(arg="bla", arg1=1): pass class Klass: - def foo(self, kwarg="bla", kwarg1=1): + def foo(self, arg="bla", arg1=1): pass instance = Klass() src = dedent(""" - def foo2(kwarg="bla", kwarg1=1): + def foo2(arg="bla", arg1=1): pass class Klass2: - def foo2(self, kwarg="bla", kwarg1=1): + def foo2(self, arg="bla", arg1=1): pass instance = Klass2() @@ -427,8 +427,8 @@ def test_kwarg_defaults(Script, environment, code): for script in iter_scripts(): signatures = script.call_signatures() - assert signatures[0].params[0].description == 'param kwarg="bla"' - assert signatures[0].params[1].description == 'param kwarg1=1' + assert signatures[0].params[0].description in ('param arg="bla"', "param arg='bla'") + assert signatures[0].params[1].description == 'param arg1=1' def test_bracket_start(Script):