22# Licensed under the MIT License.
33
44import json
5- import sys
65import logging
76import os
7+ import subprocess
8+ import sys
89from datascience .daemon .daemon_python import (
910 error_decorator ,
1011 PythonDaemon as BasePythonDaemon ,
@@ -26,18 +27,47 @@ def m_exec_module(self, module_name, args=[], cwd=None, env=None):
2627 self .log .info ("Exec in DS Daemon %s with args %s" , module_name , args )
2728 args = [] if args is None else args
2829
29- if module_name == "jupyter" and args == ["kernelspec" , "list" , "--json" ]:
30- return self ._execute_and_capture_output (self ._print_kernel_list_json )
31- elif module_name == "jupyter" and args == ["kernelspec" , "list" ]:
32- return self ._execute_and_capture_output (self ._print_kernel_list )
33- elif module_name == "jupyter" and args == ["kernelspec" , "--version" ]:
34- return self ._execute_and_capture_output (self ._print_kernelspec_version )
35- elif module_name == "jupyter" and args [0 ] == "nbconvert" and args [- 1 ] != "--version" :
36- return self ._execute_and_capture_output (lambda : self ._convert (args ))
30+ if module_name == "jupyter" :
31+ if args [0 ] == "kernelspec" and self ._is_module_installed ("jupyter_client.kernelspec" ):
32+ if args == ["kernelspec" , "list" , "--json" ]:
33+ return self ._execute_and_capture_output (self ._print_kernel_list_json )
34+ elif args == ["kernelspec" , "list" ]:
35+ return self ._execute_and_capture_output (self ._print_kernel_list )
36+ elif args == ["kernelspec" , "--version" ]:
37+ return self ._execute_and_capture_output (self ._print_kernelspec_version )
38+ if args [0 ] == "nbconvert" and self ._is_module_installed ("nbconvert" ) and args [- 1 ] != "--version" :
39+ return self ._execute_and_capture_output (lambda : self ._convert (args ))
40+ if args [0 ] == "notebook" and args [1 ] == "--version" :
41+ try :
42+ from notebook import notebookapp as app
43+ return {"stdout" : '.' .join (list (str (v ) for v in app .version_info ))}
44+ except Exception :
45+ pass
46+ # kernelspec, nbconvert are subcommands of jupyter.
47+ # python -m jupyter kernelspec, python -m jupyter nbconvert,
48+ # In such cases, even if the modules kernelspec or nbconvert are not installed in the current
49+ # environment, jupyter will find them in current path.
50+ # So if we cannot find the corresponding subcommands, lets revert to subprocess.
51+ self .log .info ("Exec in DS Daemon with as subprocess, %s with args %s" , module_name , args )
52+ return self ._exec_with_subprocess (module_name , args , cwd , env )
3753 else :
3854 self .log .info ("check base class stuff" )
3955 return super ().m_exec_module (module_name , args , cwd , env )
4056
57+ def _exec_with_subprocess (self , module_name , args = [], cwd = None , env = None ):
58+ # # result = subprocess.run([sys.executable, "-m"] + args, stdout=sys.stdout, stderr=sys.stderr)
59+ # return self._execute_and_capture_output(lambda: subprocess.run([sys.executable, "-m", module_name] + args, stdout=sys.stdout, stderr=sys.stderr))
60+ result = subprocess .run ([sys .executable , "-m" , module_name ] + args , capture_output = True )
61+ encoding = os .getenv ('PYTHONIOENCODING' , 'utf-8' )
62+ stdout = result .stdout .decode (encoding )
63+ stderr = result .stderr .decode (encoding )
64+ self .log .info ("subprocess output for, %s with args %s, \n stdout is %s, \n stderr is %s" ,
65+ module_name , args , stdout , stderr )
66+ return {
67+ "stdout" : stdout ,
68+ "stderr" : stderr
69+ }
70+
4171 @error_decorator
4272 def m_exec_module_observable (self , module_name , args = None , cwd = None , env = None ):
4373 self .log .info ("Exec in DS Daemon (observable) %s with args %s" , module_name , args )
@@ -50,13 +80,7 @@ def m_exec_module_observable(self, module_name, args=None, cwd=None, env=None):
5080 if (module_name == "jupyter" and args [0 ] == "notebook" ) or (
5181 module_name == "notebook"
5282 ):
53- # Args must not have ['notebook'] in the begining. Drop the `notebook` subcommand when using `jupyter`
54- args = args [1 :] if args [0 ] == "notebook" else args
55- self .log .info ("Starting notebook with args %s" , args )
56-
57- # When launching notebook always ensure the first argument is `notebook`.
58- with change_exec_context (args , cwd , env ):
59- self ._start_notebook (args )
83+ self ._start_notebook (args , cwd , env )
6084 else :
6185 return super ().m_exec_module_observable (module_name , args , cwd , env )
6286
@@ -107,8 +131,13 @@ def _convert(self, args):
107131 sys .argv = ["" ] + args
108132 app .main ()
109133
110- def _start_notebook (self , args ):
134+ def _start_notebook (self , args , cwd , env ):
111135 from notebook import notebookapp as app
112136
113- sys .argv = ["" ] + args
114- app .launch_new_instance ()
137+ # Args must not have ['notebook'] in the begining. Drop the `notebook` subcommand when using `jupyter`
138+ args = args [1 :] if args [0 ] == "notebook" else args
139+ self .log .info ("Starting notebook with args %s" , args )
140+
141+ # When launching notebook always ensure the first argument is `notebook`.
142+ with change_exec_context (args , cwd , env ):
143+ app .launch_new_instance ()
0 commit comments