forked from VimPlug/jedi
Create a way of accessing access objects through a subprocess
This commit is contained in:
@@ -114,9 +114,8 @@ def compiled_objects_cache(attribute_name):
|
|||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
@compiled_objects_cache('compiled_cache')
|
|
||||||
def create_access(evaluator, obj):
|
def create_access(evaluator, obj):
|
||||||
return DirectObjectAccess(evaluator, obj)
|
return evaluator.compiled_subprocess.get_or_create_access_handle(obj)
|
||||||
|
|
||||||
|
|
||||||
def load_module(evaluator, path=None, name=None):
|
def load_module(evaluator, path=None, name=None):
|
||||||
@@ -329,9 +328,10 @@ class DirectObjectAccess(object):
|
|||||||
|
|
||||||
return list(reversed(list(get())))
|
return list(reversed(list(get())))
|
||||||
|
|
||||||
def execute_operation(self, other, operator):
|
def execute_operation(self, other_access_handle, operator):
|
||||||
|
other_access = other_access_handle.access
|
||||||
op = _OPERATORS[operator]
|
op = _OPERATORS[operator]
|
||||||
return self._create_access_path(op(self._obj, other._obj))
|
return self._create_access_path(op(self._obj, other_access._obj))
|
||||||
|
|
||||||
def needs_type_completions(self):
|
def needs_type_completions(self):
|
||||||
return inspect.isclass(self._obj) and self._obj != type
|
return inspect.isclass(self._obj) and self._obj != type
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from functools import partial
|
|||||||
|
|
||||||
from jedi.cache import memoize_method
|
from jedi.cache import memoize_method
|
||||||
from jedi.evaluate.compiled.subprocess import functions
|
from jedi.evaluate.compiled.subprocess import functions
|
||||||
from jedi.evaluate.compiled import CompiledObject
|
from jedi.evaluate.compiled.access import DirectObjectAccess
|
||||||
|
|
||||||
_PICKLE_PROTOCOL = 2
|
_PICKLE_PROTOCOL = 2
|
||||||
|
|
||||||
@@ -37,24 +37,39 @@ def _get_function(name):
|
|||||||
return getattr(functions, name)
|
return getattr(functions, name)
|
||||||
|
|
||||||
|
|
||||||
class EvaluatorSameProcess(object):
|
class _EvaluatorProcess(object):
|
||||||
|
def __init__(self, evaluator):
|
||||||
|
self._evaluator_weakref = weakref.ref(evaluator)
|
||||||
|
self._evaluator_id = id(evaluator)
|
||||||
|
self._handles = {}
|
||||||
|
|
||||||
|
def get_or_create_access_handle(self, obj):
|
||||||
|
id_ = id(obj)
|
||||||
|
try:
|
||||||
|
return self.get_access_handle(id_)
|
||||||
|
except KeyError:
|
||||||
|
access = DirectObjectAccess(self._evaluator_weakref(), obj)
|
||||||
|
handle = self._handles[id_] = AccessHandle(self, access, id_)
|
||||||
|
return handle
|
||||||
|
|
||||||
|
def get_access_handle(self, id_):
|
||||||
|
return self._handles[id_]
|
||||||
|
|
||||||
|
|
||||||
|
class EvaluatorSameProcess(_EvaluatorProcess):
|
||||||
"""
|
"""
|
||||||
Basically just an easy access to functions.py. It has the same API
|
Basically just an easy access to functions.py. It has the same API
|
||||||
as EvaluatorSubprocess and does the same thing without using a subprocess.
|
as EvaluatorSubprocess and does the same thing without using a subprocess.
|
||||||
This is necessary for the Interpreter process.
|
This is necessary for the Interpreter process.
|
||||||
"""
|
"""
|
||||||
def __init__(self, evaluator):
|
|
||||||
self._evaluator = evaluator
|
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
return partial(_get_function(name), self._evaluator, IgnoreHandles())
|
return partial(_get_function(name), self._evaluator_weakref())
|
||||||
|
|
||||||
|
|
||||||
class EvaluatorSubprocess(object):
|
class EvaluatorSubprocess(_EvaluatorProcess):
|
||||||
def __init__(self, evaluator, compiled_subprocess):
|
def __init__(self, evaluator, compiled_subprocess):
|
||||||
|
super(EvaluatorSubprocess).__init__(evaluator)
|
||||||
self._used = False
|
self._used = False
|
||||||
self._evaluator_weakref = weakref.ref(evaluator)
|
|
||||||
self._evaluator_id = id(evaluator)
|
|
||||||
self._compiled_subprocess = compiled_subprocess
|
self._compiled_subprocess = compiled_subprocess
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
@@ -70,7 +85,7 @@ class EvaluatorSubprocess(object):
|
|||||||
kwargs=kwargs,
|
kwargs=kwargs,
|
||||||
unpickler=lambda stdout: ModifiedUnpickler(self, stdout).load()
|
unpickler=lambda stdout: ModifiedUnpickler(self, stdout).load()
|
||||||
)
|
)
|
||||||
if isinstance(result, CompiledHandle):
|
if isinstance(result, AccessHandle):
|
||||||
result.add_subprocess(self)
|
result.add_subprocess(self)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
@@ -142,12 +157,11 @@ class Listener():
|
|||||||
from jedi.evaluate import Evaluator, project
|
from jedi.evaluate import Evaluator, project
|
||||||
|
|
||||||
try:
|
try:
|
||||||
evaluator, handles = self._evaluators[evaluator_id]
|
evaluator = self._evaluators[evaluator_id]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
evaluator = Evaluator(None, project=project.Project())
|
evaluator = Evaluator(None, project=project.Project())
|
||||||
handles = Handles()
|
self._evaluators[evaluator_id] = evaluator
|
||||||
self._evaluators[evaluator_id] = evaluator, handles
|
return evaluator
|
||||||
return evaluator, handles
|
|
||||||
|
|
||||||
def _run(self, evaluator_id, function, args, kwargs):
|
def _run(self, evaluator_id, function, args, kwargs):
|
||||||
if evaluator_id is None:
|
if evaluator_id is None:
|
||||||
@@ -155,8 +169,8 @@ class Listener():
|
|||||||
elif function is None:
|
elif function is None:
|
||||||
del self._evaluators[evaluator_id]
|
del self._evaluators[evaluator_id]
|
||||||
else:
|
else:
|
||||||
evaluator, handles = self._get_evaluator(function, evaluator_id)
|
evaluator = self._get_evaluator(function, evaluator_id)
|
||||||
return function(evaluator, handles, *args, **kwargs)
|
return function(evaluator, *args, **kwargs)
|
||||||
|
|
||||||
def listen(self):
|
def listen(self):
|
||||||
stdout = sys.stdout
|
stdout = sys.stdout
|
||||||
@@ -194,44 +208,26 @@ class ModifiedUnpickler(pickle._Unpickler):
|
|||||||
super(ModifiedUnpickler, self).load_newobj()
|
super(ModifiedUnpickler, self).load_newobj()
|
||||||
tos = self.stack[-1]
|
tos = self.stack[-1]
|
||||||
print('pop', tos, file=sys.stderr)
|
print('pop', tos, file=sys.stderr)
|
||||||
if isinstance(tos, CompiledHandle):
|
if isinstance(tos, AccessHandle):
|
||||||
tos.add_subprocess(self._subprocess)
|
tos.add_subprocess(self._subprocess)
|
||||||
dispatch[pickle.NEWOBJ[0]] = load_newobj
|
dispatch[pickle.NEWOBJ[0]] = load_newobj
|
||||||
|
|
||||||
|
|
||||||
class ModifiedPickler(pickle._Pickler):
|
class ModifiedPickler(pickle._Pickler):
|
||||||
|
def __init__(self, subprocess, *args, **kwargs):
|
||||||
|
super(ModifiedPickler, self).__init__(*args, **kwargs)
|
||||||
|
self._subprocess = subprocess
|
||||||
|
|
||||||
def save(self, obj, *args, **kwargs):
|
def save(self, obj, *args, **kwargs):
|
||||||
print('s', obj, args, kwargs, file=sys.stderr)
|
print('s', obj, args, kwargs, file=sys.stderr)
|
||||||
if isinstance(obj, CompiledObject):
|
|
||||||
obj = CompiledHandle(obj)
|
|
||||||
return super(ModifiedPickler, self).save(obj, *args, **kwargs)
|
return super(ModifiedPickler, self).save(obj, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Handles(object):
|
class AccessHandle(object):
|
||||||
def __init__(self):
|
def __init__(self, subprocess, access, id_):
|
||||||
self._handles = {}
|
self.access = access
|
||||||
|
self._subprocess = subprocess
|
||||||
def create(self, obj):
|
self._id = id_
|
||||||
handle = self._handles[id(obj)] = CompiledHandle(obj)
|
|
||||||
return handle
|
|
||||||
|
|
||||||
def get_compiled_object(self, id_):
|
|
||||||
return self._handles[id_].compiled_object
|
|
||||||
|
|
||||||
|
|
||||||
class IgnoreHandles(object):
|
|
||||||
def create(self, obj):
|
|
||||||
return obj
|
|
||||||
|
|
||||||
|
|
||||||
class CompiledHandle(object):
|
|
||||||
def __init__(self, compiled_object):
|
|
||||||
self.compiled_object = compiled_object
|
|
||||||
self._id = id(compiled_object)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def obj(self):
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def add_subprocess(self, subprocess):
|
def add_subprocess(self, subprocess):
|
||||||
self._subprocess = subprocess
|
self._subprocess = subprocess
|
||||||
@@ -244,15 +240,6 @@ class CompiledHandle(object):
|
|||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
print('getattr', name, file=sys.stderr)
|
print('getattr', name, file=sys.stderr)
|
||||||
from jedi.evaluate import compiled
|
|
||||||
attr = getattr(compiled.CompiledObject, name)
|
|
||||||
if isinstance(attr, property):
|
|
||||||
return self._subprocess.get_compiled_property(self._id, name)
|
|
||||||
elif isinstance(attr, compiled.CheckAttribute):
|
|
||||||
# It might raise an AttributeError, however we're interested in the
|
|
||||||
# function return value.
|
|
||||||
self._subprocess.get_compiled_property(self._id, name)
|
|
||||||
|
|
||||||
def compiled_method(*args, **kwargs):
|
def compiled_method(*args, **kwargs):
|
||||||
return self._subprocess.get_compiled_method_return(self._id, name, *args, **kwargs)
|
return self._subprocess.get_compiled_method_return(self._id, name, *args, **kwargs)
|
||||||
return compiled_method
|
return compiled_method
|
||||||
|
|||||||
@@ -13,14 +13,9 @@ def import_module(evaluator, handles, path=None, name=None):
|
|||||||
return handles.create(compiled_object)
|
return handles.create(compiled_object)
|
||||||
|
|
||||||
|
|
||||||
def get_compiled_property(evaluator, handles, id, attribute):
|
def get_compiled_method_return(evaluator, id, attribute, *args, **kwargs):
|
||||||
compiled_object = handles.get_compiled_object(id)
|
handle = evaluator.compiled_subprocess.get_access_handle(id)
|
||||||
return getattr(compiled_object, attribute)
|
return getattr(handle.access, attribute)(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_compiled_method_return(evaluator, handles, id, attribute, *args, **kwargs):
|
|
||||||
compiled_object = handles.get_compiled_object(id)
|
|
||||||
return getattr(compiled_object, attribute)(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def get_special_object(evaluator, handles, identifier):
|
def get_special_object(evaluator, handles, identifier):
|
||||||
|
|||||||
@@ -378,8 +378,7 @@ class Importer(object):
|
|||||||
module = ImplicitNamespaceContext(self._evaluator, fullname=fullname)
|
module = ImplicitNamespaceContext(self._evaluator, fullname=fullname)
|
||||||
module.paths = paths
|
module.paths = paths
|
||||||
elif module_file is None and not module_path.endswith(('.py', '.zip', '.egg')):
|
elif module_file is None and not module_path.endswith(('.py', '.zip', '.egg')):
|
||||||
module = self._evaluator.compiled_subprocess.import_module(module_path)
|
module = compiled.load_module(self._evaluator, path=module_path)
|
||||||
#module = compiled.load_module(self._evaluator, module_path)
|
|
||||||
else:
|
else:
|
||||||
module = _load_module(self._evaluator, module_path, code, sys_path, parent_module)
|
module = _load_module(self._evaluator, module_path, code, sys_path, parent_module)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user