forked from VimPlug/jedi
Way better support for instantiated classes in REPL
Fixes several issues: - It was not possible to correctly trace where instances were coming from in a REPL. This led to them being pretty much ignored. - Instances were then just treated as classes and not as actual instances in MixedObjects. (However since they were ignored in the first place this wasn't really an issue). - Avoiding the repr bug https://github.com/python/cpython/pull/2132/files in Jedi is working a bit differently. We're just never accessing Objects directly. This should work around 99.99% of the cases were people are using this stuff. Fixes #872
This commit is contained in:
@@ -11,6 +11,7 @@ from jedi.cache import underscore_memoization
|
||||
from jedi.evaluate import imports
|
||||
from jedi.evaluate.context import Context
|
||||
from jedi.evaluate.cache import evaluator_function_cache
|
||||
from jedi.evaluate.compiled.getattr_static import getattr_static
|
||||
|
||||
|
||||
class MixedObject(object):
|
||||
@@ -77,13 +78,14 @@ class MixedName(compiled.CompiledName):
|
||||
def infer(self):
|
||||
obj = self.parent_context.obj
|
||||
try:
|
||||
# TODO use logic from compiled.CompiledObjectFilter
|
||||
obj = getattr(obj, self.string_name)
|
||||
except AttributeError:
|
||||
# Happens e.g. in properties of
|
||||
# PyQt4.QtGui.QStyleOptionComboBox.currentText
|
||||
# -> just set it to None
|
||||
obj = None
|
||||
return [create(self._evaluator, obj, parent_context=self.parent_context)]
|
||||
return [_create(self._evaluator, obj, parent_context=self.parent_context)]
|
||||
|
||||
@property
|
||||
def api_type(self):
|
||||
@@ -116,21 +118,26 @@ def _load_module(evaluator, path, python_object):
|
||||
return module
|
||||
|
||||
|
||||
def source_findable(python_object):
|
||||
def _get_object_to_check(python_object):
|
||||
"""Check if inspect.getfile has a chance to find the source."""
|
||||
return (inspect.ismodule(python_object) or
|
||||
if (inspect.ismodule(python_object) or
|
||||
inspect.isclass(python_object) or
|
||||
inspect.ismethod(python_object) or
|
||||
inspect.isfunction(python_object) or
|
||||
inspect.istraceback(python_object) or
|
||||
inspect.isframe(python_object) or
|
||||
inspect.iscode(python_object))
|
||||
inspect.iscode(python_object)):
|
||||
return python_object
|
||||
|
||||
try:
|
||||
return python_object.__class__
|
||||
except AttributeError:
|
||||
raise TypeError # Prevents computation of `repr` within inspect.
|
||||
|
||||
|
||||
def find_syntax_node_name(evaluator, python_object):
|
||||
try:
|
||||
if not source_findable(python_object):
|
||||
raise TypeError # Prevents computation of `repr` within inspect.
|
||||
python_object = _get_object_to_check(python_object)
|
||||
path = inspect.getsourcefile(python_object)
|
||||
except TypeError:
|
||||
# The type might not be known (e.g. class_with_dict.__weakref__)
|
||||
@@ -188,7 +195,7 @@ def find_syntax_node_name(evaluator, python_object):
|
||||
|
||||
|
||||
@compiled.compiled_objects_cache('mixed_cache')
|
||||
def create(evaluator, obj, parent_context=None, *args):
|
||||
def _create(evaluator, obj, parent_context=None, *args):
|
||||
tree_node, path = find_syntax_node_name(evaluator, obj)
|
||||
|
||||
compiled_object = compiled.create(
|
||||
@@ -210,6 +217,10 @@ def create(evaluator, obj, parent_context=None, *args):
|
||||
node_is_context=True,
|
||||
node_is_object=True
|
||||
)
|
||||
if tree_node.type == 'classdef':
|
||||
if not isinstance(obj, type):
|
||||
# Is an instance, not a class.
|
||||
tree_context, = tree_context.execute_evaluated()
|
||||
|
||||
return MixedObject(
|
||||
evaluator,
|
||||
|
||||
Reference in New Issue
Block a user