forked from microsoft/vscode-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjupyter_daemon.py
More file actions
100 lines (80 loc) · 3.76 KB
/
jupyter_daemon.py
File metadata and controls
100 lines (80 loc) · 3.76 KB
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
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import sys
import logging
import os
from datascience.daemon.daemon_python import (
error_decorator,
PythonDaemon as BasePythonDaemon,
change_exec_context,
)
class PythonDaemon(BasePythonDaemon):
def __init__(self, rx, tx):
super().__init__(rx, tx)
self.log.info("DataScience Daemon init")
def __getitem__(self, item):
"""Override getitem to ensure we use these methods."""
self.log.info("Execute rpc method %s in DS Daemon", item)
return super().__getitem__(item)
@error_decorator
def m_exec_module(self, module_name, args=[], cwd=None, env=None):
self.log.info("Exec in DS Daemon %s with args %s", module_name, args)
args = [] if args is None else args
if module_name == "jupyter" and args == ["kernelspec", "list"]:
return self._execute_and_capture_output(self._print_kernel_list)
elif module_name == "jupyter" and args == ["kernelspec", "--version"]:
return self._execute_and_capture_output(self._print_kernelspec_version)
elif module_name == "jupyter" and args[0] == "nbconvert" and args[-1] != "--version":
return self._execute_and_capture_output(lambda : self._convert(args))
else:
self.log.info("check base class stuff")
return super().m_exec_module(module_name, args, cwd, env)
@error_decorator
def m_exec_module_observable(self, module_name, args=None, cwd=None, env=None):
self.log.info("Exec in DS Daemon (observable) %s with args %s", module_name, args)
args = [] if args is None else args
# Assumption is that `python -m jupyter notebook` or `python -m notebook` with observable output
# will only ever be used to start a notebook and nothing else.
# E.g. `python -m jupyter notebook --version` wouldn't require the use of exec_module_observable,
# In such cases, we can get the output immediately.
if (module_name == "jupyter" and args[0] == "notebook") or (
module_name == "notebook"
):
# Args must not have ['notebook'] in the begining. Drop the `notebook` subcommand when using `jupyter`
args = args[1:] if args[0] == "notebook" else args
self.log.info("Starting notebook with args %s", args)
# When launching notebook always ensure the first argument is `notebook`.
with change_exec_context(args, cwd, env):
self._start_notebook(args)
else:
return super().m_exec_module_observable(module_name, args, cwd, env)
def _print_kernelspec_version(self):
import jupyter_client
# Check whether kernelspec module exists.
import jupyter_client.kernelspec
sys.stdout.write(jupyter_client.__version__)
sys.stdout.flush()
def _print_kernelspec_version(self):
import jupyter_client
# Check whether kernelspec module exists.
import jupyter_client.kernelspec
sys.stdout.write(jupyter_client.__version__)
sys.stdout.flush()
def _print_kernel_list(self):
self.log.info("check kernels")
# Get kernel specs.
import jupyter_client.kernelspec
specs = jupyter_client.kernelspec.find_kernel_specs()
sys.stdout.write(
os.linesep.join(list("{0} {1}".format(k, v) for k, v in specs.items()))
)
sys.stdout.flush()
def _convert(self, args):
self.log.info("nbconvert")
from nbconvert import nbconvertapp as app
sys.argv = [""] + args
app.main()
def _start_notebook(self, args):
from notebook import notebookapp as app
sys.argv = [""] + args
app.launch_new_instance()