Skip to content

Commit b209e1b

Browse files
authored
Merge pull request #184 from dsblank/master
Adds jupyter-run to jupyter_client
2 parents 9ae917f + df03086 commit b209e1b

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed

jupyter_client/runapp.py

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
2+
# Copyright (c) Jupyter Development Team.
3+
# Distributed under the terms of the Modified BSD License.
4+
5+
from __future__ import print_function
6+
7+
import logging
8+
import signal
9+
import time
10+
import sys
11+
12+
from traitlets.config import catch_config_error
13+
from traitlets import (
14+
Instance, Dict, Unicode, Bool, List, CUnicode, Any, Float
15+
)
16+
from jupyter_core.application import (
17+
JupyterApp, base_flags, base_aliases
18+
)
19+
20+
from . import __version__
21+
from .consoleapp import JupyterConsoleApp, app_aliases, app_flags
22+
23+
try:
24+
import queue
25+
except ImportError:
26+
import Queue as queue
27+
28+
OUTPUT_TIMEOUT = 10
29+
30+
# copy flags from mixin:
31+
flags = dict(base_flags)
32+
# start with mixin frontend flags:
33+
frontend_flags = dict(app_flags)
34+
# update full dict with frontend flags:
35+
flags.update(frontend_flags)
36+
37+
# copy flags from mixin
38+
aliases = dict(base_aliases)
39+
# start with mixin frontend flags
40+
frontend_aliases = dict(app_aliases)
41+
# load updated frontend flags into full dict
42+
aliases.update(frontend_aliases)
43+
44+
# get flags&aliases into sets, and remove a couple that
45+
# shouldn't be scrubbed from backend flags:
46+
frontend_aliases = set(frontend_aliases.keys())
47+
frontend_flags = set(frontend_flags.keys())
48+
49+
class RunApp(JupyterApp, JupyterConsoleApp):
50+
version = __version__
51+
name = "jupyter run"
52+
description = """Run Jupyter kernel code."""
53+
flags = Dict(flags)
54+
aliases = Dict(aliases)
55+
frontend_aliases = Any(frontend_aliases)
56+
frontend_flags = Any(frontend_flags)
57+
kernel_timeout = Float(60, config=True,
58+
help="""Timeout for giving up on a kernel (in seconds).
59+
60+
On first connect and restart, the console tests whether the
61+
kernel is running and responsive by sending kernel_info_requests.
62+
This sets the timeout in seconds for how long the kernel can take
63+
before being presumed dead.
64+
"""
65+
)
66+
67+
def parse_command_line(self, argv=None):
68+
super(RunApp, self).parse_command_line(argv)
69+
self.build_kernel_argv(self.extra_args)
70+
self.filenames_to_run = self.extra_args[:]
71+
72+
@catch_config_error
73+
def initialize(self, argv=None):
74+
self.log.debug("jupyter run: initialize...")
75+
super(RunApp, self).initialize(argv)
76+
JupyterConsoleApp.initialize(self)
77+
signal.signal(signal.SIGINT, self.handle_sigint)
78+
self.init_kernel_info()
79+
80+
def handle_sigint(self, *args):
81+
if self.kernel_manager:
82+
self.kernel_manager.interrupt_kernel()
83+
else:
84+
print("", file=sys.stderr)
85+
error("Cannot interrupt kernels we didn't start.\n")
86+
87+
def init_kernel_info(self):
88+
"""Wait for a kernel to be ready, and store kernel info"""
89+
timeout = self.kernel_timeout
90+
tic = time.time()
91+
self.kernel_client.hb_channel.unpause()
92+
msg_id = self.kernel_client.kernel_info()
93+
while True:
94+
try:
95+
reply = self.kernel_client.get_shell_msg(timeout=1)
96+
except queue.Empty:
97+
if (time.time() - tic) > timeout:
98+
raise RuntimeError("Kernel didn't respond to kernel_info_request")
99+
else:
100+
if reply['parent_header'].get('msg_id') == msg_id:
101+
self.kernel_info = reply['content']
102+
return
103+
104+
def start(self):
105+
self.log.debug("jupyter run: starting...")
106+
super(RunApp, self).start()
107+
if self.filenames_to_run:
108+
for filename in self.filenames_to_run:
109+
self.log.debug("jupyter run: executing `%s`" % filename)
110+
with open(filename) as fp:
111+
code = fp.read()
112+
reply = self.kernel_client.execute_interactive(code, timeout=OUTPUT_TIMEOUT)
113+
return_code = 0 if reply['content']['status'] == 'ok' else 1
114+
if return_code:
115+
raise Exception("jupyter-run error running '%s'" % filename)
116+
else:
117+
code = sys.stdin.read()
118+
reply = self.kernel_client.execute_interactive(code, timeout=OUTPUT_TIMEOUT)
119+
return_code = 0 if reply['content']['status'] == 'ok' else 1
120+
if return_code:
121+
raise Exception("jupyter-run error running 'stdin'")
122+
123+
main = launch_new_instance = RunApp.launch_instance
124+
125+
if __name__ == '__main__':
126+
main()

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
setup_args['entry_points'] = {
9191
'console_scripts': [
9292
'jupyter-kernelspec = jupyter_client.kernelspecapp:KernelSpecApp.launch_instance',
93+
'jupyter-run = jupyter_client.runapp:RunApp.launch_instance',
9394
]
9495
}
9596
setup_args.pop('scripts', None)

0 commit comments

Comments
 (0)