| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- import json
- import os
- import pathlib
- import shutil
- from pathlib import Path
- from typing import Text
- from jupyter_server.serverapp import ServerApp
- from pytest import fixture
- from tornado.httpserver import HTTPRequest
- from tornado.httputil import HTTPServerRequest
- from tornado.queues import Queue
- from tornado.web import Application
- # local imports
- from jupyter_lsp import LanguageServerManager
- from jupyter_lsp.constants import APP_CONFIG_D_SECTIONS
- from jupyter_lsp.handlers import LanguageServersHandler, LanguageServerWebSocketHandler
- # these should always be available in a test environment
- KNOWN_SERVERS = [
- "bash-language-server",
- "dockerfile-language-server-nodejs",
- "typescript-language-server",
- "pylsp",
- "unified-language-server",
- "sql-language-server",
- "vscode-css-languageserver-bin",
- "vscode-html-languageserver-bin",
- "vscode-json-languageserver-bin",
- "yaml-language-server",
- ]
- CMD_BASED_SERVERS = {
- "Rscript": ["r-languageserver"],
- "texlab": ["texlab"],
- "jedi-language-server": ["jedi-language-server"],
- "julia": ["julia-language-server"],
- }
- KNOWN_SERVERS += sum(
- [langs for cmd, langs in CMD_BASED_SERVERS.items() if shutil.which(cmd)], []
- )
- KNOWN_UNKNOWN_SERVERS = ["foo-language-server"]
- def extra_node_roots():
- root = Path(os.environ.get("JLSP_TEST_ROOT") or Path.cwd())
- return dict(extra_node_roots=[str(root)] if root else [])
- @fixture
- def manager() -> LanguageServerManager:
- return LanguageServerManager(**extra_node_roots())
- @fixture
- def echo_spec():
- return {"argv": ["echo", "no server here"], "languages": ["klingon"], "version": 2}
- @fixture
- def echo_conf_json(echo_spec) -> str:
- return json.dumps(
- {"LanguageServerManager": {"language_servers": {"_echo_": echo_spec}}},
- indent=2,
- sort_keys=True,
- )
- @fixture(params=sorted(APP_CONFIG_D_SECTIONS))
- def app_config_d(request, tmp_path, monkeypatch) -> pathlib.Path:
- conf_d = tmp_path / f"jupyter{request.param}config.d"
- conf_d.mkdir()
- monkeypatch.setenv("JUPYTER_CONFIG_PATH", f"{tmp_path}")
- return conf_d
- @fixture(params=sorted(KNOWN_SERVERS))
- def known_server(request):
- return request.param
- @fixture(params=sorted(KNOWN_UNKNOWN_SERVERS))
- def known_unknown_server(request):
- return request.param
- @fixture
- def handlers(manager):
- ws_handler = MockWebsocketHandler()
- ws_handler.initialize(manager)
- handler = MockHandler()
- handler.initialize(manager)
- return handler, ws_handler
- @fixture
- def jsonrpc_init_msg():
- return json.dumps(
- {
- "id": 0,
- "jsonrpc": "2.0",
- "method": "initialize",
- "params": {
- "capabilities": {
- # see: https://github.com/julia-vscode/LanguageServer.jl/issues/1008
- # LanguageServer.jl assumes that it is not missing
- "workspace": {"didChangeConfiguration": {}},
- # LanguageServer.jl assumes that it is not missing
- "textDocument": {},
- },
- "initializationOptions": None,
- "processId": None,
- "rootUri": pathlib.Path(__file__).parent.as_uri(),
- "workspaceFolders": None,
- },
- }
- )
- @fixture
- def app():
- return MockServerApp()
- # mocks
- class MockWebsocketHandler(LanguageServerWebSocketHandler):
- _messages_wrote = None # type: Queue
- _ping_sent = None # type: bool
- def __init__(self):
- self.request = HTTPServerRequest()
- self.application = Application()
- def initialize(self, manager):
- super().initialize(manager)
- self._messages_wrote = Queue()
- self._ping_sent = False
- def write_message(self, message: Text) -> None: # type: ignore
- self.log.warning("write_message %s", message)
- self._messages_wrote.put_nowait(message)
- def send_ping(self):
- self._ping_sent = True
- class MockHandler(LanguageServersHandler):
- _payload = None
- _jupyter_current_user = "foo" # type:ignore[assignment]
- def __init__(self):
- self.request = HTTPRequest("GET")
- self.application = Application()
- def finish(self, payload):
- self._payload = payload
- class MockServerApp(ServerApp):
- pass
|