mbuali's picture
Upload folder using huggingface_hub
d1ceb73 verified
import os
import shutil
import sys
from pathlib import Path
from subprocess import check_output
from typing import List, Text, Union
from ..schema import SPEC_VERSION
from ..types import (
KeyedLanguageServerSpecs,
LanguageServerManagerAPI,
LanguageServerSpec,
SpecBase,
Token,
)
# helper scripts for known tricky language servers
HELPERS = Path(__file__).parent / "helpers"
# when building docs, let all specs go through
BUILDING_DOCS = os.environ.get("JUPYTER_LSP_BUILDING_DOCS") is not None
class ShellSpec(SpecBase): # pragma: no cover
"""Helper for a language server spec for executables on $PATH in the
notebook server environment.
"""
cmd = ""
# [optional] arguments passed to `cmd` which upon execution should print
# out a non-empty string if the the required language server package
# is installed, or nothing if it is missing and user action is required.
is_installed_args: List[Token] = []
def is_installed(self, mgr: LanguageServerManagerAPI) -> bool:
cmd = self.solve()
if not cmd:
return False
if not self.is_installed_args:
return bool(cmd)
else:
check_result = check_output([cmd, *self.is_installed_args]).decode(
encoding="utf-8"
)
return check_result != ""
def solve(self) -> Union[str, None]:
for ext in ["", ".cmd", ".bat", ".exe"]:
cmd = shutil.which(self.cmd + ext)
if cmd:
break
return cmd
def __call__(self, mgr: LanguageServerManagerAPI) -> KeyedLanguageServerSpecs:
cmd = self.solve()
spec = dict(self.spec)
if not cmd:
troubleshooting = [f"{self.cmd} not found."]
if "troubleshoot" in spec:
troubleshooting.append(spec["troubleshoot"])
spec["troubleshoot"] = "\n\n".join(troubleshooting)
if not cmd and BUILDING_DOCS: # pragma: no cover
cmd = self.cmd
return {
self.key: {
"argv": [cmd, *self.args] if cmd else [self.cmd, *self.args],
"languages": self.languages,
"version": SPEC_VERSION,
**spec,
}
}
class PythonModuleSpec(SpecBase):
"""Helper for a python-based language server spec in the notebook server
environment
"""
python_module = ""
def is_installed(self, mgr: LanguageServerManagerAPI) -> bool:
spec = self.solve()
if not spec:
return False
if not spec.origin: # pragma: no cover
return False
return True
def solve(self):
return __import__("importlib").util.find_spec(self.python_module)
def __call__(self, mgr: LanguageServerManagerAPI) -> KeyedLanguageServerSpecs:
is_installed = self.is_installed(mgr)
return {
self.key: {
"argv": (
[sys.executable, "-m", self.python_module, *self.args]
if is_installed
else []
),
"languages": self.languages,
"version": SPEC_VERSION,
**self.spec,
}
}
class NodeModuleSpec(SpecBase):
"""Helper for a nodejs-based language server spec in one of several
node_modules
"""
node_module = ""
script: List[Text] = []
def is_installed(self, mgr: LanguageServerManagerAPI) -> bool:
node_module = self.solve(mgr)
return bool(node_module)
def solve(self, mgr: LanguageServerManagerAPI):
return mgr.find_node_module(self.node_module, *self.script)
def __call__(self, mgr: LanguageServerManagerAPI) -> KeyedLanguageServerSpecs:
node_module = self.solve(mgr)
spec = dict(self.spec)
troubleshooting = ["Node.js is required to install this server."]
if "troubleshoot" in spec: # pragma: no cover
troubleshooting.append(spec["troubleshoot"])
spec["troubleshoot"] = "\n\n".join(troubleshooting)
is_installed = self.is_installed(mgr)
return {
self.key: {
"argv": ([mgr.nodejs, node_module, *self.args] if is_installed else []),
"languages": self.languages,
"version": SPEC_VERSION,
**spec,
}
}
# these are not desirable to publish to the frontend
# and will be replaced with the simplest schema-compliant values
SKIP_JSON_SPEC = {"argv": [""], "debug_argv": [""], "env": {}}
def censored_spec(spec: LanguageServerSpec) -> LanguageServerSpec:
return {k: SKIP_JSON_SPEC.get(k, v) for k, v in spec.items()}