File size: 4,327 Bytes
d1ceb73 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
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
|