mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 14:04:26 +08:00
Use highest possible pickle protocol
This commit is contained in:
@@ -446,9 +446,6 @@ if sys.version_info[:2] == (3, 3):
|
|||||||
pickle.loads = loads
|
pickle.loads = loads
|
||||||
|
|
||||||
|
|
||||||
_PICKLE_PROTOCOL = 2
|
|
||||||
|
|
||||||
|
|
||||||
def pickle_load(file):
|
def pickle_load(file):
|
||||||
try:
|
try:
|
||||||
if is_py3:
|
if is_py3:
|
||||||
@@ -462,9 +459,9 @@ def pickle_load(file):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def pickle_dump(data, file):
|
def pickle_dump(data, file, protocol):
|
||||||
try:
|
try:
|
||||||
pickle.dump(data, file, protocol=_PICKLE_PROTOCOL)
|
pickle.dump(data, file, protocol)
|
||||||
# On Python 3.3 flush throws sometimes an error even though the writing
|
# On Python 3.3 flush throws sometimes an error even though the writing
|
||||||
# operation should be completed.
|
# operation should be completed.
|
||||||
file.flush()
|
file.flush()
|
||||||
@@ -476,6 +473,20 @@ def pickle_dump(data, file):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the highest protocol version compatible for a given list of Python
|
||||||
|
# versions.
|
||||||
|
def highest_pickle_protocol(python_versions):
|
||||||
|
protocol = 4
|
||||||
|
for version in python_versions:
|
||||||
|
if version[0] == 2:
|
||||||
|
# The minimum protocol version for the versions of Python that we
|
||||||
|
# support (2.7 and 3.3+) is 2.
|
||||||
|
return 2
|
||||||
|
if version[1] < 4:
|
||||||
|
protocol = 3
|
||||||
|
return protocol
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from inspect import Parameter
|
from inspect import Parameter
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ class Environment(_BaseEnvironment):
|
|||||||
return EvaluatorSubprocess(evaluator, self._get_subprocess())
|
return EvaluatorSubprocess(evaluator, self._get_subprocess())
|
||||||
|
|
||||||
def _get_subprocess(self):
|
def _get_subprocess(self):
|
||||||
return get_subprocess(self.executable)
|
return get_subprocess(self.executable, self.version_info)
|
||||||
|
|
||||||
@memoize_method
|
@memoize_method
|
||||||
def get_sys_path(self):
|
def get_sys_path(self):
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import traceback
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from jedi._compatibility import queue, is_py3, force_unicode, \
|
from jedi._compatibility import queue, is_py3, force_unicode, \
|
||||||
pickle_dump, pickle_load, GeneralizedPopen
|
pickle_dump, pickle_load, highest_pickle_protocol, GeneralizedPopen
|
||||||
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, AccessPath, \
|
from jedi.evaluate.compiled.access import DirectObjectAccess, AccessPath, \
|
||||||
@@ -29,11 +29,12 @@ _subprocesses = {}
|
|||||||
_MAIN_PATH = os.path.join(os.path.dirname(__file__), '__main__.py')
|
_MAIN_PATH = os.path.join(os.path.dirname(__file__), '__main__.py')
|
||||||
|
|
||||||
|
|
||||||
def get_subprocess(executable):
|
def get_subprocess(executable, version):
|
||||||
try:
|
try:
|
||||||
return _subprocesses[executable]
|
return _subprocesses[executable]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
sub = _subprocesses[executable] = _CompiledSubprocess(executable)
|
sub = _subprocesses[executable] = _CompiledSubprocess(executable,
|
||||||
|
version)
|
||||||
return sub
|
return sub
|
||||||
|
|
||||||
|
|
||||||
@@ -125,9 +126,11 @@ class EvaluatorSubprocess(_EvaluatorProcess):
|
|||||||
class _CompiledSubprocess(object):
|
class _CompiledSubprocess(object):
|
||||||
_crashed = False
|
_crashed = False
|
||||||
|
|
||||||
def __init__(self, executable):
|
def __init__(self, executable, version):
|
||||||
self._executable = executable
|
self._executable = executable
|
||||||
self._evaluator_deletion_queue = queue.deque()
|
self._evaluator_deletion_queue = queue.deque()
|
||||||
|
self._pickle_protocol = highest_pickle_protocol([sys.version_info,
|
||||||
|
version])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@memoize_method
|
@memoize_method
|
||||||
@@ -136,7 +139,8 @@ class _CompiledSubprocess(object):
|
|||||||
args = (
|
args = (
|
||||||
self._executable,
|
self._executable,
|
||||||
_MAIN_PATH,
|
_MAIN_PATH,
|
||||||
os.path.dirname(os.path.dirname(parso_path))
|
os.path.dirname(os.path.dirname(parso_path)),
|
||||||
|
str(self._pickle_protocol)
|
||||||
)
|
)
|
||||||
return GeneralizedPopen(
|
return GeneralizedPopen(
|
||||||
args,
|
args,
|
||||||
@@ -190,7 +194,7 @@ class _CompiledSubprocess(object):
|
|||||||
|
|
||||||
data = evaluator_id, function, args, kwargs
|
data = evaluator_id, function, args, kwargs
|
||||||
try:
|
try:
|
||||||
pickle_dump(data, self._process.stdin)
|
pickle_dump(data, self._process.stdin, self._pickle_protocol)
|
||||||
except (socket.error, IOError) as e:
|
except (socket.error, IOError) as e:
|
||||||
# Once Python2 will be removed we can just use `BrokenPipeError`.
|
# Once Python2 will be removed we can just use `BrokenPipeError`.
|
||||||
# Also, somehow in windows it returns EINVAL instead of EPIPE if
|
# Also, somehow in windows it returns EINVAL instead of EPIPE if
|
||||||
@@ -236,11 +240,12 @@ class _CompiledSubprocess(object):
|
|||||||
|
|
||||||
|
|
||||||
class Listener(object):
|
class Listener(object):
|
||||||
def __init__(self):
|
def __init__(self, pickle_protocol):
|
||||||
self._evaluators = {}
|
self._evaluators = {}
|
||||||
# TODO refactor so we don't need to process anymore just handle
|
# TODO refactor so we don't need to process anymore just handle
|
||||||
# controlling.
|
# controlling.
|
||||||
self._process = _EvaluatorProcess(Listener)
|
self._process = _EvaluatorProcess(Listener)
|
||||||
|
self._pickle_protocol = pickle_protocol
|
||||||
|
|
||||||
def _get_evaluator(self, function, evaluator_id):
|
def _get_evaluator(self, function, evaluator_id):
|
||||||
from jedi.evaluate import Evaluator
|
from jedi.evaluate import Evaluator
|
||||||
@@ -307,7 +312,7 @@ class Listener(object):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
result = True, traceback.format_exc(), e
|
result = True, traceback.format_exc(), e
|
||||||
|
|
||||||
pickle_dump(result, file=stdout)
|
pickle_dump(result, stdout, self._pickle_protocol)
|
||||||
|
|
||||||
|
|
||||||
class AccessHandle(object):
|
class AccessHandle(object):
|
||||||
|
|||||||
@@ -45,5 +45,7 @@ else:
|
|||||||
load('jedi')
|
load('jedi')
|
||||||
from jedi.evaluate.compiled import subprocess # NOQA
|
from jedi.evaluate.compiled import subprocess # NOQA
|
||||||
|
|
||||||
|
# Retrieve the pickle protocol.
|
||||||
|
pickle_protocol = int(sys.argv[2])
|
||||||
# And finally start the client.
|
# And finally start the client.
|
||||||
subprocess.Listener().listen()
|
subprocess.Listener(pickle_protocol).listen()
|
||||||
|
|||||||
26
test/test_compatibility.py
Normal file
26
test/test_compatibility.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
from collections import namedtuple
|
||||||
|
from jedi._compatibility import highest_pickle_protocol
|
||||||
|
|
||||||
|
|
||||||
|
def test_highest_pickle_protocol():
|
||||||
|
v = namedtuple('version', 'major, minor')
|
||||||
|
assert highest_pickle_protocol([v(2, 7), v(2, 7)]) == 2
|
||||||
|
assert highest_pickle_protocol([v(2, 7), v(3, 3)]) == 2
|
||||||
|
assert highest_pickle_protocol([v(2, 7), v(3, 4)]) == 2
|
||||||
|
assert highest_pickle_protocol([v(2, 7), v(3, 5)]) == 2
|
||||||
|
assert highest_pickle_protocol([v(2, 7), v(3, 6)]) == 2
|
||||||
|
assert highest_pickle_protocol([v(3, 3), v(2, 7)]) == 2
|
||||||
|
assert highest_pickle_protocol([v(3, 3), v(3, 3)]) == 3
|
||||||
|
assert highest_pickle_protocol([v(3, 3), v(3, 4)]) == 3
|
||||||
|
assert highest_pickle_protocol([v(3, 3), v(3, 5)]) == 3
|
||||||
|
assert highest_pickle_protocol([v(3, 3), v(3, 6)]) == 3
|
||||||
|
assert highest_pickle_protocol([v(3, 4), v(2, 7)]) == 2
|
||||||
|
assert highest_pickle_protocol([v(3, 4), v(3, 3)]) == 3
|
||||||
|
assert highest_pickle_protocol([v(3, 4), v(3, 4)]) == 4
|
||||||
|
assert highest_pickle_protocol([v(3, 4), v(3, 5)]) == 4
|
||||||
|
assert highest_pickle_protocol([v(3, 4), v(3, 6)]) == 4
|
||||||
|
assert highest_pickle_protocol([v(3, 6), v(2, 7)]) == 2
|
||||||
|
assert highest_pickle_protocol([v(3, 6), v(3, 3)]) == 3
|
||||||
|
assert highest_pickle_protocol([v(3, 6), v(3, 4)]) == 4
|
||||||
|
assert highest_pickle_protocol([v(3, 6), v(3, 5)]) == 4
|
||||||
|
assert highest_pickle_protocol([v(3, 6), v(3, 6)]) == 4
|
||||||
Reference in New Issue
Block a user