Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-jedi for openSUSE:Factory checked in at 2023-08-11 15:55:28 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-jedi (Old) and /work/SRC/openSUSE:Factory/.python-jedi.new.11712 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-jedi" Fri Aug 11 15:55:28 2023 rev:39 rq:1103417 version:0.19.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-jedi/python-jedi.changes 2023-05-11 12:32:03.598282504 +0200 +++ /work/SRC/openSUSE:Factory/.python-jedi.new.11712/python-jedi.changes 2023-08-11 15:55:39.695808591 +0200 @@ -1,0 +2,19 @@ +Thu Aug 10 22:27:43 UTC 2023 - Benjamin Greiner <c...@bnavigator.de> + +- Update requirements + +------------------------------------------------------------------- +Thu Aug 10 21:59:38 UTC 2023 - Arun Persaud <a...@gmx.de> + +- specfile: + * remove patch supported_pythons_310_311.patch, included upstream + * remove patch support-python-311-typing.patch, included upstreamx + +- update to version 0.19.0: + * Python 3.11 support + * Massive improvements in performance for Interpreter (e.g. IPython) + users. This especially affects pandas users with large datasets. + * Add jedi.settings.allow_unsafe_interpreter_executions to make it + easier for IPython users to avoid unsafe executions. + +------------------------------------------------------------------- Old: ---- jedi-0.18.2.tar.gz support-python-311-typing.patch supported_pythons_310_311.patch New: ---- jedi-0.19.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-jedi.spec ++++++ --- /var/tmp/diff_new_pack.wT6cH2/_old 2023-08-11 15:55:40.483813286 +0200 +++ /var/tmp/diff_new_pack.wT6cH2/_new 2023-08-11 15:55:40.487813310 +0200 @@ -19,7 +19,7 @@ %define skip_python2 1 %{?sle15_python_module_pythons} Name: python-jedi -Version: 0.18.2 +Version: 0.19.0 Release: 0 Summary: An autocompletion tool for Python License: MIT AND Python-2.0 @@ -27,13 +27,8 @@ URL: https://github.com/davidhalter/jedi Source0: https://files.pythonhosted.org/packages/source/j/jedi/jedi-%{version}.tar.gz Source1: %{name}-rpmlintrc -# PATCH-FIX-UPSTREAM gh#davidhalter/jedi#1903 -Patch0: support-python-311-typing.patch -# PATCH-FIX-UPSTREAM supported_pythons_310_311.patch gh#davidhalter/jedi#1914 mc...@suse.com -# Add '3.11' among _SUPPORTED_PYTHONS -Patch2: supported_pythons_310_311.patch # The author of jedi and parso takes pinning very seriously, adhere to it! -BuildRequires: %{python_module parso >= 0.8.0 with %python-parso < 0.9} +BuildRequires: %{python_module parso >= 0.8.3 with %python-parso < 0.9} BuildRequires: %{python_module pip} BuildRequires: %{python_module pytest >= 5} BuildRequires: %{python_module setuptools} @@ -42,7 +37,7 @@ BuildRequires: fdupes BuildRequires: python-rpm-macros # See pinning note above -Requires: (python-parso >= 0.8.0 with python-parso < 0.9) +Requires: (python-parso >= 0.8.3 with python-parso < 0.9) BuildArch: noarch %python_subpackages ++++++ jedi-0.18.2.tar.gz -> jedi-0.19.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/CHANGELOG.rst new/jedi-0.19.0/CHANGELOG.rst --- old/jedi-0.18.2/CHANGELOG.rst 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/CHANGELOG.rst 2023-07-29 00:59:28.000000000 +0200 @@ -6,6 +6,15 @@ Unreleased ++++++++++ +0.19.0 (2023-07-29) ++++++++++++++++++++ + +- Python 3.11 support +- Massive improvements in performance for ``Interpreter`` (e.g. IPython) users. + This especially affects ``pandas`` users with large datasets. +- Add ``jedi.settings.allow_unsafe_interpreter_executions`` to make it easier + for IPython users to avoid unsafe executions. + 0.18.2 (2022-11-21) +++++++++++++++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/PKG-INFO new/jedi-0.19.0/PKG-INFO --- old/jedi-0.18.2/PKG-INFO 2022-11-21 23:29:14.449261000 +0100 +++ new/jedi-0.19.0/PKG-INFO 2023-07-29 01:05:44.501212400 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: jedi -Version: 0.18.2 +Version: 0.19.0 Summary: An autocompletion tool for Python that can be used for text editors. Home-page: https://github.com/davidhalter/jedi Author: David Halter @@ -52,7 +52,7 @@ - `GNOME Builder`_ (with support for GObject Introspection) - Gedit (gedi_) - wdb_ - Web Debugger - - `Eric IDE`_ (Available as a plugin) + - `Eric IDE`_ - `IPython 6.0.0+ <https://ipython.readthedocs.io/en/stable/whatsnew/version6.html>`_ - `xonsh shell <https://xon.sh/contents.html>`_ has `jedi extension <https://xon.sh/xontribs.html#jedi>`_ @@ -61,7 +61,8 @@ There are a few language servers that use Jedi: - `jedi-language-server <https://github.com/pappasam/jedi-language-server>`_ - - `python-language-server <https://github.com/palantir/python-language-server>`_ + - `python-language-server <https://github.com/palantir/python-language-server>`_ (currently unmaintained) + - `python-lsp-server <https://github.com/python-lsp/python-lsp-server>`_ (fork from python-language-server) - `anakin-language-server <https://github.com/muffinmad/anakin-language-server>`_ Here are some pictures taken from jedi-vim_: @@ -234,6 +235,15 @@ Unreleased ++++++++++ + 0.19.0 (2023-07-29) + +++++++++++++++++++ + + - Python 3.11 support + - Massive improvements in performance for ``Interpreter`` (e.g. IPython) users. + This especially affects ``pandas`` users with large datasets. + - Add ``jedi.settings.allow_unsafe_interpreter_executions`` to make it easier + for IPython users to avoid unsafe executions. + 0.18.2 (2022-11-21) +++++++++++++++++++ @@ -554,6 +564,7 @@ Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: Text Editors :: Integrated Development Environments (IDE) Classifier: Topic :: Utilities diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/README.rst new/jedi-0.19.0/README.rst --- old/jedi-0.18.2/README.rst 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/README.rst 2023-07-29 00:59:28.000000000 +0200 @@ -42,7 +42,7 @@ - `GNOME Builder`_ (with support for GObject Introspection) - Gedit (gedi_) - wdb_ - Web Debugger -- `Eric IDE`_ (Available as a plugin) +- `Eric IDE`_ - `IPython 6.0.0+ <https://ipython.readthedocs.io/en/stable/whatsnew/version6.html>`_ - `xonsh shell <https://xon.sh/contents.html>`_ has `jedi extension <https://xon.sh/xontribs.html#jedi>`_ @@ -51,7 +51,8 @@ There are a few language servers that use Jedi: - `jedi-language-server <https://github.com/pappasam/jedi-language-server>`_ -- `python-language-server <https://github.com/palantir/python-language-server>`_ +- `python-language-server <https://github.com/palantir/python-language-server>`_ (currently unmaintained) +- `python-lsp-server <https://github.com/python-lsp/python-lsp-server>`_ (fork from python-language-server) - `anakin-language-server <https://github.com/muffinmad/anakin-language-server>`_ Here are some pictures taken from jedi-vim_: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/docs/docs/acknowledgements.rst new/jedi-0.19.0/docs/docs/acknowledgements.rst --- old/jedi-0.18.2/docs/docs/acknowledgements.rst 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/docs/docs/acknowledgements.rst 2023-07-29 00:59:28.000000000 +0200 @@ -35,7 +35,7 @@ The first idea was to execute non-dangerous code. But I soon realized, that this would not work. So I started to build a static analysis tool. The biggest problem that I had at the time was that I did not know a thing -about parsers.I did not did not even know the word static analysis. It turns +about parsers. I did not even know the word static analysis. It turns out they are the foundation of a good static analysis tool. I of course did not know that and tried to write my own poor version of a parser that I ended up throwing away two years later. @@ -53,7 +53,7 @@ -------- -I will leave you with a small annectote that happend in 2012, if I remember +I will leave you with a small anecdote that happened in 2012, if I remember correctly. After I explained Guido van Rossum, how some parts of my auto-completion work, he said: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/docs/docs/features.rst new/jedi-0.19.0/docs/docs/features.rst --- old/jedi-0.18.2/docs/docs/features.rst 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/docs/docs/features.rst 2023-07-29 00:59:28.000000000 +0200 @@ -77,7 +77,7 @@ Importing ``numpy`` can be quite slow sometimes, as well as loading the builtins the first time. If you want to speed things up, you could preload -libriaries in |jedi|, with :func:`.preload_module`. However, once loaded, this +libraries in |jedi|, with :func:`.preload_module`. However, once loaded, this should not be a problem anymore. The same is true for huge modules like ``PySide``, ``wx``, ``tensorflow``, ``pandas``, etc. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/docs/docs/usage.rst new/jedi-0.19.0/docs/docs/usage.rst --- old/jedi-0.18.2/docs/docs/usage.rst 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/docs/docs/usage.rst 2023-07-29 00:59:28.000000000 +0200 @@ -4,7 +4,7 @@ ========== |jedi| is can be used with a variety of :ref:`plugins <editor-plugins>`, -`language servers <language-servers>` and other software. +:ref:`language servers <language-servers>` and other software. It is also possible to use |jedi| in the :ref:`Python shell or with IPython <repl-completion>`. @@ -16,7 +16,8 @@ -------------- - `jedi-language-server <https://github.com/pappasam/jedi-language-server>`_ -- `python-language-server <https://github.com/palantir/python-language-server>`_ +- `python-language-server <https://github.com/palantir/python-language-server>`_ (currently unmaintained) +- `python-lsp-server <https://github.com/python-lsp/python-lsp-server>`_ (fork from python-language-server) - `anakin-language-server <https://github.com/muffinmad/anakin-language-server>`_ .. _editor-plugins: @@ -86,7 +87,7 @@ Eric IDE ~~~~~~~~ -- `Eric IDE`_ (Available as a plugin) +- `Eric IDE`_ Web Debugger ~~~~~~~~~~~~ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/__init__.py new/jedi-0.19.0/jedi/__init__.py --- old/jedi-0.18.2/jedi/__init__.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/__init__.py 2023-07-29 00:59:28.000000000 +0200 @@ -27,7 +27,7 @@ load """ -__version__ = '0.18.2' +__version__ = '0.19.0' from jedi.api import Script, Interpreter, set_debug_function, preload_module from jedi import settings diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/api/__init__.py new/jedi-0.19.0/jedi/api/__init__.py --- old/jedi-0.18.2/jedi/api/__init__.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/api/__init__.py 2023-07-29 00:59:28.000000000 +0200 @@ -206,6 +206,7 @@ before magic methods and name mangled names that start with ``__``. :rtype: list of :class:`.Completion` """ + self._inference_state.reset_recursion_limitations() with debug.increase_indent_cm('complete'): completion = Completion( self._inference_state, self._get_module_context(), self._code_lines, @@ -215,6 +216,7 @@ @validate_line_column def infer(self, line=None, column=None, *, only_stubs=False, prefer_stubs=False): + self._inference_state.reset_recursion_limitations() """ Return the definitions of under the cursor. It is basically a wrapper around Jedi's type inference. @@ -260,6 +262,7 @@ @validate_line_column def goto(self, line=None, column=None, *, follow_imports=False, follow_builtin_imports=False, only_stubs=False, prefer_stubs=False): + self._inference_state.reset_recursion_limitations() """ Goes to the name that defined the object under the cursor. Optionally you can follow imports. @@ -365,10 +368,17 @@ :rtype: list of :class:`.Name` """ + self._inference_state.reset_recursion_limitations() definitions = self.goto(line, column, follow_imports=True) if definitions: return definitions leaf = self._module_node.get_leaf_for_position((line, column)) + + if leaf is not None and leaf.end_pos == (line, column) and leaf.type == 'newline': + next_ = leaf.get_next_leaf() + if next_ is not None and next_.start_pos == leaf.end_pos: + leaf = next_ + if leaf is not None and leaf.type in ('keyword', 'operator', 'error_leaf'): def need_pydoc(): if leaf.value in ('(', ')', '[', ']'): @@ -400,6 +410,7 @@ the current module only. :rtype: list of :class:`.Name` """ + self._inference_state.reset_recursion_limitations() def _references(include_builtins=True, scope='project'): if scope not in ('project', 'file'): @@ -434,6 +445,7 @@ :rtype: list of :class:`.Signature` """ + self._inference_state.reset_recursion_limitations() pos = line, column call_details = helpers.get_signature_details(self._module_node, pos) if call_details is None: @@ -553,6 +565,7 @@ return parso_to_jedi_errors(self._inference_state.grammar, self._module_node) def _names(self, all_scopes=False, definitions=True, references=False): + self._inference_state.reset_recursion_limitations() # Set line/column to a random position, because they don't matter. module_context = self._get_module_context() defs = [ @@ -708,7 +721,6 @@ :param namespaces: A list of namespace dictionaries such as the one returned by :func:`globals` and :func:`locals`. """ - _allow_descriptor_getattr_default = True def __init__(self, code, namespaces, *, project=None, **kwds): try: @@ -729,7 +741,16 @@ super().__init__(code, environment=environment, project=project, **kwds) self.namespaces = namespaces - self._inference_state.allow_descriptor_getattr = self._allow_descriptor_getattr_default + self._inference_state.allow_unsafe_executions = \ + settings.allow_unsafe_interpreter_executions + # Dynamic params search is important when we work on functions that are + # called by other pieces of code. However for interpreter completions + # this is not important at all, because the current code is always new + # and will never be called by something. + # Also sometimes this logic goes a bit too far like in + # https://github.com/ipython/ipython/issues/13866, where it takes + # seconds to do a simple completion. + self._inference_state.do_dynamic_params_search = False @cache.memoize_method def _get_module_context(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/api/classes.py new/jedi-0.19.0/jedi/api/classes.py --- old/jedi-0.18.2/jedi/api/classes.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/api/classes.py 2023-07-29 00:59:28.000000000 +0200 @@ -105,8 +105,7 @@ # Compiled modules should not return a module path even if they # have one. path: Optional[Path] = self._get_module_context().py__file__() - if path is not None: - return path + return path return None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/api/environment.py new/jedi-0.19.0/jedi/api/environment.py --- old/jedi-0.18.2/jedi/api/environment.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/api/environment.py 2023-07-29 00:59:28.000000000 +0200 @@ -15,9 +15,9 @@ import parso -_VersionInfo = namedtuple('VersionInfo', 'major minor micro') +_VersionInfo = namedtuple('VersionInfo', 'major minor micro') # type: ignore[name-match] -_SUPPORTED_PYTHONS = ['3.10', '3.9', '3.8', '3.7', '3.6'] +_SUPPORTED_PYTHONS = ['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) @@ -384,8 +384,7 @@ def _get_executables_from_windows_registry(version): - # https://github.com/python/typeshed/pull/3794 adds winreg - import winreg # type: ignore[import] + import winreg # TODO: support Python Anaconda. sub_keys = [ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/api/keywords.py new/jedi-0.19.0/jedi/api/keywords.py --- old/jedi-0.18.2/jedi/api/keywords.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/api/keywords.py 2023-07-29 00:59:28.000000000 +0200 @@ -5,8 +5,7 @@ from jedi.inference.names import AbstractArbitraryName try: - # https://github.com/python/typeshed/pull/4351 adds pydoc_data - from pydoc_data import topics # type: ignore[import] + from pydoc_data import topics pydoc_topics: Optional[Dict[str, str]] = topics.topics except ImportError: # Python 3.6.8 embeddable does not have pydoc_data. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/api/refactoring/__init__.py new/jedi-0.19.0/jedi/api/refactoring/__init__.py --- old/jedi-0.18.2/jedi/api/refactoring/__init__.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/api/refactoring/__init__.py 2023-07-29 00:59:28.000000000 +0200 @@ -5,6 +5,7 @@ from parso import split_lines from jedi.api.exceptions import RefactoringError +from jedi.inference.value.namespace import ImplicitNSName EXPRESSION_PARTS = ( 'or_test and_test not_test comparison ' @@ -102,7 +103,12 @@ to_path=calculate_to_path(path), module_node=next(iter(map_)).get_root_node(), node_to_str_map=map_ - ) for path, map_ in sorted(self._file_to_node_changes.items()) + ) + # We need to use `or`, because the path can be None + for path, map_ in sorted( + self._file_to_node_changes.items(), + key=lambda x: x[0] or Path("") + ) } def get_renames(self) -> Iterable[Tuple[Path, Path]]: @@ -116,7 +122,7 @@ project_path = self._inference_state.project.path for from_, to in self.get_renames(): text += 'rename from %s\nrename to %s\n' \ - % (from_.relative_to(project_path), to.relative_to(project_path)) + % (_try_relative_to(from_, project_path), _try_relative_to(to, project_path)) return text + ''.join(f.get_diff() for f in self.get_changed_files().values()) @@ -146,13 +152,16 @@ raise RefactoringError("There is no name under the cursor") for d in definitions: + # This private access is ok in a way. It's not public to + # protect Jedi users from seeing it. tree_name = d._name.tree_name - if d.type == 'module' and tree_name is None: - p = None if d.module_path is None else Path(d.module_path) + if d.type == 'module' and tree_name is None and d.module_path is not None: + p = Path(d.module_path) file_renames.add(_calculate_rename(p, new_name)) + elif isinstance(d._name, ImplicitNSName): + for p in d._name._value.py__path__(): + file_renames.add(_calculate_rename(Path(p), new_name)) else: - # This private access is ok in a way. It's not public to - # protect Jedi users from seeing it. if tree_name is not None: fmap = file_tree_name_map.setdefault(d.module_path, {}) fmap[tree_name] = tree_name.prefix + new_name @@ -246,3 +255,10 @@ Removes the last indentation of a prefix, e.g. " \n \n " becomes " \n \n". """ return ''.join(split_lines(prefix, keepends=True)[:-1]) + + +def _try_relative_to(path: Path, base: Path) -> Path: + try: + return path.relative_to(base) + except ValueError: + return path diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/api/strings.py new/jedi-0.19.0/jedi/api/strings.py --- old/jedi-0.18.2/jedi/api/strings.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/api/strings.py 2023-07-29 00:59:28.000000000 +0200 @@ -36,8 +36,11 @@ string = cut_value_at_position(leaf, position) context = module_context.create_context(bracket_leaf) - before_bracket_leaf = bracket_leaf.get_previous_leaf() - if before_bracket_leaf.type in ('atom', 'trailer', 'name'): + + before_node = before_bracket_leaf = bracket_leaf.get_previous_leaf() + if before_node in (')', ']', '}'): + before_node = before_node.parent + if before_node.type in ('atom', 'trailer', 'name'): values = infer_call_of_leaf(context, before_bracket_leaf) return list(_completions_for_dicts( module_context.inference_state, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/inference/__init__.py new/jedi-0.19.0/jedi/inference/__init__.py --- old/jedi-0.18.2/jedi/inference/__init__.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/inference/__init__.py 2023-07-29 00:59:28.000000000 +0200 @@ -90,7 +90,7 @@ self.compiled_subprocess = environment.get_inference_state_subprocess(self) self.grammar = environment.get_grammar() - self.latest_grammar = parso.load_grammar(version='3.10') + self.latest_grammar = parso.load_grammar(version='3.11') 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]] @@ -99,10 +99,11 @@ self.mixed_cache = {} # see `inference.compiled.mixed._create()` self.analysis = [] self.dynamic_params_depth = 0 + self.do_dynamic_params_search = settings.dynamic_params self.is_analysis = False self.project = project self.access_cache = {} - self.allow_descriptor_getattr = False + self.allow_unsafe_executions = False self.flow_analysis_enabled = True self.reset_recursion_limitations() @@ -125,7 +126,7 @@ @inference_state_function_cache() def builtins_module(self): module_name = 'builtins' - builtins_module, = self.import_module((module_name,), sys_path=()) + builtins_module, = self.import_module((module_name,), sys_path=[]) return builtins_module @property # type: ignore[misc] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/inference/compiled/access.py new/jedi-0.19.0/jedi/inference/compiled/access.py --- old/jedi-0.18.2/jedi/inference/compiled/access.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/inference/compiled/access.py 2023-07-29 00:59:28.000000000 +0200 @@ -9,7 +9,7 @@ import builtins import typing from pathlib import Path -from typing import Optional +from typing import Optional, Tuple from jedi.inference.compiled.getattr_static import getattr_static @@ -40,7 +40,7 @@ MethodDescriptorType = type(str.replace) WrapperDescriptorType = type(set.__iter__) # `object.__subclasshook__` is an already executed descriptor. -object_class_dict = type.__dict__["__dict__"].__get__(object) +object_class_dict = type.__dict__["__dict__"].__get__(object) # type: ignore[index] ClassMethodDescriptorType = type(object_class_dict['__subclasshook__']) _sentinel = object() @@ -147,7 +147,7 @@ self.accesses = accesses -def create_access_path(inference_state, obj): +def create_access_path(inference_state, obj) -> AccessPath: access = create_access(inference_state, obj) return AccessPath(access.get_access_path_tuples()) @@ -175,7 +175,7 @@ def _create_access(self, obj): return create_access(self._inference_state, obj) - def _create_access_path(self, obj): + def _create_access_path(self, obj) -> AccessPath: return create_access_path(self._inference_state, obj) def py__bool__(self): @@ -230,8 +230,8 @@ return [annotation] return None - def py__simple_getitem__(self, index): - if type(self._obj) not in ALLOWED_GETITEM_TYPES: + def py__simple_getitem__(self, index, *, safe=True): + if safe and type(self._obj) not in ALLOWED_GETITEM_TYPES: # Get rid of side effects, we won't call custom `__getitem__`s. return None @@ -329,33 +329,37 @@ except TypeError: return False - def is_allowed_getattr(self, name, safe=True): + def is_allowed_getattr(self, name, safe=True) -> Tuple[bool, bool, Optional[AccessPath]]: # TODO this API is ugly. - if not safe: - # Unsafe is mostly used to check for __getattr__/__getattribute__. - # getattr_static works for properties, but the underscore methods - # are just ignored (because it's safer and avoids more code - # execution). See also GH #1378. - - # Avoid warnings, see comment in the next function. - with warnings.catch_warnings(record=True): - warnings.simplefilter("always") - try: - return hasattr(self._obj, name), False - except Exception: - # Obviously has an attribute (propably a property) that - # gets executed, so just avoid all exceptions here. - return False, False try: attr, is_get_descriptor = getattr_static(self._obj, name) except AttributeError: - return False, False + if not safe: + # Unsafe is mostly used to check for __getattr__/__getattribute__. + # getattr_static works for properties, but the underscore methods + # are just ignored (because it's safer and avoids more code + # execution). See also GH #1378. + + # Avoid warnings, see comment in the next function. + with warnings.catch_warnings(record=True): + warnings.simplefilter("always") + try: + return hasattr(self._obj, name), False, None + except Exception: + # Obviously has an attribute (probably a property) that + # gets executed, so just avoid all exceptions here. + pass + return False, False, None else: if is_get_descriptor and type(attr) not in ALLOWED_DESCRIPTOR_ACCESS: + if isinstance(attr, property): + if hasattr(attr.fget, '__annotations__'): + a = DirectObjectAccess(self._inference_state, attr.fget) + return True, True, a.get_return_annotation() # In case of descriptors that have get methods we cannot return # it's value, because that would mean code execution. - return True, True - return True, False + return True, True, None + return True, False, None def getattr_paths(self, name, default=_sentinel): try: @@ -515,7 +519,7 @@ # the signature. In that case we just want a simple escape for now. raise ValueError - def get_return_annotation(self): + def get_return_annotation(self) -> Optional[AccessPath]: try: o = self._obj.__annotations__.get('return') except AttributeError: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/inference/compiled/mixed.py new/jedi-0.19.0/jedi/inference/compiled/mixed.py --- old/jedi-0.18.2/jedi/inference/compiled/mixed.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/inference/compiled/mixed.py 2023-07-29 00:59:28.000000000 +0200 @@ -142,9 +142,9 @@ super().__init__(inference_state, compiled_value) self._tree_value = tree_value - def _create_name(self, name): + def _create_name(self, *args, **kwargs): return MixedName( - super()._create_name(name), + super()._create_name(*args, **kwargs), self._tree_value, ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/inference/compiled/subprocess/__main__.py new/jedi-0.19.0/jedi/inference/compiled/subprocess/__main__.py --- old/jedi-0.18.2/jedi/inference/compiled/subprocess/__main__.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/inference/compiled/subprocess/__main__.py 2023-07-29 00:59:28.000000000 +0200 @@ -21,11 +21,11 @@ def __init__(self, path_dct): self._path_dct = path_dct - def find_module(self, fullname, path=None): + def find_spec(self, fullname, path=None, target=None): if path is None and fullname in self._path_dct: p = self._path_dct[fullname] - loader = PathFinder.find_module(fullname, path=[p]) - return loader + spec = PathFinder.find_spec(fullname, path=[p], target=target) + return spec return None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/inference/compiled/subprocess/functions.py new/jedi-0.19.0/jedi/inference/compiled/subprocess/functions.py --- old/jedi-0.18.2/jedi/inference/compiled/subprocess/functions.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/inference/compiled/subprocess/functions.py 2023-07-29 00:59:28.000000000 +0200 @@ -2,7 +2,6 @@ import os import inspect import importlib -import warnings from pathlib import Path from zipfile import ZipFile from zipimport import zipimporter, ZipImportError @@ -167,17 +166,16 @@ def _find_module_py33(string, path=None, loader=None, full_name=None, is_global_search=True): - loader = loader or importlib.machinery.PathFinder.find_module(string, path) + if not loader: + spec = importlib.machinery.PathFinder.find_spec(string, path) + if spec is not None: + loader = spec.loader if loader is None and path is None: # Fallback to find builtins try: - with warnings.catch_warnings(record=True): - # Mute "DeprecationWarning: Use importlib.util.find_spec() - # instead." While we should replace that in the future, it's - # probably good to wait until we deprecate Python 3.3, since - # it was added in Python 3.4 and find_loader hasn't been - # removed in 3.6. - loader = importlib.find_loader(string) + spec = importlib.util.find_spec(string) + if spec is not None: + loader = spec.loader except ValueError as e: # See #491. Importlib might raise a ValueError, to avoid this, we # just raise an ImportError to fix the issue. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/inference/compiled/value.py new/jedi-0.19.0/jedi/inference/compiled/value.py --- old/jedi-0.18.2/jedi/inference/compiled/value.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/inference/compiled/value.py 2023-07-29 00:59:28.000000000 +0200 @@ -51,7 +51,6 @@ def py__call__(self, arguments): return_annotation = self.access_handle.get_return_annotation() if return_annotation is not None: - # TODO the return annotation may also be a string. return create_from_access_path( self.inference_state, return_annotation @@ -163,7 +162,10 @@ def py__simple_getitem__(self, index): with reraise_getitem_errors(IndexError, KeyError, TypeError): try: - access = self.access_handle.py__simple_getitem__(index) + access = self.access_handle.py__simple_getitem__( + index, + safe=not self.inference_state.allow_unsafe_executions + ) except AttributeError: return super().py__simple_getitem__(index) if access is None: @@ -311,11 +313,12 @@ class CompiledName(AbstractNameDefinition): - def __init__(self, inference_state, parent_value, name): + def __init__(self, inference_state, parent_value, name, is_descriptor): self._inference_state = inference_state self.parent_context = parent_value.as_context() self._parent_value = parent_value self.string_name = name + self.is_descriptor = is_descriptor def py__doc__(self): return self.infer_compiled_value().py__doc__() @@ -342,6 +345,11 @@ @property def api_type(self): + if self.is_descriptor: + # In case of properties we want to avoid executions as much as + # possible. Since the api_type can be wrong for other reasons + # anyway, we just return instance here. + return "instance" return self.infer_compiled_value().api_type def infer(self): @@ -432,9 +440,10 @@ def get(self, name): access_handle = self.compiled_value.access_handle + safe = not self._inference_state.allow_unsafe_executions return self._get( name, - lambda name, safe: access_handle.is_allowed_getattr(name, safe=safe), + lambda name: access_handle.is_allowed_getattr(name, safe=safe), lambda name: name in access_handle.dir(), check_has_attribute=True ) @@ -443,30 +452,34 @@ """ To remove quite a few access calls we introduced the callback here. """ - if self._inference_state.allow_descriptor_getattr: - pass - - has_attribute, is_descriptor = allowed_getattr_callback( + has_attribute, is_descriptor, property_return_annotation = allowed_getattr_callback( name, - safe=not self._inference_state.allow_descriptor_getattr ) + if property_return_annotation is not None: + values = create_from_access_path( + self._inference_state, + property_return_annotation + ).execute_annotation() + if values: + return [CompiledValueName(v, name) for v in values] + if check_has_attribute and not has_attribute: return [] if (is_descriptor or not has_attribute) \ - and not self._inference_state.allow_descriptor_getattr: + and not self._inference_state.allow_unsafe_executions: return [self._get_cached_name(name, is_empty=True)] if self.is_instance and not in_dir_callback(name): return [] - return [self._get_cached_name(name)] + return [self._get_cached_name(name, is_descriptor=is_descriptor)] @memoize_method - def _get_cached_name(self, name, is_empty=False): + def _get_cached_name(self, name, is_empty=False, *, is_descriptor=False): if is_empty: return EmptyCompiledName(self._inference_state, name) else: - return self._create_name(name) + return self._create_name(name, is_descriptor=is_descriptor) def values(self): from jedi.inference.compiled import builtin_from_name @@ -480,7 +493,7 @@ for name in dir_infos: names += self._get( name, - lambda name, safe: dir_infos[name], + lambda name: dir_infos[name], lambda name: name in dir_infos, ) @@ -490,11 +503,12 @@ names += filter.values() return names - def _create_name(self, name): + def _create_name(self, name, is_descriptor): return CompiledName( self._inference_state, self.compiled_value, - name + name, + is_descriptor, ) def __repr__(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/inference/dynamic_params.py new/jedi-0.19.0/jedi/inference/dynamic_params.py --- old/jedi-0.18.2/jedi/inference/dynamic_params.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/inference/dynamic_params.py 2023-07-29 00:59:28.000000000 +0200 @@ -66,11 +66,11 @@ have to look for all calls to ``func`` to find out what ``foo`` possibly is. """ - funcdef = function_value.tree_node - - if not settings.dynamic_params: + if not function_value.inference_state.do_dynamic_params_search: return NO_VALUES + funcdef = function_value.tree_node + path = function_value.get_root_context().py__file__() if path is not None and is_stdlib_path(path): # We don't want to search for references in the stdlib. Usually people diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/inference/gradual/annotation.py new/jedi-0.19.0/jedi/inference/gradual/annotation.py --- old/jedi-0.18.2/jedi/inference/gradual/annotation.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/inference/gradual/annotation.py 2023-07-29 00:59:28.000000000 +0200 @@ -402,6 +402,10 @@ def find_type_from_comment_hint_with(context, node, name): + if len(node.children) > 4: + # In case there are multiple with_items, we do not want a type hint for + # now. + return [] assert len(node.children[1].children) == 3, \ "Can only be here when children[1] is 'foo() as f'" varlist = node.children[1].children[2] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/inference/gradual/typing.py new/jedi-0.19.0/jedi/inference/gradual/typing.py --- old/jedi-0.18.2/jedi/inference/gradual/typing.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/inference/gradual/typing.py 2023-07-29 00:59:28.000000000 +0200 @@ -32,7 +32,7 @@ 'DefaultDict': 'collections.defaultdict', 'Deque': 'collections.deque', } -_PROXY_TYPES = 'Optional Union ClassVar'.split() +_PROXY_TYPES = 'Optional Union ClassVar Annotated'.split() class TypingModuleName(NameWrapper): @@ -113,7 +113,7 @@ elif string_name == 'Type': # The type is actually already given in the index_value return self._generics_manager[0] - elif string_name == 'ClassVar': + elif string_name in ['ClassVar', 'Annotated']: # For now don't do anything here, ClassVars are always used. return self._generics_manager[0].execute_annotation() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/inference/syntax_tree.py new/jedi-0.19.0/jedi/inference/syntax_tree.py --- old/jedi-0.18.2/jedi/inference/syntax_tree.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/inference/syntax_tree.py 2023-07-29 00:59:28.000000000 +0200 @@ -329,8 +329,8 @@ c = atom.children # Parentheses without commas are not tuples. if c[0] == '(' and not len(c) == 2 \ - and not(c[1].type == 'testlist_comp' - and len(c[1].children) > 1): + and not (c[1].type == 'testlist_comp' + and len(c[1].children) > 1): return context.infer_node(c[1]) try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/plugins/pytest.py new/jedi-0.19.0/jedi/plugins/pytest.py --- old/jedi-0.18.2/jedi/plugins/pytest.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/plugins/pytest.py 2023-07-29 00:59:28.000000000 +0200 @@ -1,3 +1,5 @@ +import sys +from typing import List from pathlib import Path from parso.tree import search_ancestor @@ -131,15 +133,34 @@ or any('fixture' in n.get_code() for n in decorator_nodes) -def _find_pytest_plugin_modules(): +def _find_pytest_plugin_modules() -> List[List[str]]: """ Finds pytest plugin modules hooked by setuptools entry points See https://docs.pytest.org/en/stable/how-to/writing_plugins.html#setuptools-entry-points """ - from pkg_resources import iter_entry_points + if sys.version_info >= (3, 8): + from importlib.metadata import entry_points - return [ep.module_name.split(".") for ep in iter_entry_points(group="pytest11")] + if sys.version_info >= (3, 10): + pytest_entry_points = entry_points(group="pytest11") + else: + pytest_entry_points = entry_points().get("pytest11", ()) + + if sys.version_info >= (3, 9): + return [ep.module.split(".") for ep in pytest_entry_points] + else: + # Python 3.8 doesn't have `EntryPoint.module`. Implement equivalent + # to what Python 3.9 does (with additional None check to placate `mypy`) + matches = [ + ep.pattern.match(ep.value) + for ep in pytest_entry_points + ] + return [x.group('module').split(".") for x in matches if x] + + else: + from pkg_resources import iter_entry_points + return [ep.module_name.split(".") for ep in iter_entry_points(group="pytest11")] @inference_state_method_cache() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/plugins/stdlib.py new/jedi-0.19.0/jedi/plugins/stdlib.py --- old/jedi-0.18.2/jedi/plugins/stdlib.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/plugins/stdlib.py 2023-07-29 00:59:28.000000000 +0200 @@ -808,9 +808,11 @@ # https://www.attrs.org/en/stable/names.html 'attr': { 'define': _dataclass, + 'frozen': _dataclass, }, 'attrs': { 'define': _dataclass, + 'frozen': _dataclass, }, 'os.path': { 'dirname': _create_string_input_function(os.path.dirname), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/settings.py new/jedi-0.19.0/jedi/settings.py --- old/jedi-0.18.2/jedi/settings.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/settings.py 2023-07-29 00:59:28.000000000 +0200 @@ -143,6 +143,15 @@ ``globals()`` modifications a lot. """ +allow_unsafe_interpreter_executions = True +""" +Controls whether descriptors are evaluated when using an Interpreter. This is +something you might want to control when using Jedi from a Repl (e.g. IPython) + +Generally this setting allows Jedi to execute __getitem__ and descriptors like +`property`. +""" + # ---------------- # Caching Validity # ---------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi/utils.py new/jedi-0.19.0/jedi/utils.py --- old/jedi-0.18.2/jedi/utils.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/jedi/utils.py 2023-07-29 00:59:28.000000000 +0200 @@ -2,7 +2,7 @@ Utilities for end-users. """ -import __main__ # type: ignore[import] +import __main__ from collections import namedtuple import logging import traceback diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi.egg-info/PKG-INFO new/jedi-0.19.0/jedi.egg-info/PKG-INFO --- old/jedi-0.18.2/jedi.egg-info/PKG-INFO 2022-11-21 23:29:14.000000000 +0100 +++ new/jedi-0.19.0/jedi.egg-info/PKG-INFO 2023-07-29 01:05:44.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: jedi -Version: 0.18.2 +Version: 0.19.0 Summary: An autocompletion tool for Python that can be used for text editors. Home-page: https://github.com/davidhalter/jedi Author: David Halter @@ -52,7 +52,7 @@ - `GNOME Builder`_ (with support for GObject Introspection) - Gedit (gedi_) - wdb_ - Web Debugger - - `Eric IDE`_ (Available as a plugin) + - `Eric IDE`_ - `IPython 6.0.0+ <https://ipython.readthedocs.io/en/stable/whatsnew/version6.html>`_ - `xonsh shell <https://xon.sh/contents.html>`_ has `jedi extension <https://xon.sh/xontribs.html#jedi>`_ @@ -61,7 +61,8 @@ There are a few language servers that use Jedi: - `jedi-language-server <https://github.com/pappasam/jedi-language-server>`_ - - `python-language-server <https://github.com/palantir/python-language-server>`_ + - `python-language-server <https://github.com/palantir/python-language-server>`_ (currently unmaintained) + - `python-lsp-server <https://github.com/python-lsp/python-lsp-server>`_ (fork from python-language-server) - `anakin-language-server <https://github.com/muffinmad/anakin-language-server>`_ Here are some pictures taken from jedi-vim_: @@ -234,6 +235,15 @@ Unreleased ++++++++++ + 0.19.0 (2023-07-29) + +++++++++++++++++++ + + - Python 3.11 support + - Massive improvements in performance for ``Interpreter`` (e.g. IPython) users. + This especially affects ``pandas`` users with large datasets. + - Add ``jedi.settings.allow_unsafe_interpreter_executions`` to make it easier + for IPython users to avoid unsafe executions. + 0.18.2 (2022-11-21) +++++++++++++++++++ @@ -554,6 +564,7 @@ Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: Text Editors :: Integrated Development Environments (IDE) Classifier: Topic :: Utilities diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi.egg-info/SOURCES.txt new/jedi-0.19.0/jedi.egg-info/SOURCES.txt --- old/jedi-0.18.2/jedi.egg-info/SOURCES.txt 2022-11-21 23:29:14.000000000 +0100 +++ new/jedi-0.19.0/jedi.egg-info/SOURCES.txt 2023-07-29 01:05:44.000000000 +0200 @@ -1964,6 +1964,7 @@ test/completion/pep0484_overload.py test/completion/pep0484_typing.py test/completion/pep0526_variables.py +test/completion/pep0593_annotations.py test/completion/pep0604.py test/completion/positional_only_params.py test/completion/precedence.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/jedi.egg-info/requires.txt new/jedi-0.19.0/jedi.egg-info/requires.txt --- old/jedi-0.18.2/jedi.egg-info/requires.txt 2022-11-21 23:29:14.000000000 +0100 +++ new/jedi-0.19.0/jedi.egg-info/requires.txt 2023-07-29 01:05:44.000000000 +0200 @@ -1,4 +1,4 @@ -parso<0.9.0,>=0.8.0 +parso<0.9.0,>=0.8.3 [docs] Jinja2==2.11.3 @@ -28,8 +28,9 @@ urllib3==1.26.4 [qa] -flake8==3.8.3 -mypy==0.782 +flake8==5.0.4 +mypy==0.971 +types-setuptools==67.2.0.1 [testing] Django<3.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/setup.cfg new/jedi-0.19.0/setup.cfg --- old/jedi-0.18.2/setup.cfg 2022-11-21 23:29:14.449261000 +0100 +++ new/jedi-0.19.0/setup.cfg 2023-07-29 01:05:44.501212400 +0200 @@ -19,6 +19,9 @@ max-line-length = 100 [mypy] +exclude = ^jedi/third_party +show_error_codes = true +enable_error_code = ignore-without-code disallow_any_generics = True disallow_subclassing_any = True warn_redundant_casts = True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/setup.py new/jedi-0.19.0/setup.py --- old/jedi-0.18.2/setup.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/setup.py 2023-07-29 00:59:28.000000000 +0200 @@ -32,7 +32,8 @@ long_description=readme, packages=find_packages(exclude=['test', 'test.*']), python_requires='>=3.6', - install_requires=['parso>=0.8.0,<0.9.0'], + # Python 3.11 grammar is added to parso in 0.8.3 + install_requires=['parso>=0.8.3,<0.9.0'], extras_require={ 'testing': [ 'pytest<7.0.0', @@ -44,8 +45,12 @@ 'attrs', ], 'qa': [ - 'flake8==3.8.3', - 'mypy==0.782', + # latest version supporting Python 3.6 + 'flake8==5.0.4', + # latest version supporting Python 3.6 + 'mypy==0.971', + # Arbitrary pins, latest at the time of pinning + 'types-setuptools==67.2.0.1', ], 'docs': [ # Just pin all of these. @@ -91,6 +96,7 @@ 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', 'Topic :: Software Development :: Libraries :: Python Modules', 'Topic :: Text Editors :: Integrated Development Environments (IDE)', 'Topic :: Utilities', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/test/completion/basic.py new/jedi-0.19.0/test/completion/basic.py --- old/jedi-0.18.2/test/completion/basic.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/test/completion/basic.py 2023-07-29 00:59:28.000000000 +0200 @@ -413,6 +413,10 @@ with Foo() as f3: f3 +with open("a"), open("b") as bfile: + #? ['flush'] + bfile.flush + # ----------------- # Avoiding multiple definitions # ----------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/test/completion/on_import.py new/jedi-0.19.0/test/completion/on_import.py --- old/jedi-0.18.2/test/completion/on_import.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/test/completion/on_import.py 2023-07-29 00:59:28.000000000 +0200 @@ -76,7 +76,7 @@ #? 22 ['mod1', 'base'] from import_tree.pkg. import mod1 #? 17 ['mod1', 'mod2', 'random', 'pkg', 'references', 'rename1', 'rename2', 'classes', 'globals', 'recurse_class1', 'recurse_class2', 'invisible_pkg', 'flow_import'] -from import_tree. import pkg +from import_tree. import new_pkg #? 18 ['pkg'] from import_tree.p import pkg diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/test/completion/pep0593_annotations.py new/jedi-0.19.0/test/completion/pep0593_annotations.py --- old/jedi-0.18.2/test/completion/pep0593_annotations.py 1970-01-01 01:00:00.000000000 +0100 +++ new/jedi-0.19.0/test/completion/pep0593_annotations.py 2023-07-29 00:59:28.000000000 +0200 @@ -0,0 +1,26 @@ +# python >= 3.9 + +from typing import Annotated + +# This is just a dummy and very meaningless thing to use with to the Annotated +# type hint +class Foo: + pass + +class A: + pass + + +def annotated_function_params( + basic: Annotated[str, Foo()], + obj: A, + annotated_obj: Annotated[A, Foo()], +): + #? str() + basic + + #? A() + obj + + #? A() + annotated_obj diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/test/test_api/test_documentation.py new/jedi-0.19.0/test/test_api/test_documentation.py --- old/jedi-0.18.2/test/test_api/test_documentation.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/test/test_api/test_documentation.py 2023-07-29 00:59:28.000000000 +0200 @@ -28,6 +28,11 @@ # unrelated to #44 +def test_import_keyword_after_newline(Script): + d, = Script("import x\nimport y").help(line=2, column=0) + assert d.docstring().startswith('The "import" statement') + + def test_import_keyword_with_gotos(goto_or_infer): assert not goto_or_infer("import x", column=0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/test/test_api/test_interpreter.py new/jedi-0.19.0/test/test_api/test_interpreter.py --- old/jedi-0.18.2/test/test_api/test_interpreter.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/test/test_api/test_interpreter.py 2023-07-29 00:59:28.000000000 +0200 @@ -8,6 +8,7 @@ import pytest import jedi +import jedi.settings from jedi.inference.compiled import mixed from importlib import import_module @@ -101,11 +102,13 @@ assert foo.name == 'foo' -def _assert_interpreter_complete(source, namespace, completions, - **kwds): +def _assert_interpreter_complete(source, namespace, completions, *, check_type=False, **kwds): script = jedi.Interpreter(source, [namespace], **kwds) cs = script.complete() actual = [c.name for c in cs] + if check_type: + for c in cs: + c.type assert sorted(actual) == sorted(completions) @@ -219,7 +222,7 @@ @pytest.fixture(params=[False, True]) def allow_unsafe_getattr(request, monkeypatch): - monkeypatch.setattr(jedi.Interpreter, '_allow_descriptor_getattr_default', request.param) + monkeypatch.setattr(jedi.settings, 'allow_unsafe_interpreter_executions', request.param) return request.param @@ -610,12 +613,12 @@ #('for x in dunder: x', 'str'), ] ) -def test_dunders(class_is_findable, code, expected): +def test_dunders(class_is_findable, code, expected, allow_unsafe_getattr): from typing import Iterator class DunderCls: def __getitem__(self, key) -> int: - pass + return 1 def __iter__(self, key) -> Iterator[str]: pass @@ -656,10 +659,12 @@ ({'return': 'typing.Union[str, int]'}, ['int', 'str'], ''), ({'return': 'typing.Union["str", int]'}, ['int', 'str'] if sys.version_info >= (3, 9) else ['int'], ''), - ({'return': 'typing.Union["str", 1]'}, [], ''), + ({'return': 'typing.Union["str", 1]'}, + ['str'] if sys.version_info >= (3, 11) else [], ''), ({'return': 'typing.Optional[str]'}, ['NoneType', 'str'], ''), ({'return': 'typing.Optional[str, int]'}, [], ''), # Takes only one arg - ({'return': 'typing.Any'}, [], ''), + ({'return': 'typing.Any'}, + ['_AnyMeta'] if sys.version_info >= (3, 11) else [], ''), ({'return': 'typing.Tuple[int, str]'}, ['Tuple' if sys.version_info[:2] == (3, 6) else 'tuple'], ''), @@ -754,3 +759,99 @@ import random completions = jedi.Interpreter(code, [locals()]).complete() assert expected == [c.name for c in completions if c.name.endswith('=')] + + +@pytest.mark.parametrize('class_is_findable', [False, True]) +def test_avoid_descriptor_executions_if_not_necessary(class_is_findable): + counter = 0 + + class AvoidDescriptor(object): + @property + def prop(self): + nonlocal counter + counter += 1 + return self + + if not class_is_findable: + AvoidDescriptor.__name__ = "something_somewhere" + namespace = {'b': AvoidDescriptor()} + expected = ['prop'] + _assert_interpreter_complete('b.pro', namespace, expected, check_type=True) + assert counter == 0 + _assert_interpreter_complete('b.prop.pro', namespace, expected, check_type=True) + assert counter == 1 + + +class Hello: + its_me = 1 + + +@pytest.mark.parametrize('class_is_findable', [False, True]) +def test_try_to_use_return_annotation_for_property(class_is_findable): + class WithProperties(object): + @property + def with_annotation1(self) -> str: + raise BaseException + + @property + def with_annotation2(self) -> 'str': + raise BaseException + + @property + def with_annotation3(self) -> Hello: + raise BaseException + + @property + def with_annotation4(self) -> 'Hello': + raise BaseException + + @property + def with_annotation_garbage1(self) -> 'asldjflksjdfljdslkjfsl': # noqa + return Hello() + + @property + def with_annotation_garbage2(self) -> 'sdf$@@$5*+8': # noqa + return Hello() + + @property + def without_annotation(self): + return "" + + if not class_is_findable: + WithProperties.__name__ = "something_somewhere" + Hello.__name__ = "something_somewhere_else" + + namespace = {'p': WithProperties()} + _assert_interpreter_complete('p.without_annotation.upp', namespace, ['upper']) + _assert_interpreter_complete('p.with_annotation1.upp', namespace, ['upper']) + _assert_interpreter_complete('p.with_annotation2.upp', namespace, ['upper']) + _assert_interpreter_complete('p.with_annotation3.its', namespace, ['its_me']) + _assert_interpreter_complete('p.with_annotation4.its', namespace, ['its_me']) + # This is a fallback, if the annotations don't help + _assert_interpreter_complete('p.with_annotation_garbage1.its', namespace, ['its_me']) + _assert_interpreter_complete('p.with_annotation_garbage2.its', namespace, ['its_me']) + + +def test_nested__getitem__(): + d = {'foo': {'bar': 1}} + _assert_interpreter_complete('d["fo', locals(), ['"foo"']) + _assert_interpreter_complete('d["foo"]["ba', locals(), ['"bar"']) + _assert_interpreter_complete('(d["foo"])["ba', locals(), ['"bar"']) + _assert_interpreter_complete('((d["foo"]))["ba', locals(), ['"bar"']) + + +@pytest.mark.parametrize('class_is_findable', [False, True]) +def test_custom__getitem__(class_is_findable, allow_unsafe_getattr): + class CustomGetItem: + def __getitem__(self, x: int): + return "asdf" + + if not class_is_findable: + CustomGetItem.__name__ = "something_somewhere" + + namespace = {'c': CustomGetItem()} + if not class_is_findable and not allow_unsafe_getattr: + expected = [] + else: + expected = ['upper'] + _assert_interpreter_complete('c["a"].up', namespace, expected) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/test/test_api/test_refactoring.py new/jedi-0.19.0/test/test_api/test_refactoring.py --- old/jedi-0.18.2/test/test_api/test_refactoring.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/test/test_api/test_refactoring.py 2023-07-29 00:59:28.000000000 +0200 @@ -1,4 +1,5 @@ import os +import shutil from textwrap import dedent from pathlib import Path import platform @@ -6,6 +7,7 @@ import pytest import jedi +from test.helpers import get_example_dir @pytest.fixture() @@ -52,6 +54,47 @@ ''').format(dir=dir_with_content) +@pytest.mark.skipif('sys.version_info[:2] < (3, 8)', message="Python 3.8 introduces dirs_exist_ok") +def test_namespace_package(Script, tmpdir): + origin = get_example_dir('implicit_namespace_package') + shutil.copytree(origin, tmpdir.strpath, dirs_exist_ok=True) + sys_path = [ + os.path.join(tmpdir.strpath, 'ns1'), + os.path.join(tmpdir.strpath, 'ns2') + ] + script_path = os.path.join(tmpdir.strpath, 'script.py') + script = Script( + 'import pkg\n', + path=script_path, + project=jedi.Project(os.path.join(tmpdir.strpath, 'does-not-exist'), sys_path=sys_path), + ) + refactoring = script.rename(line=1, new_name='new_pkg') + refactoring.apply() + old1 = os.path.join(sys_path[0], "pkg") + new1 = os.path.join(sys_path[0], "new_pkg") + old2 = os.path.join(sys_path[1], "pkg") + new2 = os.path.join(sys_path[1], "new_pkg") + assert not os.path.exists(old1) + assert os.path.exists(new1) + assert not os.path.exists(old2) + assert os.path.exists(new2) + + changed, = iter(refactoring.get_changed_files().values()) + assert changed.get_new_code() == "import new_pkg\n" + + assert refactoring.get_diff() == dedent(f'''\ + rename from {old1} + rename to {new1} + rename from {old2} + rename to {new2} + --- {script_path} + +++ {script_path} + @@ -1,2 +1,2 @@ + -import pkg + +import new_pkg + ''').format(dir=dir_with_content) + + def test_rename_none_path(Script): refactoring = Script('foo', path=None).rename(new_name='bar') with pytest.raises(jedi.RefactoringError, match='on a Script with path=None'): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/test/test_inference/test_signature.py new/jedi-0.19.0/test/test_inference/test_signature.py --- old/jedi-0.18.2/test/test_inference/test_signature.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/test/test_inference/test_signature.py 2023-07-29 00:59:28.000000000 +0200 @@ -355,6 +355,7 @@ price, = sig.params[-2].infer() assert price.name == 'float' + @pytest.mark.parametrize( 'start, start_params', [ ['@define\nclass X:', []], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/test/test_inference/test_sys_path.py new/jedi-0.19.0/test/test_inference/test_sys_path.py --- old/jedi-0.18.2/test/test_inference/test_sys_path.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/test/test_inference/test_sys_path.py 2023-07-29 00:59:28.000000000 +0200 @@ -30,14 +30,16 @@ assert paths('sys.path, other = ["a"], 2') == set() -def test_venv_and_pths(venv_path): +def test_venv_and_pths(venv_path, environment): pjoin = os.path.join - site_pkg_path = pjoin(venv_path, 'lib') if os.name == 'nt': - site_pkg_path = pjoin(site_pkg_path, 'site-packages') + if environment.version_info < (3, 11): + site_pkg_path = pjoin(venv_path, 'lib', 'site-packages') + else: + site_pkg_path = pjoin(venv_path, 'Lib', 'site-packages') else: - site_pkg_path = glob(pjoin(site_pkg_path, 'python*', 'site-packages'))[0] + site_pkg_path = glob(pjoin(venv_path, 'lib', 'python*', 'site-packages'))[0] shutil.rmtree(site_pkg_path) shutil.copytree(get_example_dir('sample_venvs', 'pth_directory'), site_pkg_path) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jedi-0.18.2/test/test_integration.py new/jedi-0.19.0/test/test_integration.py --- old/jedi-0.18.2/test/test_integration.py 2022-11-21 23:28:00.000000000 +0100 +++ new/jedi-0.19.0/test/test_integration.py 2023-07-29 00:59:28.000000000 +0200 @@ -1,4 +1,5 @@ import os +import sys from collections import namedtuple import pytest @@ -50,14 +51,32 @@ pytest_plugin_dir = str(helpers.get_example_dir("pytest_plugin_package")) case._project.added_sys_path = [pytest_plugin_dir] - # ... and mock setuptools entry points to include it + # ... and mock the entry points to include it # see https://docs.pytest.org/en/stable/how-to/writing_plugins.html#setuptools-entry-points - def mock_iter_entry_points(group): - assert group == "pytest11" - EntryPoint = namedtuple("EntryPoint", ["module_name"]) - return [EntryPoint("pytest_plugin.plugin")] + if sys.version_info >= (3, 8): + def mock_entry_points(*, group=None): + import importlib.metadata + entries = [importlib.metadata.EntryPoint( + name=None, + value="pytest_plugin.plugin", + group="pytest11", + )] + + if sys.version_info >= (3, 10): + assert group == "pytest11" + return entries + else: + assert group is None + return {"pytest11": entries} + + monkeypatch.setattr("importlib.metadata.entry_points", mock_entry_points) + else: + def mock_iter_entry_points(group): + assert group == "pytest11" + EntryPoint = namedtuple("EntryPoint", ["module_name"]) + return [EntryPoint("pytest_plugin.plugin")] - monkeypatch.setattr("pkg_resources.iter_entry_points", mock_iter_entry_points) + monkeypatch.setattr("pkg_resources.iter_entry_points", mock_iter_entry_points) repo_root = helpers.root_dir monkeypatch.chdir(os.path.join(repo_root, 'jedi'))