mirror of
https://github.com/davidhalter/jedi.git
synced 2026-05-24 17:28:36 +08:00
Don't use the pickler modification anymore. That doesn't work in other python versions and was in general a bit hard to do
This commit is contained in:
@@ -17,7 +17,8 @@ from functools import partial
|
|||||||
from jedi._compatibility import queue
|
from jedi._compatibility import queue
|
||||||
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.access import DirectObjectAccess
|
from jedi.evaluate.compiled.access import DirectObjectAccess, AccessPath, \
|
||||||
|
SignatureParam
|
||||||
|
|
||||||
_PICKLE_PROTOCOL = 2
|
_PICKLE_PROTOCOL = 2
|
||||||
|
|
||||||
@@ -88,15 +89,32 @@ class EvaluatorSubprocess(_EvaluatorProcess):
|
|||||||
func,
|
func,
|
||||||
args=args,
|
args=args,
|
||||||
kwargs=kwargs,
|
kwargs=kwargs,
|
||||||
unpickler=lambda stdout: _ModifiedUnpickler(self, stdout).load()
|
|
||||||
)
|
)
|
||||||
if isinstance(result, AccessHandle):
|
# IMO it should be possible to create a hook in pickle.load to
|
||||||
result.add_subprocess(self)
|
# mess with the loaded objects. However it's extremely complicated
|
||||||
|
# to work around this so just do it with this call. ~ dave
|
||||||
return result
|
return self._convert_access_handles(result)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
def _convert_access_handles(self, obj):
|
||||||
|
if isinstance(obj, SignatureParam):
|
||||||
|
return SignatureParam(*self._convert_access_handles(tuple(obj)))
|
||||||
|
elif isinstance(obj, tuple):
|
||||||
|
return tuple(self._convert_access_handles(o) for o in obj)
|
||||||
|
elif isinstance(obj, list):
|
||||||
|
return [self._convert_access_handles(o) for o in obj]
|
||||||
|
elif isinstance(obj, AccessHandle):
|
||||||
|
try:
|
||||||
|
# Rewrite the access handle to one we're already having.
|
||||||
|
obj = self.get_access_handle(obj.id)
|
||||||
|
except KeyError:
|
||||||
|
obj.add_subprocess(self)
|
||||||
|
self.set_access_handle(obj)
|
||||||
|
elif isinstance(obj, AccessPath):
|
||||||
|
return AccessPath(self._convert_access_handles(obj.accesses))
|
||||||
|
return obj
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
if self._used:
|
if self._used:
|
||||||
self._compiled_subprocess.delete_evaluator(self._evaluator_id)
|
self._compiled_subprocess.delete_evaluator(self._evaluator_id)
|
||||||
@@ -116,11 +134,11 @@ class _Subprocess(object):
|
|||||||
# stderr=subprocess.PIPE
|
# stderr=subprocess.PIPE
|
||||||
)
|
)
|
||||||
|
|
||||||
def _send(self, evaluator_id, function, args=(), kwargs={}, unpickler=pickle.load):
|
def _send(self, evaluator_id, function, args=(), kwargs={}):
|
||||||
data = evaluator_id, function, args, kwargs
|
data = evaluator_id, function, args, kwargs
|
||||||
pickle.dump(data, self._process.stdin, protocol=_PICKLE_PROTOCOL)
|
pickle.dump(data, self._process.stdin, protocol=_PICKLE_PROTOCOL)
|
||||||
self._process.stdin.flush()
|
self._process.stdin.flush()
|
||||||
is_exception, result = unpickler(self._process.stdout)
|
is_exception, result = pickle.load(self._process.stdout)
|
||||||
if is_exception:
|
if is_exception:
|
||||||
raise result
|
raise result
|
||||||
return result
|
return result
|
||||||
@@ -143,7 +161,7 @@ class _CompiledSubprocess(_Subprocess):
|
|||||||
)
|
)
|
||||||
self._evaluator_deletion_queue = queue.deque()
|
self._evaluator_deletion_queue = queue.deque()
|
||||||
|
|
||||||
def run(self, evaluator, function, args=(), kwargs={}, unpickler=None):
|
def run(self, evaluator, function, args=(), kwargs={}):
|
||||||
# Delete old evaluators.
|
# Delete old evaluators.
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
@@ -154,7 +172,7 @@ class _CompiledSubprocess(_Subprocess):
|
|||||||
self._send(evaluator_id, None)
|
self._send(evaluator_id, None)
|
||||||
|
|
||||||
assert callable(function)
|
assert callable(function)
|
||||||
return self._send(id(evaluator), function, args, kwargs, unpickler=unpickler)
|
return self._send(id(evaluator), function, args, kwargs)
|
||||||
|
|
||||||
def get_sys_path(self):
|
def get_sys_path(self):
|
||||||
return self._send(None, functions.get_sys_path, (), {})
|
return self._send(None, functions.get_sys_path, (), {})
|
||||||
@@ -229,30 +247,6 @@ class Listener():
|
|||||||
stdout.flush()
|
stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
class _ModifiedUnpickler(pickle._Unpickler):
|
|
||||||
dispatch = pickle._Unpickler.dispatch.copy()
|
|
||||||
|
|
||||||
def __init__(self, subprocess, *args, **kwargs):
|
|
||||||
super(_ModifiedUnpickler, self).__init__(*args, **kwargs)
|
|
||||||
self._subprocess = subprocess
|
|
||||||
|
|
||||||
def load_build(self):
|
|
||||||
super(_ModifiedUnpickler, self).load_build()
|
|
||||||
tos = self.stack[-1]
|
|
||||||
if isinstance(tos, AccessHandle):
|
|
||||||
self.stack[-1] = self.get_access_handle(tos)
|
|
||||||
dispatch[pickle.BUILD[0]] = load_build
|
|
||||||
|
|
||||||
def get_access_handle(self, access_handle):
|
|
||||||
try:
|
|
||||||
# Rewrite the access handle to one we're already having.
|
|
||||||
access_handle = self._subprocess.get_access_handle(access_handle.id)
|
|
||||||
except KeyError:
|
|
||||||
access_handle.add_subprocess(self._subprocess)
|
|
||||||
self._subprocess.set_access_handle(access_handle)
|
|
||||||
return access_handle
|
|
||||||
|
|
||||||
|
|
||||||
class AccessHandle(object):
|
class AccessHandle(object):
|
||||||
def __init__(self, subprocess, access, id_):
|
def __init__(self, subprocess, access, id_):
|
||||||
self.access = access
|
self.access = access
|
||||||
|
|||||||
Reference in New Issue
Block a user