Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-python-lsp-server for openSUSE:Factory checked in at 2023-04-28 16:23:25 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-python-lsp-server (Old) and /work/SRC/openSUSE:Factory/.python-python-lsp-server.new.1533 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-python-lsp-server" Fri Apr 28 16:23:25 2023 rev:21 rq:1083326 version:1.7.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-python-lsp-server/python-python-lsp-server.changes 2023-01-26 14:09:01.315801622 +0100 +++ /work/SRC/openSUSE:Factory/.python-python-lsp-server.new.1533/python-python-lsp-server.changes 2023-04-28 16:24:21.370356185 +0200 @@ -1,0 +2,11 @@ +Thu Apr 27 15:15:13 UTC 2023 - Ben Greiner <c...@bnavigator.de> + +- Update to 1.7.2 + * Initializes LSP progress token before using it and remove + progress for sync plugins. + * Adds support for pydocstyle 6.3 + * Adds support for autopep8 2 +- Drop pylsp-pr340-pydocstyle-6.3.patch +- Drop pylsp-pr345-autopep8-2.patch + +------------------------------------------------------------------- Old: ---- pylsp-pr340-pydocstyle-6.3.patch pylsp-pr345-autopep8-2.patch python-lsp-server-1.7.1.tar.gz New: ---- python-lsp-server-1.7.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-python-lsp-server.spec ++++++ --- /var/tmp/diff_new_pack.lAjYwY/_old 2023-04-28 16:24:21.842358939 +0200 +++ /var/tmp/diff_new_pack.lAjYwY/_new 2023-04-28 16:24:21.850358986 +0200 @@ -17,16 +17,12 @@ Name: python-python-lsp-server -Version: 1.7.1 +Version: 1.7.2 Release: 0 Summary: Python Language Server for the Language Server Protocol License: MIT URL: https://github.com/python-lsp/python-lsp-server Source: https://files.pythonhosted.org/packages/source/p/python-lsp-server/python-lsp-server-%{version}.tar.gz -# PATCH-FIX-UPSTREAM pylsp-pr340-pydocstyle-6.3.patch gh#python-lsp/python-lsp-server#340 -Patch1: pylsp-pr340-pydocstyle-6.3.patch -# PATCH-FIX-UPSTREAM pylsp-pr345-autopep8-2.patch.patch gh#python-lsp/python-lsp-server#345 -Patch2: pylsp-pr345-autopep8-2.patch BuildRequires: %{python_module base >= 3.7} BuildRequires: %{python_module pip} BuildRequires: %{python_module setuptools >= 61.2} @@ -53,7 +49,7 @@ BuildRequires: %{python_module toml if %python-yapf <= 0.32.0 else %python-tomli} BuildRequires: %{python_module ujson >= 3.0.0} BuildRequires: %{python_module whatthepatch >= 1.0.2 with %python-whatthepatch < 2} -BuildRequires: %{python_module yapf} +BuildRequires: %{python_module yapf < 0.32.1} # /SECTION BuildRequires: fdupes Requires: python-docstring-to-markdown @@ -70,6 +66,8 @@ Conflicts: python-pylint >= 3 Suggests: python-rope >= 1.2.0 Suggests: python-yapf +Conflicts: python-yapf >= 0.32.1 +Suggests: python-toml Suggests: python-whatthepatch >= 1.0.2 Conflicts: python-whatthepatch >= 2 # SECTION flake8 pins ++++++ python-lsp-server-1.7.1.tar.gz -> python-lsp-server-1.7.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/CHANGELOG.md new/python-lsp-server-1.7.2/CHANGELOG.md --- old/python-lsp-server-1.7.1/CHANGELOG.md 2023-01-18 00:22:26.000000000 +0100 +++ new/python-lsp-server-1.7.2/CHANGELOG.md 2023-04-03 03:18:18.000000000 +0200 @@ -1,5 +1,25 @@ # History of changes +## Version 1.7.2 (2023/04/02) + +### Issues Closed + +* [Issue 325](https://github.com/python-lsp/python-lsp-server/issues/325) - WorkDoneProgress tokens not initialized properly by the server ([PR 328](https://github.com/python-lsp/python-lsp-server/pull/328) by [@syphar](https://github.com/syphar)) +* [Issue 260](https://github.com/python-lsp/python-lsp-server/issues/260) - yapf formatting fails when pyproject.toml is in the workspace ([PR 346](https://github.com/python-lsp/python-lsp-server/pull/346) by [@bnavigator](https://github.com/bnavigator)) + +In this release 2 issues were closed. + +### Pull Requests Merged + +* [PR 346](https://github.com/python-lsp/python-lsp-server/pull/346) - Add toml dependency for yapf and constrain yapf to be less than 0.32, by [@bnavigator](https://github.com/bnavigator) ([260](https://github.com/python-lsp/python-lsp-server/issues/260)) +* [PR 345](https://github.com/python-lsp/python-lsp-server/pull/345) - Raise upper bound of autopep8, by [@bnavigator](https://github.com/bnavigator) +* [PR 340](https://github.com/python-lsp/python-lsp-server/pull/340) - Bump pydocstyle to 6.3, by [@bnavigator](https://github.com/bnavigator) +* [PR 328](https://github.com/python-lsp/python-lsp-server/pull/328) - Initialize LSP progress token before using it and remove progress for sync plugins, by [@syphar](https://github.com/syphar) ([325](https://github.com/python-lsp/python-lsp-server/issues/325)) + +In this release 4 pull requests were closed. + +---- + ## Version 1.7.1 (2023/01/17) ### Issues Closed diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/PKG-INFO new/python-lsp-server-1.7.2/PKG-INFO --- old/python-lsp-server-1.7.1/PKG-INFO 2023-01-18 00:25:16.623891800 +0100 +++ new/python-lsp-server-1.7.2/PKG-INFO 2023-04-03 03:21:16.750254000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: python-lsp-server -Version: 1.7.1 +Version: 1.7.2 Summary: Python Language Server for the Language Server Protocol Author: Python Language Server Contributors License: MIT diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/pylsp/_utils.py new/python-lsp-server-1.7.2/pylsp/_utils.py --- old/python-lsp-server-1.7.1/pylsp/_utils.py 2022-12-11 18:32:03.000000000 +0100 +++ new/python-lsp-server-1.7.2/pylsp/_utils.py 2023-04-03 03:06:12.000000000 +0200 @@ -293,8 +293,7 @@ os.kill(pid, 0) except OSError as e: return e.errno == errno.EPERM - else: - return True + return True def get_eol_chars(text): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/pylsp/_version.py new/python-lsp-server-1.7.2/pylsp/_version.py --- old/python-lsp-server-1.7.1/pylsp/_version.py 2023-01-18 00:25:16.000000000 +0100 +++ new/python-lsp-server-1.7.2/pylsp/_version.py 2023-04-03 03:21:16.000000000 +0200 @@ -1 +1 @@ -__version__ = "1.7.1" +__version__ = "1.7.2" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/pylsp/plugins/autopep8_format.py new/python-lsp-server-1.7.2/pylsp/plugins/autopep8_format.py --- old/python-lsp-server-1.7.1/pylsp/plugins/autopep8_format.py 2022-12-11 18:32:03.000000000 +0100 +++ new/python-lsp-server-1.7.2/pylsp/plugins/autopep8_format.py 2023-04-03 03:06:12.000000000 +0200 @@ -23,17 +23,16 @@ def pylsp_format_range( config, workspace, document, range, options ): # pylint: disable=redefined-builtin,unused-argument - with workspace.report_progress("format_range: autopep8"): - log.info("Formatting document %s in range %s with autopep8", document, range) + log.info("Formatting document %s in range %s with autopep8", document, range) - # First we 'round' the range up/down to full lines only - range['start']['character'] = 0 - range['end']['line'] += 1 - range['end']['character'] = 0 + # First we 'round' the range up/down to full lines only + range['start']['character'] = 0 + range['end']['line'] += 1 + range['end']['character'] = 0 - # Add 1 for 1-indexing vs LSP's 0-indexing - line_range = (range['start']['line'] + 1, range['end']['line'] + 1) - return _format(config, document, line_range=line_range) + # Add 1 for 1-indexing vs LSP's 0-indexing + line_range = (range['start']['line'] + 1, range['end']['line'] + 1) + return _format(config, document, line_range=line_range) def _format(config, document, line_range=None): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/pylsp/plugins/definition.py new/python-lsp-server-1.7.2/pylsp/plugins/definition.py --- old/python-lsp-server-1.7.1/pylsp/plugins/definition.py 2022-12-29 16:51:51.000000000 +0100 +++ new/python-lsp-server-1.7.2/pylsp/plugins/definition.py 2023-04-03 03:06:12.000000000 +0200 @@ -8,26 +8,25 @@ @hookimpl -def pylsp_definitions(config, workspace, document, position): - with workspace.report_progress("go to definitions"): - settings = config.plugin_settings('jedi_definition') - code_position = _utils.position_to_jedi_linecolumn(document, position) - definitions = document.jedi_script(use_document_path=True).goto( - follow_imports=settings.get('follow_imports', True), - follow_builtin_imports=settings.get('follow_builtin_imports', True), - **code_position) +def pylsp_definitions(config, document, position): + settings = config.plugin_settings('jedi_definition') + code_position = _utils.position_to_jedi_linecolumn(document, position) + definitions = document.jedi_script(use_document_path=True).goto( + follow_imports=settings.get('follow_imports', True), + follow_builtin_imports=settings.get('follow_builtin_imports', True), + **code_position) - follow_builtin_defns = settings.get("follow_builtin_definitions", True) - return [ - { - 'uri': uris.uri_with(document.uri, path=str(d.module_path)), - 'range': { - 'start': {'line': d.line - 1, 'character': d.column}, - 'end': {'line': d.line - 1, 'character': d.column + len(d.name)}, - } + follow_builtin_defns = settings.get("follow_builtin_definitions", True) + return [ + { + 'uri': uris.uri_with(document.uri, path=str(d.module_path)), + 'range': { + 'start': {'line': d.line - 1, 'character': d.column}, + 'end': {'line': d.line - 1, 'character': d.column + len(d.name)}, } - for d in definitions if d.is_definition() and (follow_builtin_defns or _not_internal_definition(d)) - ] + } + for d in definitions if d.is_definition() and (follow_builtin_defns or _not_internal_definition(d)) + ] def _not_internal_definition(definition): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/pylsp/plugins/jedi_rename.py new/python-lsp-server-1.7.2/pylsp/plugins/jedi_rename.py --- old/python-lsp-server-1.7.1/pylsp/plugins/jedi_rename.py 2022-12-11 18:32:03.000000000 +0100 +++ new/python-lsp-server-1.7.2/pylsp/plugins/jedi_rename.py 2023-04-03 03:06:12.000000000 +0200 @@ -9,44 +9,42 @@ @hookimpl -def pylsp_rename(config, workspace, document, position, new_name): # pylint: disable=unused-argument,too-many-locals - with workspace.report_progress("rename", percentage=0) as report_progress: - log.debug('Executing rename of %s to %s', document.word_at_position(position), new_name) - kwargs = _utils.position_to_jedi_linecolumn(document, position) - kwargs['new_name'] = new_name - report_progress("refactoring") - try: - refactoring = document.jedi_script().rename(**kwargs) - except NotImplementedError as exc: - raise Exception('No support for renaming in Python 2/3.5 with Jedi. ' - 'Consider using the rope_rename plugin instead') from exc - log.debug('Finished rename: %s', refactoring.get_diff()) - changes = [] +def pylsp_rename(config, workspace, document, position, new_name): # pylint: disable=unused-argument + log.debug('Executing rename of %s to %s', document.word_at_position(position), new_name) + kwargs = _utils.position_to_jedi_linecolumn(document, position) + kwargs['new_name'] = new_name + try: + refactoring = document.jedi_script().rename(**kwargs) + except NotImplementedError as exc: + # pylint: disable=broad-exception-raised + raise Exception('No support for renaming in Python 2/3.5 with Jedi. ' + 'Consider using the rope_rename plugin instead') from exc + log.debug('Finished rename: %s', refactoring.get_diff()) + changes = [] - changed_files = refactoring.get_changed_files() - for n, (file_path, changed_file) in enumerate(changed_files.items()): - report_progress(changed_file, percentage=n/len(changed_files)*100) - uri = uris.from_fs_path(str(file_path)) - doc = workspace.get_maybe_document(uri) - changes.append({ - 'textDocument': { - 'uri': uri, - 'version': doc.version if doc else None - }, - 'edits': [ - { - 'range': { - 'start': {'line': 0, 'character': 0}, - 'end': { - 'line': _num_lines(changed_file.get_new_code()), - 'character': 0, - }, + changed_files = refactoring.get_changed_files() + for file_path, changed_file in changed_files.items(): + uri = uris.from_fs_path(str(file_path)) + doc = workspace.get_maybe_document(uri) + changes.append({ + 'textDocument': { + 'uri': uri, + 'version': doc.version if doc else None + }, + 'edits': [ + { + 'range': { + 'start': {'line': 0, 'character': 0}, + 'end': { + 'line': _num_lines(changed_file.get_new_code()), + 'character': 0, }, - 'newText': changed_file.get_new_code(), - } - ], - }) - return {'documentChanges': changes} + }, + 'newText': changed_file.get_new_code(), + } + ], + }) + return {'documentChanges': changes} def _num_lines(file_contents): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/pylsp/plugins/pydocstyle_lint.py new/python-lsp-server-1.7.2/pylsp/plugins/pydocstyle_lint.py --- old/python-lsp-server-1.7.1/pylsp/plugins/pydocstyle_lint.py 2023-01-05 01:05:39.000000000 +0100 +++ new/python-lsp-server-1.7.2/pylsp/plugins/pydocstyle_lint.py 2023-03-18 19:10:05.000000000 +0100 @@ -28,6 +28,7 @@ @hookimpl def pylsp_lint(config, workspace, document): + # pylint: disable=too-many-locals with workspace.report_progress("lint: pydocstyle"): settings = config.plugin_settings('pydocstyle', document_path=document.path) log.debug("Got pydocstyle settings: %s", settings) @@ -66,9 +67,19 @@ # Will only yield a single filename, the document path diags = [] - for filename, checked_codes, ignore_decorators, property_decorators in conf.get_files_to_check(): + for ( + filename, + checked_codes, + ignore_decorators, + property_decorators, + ignore_self_only_init, + ) in conf.get_files_to_check(): errors = pydocstyle.checker.ConventionChecker().check_source( - document.source, filename, ignore_decorators=ignore_decorators, property_decorators=property_decorators + document.source, + filename, + ignore_decorators=ignore_decorators, + property_decorators=property_decorators, + ignore_self_only_init=ignore_self_only_init, ) try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/pylsp/plugins/references.py new/python-lsp-server-1.7.2/pylsp/plugins/references.py --- old/python-lsp-server-1.7.1/pylsp/plugins/references.py 2022-12-11 18:32:03.000000000 +0100 +++ new/python-lsp-server-1.7.2/pylsp/plugins/references.py 2023-04-03 03:06:12.000000000 +0200 @@ -8,20 +8,19 @@ @hookimpl -def pylsp_references(document, workspace, position, exclude_declaration=False): - with workspace.report_progress("references"): - code_position = _utils.position_to_jedi_linecolumn(document, position) - usages = document.jedi_script().get_references(**code_position) +def pylsp_references(document, position, exclude_declaration=False): + code_position = _utils.position_to_jedi_linecolumn(document, position) + usages = document.jedi_script().get_references(**code_position) - if exclude_declaration: - # Filter out if the usage is the actual declaration of the thing - usages = [d for d in usages if not d.is_definition()] + if exclude_declaration: + # Filter out if the usage is the actual declaration of the thing + usages = [d for d in usages if not d.is_definition()] - # Filter out builtin modules - return [{ - 'uri': uris.uri_with(document.uri, path=str(d.module_path)) if d.module_path else document.uri, - 'range': { - 'start': {'line': d.line - 1, 'character': d.column}, - 'end': {'line': d.line - 1, 'character': d.column + len(d.name)} - } - } for d in usages if not d.in_builtin_module()] + # Filter out builtin modules + return [{ + 'uri': uris.uri_with(document.uri, path=str(d.module_path)) if d.module_path else document.uri, + 'range': { + 'start': {'line': d.line - 1, 'character': d.column}, + 'end': {'line': d.line - 1, 'character': d.column + len(d.name)} + } + } for d in usages if not d.in_builtin_module()] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/pylsp/plugins/rope_rename.py new/python-lsp-server-1.7.2/pylsp/plugins/rope_rename.py --- old/python-lsp-server-1.7.1/pylsp/plugins/rope_rename.py 2022-12-11 18:32:03.000000000 +0100 +++ new/python-lsp-server-1.7.2/pylsp/plugins/rope_rename.py 2023-04-03 03:06:12.000000000 +0200 @@ -19,42 +19,41 @@ @hookimpl def pylsp_rename(config, workspace, document, position, new_name): - with workspace.report_progress("rename"): - rope_config = config.settings(document_path=document.path).get('rope', {}) - rope_project = workspace._rope_project_builder(rope_config) + rope_config = config.settings(document_path=document.path).get('rope', {}) + rope_project = workspace._rope_project_builder(rope_config) - rename = Rename( - rope_project, - libutils.path_to_resource(rope_project, document.path), - document.offset_at_position(position) - ) + rename = Rename( + rope_project, + libutils.path_to_resource(rope_project, document.path), + document.offset_at_position(position) + ) - log.debug("Executing rename of %s to %s", document.word_at_position(position), new_name) - changeset = rename.get_changes(new_name, in_hierarchy=True, docs=True) - log.debug("Finished rename: %s", changeset.changes) - changes = [] - for change in changeset.changes: - uri = uris.from_fs_path(change.resource.path) - doc = workspace.get_maybe_document(uri) - changes.append({ - 'textDocument': { - 'uri': uri, - 'version': doc.version if doc else None - }, - 'edits': [ - { - 'range': { - 'start': {'line': 0, 'character': 0}, - 'end': { - 'line': _num_lines(change.resource), - 'character': 0, - }, + log.debug("Executing rename of %s to %s", document.word_at_position(position), new_name) + changeset = rename.get_changes(new_name, in_hierarchy=True, docs=True) + log.debug("Finished rename: %s", changeset.changes) + changes = [] + for change in changeset.changes: + uri = uris.from_fs_path(change.resource.path) + doc = workspace.get_maybe_document(uri) + changes.append({ + 'textDocument': { + 'uri': uri, + 'version': doc.version if doc else None + }, + 'edits': [ + { + 'range': { + 'start': {'line': 0, 'character': 0}, + 'end': { + 'line': _num_lines(change.resource), + 'character': 0, }, - 'newText': change.new_contents, - } - ] - }) - return {'documentChanges': changes} + }, + 'newText': change.new_contents, + } + ] + }) + return {'documentChanges': changes} def _num_lines(resource): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/pylsp/plugins/yapf_format.py new/python-lsp-server-1.7.2/pylsp/plugins/yapf_format.py --- old/python-lsp-server-1.7.1/pylsp/plugins/yapf_format.py 2022-12-12 00:33:58.000000000 +0100 +++ new/python-lsp-server-1.7.2/pylsp/plugins/yapf_format.py 2023-04-03 03:06:12.000000000 +0200 @@ -23,23 +23,22 @@ @hookimpl -def pylsp_format_range(workspace, document, range, options): # pylint: disable=redefined-builtin +def pylsp_format_range(document, range, options): # pylint: disable=redefined-builtin log.info("Formatting document %s in range %s with yapf", document, range) - with workspace.report_progress("format_range: yapf"): - # First we 'round' the range up/down to full lines only - range['start']['character'] = 0 - range['end']['line'] += 1 - range['end']['character'] = 0 - - # From Yapf docs: - # lines: (list of tuples of integers) A list of tuples of lines, [start, end], - # that we want to format. The lines are 1-based indexed. It can be used by - # third-party code (e.g., IDEs) when reformatting a snippet of code rather - # than a whole file. - - # Add 1 for 1-indexing vs LSP's 0-indexing - lines = [(range['start']['line'] + 1, range['end']['line'] + 1)] - return _format(document, lines=lines, options=options) + # First we 'round' the range up/down to full lines only + range['start']['character'] = 0 + range['end']['line'] += 1 + range['end']['character'] = 0 + + # From Yapf docs: + # lines: (list of tuples of integers) A list of tuples of lines, [start, end], + # that we want to format. The lines are 1-based indexed. It can be used by + # third-party code (e.g., IDEs) when reformatting a snippet of code rather + # than a whole file. + + # Add 1 for 1-indexing vs LSP's 0-indexing + lines = [(range['start']['line'] + 1, range['end']['line'] + 1)] + return _format(document, lines=lines, options=options) def get_style_config(document_path, options=None): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/pylsp/python_lsp.py new/python-lsp-server-1.7.2/pylsp/python_lsp.py --- old/python-lsp-server-1.7.1/pylsp/python_lsp.py 2022-12-11 18:32:03.000000000 +0100 +++ new/python-lsp-server-1.7.2/pylsp/python_lsp.py 2023-04-03 03:06:12.000000000 +0200 @@ -152,7 +152,7 @@ # pylint: disable=too-many-public-methods,redefined-builtin - def __init__(self, rx, tx, check_parent_process=False, consumer=None): + def __init__(self, rx, tx, check_parent_process=False, consumer=None, *, endpoint_cls=None): self.workspace = None self.config = None self.root_uri = None @@ -172,11 +172,13 @@ else: self._jsonrpc_stream_writer = None + endpoint_cls = endpoint_cls or Endpoint + # if consumer is None, it is assumed that the default streams-based approach is being used if consumer is None: - self._endpoint = Endpoint(self, self._jsonrpc_stream_writer.write, max_workers=MAX_WORKERS) + self._endpoint = endpoint_cls(self, self._jsonrpc_stream_writer.write, max_workers=MAX_WORKERS) else: - self._endpoint = Endpoint(self, consumer, max_workers=MAX_WORKERS) + self._endpoint = endpoint_cls(self, consumer, max_workers=MAX_WORKERS) self._dispatchers = [] self._shutdown = False @@ -358,7 +360,7 @@ return self._hook('pylsp_execute_command', command=command, arguments=arguments) def format_document(self, doc_uri, options): - return self._hook('pylsp_format_document', doc_uri, options=options) + return lambda: self._hook('pylsp_format_document', doc_uri, options=options) def format_range(self, doc_uri, range, options): return self._hook('pylsp_format_range', doc_uri, range=range, options=options) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/pylsp/workspace.py new/python-lsp-server-1.7.2/pylsp/workspace.py --- old/python-lsp-server-1.7.1/pylsp/workspace.py 2022-12-11 18:32:03.000000000 +0100 +++ new/python-lsp-server-1.7.2/pylsp/workspace.py 2023-04-03 03:06:12.000000000 +0200 @@ -37,6 +37,7 @@ M_PUBLISH_DIAGNOSTICS = 'textDocument/publishDiagnostics' M_PROGRESS = '$/progress' + M_INITIALIZE_PROGRESS = 'window/workDoneProgress/create' M_APPLY_EDIT = 'workspace/applyEdit' M_SHOW_MESSAGE = 'window/showMessage' @@ -135,15 +136,43 @@ message: Optional[str] = None, percentage: Optional[int] = None, ) -> Generator[Callable[[str, Optional[int]], None], None, None]: - token = self._progress_begin(title, message, percentage) + if self._config: + client_supports_progress_reporting = ( + self._config.capabilities.get("window", {}).get("workDoneProgress", False) + ) + else: + client_supports_progress_reporting = False + + if client_supports_progress_reporting: + try: + token = self._progress_begin(title, message, percentage) + except Exception: # pylint: disable=broad-exception-caught + log.warning( + "There was an error while trying to initialize progress reporting." + "Likely progress reporting was used in a synchronous LSP handler, " + "which is not supported by progress reporting yet.", + exc_info=True + ) - def progress_message(message: str, percentage: Optional[int] = None) -> None: - self._progress_report(token, message, percentage) + else: + def progress_message(message: str, percentage: Optional[int] = None) -> None: + self._progress_report(token, message, percentage) + + try: + yield progress_message + finally: + self._progress_end(token) + + return + + # FALLBACK: + # If the client doesn't support progress reporting, or if we failed to + # initialize it, we have a dummy method for the caller to use. + def dummy_progress_message(message: str, percentage: Optional[int] = None) -> None: + # pylint: disable=unused-argument + pass - try: - yield progress_message - finally: - self._progress_end(token) + yield dummy_progress_message def _progress_begin( self, @@ -152,13 +181,16 @@ percentage: Optional[int] = None, ) -> str: token = str(uuid.uuid4()) + + self._endpoint.request(self.M_INITIALIZE_PROGRESS, {'token': token}).result(timeout=1.0) + value = { "kind": "begin", "title": title, } - if message: + if message is not None: value["message"] = message - if percentage: + if percentage is not None: value["percentage"] = percentage self._endpoint.notify( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/pyproject.toml new/python-lsp-server-1.7.2/pyproject.toml --- old/python-lsp-server-1.7.1/pyproject.toml 2023-01-07 00:50:19.000000000 +0100 +++ new/python-lsp-server-1.7.2/pyproject.toml 2023-03-18 19:10:05.000000000 +0100 @@ -27,26 +27,27 @@ [project.optional-dependencies] all = [ - "autopep8>=1.6.0,<1.7.0", + "autopep8>=1.6.0,<2.1.0", "flake8>=5.0.0,<7", "mccabe>=0.7.0,<0.8.0", "pycodestyle>=2.9.0,<2.11.0", - "pydocstyle>=6.2.0,<6.3.0", + "pydocstyle>=6.3.0,<6.4.0", "pyflakes>=2.5.0,<3.1.0", "pylint>=2.5.0,<3", "rope>1.2.0", - "yapf", + "yapf<=0.32.0", + "toml", "whatthepatch>=1.0.2,<2.0.0" ] -autopep8 = ["autopep8>=1.6.0,<1.7.0"] +autopep8 = ["autopep8>=1.6.0,<2.1.0"] flake8 = ["flake8>=5.0.0,<7"] mccabe = ["mccabe>=0.7.0,<0.8.0"] pycodestyle = ["pycodestyle>=2.9.0,<2.11.0"] -pydocstyle = ["pydocstyle>=6.2.0,<6.3.0"] +pydocstyle = ["pydocstyle>=6.3.0,<6.4.0"] pyflakes = ["pyflakes>=2.5.0,<3.1.0"] pylint = ["pylint>=2.5.0,<3"] rope = ["rope>1.2.0"] -yapf = ["yapf", "whatthepatch>=1.0.2,<2.0.0"] +yapf = ["yapf<=0.32.0", "whatthepatch>=1.0.2,<2.0.0", "toml"] websockets = ["websockets>=10.3"] test = [ "pylint>=2.5.0,<3", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/python_lsp_server.egg-info/PKG-INFO new/python-lsp-server-1.7.2/python_lsp_server.egg-info/PKG-INFO --- old/python-lsp-server-1.7.1/python_lsp_server.egg-info/PKG-INFO 2023-01-18 00:25:16.000000000 +0100 +++ new/python-lsp-server-1.7.2/python_lsp_server.egg-info/PKG-INFO 2023-04-03 03:21:16.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: python-lsp-server -Version: 1.7.1 +Version: 1.7.2 Summary: Python Language Server for the Language Server Protocol Author: Python Language Server Contributors License: MIT diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/python_lsp_server.egg-info/requires.txt new/python-lsp-server-1.7.2/python_lsp_server.egg-info/requires.txt --- old/python-lsp-server-1.7.1/python_lsp_server.egg-info/requires.txt 2023-01-18 00:25:16.000000000 +0100 +++ new/python-lsp-server-1.7.2/python_lsp_server.egg-info/requires.txt 2023-04-03 03:21:16.000000000 +0200 @@ -6,19 +6,20 @@ setuptools>=39.0.0 [all] -autopep8<1.7.0,>=1.6.0 +autopep8<2.1.0,>=1.6.0 flake8<7,>=5.0.0 mccabe<0.8.0,>=0.7.0 pycodestyle<2.11.0,>=2.9.0 -pydocstyle<6.3.0,>=6.2.0 +pydocstyle<6.4.0,>=6.3.0 pyflakes<3.1.0,>=2.5.0 pylint<3,>=2.5.0 rope>1.2.0 -yapf +yapf<=0.32.0 +toml whatthepatch<2.0.0,>=1.0.2 [autopep8] -autopep8<1.7.0,>=1.6.0 +autopep8<2.1.0,>=1.6.0 [flake8] flake8<7,>=5.0.0 @@ -30,7 +31,7 @@ pycodestyle<2.11.0,>=2.9.0 [pydocstyle] -pydocstyle<6.3.0,>=6.2.0 +pydocstyle<6.4.0,>=6.3.0 [pyflakes] pyflakes<3.1.0,>=2.5.0 @@ -56,5 +57,6 @@ websockets>=10.3 [yapf] -yapf +yapf<=0.32.0 whatthepatch<2.0.0,>=1.0.2 +toml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/test/fixtures.py new/python-lsp-server-1.7.2/test/fixtures.py --- old/python-lsp-server-1.7.1/test/fixtures.py 2022-12-11 18:32:03.000000000 +0100 +++ new/python-lsp-server-1.7.2/test/fixtures.py 2023-04-03 03:06:12.000000000 +0200 @@ -4,8 +4,11 @@ import os from io import StringIO from unittest.mock import MagicMock + import pytest +from pylsp_jsonrpc.dispatchers import MethodDispatcher from pylsp_jsonrpc.endpoint import Endpoint +from pylsp_jsonrpc.exceptions import JsonRpcException from pylsp import uris from pylsp.config.config import Config @@ -21,10 +24,48 @@ """ +class FakeEditorMethodsMixin: + """ + Represents the methods to be added to a dispatcher class when faking an editor. + """ + def m_window__work_done_progress__create(self, *_args, **_kwargs): + """ + Fake editor method `window/workDoneProgress/create`. + + related spec: + https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#window_workDoneProgress_create + """ + return None + + +class FakePythonLSPServer(FakeEditorMethodsMixin, PythonLSPServer): + pass + + +class FakeEndpoint(Endpoint): + """ + Fake Endpoint representing the editor / LSP client. + + The `dispatcher` dict will be used to synchronously calculate the responses + for calls to `.request` and resolve the futures with the value or errors. + + Fake methods in the `dispatcher` should raise `JsonRpcException` for any + error. + """ + def request(self, method, params=None): + request_future = super().request(method, params) + try: + request_future.set_result(self._dispatcher[method](params)) + except JsonRpcException as e: + request_future.set_exception(e) + + return request_future + + @pytest.fixture def pylsp(tmpdir): """ Return an initialized python LS """ - ls = PythonLSPServer(StringIO, StringIO) + ls = FakePythonLSPServer(StringIO, StringIO, endpoint_cls=FakeEndpoint) ls.m_initialize( processId=1, @@ -38,7 +79,7 @@ @pytest.fixture def pylsp_w_workspace_folders(tmpdir): """ Return an initialized python LS """ - ls = PythonLSPServer(StringIO, StringIO) + ls = FakePythonLSPServer(StringIO, StringIO, endpoint_cls=FakeEndpoint) folder1 = tmpdir.mkdir('folder1') folder2 = tmpdir.mkdir('folder2') @@ -70,7 +111,10 @@ @pytest.fixture() def endpoint(consumer): # pylint: disable=redefined-outer-name - return Endpoint({}, consumer, id_generator=lambda: "id") + class Dispatcher(FakeEditorMethodsMixin, MethodDispatcher): + pass + + return FakeEndpoint(Dispatcher(), consumer, id_generator=lambda: "id") @pytest.fixture diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/test/plugins/test_definitions.py new/python-lsp-server-1.7.2/test/plugins/test_definitions.py --- old/python-lsp-server-1.7.1/test/plugins/test_definitions.py 2022-12-29 16:51:51.000000000 +0100 +++ new/python-lsp-server-1.7.2/test/plugins/test_definitions.py 2023-04-03 03:06:12.000000000 +0200 @@ -35,7 +35,7 @@ } doc = Document(DOC_URI, workspace, DOC) - assert [{'uri': DOC_URI, 'range': def_range}] == pylsp_definitions(config, workspace, doc, cursor_pos) + assert [{'uri': DOC_URI, 'range': def_range}] == pylsp_definitions(config, doc, cursor_pos) def test_builtin_definition(config, workspace): @@ -49,14 +49,14 @@ follow_defns_setting = {'follow_builtin_definitions': True} settings = {'plugins': {'jedi_definition': follow_defns_setting}} config.update(settings) - defns = pylsp_definitions(config, workspace, doc, cursor_pos) + defns = pylsp_definitions(config, doc, cursor_pos) assert len(defns) == 1 assert defns[0]["uri"].endswith("builtins.pyi") # Check no definitions for `dict` follow_defns_setting['follow_builtin_definitions'] = False config.update(settings) - defns = pylsp_definitions(config, workspace, doc, cursor_pos) + defns = pylsp_definitions(config, doc, cursor_pos) assert not defns config.update(orig_settings) @@ -73,7 +73,7 @@ } doc = Document(DOC_URI, workspace, DOC) - assert [{'uri': DOC_URI, 'range': def_range}] == pylsp_definitions(config, workspace, doc, cursor_pos) + assert [{'uri': DOC_URI, 'range': def_range}] == pylsp_definitions(config, doc, cursor_pos) def test_document_path_definitions(config, workspace_other_root_path, tmpdir): @@ -107,5 +107,5 @@ module_uri = uris.from_fs_path(module_path) assert [{"uri": module_uri, "range": def_range}] == pylsp_definitions( - config, workspace_other_root_path, doc, cursor_pos + config, doc, cursor_pos ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/test/plugins/test_references.py new/python-lsp-server-1.7.2/test/plugins/test_references.py --- old/python-lsp-server-1.7.1/test/plugins/test_references.py 2022-12-11 18:32:03.000000000 +0100 +++ new/python-lsp-server-1.7.2/test/plugins/test_references.py 2023-04-03 03:06:12.000000000 +0200 @@ -40,13 +40,13 @@ DOC1_URI = uris.from_fs_path(os.path.join(tmp_workspace.root_path, DOC1_NAME)) doc1 = Document(DOC1_URI, tmp_workspace) - refs = pylsp_references(doc1, tmp_workspace, position) + refs = pylsp_references(doc1, position) # Definition, the import and the instantiation assert len(refs) == 3 # Briefly check excluding the definitions (also excludes imports, only counts uses) - no_def_refs = pylsp_references(doc1, tmp_workspace, position, exclude_declaration=True) + no_def_refs = pylsp_references(doc1, position, exclude_declaration=True) assert len(no_def_refs) == 1 # Make sure our definition is correctly located @@ -70,7 +70,7 @@ doc2_uri = uris.from_fs_path(os.path.join(str(tmp_workspace.root_path), DOC2_NAME)) doc2 = Document(doc2_uri, tmp_workspace) - refs = pylsp_references(doc2, tmp_workspace, position) + refs = pylsp_references(doc2, position) assert len(refs) >= 1 expected = {'start': {'line': 4, 'character': 7}, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/test/plugins/test_yapf_format.py new/python-lsp-server-1.7.2/test/plugins/test_yapf_format.py --- old/python-lsp-server-1.7.1/test/plugins/test_yapf_format.py 2022-12-11 18:32:03.000000000 +0100 +++ new/python-lsp-server-1.7.2/test/plugins/test_yapf_format.py 2023-04-03 03:06:12.000000000 +0200 @@ -41,7 +41,7 @@ 'start': {'line': 0, 'character': 0}, 'end': {'line': 4, 'character': 10} } - res = pylsp_format_range(workspace, doc, def_range, None) + res = pylsp_format_range(doc, def_range, None) # Make sure B is still badly formatted assert apply_text_edits(doc, res) == "A = ['h', 'w', 'a']\n\nB = ['h',\n\n\n'w']\n" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-lsp-server-1.7.1/test/test_workspace.py new/python-lsp-server-1.7.2/test/test_workspace.py --- old/python-lsp-server-1.7.1/test/test_workspace.py 2022-12-11 18:32:03.000000000 +0100 +++ new/python-lsp-server-1.7.2/test/test_workspace.py 2023-04-03 03:06:12.000000000 +0200 @@ -295,23 +295,56 @@ assert workspace1_jedi_settings == server_settings['pylsp']['plugins']['jedi'] +def test_no_progress_without_capability(workspace, consumer): + workspace._config.capabilities['window'] = {"workDoneProgress": False} + + with workspace.report_progress("some_title"): + pass + + assert len(consumer.call_args_list) == 0 + + def test_progress_simple(workspace, consumer): + workspace._config.capabilities['window'] = {"workDoneProgress": True} + with workspace.report_progress("some_title"): pass + init_call, *progress_calls = consumer.call_args_list + + assert init_call[0][0]['method'] == 'window/workDoneProgress/create' + # same method for all calls - assert all(call[0][0]["method"] == "$/progress" for call in consumer.call_args_list) + assert all(call[0][0]["method"] == "$/progress" for call in progress_calls), consumer.call_args_list # same token used in all calls - assert len({call[0][0]["params"]["token"] for call in consumer.call_args_list}) == 1 + assert len({call[0][0]["params"]["token"] for call in progress_calls} | {init_call[0][0]['params']['token']}) == 1 - assert [call[0][0]["params"]["value"] for call in consumer.call_args_list] == [ + assert [call[0][0]["params"]["value"] for call in progress_calls] == [ {"kind": "begin", "title": "some_title"}, {"kind": "end"}, ] +@pytest.mark.parametrize("exc", [Exception("something"), TimeoutError()]) +def test_progress_initialization_fails(workspace, consumer, endpoint, exc): + def failing_token_initialization(self, *_args, **_kwargs): + raise exc + endpoint._dispatcher.m_window__work_done_progress__create = failing_token_initialization + + workspace._config.capabilities['window'] = {"workDoneProgress": True} + + with workspace.report_progress("some_title"): + pass + + # we only see the failing token initialization call, no other calls + init_call, = consumer.call_args_list + assert init_call[0][0]['method'] == 'window/workDoneProgress/create' + + def test_progress_with_percent(workspace, consumer): + workspace._config.capabilities['window'] = {"workDoneProgress": True} + with workspace.report_progress( "some_title", "initial message", percentage=1 ) as progress_message: @@ -319,13 +352,17 @@ progress_message("fifty", 50) progress_message("ninety", 90) - # same method for all calls - assert all(call[0][0]["method"] == "$/progress" for call in consumer.call_args_list) + init_call, *progress_calls = consumer.call_args_list + + assert init_call[0][0]['method'] == 'window/workDoneProgress/create' + + # same method for all progress calls + assert all(call[0][0]["method"] == "$/progress" for call in progress_calls) # same token used in all calls - assert len({call[0][0]["params"]["token"] for call in consumer.call_args_list}) == 1 + assert len({call[0][0]["params"]["token"] for call in progress_calls} | {init_call[0][0]['params']['token']}) == 1 - assert [call[0][0]["params"]["value"] for call in consumer.call_args_list] == [ + assert [call[0][0]["params"]["value"] for call in progress_calls] == [ { "kind": "begin", "message": "initial message", @@ -340,6 +377,8 @@ def test_progress_with_exception(workspace, consumer): + workspace._config.capabilities['window'] = {"workDoneProgress": True} + class DummyError(Exception): pass @@ -353,13 +392,16 @@ # test. pass + init_call, *progress_calls = consumer.call_args_list + assert init_call[0][0]['method'] == 'window/workDoneProgress/create' + # same method for all calls - assert all(call[0][0]["method"] == "$/progress" for call in consumer.call_args_list) + assert all(call[0][0]["method"] == "$/progress" for call in progress_calls) # same token used in all calls - assert len({call[0][0]["params"]["token"] for call in consumer.call_args_list}) == 1 + assert len({call[0][0]["params"]["token"] for call in progress_calls} | {init_call[0][0]['params']['token']}) == 1 - assert [call[0][0]["params"]["value"] for call in consumer.call_args_list] == [ + assert [call[0][0]["params"]["value"] for call in progress_calls] == [ {"kind": "begin", "title": "some_title"}, {"kind": "end"}, ]