From 659f68e934633e3fc0feaf7b7df2f5d5c6bcc7cd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 21 Jun 2024 19:37:26 +0100 Subject: [PATCH 01/12] [pre-commit.ci] pre-commit autoupdate (#171) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.4.8 → v0.4.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.8...v0.4.9) * Bump ruff version --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Alex Carney --- .pre-commit-config.yaml | 2 +- lib/lsp-devtools/hatch.toml | 2 +- lib/pytest-lsp/hatch.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d6630bd..ff170a8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,7 +10,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.8 + rev: v0.4.9 hooks: - id: ruff args: [--fix] diff --git a/lib/lsp-devtools/hatch.toml b/lib/lsp-devtools/hatch.toml index 84eabdc..02db67e 100644 --- a/lib/lsp-devtools/hatch.toml +++ b/lib/lsp-devtools/hatch.toml @@ -13,4 +13,4 @@ extra-dependencies = ["pytest-asyncio"] [envs.hatch-static-analysis] config-path = "ruff_defaults.toml" -dependencies = ["ruff==0.4.8"] +dependencies = ["ruff==0.4.9"] diff --git a/lib/pytest-lsp/hatch.toml b/lib/pytest-lsp/hatch.toml index 6f34f4a..00eaf32 100644 --- a/lib/pytest-lsp/hatch.toml +++ b/lib/pytest-lsp/hatch.toml @@ -23,4 +23,4 @@ matrix.pytest.dependencies = [ [envs.hatch-static-analysis] config-path = "ruff_defaults.toml" -dependencies = ["ruff==0.4.8"] +dependencies = ["ruff==0.4.9"] From 3326ee7146c0ab84ece3a203682ef45c2abcbbae Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 27 Jun 2024 19:29:33 +0100 Subject: [PATCH 02/12] [pre-commit.ci] pre-commit autoupdate (#174) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.4.9 → v0.4.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.9...v0.4.10) * Bump ruff version --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Alex Carney --- .pre-commit-config.yaml | 2 +- lib/lsp-devtools/hatch.toml | 2 +- lib/pytest-lsp/hatch.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ff170a8..5a84053 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,7 +10,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.9 + rev: v0.4.10 hooks: - id: ruff args: [--fix] diff --git a/lib/lsp-devtools/hatch.toml b/lib/lsp-devtools/hatch.toml index 02db67e..13c1480 100644 --- a/lib/lsp-devtools/hatch.toml +++ b/lib/lsp-devtools/hatch.toml @@ -13,4 +13,4 @@ extra-dependencies = ["pytest-asyncio"] [envs.hatch-static-analysis] config-path = "ruff_defaults.toml" -dependencies = ["ruff==0.4.9"] +dependencies = ["ruff==0.4.10"] diff --git a/lib/pytest-lsp/hatch.toml b/lib/pytest-lsp/hatch.toml index 00eaf32..d236346 100644 --- a/lib/pytest-lsp/hatch.toml +++ b/lib/pytest-lsp/hatch.toml @@ -23,4 +23,4 @@ matrix.pytest.dependencies = [ [envs.hatch-static-analysis] config-path = "ruff_defaults.toml" -dependencies = ["ruff==0.4.9"] +dependencies = ["ruff==0.4.10"] From 6cb7367e8b949879ff88c602763c18b083584ef0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 19:45:45 +0100 Subject: [PATCH 03/12] [pre-commit.ci] pre-commit autoupdate (#175) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.4.10 → v0.5.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.10...v0.5.2) - [github.com/pre-commit/mirrors-mypy: v1.10.0 → v1.10.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.10.0...v1.10.1) * Bump ruff version * Update ruff config * Update ruff config --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Alex Carney --- .pre-commit-config.yaml | 4 ++-- lib/lsp-devtools/hatch.toml | 2 +- lib/lsp-devtools/ruff_defaults.toml | 13 +++++-------- lib/pytest-lsp/hatch.toml | 2 +- lib/pytest-lsp/ruff_defaults.toml | 13 +++++-------- 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5a84053..573e1f3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,7 +10,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.10 + rev: v0.5.2 hooks: - id: ruff args: [--fix] @@ -20,7 +20,7 @@ repos: files: 'lib/.*\.py' - repo: https://github.com/pre-commit/mirrors-mypy - rev: 'v1.10.0' + rev: 'v1.10.1' hooks: - id: mypy name: mypy (pytest-lsp) diff --git a/lib/lsp-devtools/hatch.toml b/lib/lsp-devtools/hatch.toml index 13c1480..29ea2b4 100644 --- a/lib/lsp-devtools/hatch.toml +++ b/lib/lsp-devtools/hatch.toml @@ -13,4 +13,4 @@ extra-dependencies = ["pytest-asyncio"] [envs.hatch-static-analysis] config-path = "ruff_defaults.toml" -dependencies = ["ruff==0.4.10"] +dependencies = ["ruff==0.5.2"] diff --git a/lib/lsp-devtools/ruff_defaults.toml b/lib/lsp-devtools/ruff_defaults.toml index 18aaec5..9b62f5a 100644 --- a/lib/lsp-devtools/ruff_defaults.toml +++ b/lib/lsp-devtools/ruff_defaults.toml @@ -14,9 +14,11 @@ select = [ "ARG003", "ARG004", "ARG005", - "ASYNC100", - "ASYNC101", - "ASYNC102", + "ASYNC210", + "ASYNC220", + "ASYNC221", + "ASYNC230", + "ASYNC251", "B002", "B003", "B004", @@ -463,11 +465,6 @@ select = [ "TID251", "TID252", "TID253", - "TRIO100", - "TRIO105", - "TRIO109", - "TRIO110", - "TRIO115", "TRY002", "TRY003", "TRY004", diff --git a/lib/pytest-lsp/hatch.toml b/lib/pytest-lsp/hatch.toml index d236346..24d59a2 100644 --- a/lib/pytest-lsp/hatch.toml +++ b/lib/pytest-lsp/hatch.toml @@ -23,4 +23,4 @@ matrix.pytest.dependencies = [ [envs.hatch-static-analysis] config-path = "ruff_defaults.toml" -dependencies = ["ruff==0.4.10"] +dependencies = ["ruff==0.5.2"] diff --git a/lib/pytest-lsp/ruff_defaults.toml b/lib/pytest-lsp/ruff_defaults.toml index 18aaec5..9b62f5a 100644 --- a/lib/pytest-lsp/ruff_defaults.toml +++ b/lib/pytest-lsp/ruff_defaults.toml @@ -14,9 +14,11 @@ select = [ "ARG003", "ARG004", "ARG005", - "ASYNC100", - "ASYNC101", - "ASYNC102", + "ASYNC210", + "ASYNC220", + "ASYNC221", + "ASYNC230", + "ASYNC251", "B002", "B003", "B004", @@ -463,11 +465,6 @@ select = [ "TID251", "TID252", "TID253", - "TRIO100", - "TRIO105", - "TRIO109", - "TRIO110", - "TRIO115", "TRY002", "TRY003", "TRY004", From bce3fe9620d5e4072c3a9c837dec0c9fccdf1078 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Mon, 26 Aug 2024 14:43:41 +0100 Subject: [PATCH 04/12] pytest-lsp: Drop Python 3.8 --- .github/workflows/pytest-lsp-pr.yml | 2 +- lib/pytest-lsp/pyproject.toml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pytest-lsp-pr.yml b/.github/workflows/pytest-lsp-pr.yml index 7313125..7979892 100644 --- a/.github/workflows/pytest-lsp-pr.yml +++ b/.github/workflows/pytest-lsp-pr.yml @@ -41,7 +41,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12"] os: [ubuntu-latest, windows-latest] steps: diff --git a/lib/pytest-lsp/pyproject.toml b/lib/pytest-lsp/pyproject.toml index 59678df..9002f99 100644 --- a/lib/pytest-lsp/pyproject.toml +++ b/lib/pytest-lsp/pyproject.toml @@ -7,7 +7,7 @@ name = "pytest-lsp" dynamic = ["version"] description = "A pytest plugin for end-to-end testing of language servers" readme = "README.md" -requires-python = ">=3.8" +requires-python = ">=3.9" license = { text = "MIT" } authors = [{ name = "Alex Carney", email = "alcarneyme@gmail.com" }] classifiers = [ @@ -17,7 +17,6 @@ classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", From ded1250c082ddb4e4643cb0418a9545878dffdda Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Mon, 26 Aug 2024 14:47:37 +0100 Subject: [PATCH 05/12] pytest-lsp: pyupgrade --py39-plus --- lib/pytest-lsp/changes/178.breaking.md | 1 + lib/pytest-lsp/pytest_lsp/checks.py | 15 ++++---- lib/pytest-lsp/pytest_lsp/client.py | 52 ++++++++++---------------- lib/pytest-lsp/pytest_lsp/plugin.py | 17 ++++----- lib/pytest-lsp/ruff_defaults.toml | 2 - 5 files changed, 35 insertions(+), 52 deletions(-) create mode 100644 lib/pytest-lsp/changes/178.breaking.md diff --git a/lib/pytest-lsp/changes/178.breaking.md b/lib/pytest-lsp/changes/178.breaking.md new file mode 100644 index 0000000..a7d42d9 --- /dev/null +++ b/lib/pytest-lsp/changes/178.breaking.md @@ -0,0 +1 @@ +Drop Python 3.8 support diff --git a/lib/pytest-lsp/pytest_lsp/checks.py b/lib/pytest-lsp/pytest_lsp/checks.py index b49cd9c..8720d8a 100644 --- a/lib/pytest-lsp/pytest_lsp/checks.py +++ b/lib/pytest-lsp/pytest_lsp/checks.py @@ -9,15 +9,14 @@ """ +from __future__ import annotations + # ruff: noqa: S101 import logging import warnings from typing import Any from typing import Callable -from typing import Dict -from typing import List from typing import Optional -from typing import Set from typing import Union from lsprotocol import types @@ -27,8 +26,8 @@ ParamsChecker = Callable[[types.ClientCapabilities, Any], None] ResultChecker = Callable[[types.ClientCapabilities, Any], None] -PARAMS_CHECKS: Dict[str, ParamsChecker] = {} -RESULT_CHECKS: Dict[str, ResultChecker] = {} +PARAMS_CHECKS: dict[str, ParamsChecker] = {} +RESULT_CHECKS: dict[str, ResultChecker] = {} class LspSpecificationWarning(UserWarning): @@ -135,7 +134,7 @@ def check_params_against_client_capabilities( def check_completion_item( item: types.CompletionItem, commit_characters_support: bool, - documentation_formats: Set[str], + documentation_formats: set[str], snippet_support: bool, ): """Ensure that the given ``CompletionItem`` complies with the given capabilities.""" @@ -155,7 +154,7 @@ def check_completion_item( @check_result_for(method=types.TEXT_DOCUMENT_COMPLETION) def completion_items( capabilities: types.ClientCapabilities, - result: Union[types.CompletionList, List[types.CompletionItem], None], + result: Union[types.CompletionList, list[types.CompletionItem], None], ): """Ensure that the completion items returned from the server are compliant with the spec and the client's declared capabilities.""" @@ -230,7 +229,7 @@ def completion_item_resolve( @check_result_for(method=types.TEXT_DOCUMENT_DOCUMENT_LINK) def document_links( - capabilities: types.ClientCapabilities, result: Optional[List[types.DocumentLink]] + capabilities: types.ClientCapabilities, result: Optional[list[types.DocumentLink]] ): """Ensure that the document links returned from the server are compliant with the Spec and the client's declared capabilities.""" diff --git a/lib/pytest-lsp/pytest_lsp/client.py b/lib/pytest-lsp/pytest_lsp/client.py index 33c6dd9..b697ed9 100644 --- a/lib/pytest-lsp/pytest_lsp/client.py +++ b/lib/pytest-lsp/pytest_lsp/client.py @@ -9,6 +9,7 @@ import traceback import typing import warnings +from importlib import resources # type: ignore[no-redef] from lsprotocol import types from lsprotocol.converters import get_converter @@ -21,18 +22,8 @@ from .checks import LspSpecificationWarning from .protocol import LanguageClientProtocol -if sys.version_info < (3, 9): - import importlib_resources as resources -else: - from importlib import resources # type: ignore[no-redef] - if typing.TYPE_CHECKING: from typing import Any - from typing import Dict - from typing import List - from typing import Optional - from typing import Type - from typing import Union __version__ = "0.4.2" @@ -44,40 +35,40 @@ class LanguageClient(BaseLanguageClient): protocol: LanguageClientProtocol - def __init__(self, *args, configuration: Optional[Dict[str, Any]] = None, **kwargs): + def __init__(self, *args, configuration: dict[str, Any] | None = None, **kwargs): if "protocol_cls" not in kwargs: kwargs["protocol_cls"] = LanguageClientProtocol super().__init__("pytest-lsp-client", __version__, *args, **kwargs) - self.capabilities: Optional[types.ClientCapabilities] = None + self.capabilities: types.ClientCapabilities | None = None """The client's capabilities.""" - self.shown_documents: List[types.ShowDocumentParams] = [] + self.shown_documents: list[types.ShowDocumentParams] = [] """Holds any received show document requests.""" - self.messages: List[types.ShowMessageParams] = [] + self.messages: list[types.ShowMessageParams] = [] """Holds any received ``window/showMessage`` requests.""" - self.log_messages: List[types.LogMessageParams] = [] + self.log_messages: list[types.LogMessageParams] = [] """Holds any received ``window/logMessage`` requests.""" - self.diagnostics: Dict[str, List[types.Diagnostic]] = {} + self.diagnostics: dict[str, list[types.Diagnostic]] = {} """Holds any recieved diagnostics.""" - self.progress_reports: Dict[ - types.ProgressToken, List[types.ProgressParams] + self.progress_reports: dict[ + types.ProgressToken, list[types.ProgressParams] ] = {} """Holds any received progress updates.""" - self.error: Optional[Exception] = None + self.error: Exception | None = None """Indicates if the client encountered an error.""" config = (configuration or {"": {}}).copy() if "" not in config: config[""] = {} - self._configuration: Dict[str, Dict[str, Any]] = config + self._configuration: dict[str, dict[str, Any]] = config """Holds ``workspace/configuration`` values.""" self._setup_log_index = 0 @@ -86,7 +77,7 @@ def __init__(self, *args, configuration: Optional[Dict[str, Any]] = None, **kwar self._last_log_index = 0 """Used to keep track of which log messages correspond with which test case.""" - self._stderr_forwarder: Optional[asyncio.Task] = None + self._stderr_forwarder: asyncio.Task | None = None """A task that forwards the server's stderr to the test process.""" async def start_io(self, cmd: str, *args, **kwargs): @@ -116,7 +107,7 @@ async def server_exit(self, server: asyncio.subprocess.Process): ) def report_server_error( - self, error: Exception, source: Union[PyglsError, JsonRpcException] + self, error: Exception, source: PyglsError | JsonRpcException ): """Called when the server does something unexpected, e.g. sending malformed JSON.""" @@ -132,8 +123,8 @@ def report_server_error( self._stop_event.set() def get_configuration( - self, *, section: Optional[str] = None, scope_uri: Optional[str] = None - ) -> Optional[Any]: + self, *, section: str | None = None, scope_uri: str | None = None + ) -> Any | None: """Get a configuration value. Parameters @@ -179,8 +170,8 @@ def set_configuration( self, item: Any, *, - section: Optional[str] = None, - scope_uri: Optional[str] = None, + section: str | None = None, + scope_uri: str | None = None, ): """Set a configuration value. @@ -287,10 +278,7 @@ def cancel_all_tasks(message: str): """Called to cancel all awaited tasks.""" for task in asyncio.all_tasks(): - if sys.version_info < (3, 9): - task.cancel() - else: - task.cancel(message) + task.cancel(message) def make_test_lsp_client() -> LanguageClient: @@ -342,7 +330,7 @@ def progress(client: LanguageClient, params: types.ProgressParams): return if (kind := params.value.get("kind", None)) == "begin": - type_: Type[Any] = types.WorkDoneProgressBegin + type_: type[Any] = types.WorkDoneProgressBegin elif kind == "report": type_ = types.WorkDoneProgressReport elif kind == "end": @@ -405,7 +393,7 @@ def client_capabilities(client_spec: str) -> types.ClientCapabilities: The requested client capabilities """ - candidates: Dict[str, pathlib.Path] = {} + candidates: dict[str, pathlib.Path] = {} client_spec = client_spec.replace("-", "_") target_version = "latest" diff --git a/lib/pytest-lsp/pytest_lsp/plugin.py b/lib/pytest-lsp/pytest_lsp/plugin.py index 76ac202..49a73d1 100644 --- a/lib/pytest-lsp/pytest_lsp/plugin.py +++ b/lib/pytest-lsp/pytest_lsp/plugin.py @@ -17,9 +17,6 @@ if typing.TYPE_CHECKING: from typing import Any from typing import Callable - from typing import Dict - from typing import List - from typing import Optional logger = logging.getLogger("client") @@ -29,7 +26,7 @@ class ClientServerConfig: """Configuration for a Client-Server connection.""" - server_command: List[str] + server_command: list[str] """The command to use to start the language server.""" client_factory: Callable[[], JsonRPCClient] = attrs.field( @@ -37,10 +34,10 @@ class ClientServerConfig: ) """Factory function to use when constructing the test client instance.""" - server_env: Optional[Dict[str, str]] = attrs.field(default=None) + server_env: dict[str, str] | None = attrs.field(default=None) """Environment variables to set when starting the server.""" - def _get_devtools_command(self, server: str) -> List[str]: + def _get_devtools_command(self, server: str) -> list[str]: """Get the lsp-devtools command required to connect to the given ``server``""" if ":" in server: @@ -55,7 +52,7 @@ def _get_devtools_command(self, server: str) -> List[str]: return ["lsp-devtools", "agent", "--host", host, "--port", port, "--"] - def get_server_command(self, devtools: Optional[str] = None) -> List[str]: + def get_server_command(self, devtools: str | None = None) -> list[str]: """Get the command to start the server with.""" server_command = [] if devtools is not None: @@ -65,7 +62,7 @@ def get_server_command(self, devtools: Optional[str] = None) -> List[str]: return server_command - async def start(self, devtools: Optional[str] = None) -> JsonRPCClient: + async def start(self, devtools: str | None = None) -> JsonRPCClient: """Return the client instance to use for the test. Parameters @@ -102,7 +99,7 @@ def pytest_addoption(parser): def pytest_runtest_makereport(item: pytest.Item, call: pytest.CallInfo): """Add any captured log messages to the report.""" - client: Optional[LanguageClient] = None + client: LanguageClient | None = None if not hasattr(item, "funcargs"): return @@ -162,7 +159,7 @@ def get_fixture_arguments( dict The set of arguments to pass to the user's fixture function """ - kwargs: Dict[str, Any] = {} + kwargs: dict[str, Any] = {} required_parameters = set(inspect.signature(fn).parameters.keys()) # Inject the 'request' fixture if requested diff --git a/lib/pytest-lsp/ruff_defaults.toml b/lib/pytest-lsp/ruff_defaults.toml index 9b62f5a..301a10e 100644 --- a/lib/pytest-lsp/ruff_defaults.toml +++ b/lib/pytest-lsp/ruff_defaults.toml @@ -100,7 +100,6 @@ select = [ "E742", "E743", "E902", - "E999", "EM101", "EM102", "EM103", @@ -244,7 +243,6 @@ select = [ "PLR0133", "PLR0206", "PLR0402", - "PLR1701", "PLR1711", "PLR1714", "PLR1722", From c7f2321d73eae3f78b7cc3af372115f82be6d278 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Mon, 26 Aug 2024 15:08:56 +0100 Subject: [PATCH 06/12] pytest-lsp: Set a preview version number --- lib/pytest-lsp/hatch.toml | 2 +- lib/pytest-lsp/pytest_lsp/client.py | 2 +- scripts/make_release.py | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/pytest-lsp/hatch.toml b/lib/pytest-lsp/hatch.toml index 24d59a2..1b94a8c 100644 --- a/lib/pytest-lsp/hatch.toml +++ b/lib/pytest-lsp/hatch.toml @@ -12,7 +12,7 @@ packages = ["pytest_lsp"] dependencies = ["pytest-asyncio"] [[envs.hatch-test.matrix]] -python = ["3.8", "3.9", "3.10", "3.11", "3.12"] +python = ["3.9", "3.10", "3.11", "3.12"] pytest = ["7", "8"] [envs.hatch-test.overrides] diff --git a/lib/pytest-lsp/pytest_lsp/client.py b/lib/pytest-lsp/pytest_lsp/client.py index b697ed9..a6fe534 100644 --- a/lib/pytest-lsp/pytest_lsp/client.py +++ b/lib/pytest-lsp/pytest_lsp/client.py @@ -26,7 +26,7 @@ from typing import Any -__version__ = "0.4.2" +__version__ = "1.0.0b0" logger = logging.getLogger(__name__) diff --git a/scripts/make_release.py b/scripts/make_release.py index 6dcdf0f..01b47e2 100755 --- a/scripts/make_release.py +++ b/scripts/make_release.py @@ -89,9 +89,10 @@ class Component(TypedDict): for c in [ Component( name="pytest-lsp", - bump_breaking="major", - bump_minor="minor", - bump_patch="patch", + # Everything is a beta version bump until we make a proper release + bump_breaking="b", + bump_minor="b", + bump_patch="b", commit_prefix="pytest-lsp v", src="lib/pytest-lsp", tag_prefix="pytest-lsp-v", From 1809d3a2cb683469b796dda0a16d79cb2ceee66d Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Mon, 26 Aug 2024 15:17:25 +0100 Subject: [PATCH 07/12] pytest-lsp: Drop support for pytest v7 --- lib/pytest-lsp/changes/180.breaking.md | 1 + lib/pytest-lsp/hatch.toml | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 lib/pytest-lsp/changes/180.breaking.md diff --git a/lib/pytest-lsp/changes/180.breaking.md b/lib/pytest-lsp/changes/180.breaking.md new file mode 100644 index 0000000..2d0b48c --- /dev/null +++ b/lib/pytest-lsp/changes/180.breaking.md @@ -0,0 +1 @@ +Drop support for pytest v7 diff --git a/lib/pytest-lsp/hatch.toml b/lib/pytest-lsp/hatch.toml index 1b94a8c..4347cf2 100644 --- a/lib/pytest-lsp/hatch.toml +++ b/lib/pytest-lsp/hatch.toml @@ -13,11 +13,10 @@ dependencies = ["pytest-asyncio"] [[envs.hatch-test.matrix]] python = ["3.9", "3.10", "3.11", "3.12"] -pytest = ["7", "8"] +pytest = ["8"] [envs.hatch-test.overrides] matrix.pytest.dependencies = [ - { value = "pytest>=7,<8", if = ["7"] }, { value = "pytest>=8,<9", if = ["8"] }, ] From f2c7d6a9f2f2f4d2e924bac1c7dbad1cbd437576 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Mon, 26 Aug 2024 15:20:23 +0100 Subject: [PATCH 08/12] pytest-lsp: Add support for Python 3.13 --- .github/workflows/pytest-lsp-pr.yml | 2 +- lib/pytest-lsp/changes/180.misc.md | 1 + lib/pytest-lsp/hatch.toml | 2 +- lib/pytest-lsp/pyproject.toml | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 lib/pytest-lsp/changes/180.misc.md diff --git a/.github/workflows/pytest-lsp-pr.yml b/.github/workflows/pytest-lsp-pr.yml index 7979892..0c44fcf 100644 --- a/.github/workflows/pytest-lsp-pr.yml +++ b/.github/workflows/pytest-lsp-pr.yml @@ -41,7 +41,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] os: [ubuntu-latest, windows-latest] steps: diff --git a/lib/pytest-lsp/changes/180.misc.md b/lib/pytest-lsp/changes/180.misc.md new file mode 100644 index 0000000..f32ba63 --- /dev/null +++ b/lib/pytest-lsp/changes/180.misc.md @@ -0,0 +1 @@ +Add support for Python 3.13 diff --git a/lib/pytest-lsp/hatch.toml b/lib/pytest-lsp/hatch.toml index 4347cf2..0e7cf09 100644 --- a/lib/pytest-lsp/hatch.toml +++ b/lib/pytest-lsp/hatch.toml @@ -12,7 +12,7 @@ packages = ["pytest_lsp"] dependencies = ["pytest-asyncio"] [[envs.hatch-test.matrix]] -python = ["3.9", "3.10", "3.11", "3.12"] +python = ["3.9", "3.10", "3.11", "3.12", "3.13"] pytest = ["8"] [envs.hatch-test.overrides] diff --git a/lib/pytest-lsp/pyproject.toml b/lib/pytest-lsp/pyproject.toml index 9002f99..a22842f 100644 --- a/lib/pytest-lsp/pyproject.toml +++ b/lib/pytest-lsp/pyproject.toml @@ -21,9 +21,9 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ] dependencies = [ - "importlib-resources; python_version<\"3.9\"", "packaging", "pygls>=1.1.0", "pytest", From 541844e88df021710dae2e499a2e057d88c92955 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sat, 24 Aug 2024 10:23:46 +0100 Subject: [PATCH 09/12] pytest-lsp: Migrate to pygls v2 --- lib/pytest-lsp/changes/177.misc.md | 1 + lib/pytest-lsp/hatch.toml | 3 ++ lib/pytest-lsp/pyproject.toml | 4 +- lib/pytest-lsp/pytest_lsp/checks.py | 2 +- .../examples/client-capabilities/server.py | 2 +- .../tests/examples/diagnostics/server.py | 38 +++++++++---------- .../examples/fixture-passthrough/server.py | 2 +- .../tests/examples/fixture-scope/server.py | 2 +- .../tests/examples/generic-rpc/server.py | 22 ++++++----- .../examples/getting-started-fail/server.py | 2 +- .../tests/examples/getting-started/server.py | 2 +- .../examples/parameterised-clients/server.py | 2 +- .../tests/examples/server-stderr/server.py | 2 +- .../examples/window-create-progress/server.py | 22 +++++------ .../window-log-message-fail/server.py | 17 ++++++--- .../examples/window-log-message/server.py | 16 +++++--- .../examples/window-show-document/server.py | 19 ++++------ .../examples/window-show-message/server.py | 17 ++++++--- .../workspace-configuration/server.py | 6 +-- lib/pytest-lsp/tests/servers/capabilities.py | 2 +- .../tests/servers/completion_exit.py | 12 +++--- lib/pytest-lsp/tests/servers/invalid_json.py | 16 ++++---- lib/pytest-lsp/tests/test_checks.py | 10 ++--- 23 files changed, 115 insertions(+), 106 deletions(-) create mode 100644 lib/pytest-lsp/changes/177.misc.md diff --git a/lib/pytest-lsp/changes/177.misc.md b/lib/pytest-lsp/changes/177.misc.md new file mode 100644 index 0000000..d89c711 --- /dev/null +++ b/lib/pytest-lsp/changes/177.misc.md @@ -0,0 +1 @@ +Migrate to pygls v2 diff --git a/lib/pytest-lsp/hatch.toml b/lib/pytest-lsp/hatch.toml index 0e7cf09..ff88486 100644 --- a/lib/pytest-lsp/hatch.toml +++ b/lib/pytest-lsp/hatch.toml @@ -11,6 +11,9 @@ packages = ["pytest_lsp"] [envs.hatch-test] dependencies = ["pytest-asyncio"] +[envs.hatch-test.env-vars] +UV_PRERELEASE="allow" + [[envs.hatch-test.matrix]] python = ["3.9", "3.10", "3.11", "3.12", "3.13"] pytest = ["8"] diff --git a/lib/pytest-lsp/pyproject.toml b/lib/pytest-lsp/pyproject.toml index a22842f..e0c3a65 100644 --- a/lib/pytest-lsp/pyproject.toml +++ b/lib/pytest-lsp/pyproject.toml @@ -11,7 +11,7 @@ requires-python = ">=3.9" license = { text = "MIT" } authors = [{ name = "Alex Carney", email = "alcarneyme@gmail.com" }] classifiers = [ - "Development Status :: 3 - Alpha", + "Development Status :: 4 - Beta", "License :: OSI Approved :: MIT License", "Framework :: Pytest", "Programming Language :: Python", @@ -25,7 +25,7 @@ classifiers = [ ] dependencies = [ "packaging", - "pygls>=1.1.0", + "pygls>=2.0.0a1", "pytest", "pytest-asyncio>=0.23", ] diff --git a/lib/pytest-lsp/pytest_lsp/checks.py b/lib/pytest-lsp/pytest_lsp/checks.py index 8720d8a..9ac8005 100644 --- a/lib/pytest-lsp/pytest_lsp/checks.py +++ b/lib/pytest-lsp/pytest_lsp/checks.py @@ -260,7 +260,7 @@ def work_done_progress_create( @check_params_of(method=types.WORKSPACE_CONFIGURATION) def workspace_configuration( capabilities: types.ClientCapabilities, - params: types.WorkspaceConfigurationParams, + params: types.ConfigurationParams, ): """Ensure that the client has support for ``workspace/configuration`` requests.""" is_supported = get_capability(capabilities, "workspace.configuration", False) diff --git a/lib/pytest-lsp/tests/examples/client-capabilities/server.py b/lib/pytest-lsp/tests/examples/client-capabilities/server.py index 7f63083..340d104 100644 --- a/lib/pytest-lsp/tests/examples/client-capabilities/server.py +++ b/lib/pytest-lsp/tests/examples/client-capabilities/server.py @@ -4,7 +4,7 @@ CompletionParams, InsertTextFormat, ) -from pygls.server import LanguageServer +from pygls.lsp.server import LanguageServer server = LanguageServer("hello-world", "v1") diff --git a/lib/pytest-lsp/tests/examples/diagnostics/server.py b/lib/pytest-lsp/tests/examples/diagnostics/server.py index 5b07c58..0379395 100644 --- a/lib/pytest-lsp/tests/examples/diagnostics/server.py +++ b/lib/pytest-lsp/tests/examples/diagnostics/server.py @@ -1,28 +1,24 @@ -from lsprotocol.types import ( - TEXT_DOCUMENT_DID_OPEN, - Diagnostic, - DidOpenTextDocumentParams, - Position, - Range, -) -from pygls.server import LanguageServer +from lsprotocol import types +from pygls.lsp.server import LanguageServer server = LanguageServer("diagnostic-server", "v1") -@server.feature(TEXT_DOCUMENT_DID_OPEN) -def did_open(ls: LanguageServer, params: DidOpenTextDocumentParams): - ls.publish_diagnostics( - params.text_document.uri, - [ - Diagnostic( - message="There is an error here.", - range=Range( - start=Position(line=1, character=1), - end=Position(line=1, character=10), - ), - ) - ], +@server.feature(types.TEXT_DOCUMENT_DID_OPEN) +def did_open(ls: LanguageServer, params: types.DidOpenTextDocumentParams): + ls.text_document_publish_diagnostics( + types.PublishDiagnosticsParams( + uri=params.text_document.uri, + diagnostics=[ + types.Diagnostic( + message="There is an error here.", + range=types.Range( + start=types.Position(line=1, character=1), + end=types.Position(line=1, character=10), + ), + ) + ], + ) ) diff --git a/lib/pytest-lsp/tests/examples/fixture-passthrough/server.py b/lib/pytest-lsp/tests/examples/fixture-passthrough/server.py index 333c1b5..da8fc40 100644 --- a/lib/pytest-lsp/tests/examples/fixture-passthrough/server.py +++ b/lib/pytest-lsp/tests/examples/fixture-passthrough/server.py @@ -1,5 +1,5 @@ from lsprotocol.types import TEXT_DOCUMENT_COMPLETION, CompletionItem, CompletionParams -from pygls.server import LanguageServer +from pygls.lsp.server import LanguageServer server = LanguageServer("hello-world", "v1") diff --git a/lib/pytest-lsp/tests/examples/fixture-scope/server.py b/lib/pytest-lsp/tests/examples/fixture-scope/server.py index 333c1b5..da8fc40 100644 --- a/lib/pytest-lsp/tests/examples/fixture-scope/server.py +++ b/lib/pytest-lsp/tests/examples/fixture-scope/server.py @@ -1,5 +1,5 @@ from lsprotocol.types import TEXT_DOCUMENT_COMPLETION, CompletionItem, CompletionParams -from pygls.server import LanguageServer +from pygls.lsp.server import LanguageServer server = LanguageServer("hello-world", "v1") diff --git a/lib/pytest-lsp/tests/examples/generic-rpc/server.py b/lib/pytest-lsp/tests/examples/generic-rpc/server.py index 3381860..20cc043 100644 --- a/lib/pytest-lsp/tests/examples/generic-rpc/server.py +++ b/lib/pytest-lsp/tests/examples/generic-rpc/server.py @@ -1,27 +1,29 @@ from pygls.protocol import JsonRPCProtocol, default_converter -from pygls.server import Server +from pygls.server import JsonRPCServer -server = Server(protocol_cls=JsonRPCProtocol, converter_factory=default_converter) +server = JsonRPCServer( + protocol_cls=JsonRPCProtocol, converter_factory=default_converter +) -@server.lsp.fm.feature("math/add") -def addition(ls: Server, params): +@server.feature("math/add") +def addition(ls: JsonRPCServer, params): a = params.a b = params.b - ls.lsp.notify("log/message", dict(message=f"{a=}")) - ls.lsp.notify("log/message", dict(message=f"{b=}")) + ls.protocol.notify("log/message", dict(message=f"{a=}")) + ls.protocol.notify("log/message", dict(message=f"{b=}")) return dict(total=a + b) -@server.lsp.fm.feature("math/sub") -def subtraction(ls: Server, params): +@server.feature("math/sub") +def subtraction(ls: JsonRPCServer, params): a = params.a b = params.b - ls.lsp.notify("log/message", dict(message=f"{a=}")) - ls.lsp.notify("log/message", dict(message=f"{b=}")) + ls.protocol.notify("log/message", dict(message=f"{a=}")) + ls.protocol.notify("log/message", dict(message=f"{b=}")) return dict(total=b - a) diff --git a/lib/pytest-lsp/tests/examples/getting-started-fail/server.py b/lib/pytest-lsp/tests/examples/getting-started-fail/server.py index a14d5a2..025b6cc 100644 --- a/lib/pytest-lsp/tests/examples/getting-started-fail/server.py +++ b/lib/pytest-lsp/tests/examples/getting-started-fail/server.py @@ -1,5 +1,5 @@ from lsprotocol.types import TEXT_DOCUMENT_COMPLETION, CompletionItem, CompletionParams -from pygls.server import LanguageServer +from pygls.lsp.server import LanguageServer server = LanguageServer("hello-world", "v1") diff --git a/lib/pytest-lsp/tests/examples/getting-started/server.py b/lib/pytest-lsp/tests/examples/getting-started/server.py index 333c1b5..da8fc40 100644 --- a/lib/pytest-lsp/tests/examples/getting-started/server.py +++ b/lib/pytest-lsp/tests/examples/getting-started/server.py @@ -1,5 +1,5 @@ from lsprotocol.types import TEXT_DOCUMENT_COMPLETION, CompletionItem, CompletionParams -from pygls.server import LanguageServer +from pygls.lsp.server import LanguageServer server = LanguageServer("hello-world", "v1") diff --git a/lib/pytest-lsp/tests/examples/parameterised-clients/server.py b/lib/pytest-lsp/tests/examples/parameterised-clients/server.py index 333c1b5..da8fc40 100644 --- a/lib/pytest-lsp/tests/examples/parameterised-clients/server.py +++ b/lib/pytest-lsp/tests/examples/parameterised-clients/server.py @@ -1,5 +1,5 @@ from lsprotocol.types import TEXT_DOCUMENT_COMPLETION, CompletionItem, CompletionParams -from pygls.server import LanguageServer +from pygls.lsp.server import LanguageServer server = LanguageServer("hello-world", "v1") diff --git a/lib/pytest-lsp/tests/examples/server-stderr/server.py b/lib/pytest-lsp/tests/examples/server-stderr/server.py index c4886e5..0f53138 100644 --- a/lib/pytest-lsp/tests/examples/server-stderr/server.py +++ b/lib/pytest-lsp/tests/examples/server-stderr/server.py @@ -1,7 +1,7 @@ import sys from lsprotocol import types -from pygls.server import LanguageServer +from pygls.lsp.server import LanguageServer server = LanguageServer("server-stderr", "v1") diff --git a/lib/pytest-lsp/tests/examples/window-create-progress/server.py b/lib/pytest-lsp/tests/examples/window-create-progress/server.py index b2819fa..47044fd 100644 --- a/lib/pytest-lsp/tests/examples/window-create-progress/server.py +++ b/lib/pytest-lsp/tests/examples/window-create-progress/server.py @@ -1,7 +1,7 @@ from unittest.mock import Mock from lsprotocol import types -from pygls.server import LanguageServer +from pygls.lsp.server import LanguageServer server = LanguageServer("window-create-progress", "v1") @@ -10,21 +10,21 @@ async def do_progress(ls: LanguageServer, *args): token = "a-token" - await ls.progress.create_async(token) + await ls.work_done_progress.create_async(token) # Begin - ls.progress.begin( + ls.work_done_progress.begin( token, types.WorkDoneProgressBegin(title="Indexing", percentage=0), ) # Report for i in range(1, 4): - ls.progress.report( + ls.work_done_progress.report( token, types.WorkDoneProgressReport(message=f"{i * 25}%", percentage=i * 25), ) # End - ls.progress.end(token, types.WorkDoneProgressEnd(message="Finished")) + ls.work_done_progress.end(token, types.WorkDoneProgressEnd(message="Finished")) return "a result" @@ -34,11 +34,11 @@ async def duplicate_progress(ls: LanguageServer, *args): token = "duplicate-token" # Need to stop pygls preventing us from using the progress API wrong. - ls.progress._check_token_registered = Mock() - await ls.progress.create_async(token) + ls.work_done_progress._check_token_registered = Mock() + await ls.work_done_progress.create_async(token) # pytest-lsp should return an error here. - await ls.progress.create_async(token) + await ls.work_done_progress.create_async(token) @server.command("no.progress") @@ -46,18 +46,18 @@ async def no_progress(ls: LanguageServer, *args): token = "undefined-token" # Begin - ls.progress.begin( + ls.work_done_progress.begin( token, types.WorkDoneProgressBegin(title="Indexing", percentage=0, cancellable=False), ) # Report for i in range(1, 4): - ls.progress.report( + ls.work_done_progress.report( token, types.WorkDoneProgressReport(message=f"{i * 25}%", percentage=i * 25), ) # End - ls.progress.end(token, types.WorkDoneProgressEnd(message="Finished")) + ls.work_done_progress.end(token, types.WorkDoneProgressEnd(message="Finished")) if __name__ == "__main__": diff --git a/lib/pytest-lsp/tests/examples/window-log-message-fail/server.py b/lib/pytest-lsp/tests/examples/window-log-message-fail/server.py index b9f762b..8794e30 100644 --- a/lib/pytest-lsp/tests/examples/window-log-message-fail/server.py +++ b/lib/pytest-lsp/tests/examples/window-log-message-fail/server.py @@ -1,16 +1,21 @@ -from lsprotocol.types import TEXT_DOCUMENT_COMPLETION, CompletionItem, CompletionParams -from pygls.server import LanguageServer +from lsprotocol import types +from pygls.lsp.server import LanguageServer server = LanguageServer("window-log-message", "v1") -@server.feature(TEXT_DOCUMENT_COMPLETION) -def completion(ls: LanguageServer, params: CompletionParams): +@server.feature(types.TEXT_DOCUMENT_COMPLETION) +def completion(ls: LanguageServer, params: types.CompletionParams): items = [] for i in range(10): - ls.show_message_log(f"Suggesting item {i}") - items.append(CompletionItem(label=f"item-{i}")) + ls.window_log_message( + types.LogMessageParams( + message=f"Suggesting item {i}", + type=types.MessageType.Log, + ) + ) + items.append(types.CompletionItem(label=f"item-{i}")) return items diff --git a/lib/pytest-lsp/tests/examples/window-log-message/server.py b/lib/pytest-lsp/tests/examples/window-log-message/server.py index b9f762b..12fa57d 100644 --- a/lib/pytest-lsp/tests/examples/window-log-message/server.py +++ b/lib/pytest-lsp/tests/examples/window-log-message/server.py @@ -1,16 +1,20 @@ -from lsprotocol.types import TEXT_DOCUMENT_COMPLETION, CompletionItem, CompletionParams -from pygls.server import LanguageServer +from lsprotocol import types +from pygls.lsp.server import LanguageServer server = LanguageServer("window-log-message", "v1") -@server.feature(TEXT_DOCUMENT_COMPLETION) -def completion(ls: LanguageServer, params: CompletionParams): +@server.feature(types.TEXT_DOCUMENT_COMPLETION) +def completion(ls: LanguageServer, params: types.CompletionParams): items = [] for i in range(10): - ls.show_message_log(f"Suggesting item {i}") - items.append(CompletionItem(label=f"item-{i}")) + ls.window_log_message( + types.LogMessageParams( + message=f"Suggesting item {i}", type=types.MessageType.Log + ) + ) + items.append(types.CompletionItem(label=f"item-{i}")) return items diff --git a/lib/pytest-lsp/tests/examples/window-show-document/server.py b/lib/pytest-lsp/tests/examples/window-show-document/server.py index 2cf056b..17f3527 100644 --- a/lib/pytest-lsp/tests/examples/window-show-document/server.py +++ b/lib/pytest-lsp/tests/examples/window-show-document/server.py @@ -1,21 +1,18 @@ -from lsprotocol.types import ( - TEXT_DOCUMENT_COMPLETION, - CompletionItem, - CompletionParams, - ShowDocumentParams, -) -from pygls.server import LanguageServer +from lsprotocol import types +from pygls.lsp.server import LanguageServer server = LanguageServer("window-show-document", "v1") -@server.feature(TEXT_DOCUMENT_COMPLETION) -async def completion(ls: LanguageServer, params: CompletionParams): +@server.feature(types.TEXT_DOCUMENT_COMPLETION) +async def completion(ls: LanguageServer, params: types.CompletionParams): items = [] - await ls.show_document_async(ShowDocumentParams(uri=params.text_document.uri)) + await ls.window_show_document_async( + types.ShowDocumentParams(uri=params.text_document.uri) + ) for i in range(10): - items.append(CompletionItem(label=f"item-{i}")) + items.append(types.CompletionItem(label=f"item-{i}")) return items diff --git a/lib/pytest-lsp/tests/examples/window-show-message/server.py b/lib/pytest-lsp/tests/examples/window-show-message/server.py index 9b272ca..bc39e7a 100644 --- a/lib/pytest-lsp/tests/examples/window-show-message/server.py +++ b/lib/pytest-lsp/tests/examples/window-show-message/server.py @@ -1,16 +1,21 @@ -from lsprotocol.types import TEXT_DOCUMENT_COMPLETION, CompletionItem, CompletionParams -from pygls.server import LanguageServer +from lsprotocol import types +from pygls.lsp.server import LanguageServer server = LanguageServer("window-show-message", "v1") -@server.feature(TEXT_DOCUMENT_COMPLETION) -def completion(ls: LanguageServer, params: CompletionParams): +@server.feature(types.TEXT_DOCUMENT_COMPLETION) +def completion(ls: LanguageServer, params: types.CompletionParams): items = [] for i in range(10): - ls.show_message(f"Suggesting item {i}") - items.append(CompletionItem(label=f"item-{i}")) + ls.window_show_message( + types.ShowMessageParams( + message=f"Suggesting item {i}", + type=types.MessageType.Log, + ) + ) + items.append(types.CompletionItem(label=f"item-{i}")) return items diff --git a/lib/pytest-lsp/tests/examples/workspace-configuration/server.py b/lib/pytest-lsp/tests/examples/workspace-configuration/server.py index 3d35bde..a7fad45 100644 --- a/lib/pytest-lsp/tests/examples/workspace-configuration/server.py +++ b/lib/pytest-lsp/tests/examples/workspace-configuration/server.py @@ -1,13 +1,13 @@ from lsprotocol import types -from pygls.server import LanguageServer +from pygls.lsp.server import LanguageServer server = LanguageServer("workspace-configuration", "v1") @server.command("server.configuration") async def configuration(ls: LanguageServer, *args): - results = await ls.get_configuration_async( - types.WorkspaceConfigurationParams( + results = await ls.workspace_configuration_async( + types.ConfigurationParams( items=[ types.ConfigurationItem(scope_uri="file://workspace/file.txt"), types.ConfigurationItem(section="not.found"), diff --git a/lib/pytest-lsp/tests/servers/capabilities.py b/lib/pytest-lsp/tests/servers/capabilities.py index ee5840c..ebd404b 100644 --- a/lib/pytest-lsp/tests/servers/capabilities.py +++ b/lib/pytest-lsp/tests/servers/capabilities.py @@ -1,5 +1,5 @@ from lsprotocol.converters import get_converter -from pygls.server import LanguageServer +from pygls.lsp.server import LanguageServer converter = get_converter() server = LanguageServer(name="capabilities-server", version="v1.0") diff --git a/lib/pytest-lsp/tests/servers/completion_exit.py b/lib/pytest-lsp/tests/servers/completion_exit.py index ddb8289..5c2defc 100644 --- a/lib/pytest-lsp/tests/servers/completion_exit.py +++ b/lib/pytest-lsp/tests/servers/completion_exit.py @@ -1,10 +1,8 @@ # A server that exits mid request. import sys -from lsprotocol.types import TEXT_DOCUMENT_COMPLETION -from lsprotocol.types import CompletionItem -from lsprotocol.types import CompletionParams -from pygls.server import LanguageServer +from lsprotocol import types +from pygls.lsp.server import LanguageServer class CountingLanguageServer(LanguageServer): @@ -14,13 +12,13 @@ class CountingLanguageServer(LanguageServer): server = CountingLanguageServer(name="completion-exit-server", version="v1.0") -@server.feature(TEXT_DOCUMENT_COMPLETION) -def on_complete(server: CountingLanguageServer, params: CompletionParams): +@server.feature(types.TEXT_DOCUMENT_COMPLETION) +def on_complete(server: CountingLanguageServer, params: types.CompletionParams): server.count += 1 if server.count == 5: sys.exit(0) - return [CompletionItem(label=f"{server.count}")] + return [types.CompletionItem(label=f"{server.count}")] if __name__ == "__main__": diff --git a/lib/pytest-lsp/tests/servers/invalid_json.py b/lib/pytest-lsp/tests/servers/invalid_json.py index b1d10bf..149394c 100644 --- a/lib/pytest-lsp/tests/servers/invalid_json.py +++ b/lib/pytest-lsp/tests/servers/invalid_json.py @@ -1,10 +1,8 @@ # A server that returns a message that cannot be parsed as JSON. import json -from lsprotocol.types import TEXT_DOCUMENT_COMPLETION -from lsprotocol.types import CompletionItem -from lsprotocol.types import CompletionParams -from pygls.server import LanguageServer +from lsprotocol import types +from pygls.lsp.server import LanguageServer server = LanguageServer(name="completion-exit-server", version="v1.0") @@ -14,7 +12,7 @@ def bad_send_data(data): if not data: return - self = server.lsp + self = server.protocol body = json.dumps(data, default=self._serialize_message) body = body.replace('"', "'").encode(self.CHARSET) header = ( @@ -25,10 +23,10 @@ def bad_send_data(data): self.transport.write(header + body) -@server.feature(TEXT_DOCUMENT_COMPLETION) -def on_complete(server: LanguageServer, params: CompletionParams): - server.lsp._send_data = bad_send_data - return [CompletionItem(label="item-one")] +@server.feature(types.TEXT_DOCUMENT_COMPLETION) +def on_complete(server: LanguageServer, params: types.CompletionParams): + server.protocol._send_data = bad_send_data + return [types.CompletionItem(label="item-one")] if __name__ == "__main__": diff --git a/lib/pytest-lsp/tests/test_checks.py b/lib/pytest-lsp/tests/test_checks.py index a815c90..1e71516 100644 --- a/lib/pytest-lsp/tests/test_checks.py +++ b/lib/pytest-lsp/tests/test_checks.py @@ -36,7 +36,7 @@ workspace=types.WorkspaceClientCapabilities(configuration=False) ), types.WORKSPACE_CONFIGURATION, - types.WorkspaceConfigurationParams(items=[]), + types.ConfigurationParams(items=[]), "does not support 'workspace/configuration'", ), ( @@ -44,7 +44,7 @@ workspace=types.WorkspaceClientCapabilities(configuration=True) ), types.WORKSPACE_CONFIGURATION, - types.WorkspaceConfigurationParams(items=[]), + types.ConfigurationParams(items=[]), None, ), ], @@ -104,7 +104,7 @@ def test_params_check_warning( types.ClientCapabilities( text_document=types.TextDocumentClientCapabilities( completion=types.CompletionClientCapabilities( - completion_item=types.CompletionClientCapabilitiesCompletionItemType( + completion_item=types.ClientCompletionItemOptions( commit_characters_support=True ) ) @@ -135,7 +135,7 @@ def test_params_check_warning( types.ClientCapabilities( text_document=types.TextDocumentClientCapabilities( completion=types.CompletionClientCapabilities( - completion_item=types.CompletionClientCapabilitiesCompletionItemType( + completion_item=types.ClientCompletionItemOptions( documentation_format=[types.MarkupKind.Markdown] ) ) @@ -171,7 +171,7 @@ def test_params_check_warning( types.ClientCapabilities( text_document=types.TextDocumentClientCapabilities( completion=types.CompletionClientCapabilities( - completion_item=types.CompletionClientCapabilitiesCompletionItemType( + completion_item=types.ClientCompletionItemOptions( snippet_support=True ) ) From fb7f6cba5619db72f01904e2867183378e4d70bc Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Thu, 29 Aug 2024 21:14:24 +0100 Subject: [PATCH 10/12] pytest-lsp: Bump pytest-asyncio to 0.24 --- lib/pytest-lsp/changes/182.misc.md | 1 + lib/pytest-lsp/pyproject.toml | 3 +- lib/pytest-lsp/pyrightconfig.json | 3 -- lib/pytest-lsp/pytest_lsp/plugin.py | 5 +++ .../tests/examples/fixture-scope/t_server.py | 4 +-- lib/pytest-lsp/tests/test_client.py | 3 +- lib/pytest-lsp/tests/test_examples.py | 33 ++++++++++++++----- lib/pytest-lsp/tests/test_plugin.py | 1 + 8 files changed, 37 insertions(+), 16 deletions(-) create mode 100644 lib/pytest-lsp/changes/182.misc.md delete mode 100644 lib/pytest-lsp/pyrightconfig.json diff --git a/lib/pytest-lsp/changes/182.misc.md b/lib/pytest-lsp/changes/182.misc.md new file mode 100644 index 0000000..0c3010e --- /dev/null +++ b/lib/pytest-lsp/changes/182.misc.md @@ -0,0 +1 @@ +Bump minimum `pytest-asyncio` verision to `v0.24` diff --git a/lib/pytest-lsp/pyproject.toml b/lib/pytest-lsp/pyproject.toml index e0c3a65..5076714 100644 --- a/lib/pytest-lsp/pyproject.toml +++ b/lib/pytest-lsp/pyproject.toml @@ -27,7 +27,7 @@ dependencies = [ "packaging", "pygls>=2.0.0a1", "pytest", - "pytest-asyncio>=0.23", + "pytest-asyncio>=0.24", ] [project.urls] @@ -48,6 +48,7 @@ sort = "Cover" [tool.pytest.ini_options] asyncio_mode = "auto" +asyncio_default_fixture_loop_scope = "function" [tool.towncrier] filename = "CHANGES.md" diff --git a/lib/pytest-lsp/pyrightconfig.json b/lib/pytest-lsp/pyrightconfig.json deleted file mode 100644 index 0622ac8..0000000 --- a/lib/pytest-lsp/pyrightconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "venv": ".env" -} diff --git a/lib/pytest-lsp/pytest_lsp/plugin.py b/lib/pytest-lsp/pytest_lsp/plugin.py index 49a73d1..95f222a 100644 --- a/lib/pytest-lsp/pytest_lsp/plugin.py +++ b/lib/pytest-lsp/pytest_lsp/plugin.py @@ -196,6 +196,11 @@ def fixture( """ def wrapper(fn): + # pytest-asyncio says `loop_scope` should be present and match `scope` + # https://pytest-asyncio.readthedocs.io/en/latest/how-to-guides/migrate_from_0_23.html + if "scope" in kwargs: + kwargs["loop_scope"] = kwargs["scope"] + @pytest_asyncio.fixture(**kwargs) async def the_fixture(request): devtools = request.config.getoption("devtools") diff --git a/lib/pytest-lsp/tests/examples/fixture-scope/t_server.py b/lib/pytest-lsp/tests/examples/fixture-scope/t_server.py index 1a7d73a..572f826 100644 --- a/lib/pytest-lsp/tests/examples/fixture-scope/t_server.py +++ b/lib/pytest-lsp/tests/examples/fixture-scope/t_server.py @@ -21,7 +21,7 @@ async def client(lsp_client: LanguageClient): await lsp_client.shutdown_session() -@pytest.mark.asyncio(scope="module") +@pytest.mark.asyncio(loop_scope="module") async def test_completion_hello(client: LanguageClient): """Ensure that the server implements completions correctly.""" @@ -42,7 +42,7 @@ async def test_completion_hello(client: LanguageClient): assert "hello" in labels -@pytest.mark.asyncio(scope="module") +@pytest.mark.asyncio(loop_scope="module") async def test_completion_world(client: LanguageClient): """Ensure that the server implements completions correctly.""" diff --git a/lib/pytest-lsp/tests/test_client.py b/lib/pytest-lsp/tests/test_client.py index 80d9f3c..300d53c 100644 --- a/lib/pytest-lsp/tests/test_client.py +++ b/lib/pytest-lsp/tests/test_client.py @@ -61,6 +61,7 @@ def test_client_capabilities( """ [pytest] asyncio_mode = auto + asyncio_default_fixture_loop_scope = function """ ) @@ -116,7 +117,7 @@ async def test_capabilities(client): ) results = pytester.runpytest("-vv") - results.assert_outcomes(passed=1) + results.assert_outcomes(passed=1, warnings=0) @pytest.mark.parametrize( diff --git a/lib/pytest-lsp/tests/test_examples.py b/lib/pytest-lsp/tests/test_examples.py index 7ee0b17..5e5055d 100644 --- a/lib/pytest-lsp/tests/test_examples.py +++ b/lib/pytest-lsp/tests/test_examples.py @@ -10,6 +10,7 @@ def setup_test(pytester: pytest.Pytester, example_name: str): """\ [pytest] asyncio_mode = auto +asyncio_default_fixture_loop_scope = function """ ) @@ -24,21 +25,35 @@ def setup_test(pytester: pytest.Pytester, example_name: str): @pytest.mark.parametrize( "name, expected", [ - pytest.param("diagnostics", dict(passed=1), id="diagnostics"), - pytest.param("getting-started", dict(passed=1), id="getting-started"), - pytest.param("fixture-passthrough", dict(passed=1), id="fixture-passthrough"), - pytest.param("fixture-scope", dict(passed=2), id="fixture-scope"), + pytest.param("diagnostics", dict(passed=1, warnings=0), id="diagnostics"), pytest.param( - "parameterised-clients", dict(passed=2), id="parameterised-clients" + "getting-started", dict(passed=1, warnings=0), id="getting-started" + ), + pytest.param( + "fixture-passthrough", dict(passed=1, warnings=0), id="fixture-passthrough" + ), + pytest.param("fixture-scope", dict(passed=2, warnings=0), id="fixture-scope"), + pytest.param( + "parameterised-clients", + dict(passed=2, warnings=0), + id="parameterised-clients", + ), + pytest.param( + "window-log-message", dict(passed=1, warnings=0), id="window-log-message" ), - pytest.param("window-log-message", dict(passed=1), id="window-log-message"), pytest.param( "window-create-progress", - dict(passed=3), + dict(passed=3, warnings=0), id="window-create-progress", ), - pytest.param("window-show-document", dict(passed=1), id="window-show-document"), - pytest.param("window-show-message", dict(passed=1), id="window-show-message"), + pytest.param( + "window-show-document", + dict(passed=1, warnings=0), + id="window-show-document", + ), + pytest.param( + "window-show-message", dict(passed=1, warnings=0), id="window-show-message" + ), pytest.param( "workspace-configuration", dict(passed=1, warnings=1), diff --git a/lib/pytest-lsp/tests/test_plugin.py b/lib/pytest-lsp/tests/test_plugin.py index 19a82be..69a1f8e 100644 --- a/lib/pytest-lsp/tests/test_plugin.py +++ b/lib/pytest-lsp/tests/test_plugin.py @@ -79,6 +79,7 @@ def setup_test(pytester: pytest.Pytester, server_name: str, test_code: str): """\ [pytest] asyncio_mode = auto +asyncio_default_fixture_loop_scope = function """ ) From 442185b699e16de9430b76ba948f1f4ff61a927a Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Wed, 4 Sep 2024 20:07:32 +0100 Subject: [PATCH 11/12] docs: Initial draft of pytest-lsp v1 migration guide --- docs/pytest-lsp/howto.rst | 1 + docs/pytest-lsp/howto/migrate-to-v1.rst | 27 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 docs/pytest-lsp/howto/migrate-to-v1.rst diff --git a/docs/pytest-lsp/howto.rst b/docs/pytest-lsp/howto.rst index 0e1f4fe..070b3d2 100644 --- a/docs/pytest-lsp/howto.rst +++ b/docs/pytest-lsp/howto.rst @@ -5,4 +5,5 @@ How To :maxdepth: 2 Integrate with lsp-devtools + Migrate to v1 Test Generic JSON-RPC Servers diff --git a/docs/pytest-lsp/howto/migrate-to-v1.rst b/docs/pytest-lsp/howto/migrate-to-v1.rst new file mode 100644 index 0000000..1de75bf --- /dev/null +++ b/docs/pytest-lsp/howto/migrate-to-v1.rst @@ -0,0 +1,27 @@ +How To Migrate to v1 +==================== + +The ``v1`` release of ``pytest-lsp`` contains some breaking changes, mostly as a result of changes in the wider ecosystem. +This guide summarises the changes and provides references on where to get more details. + +Python Support +-------------- + +This release removes support for Python 3.8 and adds support for Python 3.13. + +``pytest`` +---------- + +This release removes support for pytest ``v7``, if you have not done so already please update to pytest ``v8``. + + +``pytest-asyncio`` +------------------ + +The minimum required version for ``pytest-asyncio`` is now ``0.24``, see `this guide `__ for details on upgrading + +``pygls`` +--------- + +``pygls``, the underlying language server protocol implementation used by ``pytest-lsp`` has been upgraded to ``v2``. +See `this guide `__ for details on the breaking changes this brings. From 14e517784cfecdcce73ebe9efee69d43180728d0 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Wed, 4 Sep 2024 20:08:01 +0100 Subject: [PATCH 12/12] pytest-lsp: Update README code --- README.md | 24 +++++++++++++----------- lib/pytest-lsp/README.md | 24 +++++++++++++----------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 609fdb7..c932f7b 100644 --- a/README.md +++ b/README.md @@ -33,13 +33,9 @@ This also means `pytest-lsp` can be used to test language servers written in any ```python import sys +import pytest import pytest_lsp -from lsprotocol.types import ( - CompletionParams, - InitializeParams, - Position, - TextDocumentIdentifier, -) +from lsprotocol import types from pytest_lsp import ( ClientServerConfig, LanguageClient, @@ -48,6 +44,7 @@ from pytest_lsp import ( @pytest_lsp.fixture( + scope="module", config=ClientServerConfig( server_command=[sys.executable, "-m", "esbonio"], ), @@ -55,9 +52,13 @@ from pytest_lsp import ( async def client(lsp_client: LanguageClient): # Setup response = await lsp_client.initialize_session( - InitializeParams( + types.InitializeParams( capabilities=client_capabilities("visual-studio-code"), - root_uri="file:///path/to/test/project/root/", + workspace_folders=[ + types.WorkspaceFolder( + uri="file:///path/to/test/project/root/", name="project" + ), + ], ) ) @@ -67,11 +68,12 @@ async def client(lsp_client: LanguageClient): await lsp_client.shutdown_session() +@pytest.mark.asyncio(loop_scope="module") async def test_completion(client: LanguageClient): result = await client.text_document_completion_async( - params=CompletionParams( - position=Position(line=5, character=23), - text_document=TextDocumentIdentifier( + params=types.CompletionParams( + position=types.Position(line=5, character=23), + text_document=types.TextDocumentIdentifier( uri="file:///path/to/test/project/root/test_file.rst" ), ) diff --git a/lib/pytest-lsp/README.md b/lib/pytest-lsp/README.md index aa1b6f5..7977420 100644 --- a/lib/pytest-lsp/README.md +++ b/lib/pytest-lsp/README.md @@ -12,13 +12,9 @@ See the [documentation](https://lsp-devtools.readthedocs.io/en/latest/) for deta ```python import sys +import pytest import pytest_lsp -from lsprotocol.types import ( - CompletionParams, - InitializeParams, - Position, - TextDocumentIdentifier, -) +from lsprotocol import types from pytest_lsp import ( ClientServerConfig, LanguageClient, @@ -27,6 +23,7 @@ from pytest_lsp import ( @pytest_lsp.fixture( + scope="module", config=ClientServerConfig( server_command=[sys.executable, "-m", "esbonio"], ), @@ -34,9 +31,13 @@ from pytest_lsp import ( async def client(lsp_client: LanguageClient): # Setup response = await lsp_client.initialize_session( - InitializeParams( + types.InitializeParams( capabilities=client_capabilities("visual-studio-code"), - root_uri="file:///path/to/test/project/root/", + workspace_folders=[ + types.WorkspaceFolder( + uri="file:///path/to/test/project/root/", name="project" + ), + ], ) ) @@ -46,11 +47,12 @@ async def client(lsp_client: LanguageClient): await lsp_client.shutdown_session() +@pytest.mark.asyncio(loop_scope="module") async def test_completion(client: LanguageClient): result = await client.text_document_completion_async( - params=CompletionParams( - position=Position(line=5, character=23), - text_document=TextDocumentIdentifier( + params=types.CompletionParams( + position=types.Position(line=5, character=23), + text_document=types.TextDocumentIdentifier( uri="file:///path/to/test/project/root/test_file.rst" ), )