Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add broad spectrum tests for python #273

Merged
merged 5 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ def tests(session: nox.Session):
"""Run tests for generator and generated code in all languages."""
_install_requirements(session)

session.log("Running test data generator.")
session.run("python", "-m", "generator", "--plugin", "testdata")

session.log("Running tests: generator and generated Python code.")
session.run("pytest", "./tests")

Expand Down
117 changes: 117 additions & 0 deletions packages/python/lsprotocol/_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,88 @@ def _notebook_sync_option_selector_hook(
object_, lsp_types.NotebookDocumentSyncOptionsNotebookSelectorType2
)

def _semantic_token_registration_options_hook(
object_: Any, _: type
) -> Optional[
Union[OptionalPrimitive, lsp_types.SemanticTokensRegistrationOptionsFullType1]
]:
if object_ is None:
return None
if isinstance(object_, (bool, int, str, float)):
return object_
return converter.structure(
object_, lsp_types.SemanticTokensRegistrationOptionsFullType1
)

def _inline_completion_provider_hook(
object_: Any, _: type
) -> Optional[Union[OptionalPrimitive, lsp_types.InlineCompletionOptions]]:
if object_ is None:
return None
if isinstance(object_, (bool, int, str, float)):
return object_
return converter.structure(object_, lsp_types.InlineCompletionOptions)

def _inline_completion_list_hook(
object_: Any, _: type
) -> Optional[
Union[lsp_types.InlineCompletionList, List[lsp_types.InlineCompletionItem]]
]:
if object_ is None:
return None
if isinstance(object_, list):
return [
converter.structure(item, lsp_types.InlineCompletionItem)
for item in object_
]
return converter.structure(object_, lsp_types.InlineCompletionList)

def _string_value_hook(
object_: Any, _: type
) -> Union[OptionalPrimitive, lsp_types.StringValue]:
if object_ is None:
return None
if isinstance(object_, (bool, int, str, float)):
return object_
return converter.structure(object_, lsp_types.StringValue)

def _symbol_list_hook(
object_: Any, _: type
) -> Optional[
Union[List[lsp_types.SymbolInformation], List[lsp_types.WorkspaceSymbol]]
]:
if object_ is None:
return None
assert isinstance(object_, list)
if len(object_) == 0:
return [] # type: ignore[return-value]
if "location" in object_[0]:
return [
converter.structure(item, lsp_types.SymbolInformation)
for item in object_
]
else:
return [
converter.structure(item, lsp_types.WorkspaceSymbol) for item in object_
]

def _notebook_sync_registration_option_selector_hook(
object_: Any, _: type
) -> Union[
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1,
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2,
]:
if "notebook" in object_:
return converter.structure(
object_,
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1,
)
else:
return converter.structure(
object_,
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2,
)

structure_hooks = [
(
Optional[
Expand Down Expand Up @@ -940,6 +1022,41 @@ def _notebook_sync_option_selector_hook(
],
_position_encoding_hook,
),
(
Optional[Union[bool, lsp_types.SemanticTokensRegistrationOptionsFullType1]],
_semantic_token_registration_options_hook,
),
(
Optional[Union[bool, lsp_types.InlineCompletionOptions]],
_inline_completion_provider_hook,
),
(
Optional[
Union[
lsp_types.InlineCompletionList, List[lsp_types.InlineCompletionItem]
]
],
_inline_completion_list_hook,
),
(
Union[str, lsp_types.StringValue],
_string_value_hook,
),
(
Optional[
Union[
List[lsp_types.SymbolInformation], List[lsp_types.WorkspaceSymbol]
]
],
_symbol_list_hook,
),
(
Union[
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1,
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2,
],
_notebook_sync_registration_option_selector_hook,
),
]
for type_, hook in structure_hooks:
converter.register_structure_hook(type_, hook)
Expand Down
34 changes: 34 additions & 0 deletions tests/python/test_generated_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import json
import pathlib
from typing import Generator, List, Union

import pytest

import lsprotocol.converters as cv
import lsprotocol.types as lsp

TEST_DATA_ROOT = pathlib.Path(__file__).parent.parent.parent / "packages" / "testdata"


def get_all_json_files(root: Union[pathlib.Path, str]) -> List[pathlib.Path]:
root_path = pathlib.Path(root)
return list(root_path.glob("**/*.json"))


converter = cv.get_converter()


@pytest.mark.parametrize("json_file", get_all_json_files(TEST_DATA_ROOT))
def test_generated_data(json_file: str) -> None:
type_name, result_type, _ = json_file.name.split("-", 2)
lsp_type = getattr(lsp, type_name)
data = json.loads(json_file.read_text(encoding="utf-8"))

try:
converter.structure(data, lsp_type)
assert result_type == "True", "Expected error, but succeeded structuring"
except Exception as e:
assert result_type == "False", "Expected success, but failed structuring"
Loading