Merge remote-tracking branch 'origin' into support-dataclass-transform

* origin:
  Fix pip install -e in docs
  Upgrade Mypy
  Fix a few flake8 issues
  Upgrade flake8
  Upgrade other test runners
  Remove 3.6/3.7 references and change tests slightly
  Upgrade OS's that it is tested on
  Try to add something to the README
This commit is contained in:
Eric Masseran
2025-08-28 10:33:17 +02:00
17 changed files with 39 additions and 37 deletions

View File

@@ -6,9 +6,9 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [ubuntu-20.04, windows-2019] os: [ubuntu-24.04, windows-2022]
python-version: ["3.13", "3.12", "3.11", "3.10", "3.9", "3.8", "3.7", "3.6"] python-version: ["3.13", "3.12", "3.11", "3.10", "3.9", "3.8"]
environment: ['3.8', '3.13', '3.12', '3.11', '3.10', '3.9', '3.7', '3.6', 'interpreter'] environment: ['3.8', '3.13', '3.12', '3.11', '3.10', '3.9', 'interpreter']
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -35,7 +35,7 @@ jobs:
JEDI_TEST_ENVIRONMENT: ${{ matrix.environment }} JEDI_TEST_ENVIRONMENT: ${{ matrix.environment }}
code-quality: code-quality:
runs-on: ubuntu-20.04 runs-on: ubuntu-24.04
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -51,7 +51,7 @@ jobs:
python -m mypy jedi sith.py setup.py python -m mypy jedi sith.py setup.py
coverage: coverage:
runs-on: ubuntu-20.04 runs-on: ubuntu-24.04
steps: steps:
- name: Checkout code - name: Checkout code

View File

@@ -2,6 +2,9 @@
Jedi - an awesome autocompletion, static analysis and refactoring library for Python Jedi - an awesome autocompletion, static analysis and refactoring library for Python
#################################################################################### ####################################################################################
**I released the successor to Jedi: A
Mypy-Compatible Python Language Server Built in Rust** - `ZubanLS <https://zubanls.com>`_
.. image:: http://isitmaintained.com/badge/open/davidhalter/jedi.svg .. image:: http://isitmaintained.com/badge/open/davidhalter/jedi.svg
:target: https://github.com/davidhalter/jedi/issues :target: https://github.com/davidhalter/jedi/issues
:alt: The percentage of open issues and pull requests :alt: The percentage of open issues and pull requests
@@ -10,7 +13,7 @@ Jedi - an awesome autocompletion, static analysis and refactoring library for Py
:target: https://github.com/davidhalter/jedi/issues :target: https://github.com/davidhalter/jedi/issues
:alt: The resolution time is the median time an issue or pull request stays open. :alt: The resolution time is the median time an issue or pull request stays open.
.. image:: https://github.com/davidhalter/jedi/workflows/ci/badge.svg?branch=master .. image:: https://github.com/davidhalter/jedi/actions/workflows/ci.yml/badge.svg?branch=master
:target: https://github.com/davidhalter/jedi/actions :target: https://github.com/davidhalter/jedi/actions
:alt: Tests :alt: Tests
@@ -99,7 +102,7 @@ Features and Limitations
Jedi's features are listed here: Jedi's features are listed here:
`Features <https://jedi.readthedocs.org/en/latest/docs/features.html>`_. `Features <https://jedi.readthedocs.org/en/latest/docs/features.html>`_.
You can run Jedi on Python 3.6+ but it should also You can run Jedi on Python 3.8+ but it should also
understand code that is older than those versions. Additionally you should be understand code that is older than those versions. Additionally you should be
able to use `Virtualenvs <https://jedi.readthedocs.org/en/latest/docs/api.html#environments>`_ able to use `Virtualenvs <https://jedi.readthedocs.org/en/latest/docs/api.html#environments>`_
very well. very well.

View File

@@ -16,7 +16,7 @@ Jedi's main API calls and features are:
Basic Features Basic Features
-------------- --------------
- Python 3.6+ support - Python 3.8+ support
- Ignores syntax errors and wrong indentation - Ignores syntax errors and wrong indentation
- Can deal with complex module / function / class structures - Can deal with complex module / function / class structures
- Great ``virtualenv``/``venv`` support - Great ``virtualenv``/``venv`` support

View File

@@ -38,7 +38,7 @@ using pip::
If you want to install the current development version (master branch):: If you want to install the current development version (master branch)::
sudo pip install -e git://github.com/davidhalter/jedi.git#egg=jedi sudo pip install -e git+https://github.com/davidhalter/jedi.git#egg=jedi
System-wide installation via a package manager System-wide installation via a package manager

View File

@@ -22,7 +22,7 @@ if TYPE_CHECKING:
_VersionInfo = namedtuple('VersionInfo', 'major minor micro') # type: ignore[name-match] _VersionInfo = namedtuple('VersionInfo', 'major minor micro') # type: ignore[name-match]
_SUPPORTED_PYTHONS = ['3.13', '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']
_SAFE_PATHS = ['/usr/bin', '/usr/local/bin'] _SAFE_PATHS = ['/usr/bin', '/usr/local/bin']
_CONDA_VAR = 'CONDA_PREFIX' _CONDA_VAR = 'CONDA_PREFIX'
_CURRENT_VERSION = '%s.%s' % (sys.version_info.major, sys.version_info.minor) _CURRENT_VERSION = '%s.%s' % (sys.version_info.major, sys.version_info.minor)

View File

@@ -28,7 +28,7 @@ def clear_time_caches(delete_all: bool = False) -> None:
:param delete_all: Deletes also the cache that is normally not deleted, :param delete_all: Deletes also the cache that is normally not deleted,
like parser cache, which is important for faster parsing. like parser cache, which is important for faster parsing.
""" """
global _time_caches global _time_caches # noqa: F824
if delete_all: if delete_all:
for cache in _time_caches.values(): for cache in _time_caches.values():

View File

@@ -21,7 +21,7 @@ try:
raise ImportError raise ImportError
else: else:
# Use colorama for nicer console output. # Use colorama for nicer console output.
from colorama import Fore, init # type: ignore[import] from colorama import Fore, init # type: ignore[import, unused-ignore]
from colorama import initialise from colorama import initialise
def _lazy_colorama_init(): # noqa: F811 def _lazy_colorama_init(): # noqa: F811

View File

@@ -122,14 +122,14 @@ class InferenceState:
return value_set return value_set
# mypy doesn't suppport decorated propeties (https://github.com/python/mypy/issues/1362) # mypy doesn't suppport decorated propeties (https://github.com/python/mypy/issues/1362)
@property # type: ignore[misc] @property
@inference_state_function_cache() @inference_state_function_cache()
def builtins_module(self): def builtins_module(self):
module_name = 'builtins' module_name = 'builtins'
builtins_module, = self.import_module((module_name,), sys_path=[]) builtins_module, = self.import_module((module_name,), sys_path=[])
return builtins_module return builtins_module
@property # type: ignore[misc] @property
@inference_state_function_cache() @inference_state_function_cache()
def typing_module(self): def typing_module(self):
typing_module, = self.import_module(('typing',)) typing_module, = self.import_module(('typing',))

View File

@@ -48,7 +48,7 @@ def _get_numpy_doc_string_cls():
global _numpy_doc_string_cache global _numpy_doc_string_cache
if isinstance(_numpy_doc_string_cache, (ImportError, SyntaxError)): if isinstance(_numpy_doc_string_cache, (ImportError, SyntaxError)):
raise _numpy_doc_string_cache raise _numpy_doc_string_cache
from numpydoc.docscrape import NumpyDocString # type: ignore[import] from numpydoc.docscrape import NumpyDocString # type: ignore[import, unused-ignore]
_numpy_doc_string_cache = NumpyDocString _numpy_doc_string_cache = NumpyDocString
return _numpy_doc_string_cache return _numpy_doc_string_cache
@@ -109,7 +109,7 @@ def _expand_typestr(type_str):
yield type_str.split('of')[0] yield type_str.split('of')[0]
# Check if type has is a set of valid literal values eg: {'C', 'F', 'A'} # Check if type has is a set of valid literal values eg: {'C', 'F', 'A'}
elif type_str.startswith('{'): elif type_str.startswith('{'):
node = parse(type_str, version='3.7').children[0] node = parse(type_str, version='3.13').children[0]
if node.type == 'atom': if node.type == 'atom':
for leaf in getattr(node.children[1], "children", []): for leaf in getattr(node.children[1], "children", []):
if leaf.type == 'number': if leaf.type == 'number':

View File

@@ -80,7 +80,7 @@ class ModuleMixin(SubModuleDictMixin):
def is_stub(self): def is_stub(self):
return False return False
@property # type: ignore[misc] @property
@inference_state_method_cache() @inference_state_method_cache()
def name(self): def name(self):
return self._module_name_class(self, self.string_names[-1]) return self._module_name_class(self, self.string_names[-1])
@@ -138,7 +138,7 @@ class ModuleValue(ModuleMixin, TreeValue):
api_type = 'module' api_type = 'module'
def __init__(self, inference_state, module_node, code_lines, file_io=None, def __init__(self, inference_state, module_node, code_lines, file_io=None,
string_names=None, is_package=False): string_names=None, is_package=False) -> None:
super().__init__( super().__init__(
inference_state, inference_state,
parent_context=None, parent_context=None,
@@ -149,7 +149,7 @@ class ModuleValue(ModuleMixin, TreeValue):
self._path: Optional[Path] = None self._path: Optional[Path] = None
else: else:
self._path = file_io.path self._path = file_io.path
self.string_names = string_names # Optional[Tuple[str, ...]] self.string_names: Optional[tuple[str, ...]] = string_names
self.code_lines = code_lines self.code_lines = code_lines
self._is_package = is_package self._is_package = is_package

View File

@@ -38,7 +38,7 @@ class ImplicitNamespaceValue(Value, SubModuleDictMixin):
def get_qualified_names(self): def get_qualified_names(self):
return () return ()
@property # type: ignore[misc] @property
@inference_state_method_cache() @inference_state_method_cache()
def name(self): def name(self):
string_name = self.py__package__()[-1] string_name = self.py__package__()[-1]

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
from typing import cast
from setuptools import setup, find_packages from setuptools import setup, find_packages
from setuptools.depends import get_module_constant from setuptools.depends import get_module_constant
@@ -9,7 +10,7 @@ __AUTHOR__ = 'David Halter'
__AUTHOR_EMAIL__ = 'davidhalter88@gmail.com' __AUTHOR_EMAIL__ = 'davidhalter88@gmail.com'
# Get the version from within jedi. It's defined in exactly one place now. # Get the version from within jedi. It's defined in exactly one place now.
version = get_module_constant("jedi", "__version__") version = cast(str, get_module_constant("jedi", "__version__"))
readme = open('README.rst').read() + '\n\n' + open('CHANGELOG.rst').read() readme = open('README.rst').read() + '\n\n' + open('CHANGELOG.rst').read()
@@ -34,7 +35,7 @@ setup(name='jedi',
keywords='python completion refactoring vim', keywords='python completion refactoring vim',
long_description=readme, long_description=readme,
packages=find_packages(exclude=['test', 'test.*']), packages=find_packages(exclude=['test', 'test.*']),
python_requires='>=3.6', python_requires='>=3.8',
# Python 3.13 grammars are added to parso in 0.8.4 # Python 3.13 grammars are added to parso in 0.8.4
install_requires=['parso>=0.8.4,<0.9.0'], install_requires=['parso>=0.8.4,<0.9.0'],
extras_require={ extras_require={
@@ -49,12 +50,12 @@ setup(name='jedi',
'typing_extensions', 'typing_extensions',
], ],
'qa': [ 'qa': [
# latest version on 2025-06-16
'flake8==7.2.0',
# latest version supporting Python 3.6 # latest version supporting Python 3.6
'flake8==5.0.4', 'mypy==1.16',
# latest version supporting Python 3.6
'mypy==0.971',
# Arbitrary pins, latest at the time of pinning # Arbitrary pins, latest at the time of pinning
'types-setuptools==67.2.0.1', 'types-setuptools==80.9.0.20250529',
], ],
'docs': [ 'docs': [
# Just pin all of these. # Just pin all of these.
@@ -95,8 +96,6 @@ setup(name='jedi',
'License :: OSI Approved :: MIT License', 'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent', 'Operating System :: OS Independent',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.10',

View File

@@ -44,7 +44,7 @@ Options:
--pudb Launch pudb when error is raised. --pudb Launch pudb when error is raised.
""" """
from docopt import docopt # type: ignore[import] from docopt import docopt # type: ignore[import, unused-ignore]
import json import json
import os import os

View File

@@ -134,7 +134,7 @@ TEST_GOTO = 2
TEST_REFERENCES = 3 TEST_REFERENCES = 3
grammar36 = parso.load_grammar(version='3.6') grammar313 = parso.load_grammar(version='3.13')
class BaseTestCase(object): class BaseTestCase(object):
@@ -238,7 +238,7 @@ class IntegrationTestCase(BaseTestCase):
should_be = set() should_be = set()
for match in re.finditer('(?:[^ ]+)', correct): for match in re.finditer('(?:[^ ]+)', correct):
string = match.group(0) string = match.group(0)
parser = grammar36.parse(string, start_symbol='eval_input', error_recovery=False) parser = grammar313.parse(string, start_symbol='eval_input', error_recovery=False)
parser_utils.move(parser.get_root_node(), self.line_nr) parser_utils.move(parser.get_root_node(), self.line_nr)
node = parser.get_root_node() node = parser.get_root_node()
module_context = script._get_module_context() module_context = script._get_module_context()
@@ -504,7 +504,7 @@ if __name__ == '__main__':
if arguments['--env']: if arguments['--env']:
environment = get_system_environment(arguments['--env']) environment = get_system_environment(arguments['--env'])
else: else:
# Will be 3.6. # Will be 3.13.
environment = get_default_environment() environment = get_default_environment()
import traceback import traceback

View File

@@ -26,7 +26,7 @@ def test_find_system_environments():
@pytest.mark.parametrize( @pytest.mark.parametrize(
'version', 'version',
['3.6', '3.7', '3.8', '3.9'] ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
) )
def test_versions(version): def test_versions(version):
try: try:

View File

@@ -16,13 +16,13 @@ def test_on_code():
assert i.infer() assert i.infer()
def test_generics_without_definition(): def test_generics_without_definition() -> None:
# Used to raise a recursion error # Used to raise a recursion error
T = TypeVar('T') T = TypeVar('T')
class Stack(Generic[T]): class Stack(Generic[T]):
def __init__(self): def __init__(self) -> None:
self.items = [] # type: List[T] self.items: List[T] = []
def push(self, item): def push(self, item):
self.items.append(item) self.items.append(item)

View File

@@ -91,7 +91,7 @@ class TestSetupReadline(unittest.TestCase):
} }
# There are quite a few differences, because both Windows and Linux # There are quite a few differences, because both Windows and Linux
# (posix and nt) libraries are included. # (posix and nt) libraries are included.
assert len(difference) < 30 assert len(difference) < 40
def test_local_import(self): def test_local_import(self):
s = 'import test.test_utils' s = 'import test.test_utils'