diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 28481a0c..2d94d84a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,9 +6,9 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-20.04, windows-2019] - python-version: ["3.13", "3.12", "3.11", "3.10", "3.9", "3.8", "3.7", "3.6"] - environment: ['3.8', '3.13', '3.12', '3.11', '3.10', '3.9', '3.7', '3.6', 'interpreter'] + os: [ubuntu-24.04, windows-2022] + 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', 'interpreter'] steps: - name: Checkout code uses: actions/checkout@v4 @@ -35,7 +35,7 @@ jobs: JEDI_TEST_ENVIRONMENT: ${{ matrix.environment }} code-quality: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Checkout code uses: actions/checkout@v4 @@ -51,7 +51,7 @@ jobs: python -m mypy jedi sith.py setup.py coverage: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Checkout code diff --git a/README.rst b/README.rst index 24b22ba2..89ce88ee 100644 --- a/README.rst +++ b/README.rst @@ -2,6 +2,9 @@ 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 `_ + .. image:: http://isitmaintained.com/badge/open/davidhalter/jedi.svg :target: https://github.com/davidhalter/jedi/issues :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 :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 :alt: Tests @@ -99,7 +102,7 @@ Features and Limitations Jedi's features are listed here: `Features `_. -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 able to use `Virtualenvs `_ very well. diff --git a/docs/docs/features.rst b/docs/docs/features.rst index e7ef6731..72c3bc8a 100644 --- a/docs/docs/features.rst +++ b/docs/docs/features.rst @@ -16,7 +16,7 @@ Jedi's main API calls and features are: Basic Features -------------- -- Python 3.6+ support +- Python 3.8+ support - Ignores syntax errors and wrong indentation - Can deal with complex module / function / class structures - Great ``virtualenv``/``venv`` support diff --git a/docs/docs/installation.rst b/docs/docs/installation.rst index d8df120c..d3762781 100644 --- a/docs/docs/installation.rst +++ b/docs/docs/installation.rst @@ -38,7 +38,7 @@ using pip:: 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 diff --git a/jedi/api/environment.py b/jedi/api/environment.py index 64b318e1..d2f7bd29 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.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'] _CONDA_VAR = 'CONDA_PREFIX' _CURRENT_VERSION = '%s.%s' % (sys.version_info.major, sys.version_info.minor) diff --git a/jedi/cache.py b/jedi/cache.py index 1ff45201..2bb15105 100644 --- a/jedi/cache.py +++ b/jedi/cache.py @@ -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, like parser cache, which is important for faster parsing. """ - global _time_caches + global _time_caches # noqa: F824 if delete_all: for cache in _time_caches.values(): diff --git a/jedi/debug.py b/jedi/debug.py index 99a90601..167be41b 100644 --- a/jedi/debug.py +++ b/jedi/debug.py @@ -21,7 +21,7 @@ try: raise ImportError else: # 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 def _lazy_colorama_init(): # noqa: F811 diff --git a/jedi/inference/__init__.py b/jedi/inference/__init__.py index bd31cbd3..8e1696e2 100644 --- a/jedi/inference/__init__.py +++ b/jedi/inference/__init__.py @@ -122,14 +122,14 @@ class InferenceState: return value_set # mypy doesn't suppport decorated propeties (https://github.com/python/mypy/issues/1362) - @property # type: ignore[misc] + @property @inference_state_function_cache() def builtins_module(self): module_name = 'builtins' builtins_module, = self.import_module((module_name,), sys_path=[]) return builtins_module - @property # type: ignore[misc] + @property @inference_state_function_cache() def typing_module(self): typing_module, = self.import_module(('typing',)) diff --git a/jedi/inference/docstrings.py b/jedi/inference/docstrings.py index 809974f3..f1d0f31f 100644 --- a/jedi/inference/docstrings.py +++ b/jedi/inference/docstrings.py @@ -48,7 +48,7 @@ def _get_numpy_doc_string_cls(): global _numpy_doc_string_cache if isinstance(_numpy_doc_string_cache, (ImportError, SyntaxError)): 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 return _numpy_doc_string_cache @@ -109,7 +109,7 @@ def _expand_typestr(type_str): yield type_str.split('of')[0] # Check if type has is a set of valid literal values eg: {'C', 'F', 'A'} 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': for leaf in getattr(node.children[1], "children", []): if leaf.type == 'number': diff --git a/jedi/inference/value/module.py b/jedi/inference/value/module.py index 6461cb4b..bfcd980e 100644 --- a/jedi/inference/value/module.py +++ b/jedi/inference/value/module.py @@ -80,7 +80,7 @@ class ModuleMixin(SubModuleDictMixin): def is_stub(self): return False - @property # type: ignore[misc] + @property @inference_state_method_cache() def name(self): return self._module_name_class(self, self.string_names[-1]) @@ -138,7 +138,7 @@ class ModuleValue(ModuleMixin, TreeValue): api_type = 'module' 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__( inference_state, parent_context=None, @@ -149,7 +149,7 @@ class ModuleValue(ModuleMixin, TreeValue): self._path: Optional[Path] = None else: 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._is_package = is_package diff --git a/jedi/inference/value/namespace.py b/jedi/inference/value/namespace.py index 11737cc9..0ec5d341 100644 --- a/jedi/inference/value/namespace.py +++ b/jedi/inference/value/namespace.py @@ -38,7 +38,7 @@ class ImplicitNamespaceValue(Value, SubModuleDictMixin): def get_qualified_names(self): return () - @property # type: ignore[misc] + @property @inference_state_method_cache() def name(self): string_name = self.py__package__()[-1] diff --git a/setup.py b/setup.py index 6ed5110a..a000aa35 100755 --- a/setup.py +++ b/setup.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +from typing import cast from setuptools import setup, find_packages from setuptools.depends import get_module_constant @@ -9,7 +10,7 @@ __AUTHOR__ = 'David Halter' __AUTHOR_EMAIL__ = 'davidhalter88@gmail.com' # 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() @@ -34,7 +35,7 @@ setup(name='jedi', keywords='python completion refactoring vim', long_description=readme, 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 install_requires=['parso>=0.8.4,<0.9.0'], extras_require={ @@ -49,12 +50,12 @@ setup(name='jedi', 'typing_extensions', ], 'qa': [ + # latest version on 2025-06-16 + 'flake8==7.2.0', # latest version supporting Python 3.6 - 'flake8==5.0.4', - # latest version supporting Python 3.6 - 'mypy==0.971', + 'mypy==1.16', # Arbitrary pins, latest at the time of pinning - 'types-setuptools==67.2.0.1', + 'types-setuptools==80.9.0.20250529', ], 'docs': [ # Just pin all of these. @@ -95,8 +96,6 @@ setup(name='jedi', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', diff --git a/sith.py b/sith.py index 1a69d2ad..c4bd4b2d 100755 --- a/sith.py +++ b/sith.py @@ -44,7 +44,7 @@ Options: --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 os diff --git a/test/run.py b/test/run.py index 01fe5354..0fd01b23 100755 --- a/test/run.py +++ b/test/run.py @@ -134,7 +134,7 @@ TEST_GOTO = 2 TEST_REFERENCES = 3 -grammar36 = parso.load_grammar(version='3.6') +grammar313 = parso.load_grammar(version='3.13') class BaseTestCase(object): @@ -238,7 +238,7 @@ class IntegrationTestCase(BaseTestCase): should_be = set() for match in re.finditer('(?:[^ ]+)', correct): 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) node = parser.get_root_node() module_context = script._get_module_context() @@ -504,7 +504,7 @@ if __name__ == '__main__': if arguments['--env']: environment = get_system_environment(arguments['--env']) else: - # Will be 3.6. + # Will be 3.13. environment = get_default_environment() import traceback diff --git a/test/test_api/test_environment.py b/test/test_api/test_environment.py index 621fcb8e..ea0c1730 100644 --- a/test/test_api/test_environment.py +++ b/test/test_api/test_environment.py @@ -26,7 +26,7 @@ def test_find_system_environments(): @pytest.mark.parametrize( '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): try: diff --git a/test/test_inference/test_mixed.py b/test/test_inference/test_mixed.py index b4e6c65d..1bbe64bd 100644 --- a/test/test_inference/test_mixed.py +++ b/test/test_inference/test_mixed.py @@ -16,13 +16,13 @@ def test_on_code(): assert i.infer() -def test_generics_without_definition(): +def test_generics_without_definition() -> None: # Used to raise a recursion error T = TypeVar('T') class Stack(Generic[T]): - def __init__(self): - self.items = [] # type: List[T] + def __init__(self) -> None: + self.items: List[T] = [] def push(self, item): self.items.append(item) diff --git a/test/test_utils.py b/test/test_utils.py index 15a79174..4fc19878 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -91,7 +91,7 @@ class TestSetupReadline(unittest.TestCase): } # There are quite a few differences, because both Windows and Linux # (posix and nt) libraries are included. - assert len(difference) < 30 + assert len(difference) < 40 def test_local_import(self): s = 'import test.test_utils'