diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index 12e00786..aa40176b 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -532,7 +532,6 @@ class Script(object): :rtype: list of :class:`classes.CallSignature` """ - user_stmt = self._parser.user_stmt_with_whitespace() call, index = helpers.func_call_and_param_index(user_stmt, self._pos) if call is None: @@ -543,9 +542,10 @@ class Script(object): origins = cache.cache_call_signatures(_callable, user_stmt) debug.speed('func_call followed') - return [classes.CallSignature(self._evaluator, o, call, index) for o in origins - if o.isinstance(er.Function, er.Instance, er.Class) - or isinstance(o, compiled.CompiledObject) and o.type() != 'module'] + print([classes.CallSignature(self._evaluator, o, call, index) + for o in origins]) + return [classes.CallSignature(self._evaluator, o, call, index) + for o in origins if o.is_callable()] class Interpreter(Script): diff --git a/jedi/evaluate/compiled/__init__.py b/jedi/evaluate/compiled/__init__.py index b05d9e18..33b95b73 100644 --- a/jedi/evaluate/compiled/__init__.py +++ b/jedi/evaluate/compiled/__init__.py @@ -138,6 +138,10 @@ class CompiledObject(Base): def get_imports(self): return [] # Builtins don't have imports + def is_callable(self): + """Check if the object has a ``__call__`` method.""" + return hasattr(self.obj, '__call__') + class CompiledName(object): def __init__(self, obj, name): diff --git a/jedi/evaluate/representation.py b/jedi/evaluate/representation.py index 75f4dcc5..5cefcad4 100644 --- a/jedi/evaluate/representation.py +++ b/jedi/evaluate/representation.py @@ -160,6 +160,13 @@ class Instance(use_metaclass(CachedMetaClass, Executable)): names.append(InstanceElement(self._evaluator, self, var, True)) yield self, names + def is_callable(self): + try: + self.get_subscope_by_name('__call__') + return True + except KeyError: + return False + def get_index_types(self, index=None): args = [] if index is None else [index] try: @@ -232,6 +239,9 @@ class InstanceElement(use_metaclass(CachedMetaClass, pr.Base)): def isinstance(self, *cls): return isinstance(self.var, cls) + def is_callable(self): + return self.var.is_callable() + def __repr__(self): return "<%s of %s>" % (type(self).__name__, self.var) @@ -298,6 +308,9 @@ class Class(use_metaclass(CachedMetaClass, pr.IsScope)): return sub raise KeyError("Couldn't find subscope.") + def is_callable(self): + return True + @common.safe_property def name(self): return self.base.name @@ -379,6 +392,9 @@ class Function(use_metaclass(CachedMetaClass, pr.IsScope)): def get_magic_function_scope(self): return compiled.magic_function_class + def is_callable(self): + return True + def __getattr__(self, name): return getattr(self.base_func, name) diff --git a/jedi/parser/representation.py b/jedi/parser/representation.py index 185154d5..6894948b 100644 --- a/jedi/parser/representation.py +++ b/jedi/parser/representation.py @@ -118,6 +118,13 @@ class Base(object): scope = scope.parent return scope + def is_callable(self): + """ + By default parser objects are not callable, we make them callable by + the ``evaluate.representation`` objects. + """ + return False + def space(self, from_pos, to_pos): """Return the space between two tokens""" linecount = to_pos[0] - from_pos[0] diff --git a/test/test_api/test_call_signatures.py b/test/test_api/test_call_signatures.py index a1f12d73..6d50f12e 100644 --- a/test/test_api/test_call_signatures.py +++ b/test/test_api/test_call_signatures.py @@ -206,12 +206,11 @@ def test_signature_is_definition(): def test_no_signature(): # str doesn't have a __call__ method - assert Script('str()(').call_signatures == [] + assert Script('str()(').call_signatures() == [] s = dedent("""\ class X(): pass - X()( - """) - assert Script(s).call_signatures == [] - assert len(Script(s, column=2).call_signatures) == 1 + X()(""") + assert Script(s).call_signatures() == [] + assert len(Script(s, column=2).call_signatures()) == 1