diff --git a/jedi/api/classes.py b/jedi/api/classes.py index 19be914a..52ead9f7 100644 --- a/jedi/api/classes.py +++ b/jedi/api/classes.py @@ -293,6 +293,39 @@ class BaseDefinition(object): return '.'.join(path if path[0] else path[1:]) + def _is_callable(self): + stripped = self._definition + if isinstance(stripped, pr.Name): + stripped = stripped.parent + + return (stripped.isinstance(er.Function, er.Class) + or stripped.isinstance(compiled.CompiledObject) + and stripped.type() in ('function', 'class')) + + @property + def params(self): + """ + Raises an ``AttributeError``if the definition is not callable. + Otherwise returns a list of `Definition` that represents the params. + """ + if not self._is_callable(): + raise AttributeError() + + if self._definition.isinstance(er.Function): + if isinstance(self._definition, er.InstanceElement): + params = self._definition.params[1:] + else: + params = self._definition.params + elif self._definition.isinstance(er.compiled.CompiledObject): + params = self._definition.params + else: + try: + sub = self._definition.get_subscope_by_name('__init__') + params = sub.params[1:] # ignore self + except KeyError: + return [] + return [_Param(self._evaluator, p) for p in params] + def __repr__(self): return "<%s %s>" % (type(self).__name__, self.description) @@ -602,23 +635,6 @@ class CallSignature(Definition): """ The param index of the current call. """ self._call = call - @property - def params(self): - if self._definition.isinstance(er.Function): - if isinstance(self._definition, er.InstanceElement): - params = self._definition.params[1:] - else: - params = self._definition.params - elif self._definition.isinstance(er.compiled.CompiledObject): - params = self._definition.params - else: - try: - sub = self._definition.get_subscope_by_name('__init__') - params = sub.params[1:] # ignore self - except KeyError: - return [] - return [_Param(self._evaluator, p) for p in params] - @property def bracket_start(self): """ diff --git a/test/test_api/test_api_classes.py b/test/test_api/test_api_classes.py index 171a425e..c334be93 100644 --- a/test/test_api/test_api_classes.py +++ b/test/test_api/test_api_classes.py @@ -1,7 +1,7 @@ """ Test all things related to the ``jedi.api_classes`` module. """ -import textwrap +from textwrap import dedent from inspect import cleandoc import pytest @@ -23,7 +23,7 @@ def make_definitions(): :rtype: [jedi.api_classes.BaseDefinition] """ - source = textwrap.dedent(""" + source = dedent(""" import sys class C: @@ -43,7 +43,7 @@ def make_definitions(): definitions = [] definitions += defined_names(source) - source += textwrap.dedent(""" + source += dedent(""" variable = sys or C or x or f or g or g() or h""") lines = source.splitlines() script = Script(source, len(lines), len('variable'), None) @@ -123,3 +123,19 @@ def test_completion_documentation(): c = Script('import jedi\njedi.Scr').completions()[0] assert c.documentation(fast=False).raw() == cleandoc(Script.__doc__) + + +def test_signature_params(): + s = dedent(''' + def foo(bar): + pass + foo''') + + defs = Script(s).goto_definitions() + params = defs[0].params + assert len(params) == 1 + assert params[0].name == 'bar' + + defs = Script(s).goto_assignments() + with pytest.raises(AttributeError): + params = defs[0].params