forked from VimPlug/jedi
By adding a py__class__ method to CompiledObject and Class, we Jedi is able to understand isinstance checks, now.
This also includes a CheckAttribute class in evaluatue.compiled, because it's way easier to generalize the AttributeErrors there.
This commit is contained in:
@@ -5,6 +5,7 @@ import inspect
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
from jedi._compatibility import builtins as _builtins, unicode
|
from jedi._compatibility import builtins as _builtins, unicode
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
@@ -22,6 +23,19 @@ _path_re = re.compile('(?:\.[^{0}]+|[{0}]__init__\.py)$'.format(re.escape(_sep))
|
|||||||
del _sep
|
del _sep
|
||||||
|
|
||||||
|
|
||||||
|
class CheckAttribute(object):
|
||||||
|
"""Raises an AttributeError if the attribute X isn't available."""
|
||||||
|
def __init__(self, func):
|
||||||
|
self.func = func
|
||||||
|
# Remove the py in front of e.g. py__call__.
|
||||||
|
self.check_name = func.__name__[2:]
|
||||||
|
|
||||||
|
def __get__(self, instance, owner):
|
||||||
|
# This might raise an AttributeError. That's wanted.
|
||||||
|
getattr(instance.obj, self.check_name)
|
||||||
|
return partial(self.func, instance)
|
||||||
|
|
||||||
|
|
||||||
class CompiledObject(Base):
|
class CompiledObject(Base):
|
||||||
# comply with the parser
|
# comply with the parser
|
||||||
start_pos = 0, 0
|
start_pos = 0, 0
|
||||||
@@ -45,9 +59,15 @@ class CompiledObject(Base):
|
|||||||
self.obj.__call__
|
self.obj.__call__
|
||||||
return actual
|
return actual
|
||||||
|
|
||||||
|
@CheckAttribute
|
||||||
|
def py__class__(self, evaluator):
|
||||||
|
return CompiledObject(self.obj.__class__, parent=self.parent)
|
||||||
|
|
||||||
|
@CheckAttribute
|
||||||
def py__mro__(self, evaluator):
|
def py__mro__(self, evaluator):
|
||||||
return tuple(create(evaluator, cls) for cls in self.obj.__mro__)
|
return tuple(create(evaluator, cls) for cls in self.obj.__mro__)
|
||||||
|
|
||||||
|
@CheckAttribute
|
||||||
def py__bases__(self, evaluator):
|
def py__bases__(self, evaluator):
|
||||||
return tuple(create(evaluator, cls) for cls in self.obj.__bases__)
|
return tuple(create(evaluator, cls) for cls in self.obj.__bases__)
|
||||||
|
|
||||||
@@ -55,7 +75,7 @@ class CompiledObject(Base):
|
|||||||
return bool(self.obj)
|
return bool(self.obj)
|
||||||
|
|
||||||
def is_class(self):
|
def is_class(self):
|
||||||
return isinstance(self.obj, type)
|
return inspect.isclass(self.obj)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def doc(self):
|
def doc(self):
|
||||||
|
|||||||
@@ -110,6 +110,9 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
|
|
||||||
return actual
|
return actual
|
||||||
|
|
||||||
|
def py__class__(self, evaluator):
|
||||||
|
return self.base
|
||||||
|
|
||||||
def py__bool__(self):
|
def py__bool__(self):
|
||||||
# Signalize that we don't know about the bool type.
|
# Signalize that we don't know about the bool type.
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ def builtins_isinstance(evaluator, obj, params):
|
|||||||
for o in obj:
|
for o in obj:
|
||||||
for cls in classes:
|
for cls in classes:
|
||||||
try:
|
try:
|
||||||
mro_func = o.base.py__mro__
|
mro_func = o.py__class__(evaluator).py__mro__
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return any_bool
|
return any_bool
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user