cutter/src/python/cutter_ipykernel.py

71 lines
1.8 KiB
Python
Raw Normal View History

import logging
import threading
2018-02-23 15:24:19 +00:00
import signal
import cutter_internal
from ipykernel.kernelapp import IPKernelApp
from ipykernel.ipkernel import IPythonKernel
class IPyKernelInterfaceKernel:
2018-02-23 15:24:19 +00:00
def __init__(self, thread, app):
self._thread = thread
self._app = app
2018-02-23 12:04:53 +00:00
def send_signal(self, signum):
2018-02-23 15:24:19 +00:00
if not self._thread.is_alive():
return
if signum == signal.SIGKILL or signum == signal.SIGTERM:
self._app.io_loop.stop()
elif signum == signal.SIGINT and self._app.kernel.interruptable:
self._app.log.debug("Sending KeyboardInterrupt to ioloop thread.")
cutter_internal.thread_set_async_exc(self._thread.ident, KeyboardInterrupt())
2018-02-22 21:08:06 +00:00
def poll(self):
2018-02-23 15:24:19 +00:00
if self._thread.is_alive():
return None
else:
return 0
class CutterIPythonKernel(IPythonKernel):
2018-02-23 15:24:19 +00:00
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.interruptable = False
def pre_handler_hook(self):
2018-02-23 15:24:19 +00:00
self.interruptable = True
pass
def post_handler_hook(self):
2018-02-23 15:24:19 +00:00
self.interruptable = False
pass
class CutterIPKernelApp(IPKernelApp):
def init_signal(self):
2018-02-23 15:24:19 +00:00
# This would call signal.signal(signal.SIGINT, signal.SIG_IGN)
# Not needed in supinterpreter.
pass
def log_connection_info(self):
# Just skip this. It would only pollute Cutter's output.
pass
def launch_ipykernel(argv):
2018-02-23 15:24:19 +00:00
app = CutterIPKernelApp.instance()
def run_kernel():
app.kernel_class = CutterIPythonKernel
#app.log_level = logging.DEBUG
app.initialize(argv[3:])
app.start()
thread = threading.Thread(target=run_kernel)
thread.start()
2018-02-23 15:24:19 +00:00
return IPyKernelInterfaceKernel(thread, app)