Accepting request 1229250 from devel:languages:python
OBS-URL: https://build.opensuse.org/request/show/1229250 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python-jedi?expand=0&rev=42
This commit is contained in:
commit
633973caa7
@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd
|
|
||||||
size 1227821
|
|
3
jedi-0.19.2.tar.gz
Normal file
3
jedi-0.19.2.tar.gz
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0
|
||||||
|
size 1231287
|
@ -1,3 +1,10 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Mon Dec 9 08:41:21 UTC 2024 - John Paul Adrian Glaubitz <adrian.glaubitz@suse.com>
|
||||||
|
|
||||||
|
- Update to 0.19.2
|
||||||
|
* Python 3.13 support
|
||||||
|
- Drop python3.13-support.patch, merged upstream
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Fri Sep 20 06:56:42 UTC 2024 - John Paul Adrian Glaubitz <adrian.glaubitz@suse.com>
|
Fri Sep 20 06:56:42 UTC 2024 - John Paul Adrian Glaubitz <adrian.glaubitz@suse.com>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# spec file for package python-jedi
|
# spec file for package python-jedi
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 SUSE LLC
|
# Copyright (c) 2024 SUSE LLC
|
||||||
#
|
#
|
||||||
# All modifications and additions to the file contributed by third parties
|
# All modifications and additions to the file contributed by third parties
|
||||||
# remain the property of their copyright owners, unless otherwise agreed
|
# remain the property of their copyright owners, unless otherwise agreed
|
||||||
@ -18,17 +18,13 @@
|
|||||||
|
|
||||||
%{?sle15_python_module_pythons}
|
%{?sle15_python_module_pythons}
|
||||||
Name: python-jedi
|
Name: python-jedi
|
||||||
Version: 0.19.1
|
Version: 0.19.2
|
||||||
Release: 0
|
Release: 0
|
||||||
Summary: An autocompletion tool for Python
|
Summary: An autocompletion tool for Python
|
||||||
License: MIT AND Python-2.0
|
License: MIT AND Python-2.0
|
||||||
URL: https://github.com/davidhalter/jedi
|
URL: https://github.com/davidhalter/jedi
|
||||||
Source0: https://files.pythonhosted.org/packages/source/j/jedi/jedi-%{version}.tar.gz
|
Source0: https://files.pythonhosted.org/packages/source/j/jedi/jedi-%{version}.tar.gz
|
||||||
Source1: %{name}-rpmlintrc
|
Source1: %{name}-rpmlintrc
|
||||||
# PATCH-FIX-UPSTREAM - Add support for Python 3.13
|
|
||||||
# https://github.com/davidhalter/jedi/pull/2008
|
|
||||||
# https://github.com/davidhalter/jedi/pull/2003
|
|
||||||
Patch0: python3.13-support.patch
|
|
||||||
# The author of jedi and parso takes pinning very seriously, adhere to it!
|
# The author of jedi and parso takes pinning very seriously, adhere to it!
|
||||||
BuildRequires: %{python_module parso >= 0.8.4 with %python-parso < 0.9}
|
BuildRequires: %{python_module parso >= 0.8.4 with %python-parso < 0.9}
|
||||||
BuildRequires: %{python_module pip}
|
BuildRequires: %{python_module pip}
|
||||||
@ -39,7 +35,7 @@ BuildRequires: %{python_module wheel}
|
|||||||
BuildRequires: fdupes
|
BuildRequires: fdupes
|
||||||
BuildRequires: python-rpm-macros
|
BuildRequires: python-rpm-macros
|
||||||
# See pinning note above
|
# See pinning note above
|
||||||
Requires: (python-parso >= 0.8.3 with python-parso < 0.9)
|
Requires: (python-parso >= 0.8.4 with python-parso < 0.9)
|
||||||
BuildArch: noarch
|
BuildArch: noarch
|
||||||
%python_subpackages
|
%python_subpackages
|
||||||
|
|
||||||
|
@ -1,523 +0,0 @@
|
|||||||
From 43902d83018c950c9ac1a97c58abc32838228867 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Peter Law <PeterJCLaw@gmail.com>
|
|
||||||
Date: Thu, 4 Jul 2024 22:39:29 +0100
|
|
||||||
Subject: [PATCH 1/2] Merge branch 'ensure-unique-subprocess-reference-ids'
|
|
||||||
|
|
||||||
(cherry picked from commit e839683e91b78355f0363bcc6f74f762995344f8)
|
|
||||||
---
|
|
||||||
jedi/api/environment.py | 15 +-
|
|
||||||
.../inference/compiled/subprocess/__init__.py | 157 ++++++++++++++++--
|
|
||||||
2 files changed, 152 insertions(+), 20 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/jedi/api/environment.py b/jedi/api/environment.py
|
|
||||||
index 771a9a83..cfe8cfe3 100644
|
|
||||||
--- a/jedi/api/environment.py
|
|
||||||
+++ b/jedi/api/environment.py
|
|
||||||
@@ -8,6 +8,7 @@ import hashlib
|
|
||||||
import filecmp
|
|
||||||
from collections import namedtuple
|
|
||||||
from shutil import which
|
|
||||||
+from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from jedi.cache import memoize_method, time_cache
|
|
||||||
from jedi.inference.compiled.subprocess import CompiledSubprocess, \
|
|
||||||
@@ -15,6 +16,10 @@ from jedi.inference.compiled.subprocess import CompiledSubprocess, \
|
|
||||||
|
|
||||||
import parso
|
|
||||||
|
|
||||||
+if TYPE_CHECKING:
|
|
||||||
+ from jedi.inference import InferenceState
|
|
||||||
+
|
|
||||||
+
|
|
||||||
_VersionInfo = namedtuple('VersionInfo', 'major minor micro') # type: ignore[name-match]
|
|
||||||
|
|
||||||
_SUPPORTED_PYTHONS = ['3.12', '3.11', '3.10', '3.9', '3.8', '3.7', '3.6']
|
|
||||||
@@ -102,7 +107,10 @@ class Environment(_BaseEnvironment):
|
|
||||||
version = '.'.join(str(i) for i in self.version_info)
|
|
||||||
return '<%s: %s in %s>' % (self.__class__.__name__, version, self.path)
|
|
||||||
|
|
||||||
- def get_inference_state_subprocess(self, inference_state):
|
|
||||||
+ def get_inference_state_subprocess(
|
|
||||||
+ self,
|
|
||||||
+ inference_state: 'InferenceState',
|
|
||||||
+ ) -> InferenceStateSubprocess:
|
|
||||||
return InferenceStateSubprocess(inference_state, self._get_subprocess())
|
|
||||||
|
|
||||||
@memoize_method
|
|
||||||
@@ -134,7 +142,10 @@ class SameEnvironment(_SameEnvironmentMixin, Environment):
|
|
||||||
|
|
||||||
|
|
||||||
class InterpreterEnvironment(_SameEnvironmentMixin, _BaseEnvironment):
|
|
||||||
- def get_inference_state_subprocess(self, inference_state):
|
|
||||||
+ def get_inference_state_subprocess(
|
|
||||||
+ self,
|
|
||||||
+ inference_state: 'InferenceState',
|
|
||||||
+ ) -> InferenceStateSameProcess:
|
|
||||||
return InferenceStateSameProcess(inference_state)
|
|
||||||
|
|
||||||
def get_sys_path(self):
|
|
||||||
diff --git a/jedi/inference/compiled/subprocess/__init__.py b/jedi/inference/compiled/subprocess/__init__.py
|
|
||||||
index cd5fe74c..3a6039f7 100644
|
|
||||||
--- a/jedi/inference/compiled/subprocess/__init__.py
|
|
||||||
+++ b/jedi/inference/compiled/subprocess/__init__.py
|
|
||||||
@@ -5,6 +5,23 @@ goals:
|
|
||||||
1. Making it safer - Segfaults and RuntimeErrors as well as stdout/stderr can
|
|
||||||
be ignored and dealt with.
|
|
||||||
2. Make it possible to handle different Python versions as well as virtualenvs.
|
|
||||||
+
|
|
||||||
+The architecture here is briefly:
|
|
||||||
+ - For each Jedi `Environment` there is a corresponding subprocess which
|
|
||||||
+ operates within the target environment. If the subprocess dies it is replaced
|
|
||||||
+ at this level.
|
|
||||||
+ - `CompiledSubprocess` manages exactly one subprocess and handles communication
|
|
||||||
+ from the parent side.
|
|
||||||
+ - `Listener` runs within the subprocess, processing each request and yielding
|
|
||||||
+ results.
|
|
||||||
+ - `InterpreterEnvironment` provides an API which matches that of `Environment`,
|
|
||||||
+ but runs functionality inline rather than within a subprocess. It is thus
|
|
||||||
+ used both directly in places where a subprocess is unnecessary and/or
|
|
||||||
+ undesirable and also within subprocesses themselves.
|
|
||||||
+ - `InferenceStateSubprocess` (or `InferenceStateSameProcess`) provide high
|
|
||||||
+ level access to functionality within the subprocess from within the parent.
|
|
||||||
+ Each `InterpreterState` has an instance of one of these, provided by its
|
|
||||||
+ environment.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import collections
|
|
||||||
@@ -16,6 +33,7 @@ import traceback
|
|
||||||
import weakref
|
|
||||||
from functools import partial
|
|
||||||
from threading import Thread
|
|
||||||
+from typing import Dict, TYPE_CHECKING
|
|
||||||
|
|
||||||
from jedi._compatibility import pickle_dump, pickle_load
|
|
||||||
from jedi import debug
|
|
||||||
@@ -25,6 +43,9 @@ from jedi.inference.compiled.access import DirectObjectAccess, AccessPath, \
|
|
||||||
SignatureParam
|
|
||||||
from jedi.api.exceptions import InternalError
|
|
||||||
|
|
||||||
+if TYPE_CHECKING:
|
|
||||||
+ from jedi.inference import InferenceState
|
|
||||||
+
|
|
||||||
|
|
||||||
_MAIN_PATH = os.path.join(os.path.dirname(__file__), '__main__.py')
|
|
||||||
PICKLE_PROTOCOL = 4
|
|
||||||
@@ -83,10 +104,9 @@ def _cleanup_process(process, thread):
|
|
||||||
|
|
||||||
|
|
||||||
class _InferenceStateProcess:
|
|
||||||
- def __init__(self, inference_state):
|
|
||||||
+ def __init__(self, inference_state: 'InferenceState') -> None:
|
|
||||||
self._inference_state_weakref = weakref.ref(inference_state)
|
|
||||||
- self._inference_state_id = id(inference_state)
|
|
||||||
- self._handles = {}
|
|
||||||
+ self._handles: Dict[int, AccessHandle] = {}
|
|
||||||
|
|
||||||
def get_or_create_access_handle(self, obj):
|
|
||||||
id_ = id(obj)
|
|
||||||
@@ -116,11 +136,49 @@ class InferenceStateSameProcess(_InferenceStateProcess):
|
|
||||||
|
|
||||||
|
|
||||||
class InferenceStateSubprocess(_InferenceStateProcess):
|
|
||||||
- def __init__(self, inference_state, compiled_subprocess):
|
|
||||||
+ """
|
|
||||||
+ API to functionality which will run in a subprocess.
|
|
||||||
+
|
|
||||||
+ This mediates the interaction between an `InferenceState` and the actual
|
|
||||||
+ execution of functionality running within a `CompiledSubprocess`. Available
|
|
||||||
+ functions are defined in `.functions`, though should be accessed via
|
|
||||||
+ attributes on this class of the same name.
|
|
||||||
+
|
|
||||||
+ This class is responsible for indicating that the `InferenceState` within
|
|
||||||
+ the subprocess can be removed once the corresponding instance in the parent
|
|
||||||
+ goes away.
|
|
||||||
+ """
|
|
||||||
+
|
|
||||||
+ def __init__(
|
|
||||||
+ self,
|
|
||||||
+ inference_state: 'InferenceState',
|
|
||||||
+ compiled_subprocess: 'CompiledSubprocess',
|
|
||||||
+ ) -> None:
|
|
||||||
super().__init__(inference_state)
|
|
||||||
self._used = False
|
|
||||||
self._compiled_subprocess = compiled_subprocess
|
|
||||||
|
|
||||||
+ # Opaque id we'll pass to the subprocess to identify the context (an
|
|
||||||
+ # `InferenceState`) which should be used for the request. This allows us
|
|
||||||
+ # to make subsequent requests which operate on results from previous
|
|
||||||
+ # ones, while keeping a single subprocess which can work with several
|
|
||||||
+ # contexts in the parent process. Once it is no longer needed(i.e: when
|
|
||||||
+ # this class goes away), we also use this id to indicate that the
|
|
||||||
+ # subprocess can discard the context.
|
|
||||||
+ #
|
|
||||||
+ # Note: this id is deliberately coupled to this class (and not to
|
|
||||||
+ # `InferenceState`) as this class manages access handle mappings which
|
|
||||||
+ # must correspond to those in the subprocess. This approach also avoids
|
|
||||||
+ # race conditions from successive `InferenceState`s with the same object
|
|
||||||
+ # id (as observed while adding support for Python 3.13).
|
|
||||||
+ #
|
|
||||||
+ # This value does not need to be the `id()` of this instance, we merely
|
|
||||||
+ # need to ensure that it enables the (visible) lifetime of the context
|
|
||||||
+ # within the subprocess to match that of this class. We therefore also
|
|
||||||
+ # depend on the semantics of `CompiledSubprocess.delete_inference_state`
|
|
||||||
+ # for correctness.
|
|
||||||
+ self._inference_state_id = id(self)
|
|
||||||
+
|
|
||||||
def __getattr__(self, name):
|
|
||||||
func = _get_function(name)
|
|
||||||
|
|
||||||
@@ -128,7 +186,7 @@ class InferenceStateSubprocess(_InferenceStateProcess):
|
|
||||||
self._used = True
|
|
||||||
|
|
||||||
result = self._compiled_subprocess.run(
|
|
||||||
- self._inference_state_weakref(),
|
|
||||||
+ self._inference_state_id,
|
|
||||||
func,
|
|
||||||
args=args,
|
|
||||||
kwargs=kwargs,
|
|
||||||
@@ -164,6 +222,17 @@ class InferenceStateSubprocess(_InferenceStateProcess):
|
|
||||||
|
|
||||||
|
|
||||||
class CompiledSubprocess:
|
|
||||||
+ """
|
|
||||||
+ A subprocess which runs inference within a target environment.
|
|
||||||
+
|
|
||||||
+ This class manages the interface to a single instance of such a process as
|
|
||||||
+ well as the lifecycle of the process itself. See `.__main__` and `Listener`
|
|
||||||
+ for the implementation of the subprocess and details of the protocol.
|
|
||||||
+
|
|
||||||
+ A single live instance of this is maintained by `jedi.api.environment.Environment`,
|
|
||||||
+ so that typically a single subprocess is used at a time.
|
|
||||||
+ """
|
|
||||||
+
|
|
||||||
is_crashed = False
|
|
||||||
|
|
||||||
def __init__(self, executable, env_vars=None):
|
|
||||||
@@ -213,18 +282,18 @@ class CompiledSubprocess:
|
|
||||||
t)
|
|
||||||
return process
|
|
||||||
|
|
||||||
- def run(self, inference_state, function, args=(), kwargs={}):
|
|
||||||
+ def run(self, inference_state_id, function, args=(), kwargs={}):
|
|
||||||
# Delete old inference_states.
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
- inference_state_id = self._inference_state_deletion_queue.pop()
|
|
||||||
+ delete_id = self._inference_state_deletion_queue.pop()
|
|
||||||
except IndexError:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
- self._send(inference_state_id, None)
|
|
||||||
+ self._send(delete_id, None)
|
|
||||||
|
|
||||||
assert callable(function)
|
|
||||||
- return self._send(id(inference_state), function, args, kwargs)
|
|
||||||
+ return self._send(inference_state_id, function, args, kwargs)
|
|
||||||
|
|
||||||
def get_sys_path(self):
|
|
||||||
return self._send(None, functions.get_sys_path, (), {})
|
|
||||||
@@ -272,21 +341,65 @@ class CompiledSubprocess:
|
|
||||||
|
|
||||||
def delete_inference_state(self, inference_state_id):
|
|
||||||
"""
|
|
||||||
- Currently we are not deleting inference_state instantly. They only get
|
|
||||||
- deleted once the subprocess is used again. It would probably a better
|
|
||||||
- solution to move all of this into a thread. However, the memory usage
|
|
||||||
- of a single inference_state shouldn't be that high.
|
|
||||||
+ Indicate that an inference state (in the subprocess) is no longer
|
|
||||||
+ needed.
|
|
||||||
+
|
|
||||||
+ The state corresponding to the given id will become inaccessible and the
|
|
||||||
+ id may safely be re-used to refer to a different context.
|
|
||||||
+
|
|
||||||
+ Note: it is not guaranteed that the corresponding state will actually be
|
|
||||||
+ deleted immediately.
|
|
||||||
"""
|
|
||||||
- # With an argument - the inference_state gets deleted.
|
|
||||||
+ # Warning: if changing the semantics of context deletion see the comment
|
|
||||||
+ # in `InferenceStateSubprocess.__init__` regarding potential race
|
|
||||||
+ # conditions.
|
|
||||||
+
|
|
||||||
+ # Currently we are not deleting the related state instantly. They only
|
|
||||||
+ # get deleted once the subprocess is used again. It would probably a
|
|
||||||
+ # better solution to move all of this into a thread. However, the memory
|
|
||||||
+ # usage of a single inference_state shouldn't be that high.
|
|
||||||
self._inference_state_deletion_queue.append(inference_state_id)
|
|
||||||
|
|
||||||
|
|
||||||
class Listener:
|
|
||||||
+ """
|
|
||||||
+ Main loop for the subprocess which actually does the inference.
|
|
||||||
+
|
|
||||||
+ This class runs within the target environment. It listens to instructions
|
|
||||||
+ from the parent process, runs inference and returns the results.
|
|
||||||
+
|
|
||||||
+ The subprocess has a long lifetime and is expected to process several
|
|
||||||
+ requests, including for different `InferenceState` instances in the parent.
|
|
||||||
+ See `CompiledSubprocess` for the parent half of the system.
|
|
||||||
+
|
|
||||||
+ Communication is via pickled data sent serially over stdin and stdout.
|
|
||||||
+ Stderr is read only if the child process crashes.
|
|
||||||
+
|
|
||||||
+ The request protocol is a 4-tuple of:
|
|
||||||
+ * inference_state_id | None: an opaque identifier of the parent's
|
|
||||||
+ `InferenceState`. An `InferenceState` operating over an
|
|
||||||
+ `InterpreterEnvironment` is created within this process for each of
|
|
||||||
+ these, ensuring that each parent context has a corresponding context
|
|
||||||
+ here. This allows context to be persisted between requests. Unless
|
|
||||||
+ `None`, the local `InferenceState` will be passed to the given function
|
|
||||||
+ as the first positional argument.
|
|
||||||
+ * function | None: the function to run. This is expected to be a member of
|
|
||||||
+ `.functions`. `None` indicates that the corresponding inference state is
|
|
||||||
+ no longer needed and should be dropped.
|
|
||||||
+ * args: positional arguments to the `function`. If any of these are
|
|
||||||
+ `AccessHandle` instances they will be adapted to the local
|
|
||||||
+ `InferenceState` before being passed.
|
|
||||||
+ * kwargs: keyword arguments to the `function`. If any of these are
|
|
||||||
+ `AccessHandle` instances they will be adapted to the local
|
|
||||||
+ `InferenceState` before being passed.
|
|
||||||
+
|
|
||||||
+ The result protocol is a 3-tuple of either:
|
|
||||||
+ * (False, None, function result): if the function returns without error, or
|
|
||||||
+ * (True, traceback, exception): if the function raises an exception
|
|
||||||
+ """
|
|
||||||
+
|
|
||||||
def __init__(self):
|
|
||||||
self._inference_states = {}
|
|
||||||
- # TODO refactor so we don't need to process anymore just handle
|
|
||||||
- # controlling.
|
|
||||||
- self._process = _InferenceStateProcess(Listener)
|
|
||||||
|
|
||||||
def _get_inference_state(self, function, inference_state_id):
|
|
||||||
from jedi.inference import InferenceState
|
|
||||||
@@ -308,6 +421,9 @@ class Listener:
|
|
||||||
if inference_state_id is None:
|
|
||||||
return function(*args, **kwargs)
|
|
||||||
elif function is None:
|
|
||||||
+ # Warning: if changing the semantics of context deletion see the comment
|
|
||||||
+ # in `InferenceStateSubprocess.__init__` regarding potential race
|
|
||||||
+ # conditions.
|
|
||||||
del self._inference_states[inference_state_id]
|
|
||||||
else:
|
|
||||||
inference_state = self._get_inference_state(function, inference_state_id)
|
|
||||||
@@ -348,7 +464,12 @@ class Listener:
|
|
||||||
|
|
||||||
|
|
||||||
class AccessHandle:
|
|
||||||
- def __init__(self, subprocess, access, id_):
|
|
||||||
+ def __init__(
|
|
||||||
+ self,
|
|
||||||
+ subprocess: _InferenceStateProcess,
|
|
||||||
+ access: DirectObjectAccess,
|
|
||||||
+ id_: int,
|
|
||||||
+ ) -> None:
|
|
||||||
self.access = access
|
|
||||||
self._subprocess = subprocess
|
|
||||||
self.id = id_
|
|
||||||
--
|
|
||||||
2.45.2
|
|
||||||
|
|
||||||
From 2a638c784ff63ab869626d23ce95856dece31a9b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Peter Law <PeterJCLaw@gmail.com>
|
|
||||||
Date: Sat, 6 Jul 2024 11:39:06 +0100
|
|
||||||
Subject: [PATCH 2/2] Merge branch 'python-3.13'
|
|
||||||
|
|
||||||
(cherry picked from commit 82d1902f382ddac5b0e6647646b72f28a3181ec3)
|
|
||||||
---
|
|
||||||
CHANGELOG.rst | 2 ++
|
|
||||||
jedi/_compatibility.py | 15 ++++++++++++++-
|
|
||||||
jedi/api/environment.py | 2 +-
|
|
||||||
jedi/inference/__init__.py | 2 +-
|
|
||||||
setup.py | 5 +++--
|
|
||||||
test/test_api/test_interpreter.py | 13 +++++++++----
|
|
||||||
test/test_inference/test_signature.py | 5 +++--
|
|
||||||
test/test_utils.py | 14 ++++++++++----
|
|
||||||
8 files changed, 43 insertions(+), 15 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
|
|
||||||
index fca94429..cf6810fa 100644
|
|
||||||
--- a/CHANGELOG.rst
|
|
||||||
+++ b/CHANGELOG.rst
|
|
||||||
@@ -6,6 +6,8 @@ Changelog
|
|
||||||
Unreleased
|
|
||||||
++++++++++
|
|
||||||
|
|
||||||
+- Python 3.13 support
|
|
||||||
+
|
|
||||||
0.19.1 (2023-10-02)
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
diff --git a/jedi/_compatibility.py b/jedi/_compatibility.py
|
|
||||||
index 13a74b7b..48563d00 100644
|
|
||||||
--- a/jedi/_compatibility.py
|
|
||||||
+++ b/jedi/_compatibility.py
|
|
||||||
@@ -5,11 +5,24 @@ different Python versions.
|
|
||||||
import errno
|
|
||||||
import sys
|
|
||||||
import pickle
|
|
||||||
+from typing import Any
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+class Unpickler(pickle.Unpickler):
|
|
||||||
+ def find_class(self, module: str, name: str) -> Any:
|
|
||||||
+ # Python 3.13 moved pathlib implementation out of __init__.py as part of
|
|
||||||
+ # generalising its implementation. Ensure that we support loading
|
|
||||||
+ # pickles from 3.13 on older version of Python. Since 3.13 maintained a
|
|
||||||
+ # compatible API, pickles from older Python work natively on the newer
|
|
||||||
+ # version.
|
|
||||||
+ if module == 'pathlib._local':
|
|
||||||
+ module = 'pathlib'
|
|
||||||
+ return super().find_class(module, name)
|
|
||||||
|
|
||||||
|
|
||||||
def pickle_load(file):
|
|
||||||
try:
|
|
||||||
- return pickle.load(file)
|
|
||||||
+ return Unpickler(file).load()
|
|
||||||
# Python on Windows don't throw EOF errors for pipes. So reraise them with
|
|
||||||
# the correct type, which is caught upwards.
|
|
||||||
except OSError:
|
|
||||||
diff --git a/jedi/api/environment.py b/jedi/api/environment.py
|
|
||||||
index cfe8cfe3..a2134110 100644
|
|
||||||
--- a/jedi/api/environment.py
|
|
||||||
+++ b/jedi/api/environment.py
|
|
||||||
@@ -22,7 +22,7 @@ if TYPE_CHECKING:
|
|
||||||
|
|
||||||
_VersionInfo = namedtuple('VersionInfo', 'major minor micro') # type: ignore[name-match]
|
|
||||||
|
|
||||||
-_SUPPORTED_PYTHONS = ['3.12', '3.11', '3.10', '3.9', '3.8', '3.7', '3.6']
|
|
||||||
+_SUPPORTED_PYTHONS = ['3.13', '3.12', '3.11', '3.10', '3.9', '3.8', '3.7', '3.6']
|
|
||||||
_SAFE_PATHS = ['/usr/bin', '/usr/local/bin']
|
|
||||||
_CONDA_VAR = 'CONDA_PREFIX'
|
|
||||||
_CURRENT_VERSION = '%s.%s' % (sys.version_info.major, sys.version_info.minor)
|
|
||||||
diff --git a/jedi/inference/__init__.py b/jedi/inference/__init__.py
|
|
||||||
index aadfeba9..bd31cbd3 100644
|
|
||||||
--- a/jedi/inference/__init__.py
|
|
||||||
+++ b/jedi/inference/__init__.py
|
|
||||||
@@ -90,7 +90,7 @@ class InferenceState:
|
|
||||||
self.compiled_subprocess = environment.get_inference_state_subprocess(self)
|
|
||||||
self.grammar = environment.get_grammar()
|
|
||||||
|
|
||||||
- self.latest_grammar = parso.load_grammar(version='3.12')
|
|
||||||
+ self.latest_grammar = parso.load_grammar(version='3.13')
|
|
||||||
self.memoize_cache = {} # for memoize decorators
|
|
||||||
self.module_cache = imports.ModuleCache() # does the job of `sys.modules`.
|
|
||||||
self.stub_module_cache = {} # Dict[Tuple[str, ...], Optional[ModuleValue]]
|
|
||||||
diff --git a/setup.py b/setup.py
|
|
||||||
index 68210ef2..ed1e67a4 100755
|
|
||||||
--- a/setup.py
|
|
||||||
+++ b/setup.py
|
|
||||||
@@ -35,8 +35,8 @@ setup(name='jedi',
|
|
||||||
long_description=readme,
|
|
||||||
packages=find_packages(exclude=['test', 'test.*']),
|
|
||||||
python_requires='>=3.6',
|
|
||||||
- # Python 3.11 & 3.12 grammars are added to parso in 0.8.3
|
|
||||||
- install_requires=['parso>=0.8.3,<0.9.0'],
|
|
||||||
+ # Python 3.13 grammars are added to parso in 0.8.4
|
|
||||||
+ install_requires=['parso>=0.8.4,<0.9.0'],
|
|
||||||
extras_require={
|
|
||||||
'testing': [
|
|
||||||
'pytest<7.0.0',
|
|
||||||
@@ -101,6 +101,7 @@ setup(name='jedi',
|
|
||||||
'Programming Language :: Python :: 3.10',
|
|
||||||
'Programming Language :: Python :: 3.11',
|
|
||||||
'Programming Language :: Python :: 3.12',
|
|
||||||
+ 'Programming Language :: Python :: 3.13',
|
|
||||||
'Topic :: Software Development :: Libraries :: Python Modules',
|
|
||||||
'Topic :: Text Editors :: Integrated Development Environments (IDE)',
|
|
||||||
'Topic :: Utilities',
|
|
||||||
diff --git a/test/test_api/test_interpreter.py b/test/test_api/test_interpreter.py
|
|
||||||
index 74f066b8..efff7c5b 100644
|
|
||||||
--- a/test/test_api/test_interpreter.py
|
|
||||||
+++ b/test/test_api/test_interpreter.py
|
|
||||||
@@ -310,8 +310,9 @@ def test_completion_param_annotations():
|
|
||||||
# Need to define this function not directly in Python. Otherwise Jedi is too
|
|
||||||
# clever and uses the Python code instead of the signature object.
|
|
||||||
code = 'def foo(a: 1, b: str, c: int = 1.0) -> bytes: pass'
|
|
||||||
- exec(code, locals())
|
|
||||||
- script = jedi.Interpreter('foo', [locals()])
|
|
||||||
+ exec_locals = {}
|
|
||||||
+ exec(code, exec_locals)
|
|
||||||
+ script = jedi.Interpreter('foo', [exec_locals])
|
|
||||||
c, = script.complete()
|
|
||||||
sig, = c.get_signatures()
|
|
||||||
a, b, c = sig.params
|
|
||||||
@@ -323,7 +324,7 @@ def test_completion_param_annotations():
|
|
||||||
assert b.description == 'param b: str'
|
|
||||||
assert c.description == 'param c: int=1.0'
|
|
||||||
|
|
||||||
- d, = jedi.Interpreter('foo()', [locals()]).infer()
|
|
||||||
+ d, = jedi.Interpreter('foo()', [exec_locals]).infer()
|
|
||||||
assert d.name == 'bytes'
|
|
||||||
|
|
||||||
|
|
||||||
@@ -525,10 +526,14 @@ def test_partial_signatures(code, expected, index):
|
|
||||||
c = functools.partial(func, 1, c=2)
|
|
||||||
|
|
||||||
sig, = jedi.Interpreter(code, [locals()]).get_signatures()
|
|
||||||
- assert sig.name == 'partial'
|
|
||||||
assert [p.name for p in sig.params] == expected
|
|
||||||
assert index == sig.index
|
|
||||||
|
|
||||||
+ if sys.version_info < (3, 13):
|
|
||||||
+ # Python 3.13.0b3 makes functools.partial be a descriptor, which breaks
|
|
||||||
+ # Jedi's `py__name__` detection; see https://github.com/davidhalter/jedi/issues/2012
|
|
||||||
+ assert sig.name == 'partial'
|
|
||||||
+
|
|
||||||
|
|
||||||
def test_type_var():
|
|
||||||
"""This was an issue before, see Github #1369"""
|
|
||||||
diff --git a/test/test_inference/test_signature.py b/test/test_inference/test_signature.py
|
|
||||||
index f8f71581..4a1fcb62 100644
|
|
||||||
--- a/test/test_inference/test_signature.py
|
|
||||||
+++ b/test/test_inference/test_signature.py
|
|
||||||
@@ -1,5 +1,5 @@
|
|
||||||
from textwrap import dedent
|
|
||||||
-from operator import ge, lt
|
|
||||||
+from operator import eq, ge, lt
|
|
||||||
import re
|
|
||||||
import os
|
|
||||||
|
|
||||||
@@ -14,7 +14,8 @@ from ..helpers import get_example_dir
|
|
||||||
('import math; math.cos', 'cos(x, /)', ['x'], ge, (3, 6)),
|
|
||||||
|
|
||||||
('next', 'next(iterator, default=None, /)', ['iterator', 'default'], lt, (3, 12)),
|
|
||||||
- ('next', 'next()', [], ge, (3, 12)),
|
|
||||||
+ ('next', 'next()', [], eq, (3, 12)),
|
|
||||||
+ ('next', 'next(iterator, default=None, /)', ['iterator', 'default'], ge, (3, 13)),
|
|
||||||
|
|
||||||
('str', "str(object='', /) -> str", ['object'], ge, (3, 6)),
|
|
||||||
|
|
||||||
diff --git a/test/test_utils.py b/test/test_utils.py
|
|
||||||
index f17fc246..13786d38 100644
|
|
||||||
--- a/test/test_utils.py
|
|
||||||
+++ b/test/test_utils.py
|
|
||||||
@@ -73,15 +73,21 @@ class TestSetupReadline(unittest.TestCase):
|
|
||||||
import os
|
|
||||||
s = 'from os import '
|
|
||||||
goal = {s + el for el in dir(os)}
|
|
||||||
+
|
|
||||||
# There are minor differences, e.g. the dir doesn't include deleted
|
|
||||||
# items as well as items that are not only available on linux.
|
|
||||||
difference = set(self.complete(s)).symmetric_difference(goal)
|
|
||||||
+ ACCEPTED_DIFFERENCE_PREFIXES = [
|
|
||||||
+ '_', 'O_', 'EX_', 'EFD_', 'MFD_', 'TFD_',
|
|
||||||
+ 'SF_', 'ST_', 'CLD_', 'POSIX_SPAWN_', 'P_',
|
|
||||||
+ 'RWF_', 'CLONE_', 'SCHED_', 'SPLICE_',
|
|
||||||
+ ]
|
|
||||||
difference = {
|
|
||||||
x for x in difference
|
|
||||||
- if all(not x.startswith('from os import ' + s)
|
|
||||||
- for s in ['_', 'O_', 'EX_', 'MFD_', 'SF_', 'ST_',
|
|
||||||
- 'CLD_', 'POSIX_SPAWN_', 'P_', 'RWF_',
|
|
||||||
- 'CLONE_', 'SCHED_'])
|
|
||||||
+ if not any(
|
|
||||||
+ x.startswith('from os import ' + prefix)
|
|
||||||
+ for prefix in ACCEPTED_DIFFERENCE_PREFIXES
|
|
||||||
+ )
|
|
||||||
}
|
|
||||||
# There are quite a few differences, because both Windows and Linux
|
|
||||||
# (posix and nt) libraries are included.
|
|
||||||
--
|
|
||||||
2.45.2
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user