From 03c53724654477b8a85eb816275a9ea06b13c7eb Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Sat, 31 Dec 2022 14:40:16 +0100 Subject: [PATCH 01/15] fixes #325: initialize LSP progress token before using it --- pylsp/_utils.py | 1 + pylsp/python_lsp.py | 8 +++--- pylsp/workspace.py | 4 +++ test/fixtures.py | 49 +++++++++++++++++++++++++++++++++--- test/test_language_server.py | 2 +- test/test_workspace.py | 31 +++++++++++++++-------- 6 files changed, 78 insertions(+), 17 deletions(-) diff --git a/pylsp/_utils.py b/pylsp/_utils.py index 2c6111d8..a88c8534 100644 --- a/pylsp/_utils.py +++ b/pylsp/_utils.py @@ -14,6 +14,7 @@ import jedi JEDI_VERSION = jedi.__version__ +CALL_TIMEOUT = 10 # Eol chars accepted by the LSP protocol # the ordering affects performance diff --git a/pylsp/python_lsp.py b/pylsp/python_lsp.py index e663a8a0..fc9fe5c8 100644 --- a/pylsp/python_lsp.py +++ b/pylsp/python_lsp.py @@ -152,7 +152,7 @@ class PythonLSPServer(MethodDispatcher): # 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 @@ def __init__(self, rx, tx, check_parent_process=False, consumer=None): 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 diff --git a/pylsp/workspace.py b/pylsp/workspace.py index 5647a90a..5245bb30 100644 --- a/pylsp/workspace.py +++ b/pylsp/workspace.py @@ -37,6 +37,7 @@ class Workspace: M_PUBLISH_DIAGNOSTICS = 'textDocument/publishDiagnostics' M_PROGRESS = '$/progress' + M_INITIALIZE_PROGRESS = 'window/workDoneProgress/create' M_APPLY_EDIT = 'workspace/applyEdit' M_SHOW_MESSAGE = 'window/showMessage' @@ -152,6 +153,9 @@ def _progress_begin( percentage: Optional[int] = None, ) -> str: token = str(uuid.uuid4()) + + self._endpoint.request(self.M_INITIALIZE_PROGRESS, {'token': token}).result(_utils.CALL_TIMEOUT) + value = { "kind": "begin", "title": title, diff --git a/test/fixtures.py b/test/fixtures.py index 5763d462..07abe6c4 100644 --- a/test/fixtures.py +++ b/test/fixtures.py @@ -5,7 +5,9 @@ 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 @@ -24,7 +26,7 @@ def main(): @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 +40,7 @@ def pylsp(tmpdir): @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') @@ -63,6 +65,44 @@ def pylsp_w_workspace_folders(tmpdir): return (ls, workspace_folders) +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 consumer(): return MagicMock() @@ -70,7 +110,10 @@ def consumer(): @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 --git a/test/test_language_server.py b/test/test_language_server.py index 92d1ea84..0445b323 100644 --- a/test/test_language_server.py +++ b/test/test_language_server.py @@ -12,8 +12,8 @@ import pytest from pylsp.python_lsp import start_io_lang_server, PythonLSPServer +from pylsp._utils import CALL_TIMEOUT -CALL_TIMEOUT = 10 RUNNING_IN_CI = bool(os.environ.get('CI')) diff --git a/test/test_workspace.py b/test/test_workspace.py index 6699b4b8..6bf8d287 100644 --- a/test/test_workspace.py +++ b/test/test_workspace.py @@ -299,13 +299,17 @@ def test_progress_simple(workspace, consumer): 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"}, ] @@ -319,13 +323,17 @@ def test_progress_with_percent(workspace, consumer): 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", @@ -353,13 +361,16 @@ class DummyError(Exception): # 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"}, ] From 8c76f8a9c098f7c83ef8481208a9e73888321ac0 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Mon, 2 Jan 2023 20:11:38 +0100 Subject: [PATCH 02/15] respect window.workDoneProgress capability to activate progress reporting --- pylsp/workspace.py | 27 +++++++++++++++++++-------- test/test_workspace.py | 14 ++++++++++++++ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/pylsp/workspace.py b/pylsp/workspace.py index 5245bb30..d914450a 100644 --- a/pylsp/workspace.py +++ b/pylsp/workspace.py @@ -136,15 +136,26 @@ def report_progress( 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: + token = self._progress_begin(title, message, percentage) - def progress_message(message: str, percentage: Optional[int] = None) -> None: - self._progress_report(token, message, percentage) + 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) + else: + def dummy_progress_message(message: str, percentage: Optional[int] = None) -> None: + pass - try: - yield progress_message - finally: - self._progress_end(token) + yield dummy_progress_message def _progress_begin( self, @@ -154,7 +165,7 @@ def _progress_begin( ) -> str: token = str(uuid.uuid4()) - self._endpoint.request(self.M_INITIALIZE_PROGRESS, {'token': token}).result(_utils.CALL_TIMEOUT) + self._endpoint.request(self.M_INITIALIZE_PROGRESS, {'token': token}).result() value = { "kind": "begin", diff --git a/test/test_workspace.py b/test/test_workspace.py index 6bf8d287..9849ce80 100644 --- a/test/test_workspace.py +++ b/test/test_workspace.py @@ -294,8 +294,18 @@ def test_settings_of_added_workspace(pylsp, tmpdir): workspace1_jedi_settings = workspace1_object._config.plugin_settings('jedi') 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 @@ -316,6 +326,8 @@ def test_progress_simple(workspace, consumer): 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: @@ -348,6 +360,8 @@ def test_progress_with_percent(workspace, consumer): def test_progress_with_exception(workspace, consumer): + workspace._config.capabilities['window'] = {"workDoneProgress": True} + class DummyError(Exception): pass From a0babc0825c287b83238c1a8cc8ce9801730a233 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Mon, 2 Jan 2023 20:18:07 +0100 Subject: [PATCH 03/15] don't timeout for progress-reporting RPC requests to editor --- pylsp/_utils.py | 1 - test/test_language_server.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pylsp/_utils.py b/pylsp/_utils.py index a88c8534..2c6111d8 100644 --- a/pylsp/_utils.py +++ b/pylsp/_utils.py @@ -14,7 +14,6 @@ import jedi JEDI_VERSION = jedi.__version__ -CALL_TIMEOUT = 10 # Eol chars accepted by the LSP protocol # the ordering affects performance diff --git a/test/test_language_server.py b/test/test_language_server.py index 0445b323..92d1ea84 100644 --- a/test/test_language_server.py +++ b/test/test_language_server.py @@ -12,8 +12,8 @@ import pytest from pylsp.python_lsp import start_io_lang_server, PythonLSPServer -from pylsp._utils import CALL_TIMEOUT +CALL_TIMEOUT = 10 RUNNING_IN_CI = bool(os.environ.get('CI')) From eeb43af9e56b7f373e89b5bc4d5476e80d988724 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Mon, 2 Jan 2023 20:19:43 +0100 Subject: [PATCH 04/15] move test-helper classes to top of fixture file --- test/fixtures.py | 76 ++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/test/fixtures.py b/test/fixtures.py index 07abe6c4..d02aa2b1 100644 --- a/test/fixtures.py +++ b/test/fixtures.py @@ -23,6 +23,44 @@ def main(): """ +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 """ @@ -65,44 +103,6 @@ def pylsp_w_workspace_folders(tmpdir): return (ls, workspace_folders) -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 consumer(): return MagicMock() From 5815d3a724b86cfaf675a0da6a8ad65f488d5b17 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Mon, 2 Jan 2023 20:20:36 +0100 Subject: [PATCH 05/15] fix import grouping / format --- test/fixtures.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/fixtures.py b/test/fixtures.py index d02aa2b1..7c7bcf62 100644 --- a/test/fixtures.py +++ b/test/fixtures.py @@ -4,6 +4,7 @@ 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 8dfcce7ac0fc3e2c268d5be2cc5a87e4e04913a4 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Mon, 2 Jan 2023 20:24:01 +0100 Subject: [PATCH 06/15] fix pylint errors --- pylsp/workspace.py | 5 ++++- test/test_workspace.py | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pylsp/workspace.py b/pylsp/workspace.py index d914450a..0b86ffb9 100644 --- a/pylsp/workspace.py +++ b/pylsp/workspace.py @@ -137,7 +137,9 @@ def report_progress( percentage: Optional[int] = None, ) -> Generator[Callable[[str, Optional[int]], None], None, None]: if self._config: - client_supports_progress_reporting = self._config.capabilities.get("window", {}).get("workDoneProgress", False) + client_supports_progress_reporting = ( + self._config.capabilities.get("window", {}).get("workDoneProgress", False) + ) else: client_supports_progress_reporting = False @@ -153,6 +155,7 @@ def progress_message(message: str, percentage: Optional[int] = None) -> None: self._progress_end(token) else: def dummy_progress_message(message: str, percentage: Optional[int] = None) -> None: + # pylint: disable=unused-argument pass yield dummy_progress_message diff --git a/test/test_workspace.py b/test/test_workspace.py index 9849ce80..87ce41cc 100644 --- a/test/test_workspace.py +++ b/test/test_workspace.py @@ -294,6 +294,7 @@ def test_settings_of_added_workspace(pylsp, tmpdir): workspace1_jedi_settings = workspace1_object._config.plugin_settings('jedi') assert workspace1_jedi_settings == server_settings['pylsp']['plugins']['jedi'] + def test_no_progress_without_capability(workspace, consumer): workspace._config.capabilities['window'] = {"workDoneProgress": False} From 293fbfb53fc68afdaebc853b7567382dfbb5afe7 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Wed, 4 Jan 2023 21:06:23 +0100 Subject: [PATCH 07/15] handle some RPC calls asynchronously to support progress --- pylsp/python_lsp.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pylsp/python_lsp.py b/pylsp/python_lsp.py index fc9fe5c8..5a18a453 100644 --- a/pylsp/python_lsp.py +++ b/pylsp/python_lsp.py @@ -348,7 +348,7 @@ def completion_item_resolve(self, completion_item): return self._hook('pylsp_completion_item_resolve', doc_uri, completion_item=completion_item) def definitions(self, doc_uri, position): - return flatten(self._hook('pylsp_definitions', doc_uri, position=position)) + return lambda: flatten(self._hook('pylsp_definitions', doc_uri, position=position)) def document_symbols(self, doc_uri): return flatten(self._hook('pylsp_document_symbols', doc_uri)) @@ -360,10 +360,10 @@ def execute_command(self, command, arguments): 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) + return lambda: self._hook('pylsp_format_range', doc_uri, range=range, options=options) def highlight(self, doc_uri, position): return flatten(self._hook('pylsp_document_highlight', doc_uri, position=position)) or None @@ -382,13 +382,13 @@ def lint(self, doc_uri, is_saved): ) def references(self, doc_uri, position, exclude_declaration): - return flatten(self._hook( + return lambda: flatten(self._hook( 'pylsp_references', doc_uri, position=position, exclude_declaration=exclude_declaration )) def rename(self, doc_uri, position, new_name): - return self._hook('pylsp_rename', doc_uri, position=position, new_name=new_name) + return lambda: self._hook('pylsp_rename', doc_uri, position=position, new_name=new_name) def signature_help(self, doc_uri, position): return self._hook('pylsp_signature_help', doc_uri, position=position) From cc16c99d9304bbc67ed0b3d147d83d9dd0696e92 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Thu, 5 Jan 2023 18:56:41 +0100 Subject: [PATCH 08/15] support empty progress messages and zero percent progress --- pylsp/workspace.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pylsp/workspace.py b/pylsp/workspace.py index 0b86ffb9..14191688 100644 --- a/pylsp/workspace.py +++ b/pylsp/workspace.py @@ -174,9 +174,9 @@ def _progress_begin( "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( From 950a255719dc3579387db76480763f666a70a4d7 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Sun, 26 Mar 2023 14:02:35 +0200 Subject: [PATCH 09/15] revert some commands back to synchronous calls --- pylsp/python_lsp.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pylsp/python_lsp.py b/pylsp/python_lsp.py index 5a18a453..fc9fe5c8 100644 --- a/pylsp/python_lsp.py +++ b/pylsp/python_lsp.py @@ -348,7 +348,7 @@ def completion_item_resolve(self, completion_item): return self._hook('pylsp_completion_item_resolve', doc_uri, completion_item=completion_item) def definitions(self, doc_uri, position): - return lambda: flatten(self._hook('pylsp_definitions', doc_uri, position=position)) + return flatten(self._hook('pylsp_definitions', doc_uri, position=position)) def document_symbols(self, doc_uri): return flatten(self._hook('pylsp_document_symbols', doc_uri)) @@ -360,10 +360,10 @@ def execute_command(self, command, arguments): return self._hook('pylsp_execute_command', command=command, arguments=arguments) def format_document(self, doc_uri, options): - return lambda: self._hook('pylsp_format_document', doc_uri, options=options) + return self._hook('pylsp_format_document', doc_uri, options=options) def format_range(self, doc_uri, range, options): - return lambda: self._hook('pylsp_format_range', doc_uri, range=range, options=options) + return self._hook('pylsp_format_range', doc_uri, range=range, options=options) def highlight(self, doc_uri, position): return flatten(self._hook('pylsp_document_highlight', doc_uri, position=position)) or None @@ -382,13 +382,13 @@ def lint(self, doc_uri, is_saved): ) def references(self, doc_uri, position, exclude_declaration): - return lambda: flatten(self._hook( + return flatten(self._hook( 'pylsp_references', doc_uri, position=position, exclude_declaration=exclude_declaration )) def rename(self, doc_uri, position, new_name): - return lambda: self._hook('pylsp_rename', doc_uri, position=position, new_name=new_name) + return self._hook('pylsp_rename', doc_uri, position=position, new_name=new_name) def signature_help(self, doc_uri, position): return self._hook('pylsp_signature_help', doc_uri, position=position) From 2258206b1414904001842d8b70edd8f378ae344f Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Sun, 26 Mar 2023 14:12:43 +0200 Subject: [PATCH 10/15] re-add async formatting, it doesn't use position / ranges --- pylsp/python_lsp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylsp/python_lsp.py b/pylsp/python_lsp.py index fc9fe5c8..43f886cc 100644 --- a/pylsp/python_lsp.py +++ b/pylsp/python_lsp.py @@ -360,7 +360,7 @@ def execute_command(self, command, arguments): 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) From 4276d80683133fce08bc9193e730a2405a1625b3 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Sun, 26 Mar 2023 15:31:50 +0200 Subject: [PATCH 11/15] fix pylint warnigs --- pylsp/_utils.py | 3 +-- pylsp/plugins/jedi_rename.py | 1 + pylsp/workspace.py | 40 ++++++++++++++++++++++++------------ test/test_workspace.py | 16 +++++++++++++++ 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/pylsp/_utils.py b/pylsp/_utils.py index 2c6111d8..610cdbde 100644 --- a/pylsp/_utils.py +++ b/pylsp/_utils.py @@ -293,8 +293,7 @@ def is_process_alive(pid): os.kill(pid, 0) except OSError as e: return e.errno == errno.EPERM - else: - return True + return True def get_eol_chars(text): diff --git a/pylsp/plugins/jedi_rename.py b/pylsp/plugins/jedi_rename.py index 64949bb0..ffca7e94 100644 --- a/pylsp/plugins/jedi_rename.py +++ b/pylsp/plugins/jedi_rename.py @@ -18,6 +18,7 @@ def pylsp_rename(config, workspace, document, position, new_name): # pylint: di 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()) diff --git a/pylsp/workspace.py b/pylsp/workspace.py index 14191688..9133417b 100644 --- a/pylsp/workspace.py +++ b/pylsp/workspace.py @@ -144,21 +144,35 @@ def report_progress( client_supports_progress_reporting = False if client_supports_progress_reporting: - token = self._progress_begin(title, message, percentage) + try: + token = self._progress_begin(title, message, percentage) + except Exception: # pylint: disable=broad-exception-caught + log.warning( + "error while trying to initialize progress reporting." + "Either the editor failed, was too slow to answer, or this LSP " + "call is synchronous, 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) - else: - 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) + + 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 - yield dummy_progress_message + yield dummy_progress_message def _progress_begin( self, @@ -168,7 +182,7 @@ def _progress_begin( ) -> str: token = str(uuid.uuid4()) - self._endpoint.request(self.M_INITIALIZE_PROGRESS, {'token': token}).result() + self._endpoint.request(self.M_INITIALIZE_PROGRESS, {'token': token}).result(timeout=1.0) value = { "kind": "begin", diff --git a/test/test_workspace.py b/test/test_workspace.py index 87ce41cc..94a9cba1 100644 --- a/test/test_workspace.py +++ b/test/test_workspace.py @@ -326,6 +326,22 @@ def test_progress_simple(workspace, consumer): ] +@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} From 1ad4dd11952de196c27e46e06e11512845c580de Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Sun, 26 Mar 2023 15:40:34 +0200 Subject: [PATCH 12/15] remove progress reporting from unsupported plugins --- pylsp/plugins/autopep8_format.py | 17 ++++---- pylsp/plugins/definition.py | 33 +++++++-------- pylsp/plugins/jedi_rename.py | 71 +++++++++++++++----------------- pylsp/plugins/references.py | 27 ++++++------ pylsp/plugins/rope_rename.py | 69 +++++++++++++++---------------- pylsp/plugins/yapf_format.py | 29 +++++++------ 6 files changed, 119 insertions(+), 127 deletions(-) diff --git a/pylsp/plugins/autopep8_format.py b/pylsp/plugins/autopep8_format.py index 44f45dc2..50be2c33 100644 --- a/pylsp/plugins/autopep8_format.py +++ b/pylsp/plugins/autopep8_format.py @@ -23,17 +23,16 @@ def pylsp_format_document(config, workspace, document, options): # pylint: disa 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 --git a/pylsp/plugins/definition.py b/pylsp/plugins/definition.py index b2110af4..c4b5c88b 100644 --- a/pylsp/plugins/definition.py +++ b/pylsp/plugins/definition.py @@ -9,25 +9,24 @@ @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) + 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 --git a/pylsp/plugins/jedi_rename.py b/pylsp/plugins/jedi_rename.py index ffca7e94..5b3b1f00 100644 --- a/pylsp/plugins/jedi_rename.py +++ b/pylsp/plugins/jedi_rename.py @@ -10,44 +10,41 @@ @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: - # 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, - }, + 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()): + 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 --git a/pylsp/plugins/references.py b/pylsp/plugins/references.py index 9873d7e1..105acd06 100644 --- a/pylsp/plugins/references.py +++ b/pylsp/plugins/references.py @@ -9,19 +9,18 @@ @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) + 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 --git a/pylsp/plugins/rope_rename.py b/pylsp/plugins/rope_rename.py index eccbbbec..d9ebab5c 100644 --- a/pylsp/plugins/rope_rename.py +++ b/pylsp/plugins/rope_rename.py @@ -19,42 +19,41 @@ def pylsp_settings(): @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) - - 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, - }, + 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) + ) + + 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 --git a/pylsp/plugins/yapf_format.py b/pylsp/plugins/yapf_format.py index 754d9cbb..3e4ee2b7 100644 --- a/pylsp/plugins/yapf_format.py +++ b/pylsp/plugins/yapf_format.py @@ -25,21 +25,20 @@ def pylsp_format_document(workspace, document, options): @hookimpl def pylsp_format_range(workspace, 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): From 52a8deed7ac4f114467436746e422aba5296641c Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Sun, 26 Mar 2023 15:49:39 +0200 Subject: [PATCH 13/15] fix pylint errors --- pylsp/plugins/definition.py | 2 +- pylsp/plugins/jedi_rename.py | 4 ++-- pylsp/plugins/references.py | 2 +- pylsp/plugins/yapf_format.py | 2 +- test/plugins/test_definitions.py | 10 +++++----- test/plugins/test_references.py | 6 +++--- test/plugins/test_yapf_format.py | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pylsp/plugins/definition.py b/pylsp/plugins/definition.py index c4b5c88b..fe06ab3c 100644 --- a/pylsp/plugins/definition.py +++ b/pylsp/plugins/definition.py @@ -8,7 +8,7 @@ @hookimpl -def pylsp_definitions(config, workspace, document, 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( diff --git a/pylsp/plugins/jedi_rename.py b/pylsp/plugins/jedi_rename.py index 5b3b1f00..d44b28e9 100644 --- a/pylsp/plugins/jedi_rename.py +++ b/pylsp/plugins/jedi_rename.py @@ -9,7 +9,7 @@ @hookimpl -def pylsp_rename(config, workspace, document, position, new_name): # pylint: disable=unused-argument,too-many-locals +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 @@ -23,7 +23,7 @@ def pylsp_rename(config, workspace, document, position, new_name): # pylint: di changes = [] changed_files = refactoring.get_changed_files() - for n, (file_path, changed_file) in enumerate(changed_files.items()): + 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({ diff --git a/pylsp/plugins/references.py b/pylsp/plugins/references.py index 105acd06..4ef2072a 100644 --- a/pylsp/plugins/references.py +++ b/pylsp/plugins/references.py @@ -8,7 +8,7 @@ @hookimpl -def pylsp_references(document, workspace, position, exclude_declaration=False): +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) diff --git a/pylsp/plugins/yapf_format.py b/pylsp/plugins/yapf_format.py index 3e4ee2b7..308fd5cf 100644 --- a/pylsp/plugins/yapf_format.py +++ b/pylsp/plugins/yapf_format.py @@ -23,7 +23,7 @@ def pylsp_format_document(workspace, document, options): @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) # First we 'round' the range up/down to full lines only range['start']['character'] = 0 diff --git a/test/plugins/test_definitions.py b/test/plugins/test_definitions.py index a8972cd2..4a8855c6 100644 --- a/test/plugins/test_definitions.py +++ b/test/plugins/test_definitions.py @@ -35,7 +35,7 @@ def test_definitions(config, workspace): } 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 @@ def test_builtin_definition(config, workspace): 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 @@ def test_assignment(config, workspace): } 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 @@ def foo(): 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 --git a/test/plugins/test_references.py b/test/plugins/test_references.py index 79cd7a0e..c1df037b 100644 --- a/test/plugins/test_references.py +++ b/test/plugins/test_references.py @@ -40,13 +40,13 @@ def test_references(tmp_workspace): # pylint: disable=redefined-outer-name 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 @@ def test_references_builtin(tmp_workspace): # pylint: disable=redefined-outer-n 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 --git a/test/plugins/test_yapf_format.py b/test/plugins/test_yapf_format.py index 0e989c0d..62808e6a 100644 --- a/test/plugins/test_yapf_format.py +++ b/test/plugins/test_yapf_format.py @@ -41,7 +41,7 @@ def test_range_format(workspace): '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" From ec01cf5b18aeb00994f6984780b58041fb6f7839 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Mon, 27 Mar 2023 19:08:49 +0200 Subject: [PATCH 14/15] fix typos --- pylsp/workspace.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pylsp/workspace.py b/pylsp/workspace.py index 9133417b..8d949244 100644 --- a/pylsp/workspace.py +++ b/pylsp/workspace.py @@ -148,7 +148,7 @@ def report_progress( token = self._progress_begin(title, message, percentage) except Exception: # pylint: disable=broad-exception-caught log.warning( - "error while trying to initialize progress reporting." + "There was an error while trying to initialize progress reporting." "Either the editor failed, was too slow to answer, or this LSP " "call is synchronous, which is not supported by progress reporting yet.", exc_info=True @@ -166,7 +166,7 @@ def progress_message(message: str, percentage: Optional[int] = None) -> None: return # FALLBACK: - # if the client doesn't support progress reporting, or if we failed to + # 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 From b26681e188688d5985f1ac4e5dbcda7cc7ee48f2 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Mon, 27 Mar 2023 19:12:28 +0200 Subject: [PATCH 15/15] update warning message when progress coudln't be initialized --- pylsp/workspace.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pylsp/workspace.py b/pylsp/workspace.py index 8d949244..ea7f55e8 100644 --- a/pylsp/workspace.py +++ b/pylsp/workspace.py @@ -149,8 +149,8 @@ def report_progress( except Exception: # pylint: disable=broad-exception-caught log.warning( "There was an error while trying to initialize progress reporting." - "Either the editor failed, was too slow to answer, or this LSP " - "call is synchronous, which is not supported by progress reporting yet.", + "Likely progress reporting was used in a synchronous LSP handler, " + "which is not supported by progress reporting yet.", exc_info=True )