handlers.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. """Tornado handlers for kernels.
  2. Preliminary documentation at https://github.com/ipython/ipython/wiki/IPEP-16%3A-Notebook-multi-directory-dashboard-and-URL-mapping#kernels-api
  3. """
  4. # Copyright (c) Jupyter Development Team.
  5. # Distributed under the terms of the Modified BSD License.
  6. import json
  7. try:
  8. from jupyter_client.jsonutil import json_default
  9. except ImportError:
  10. from jupyter_client.jsonutil import date_default as json_default
  11. from jupyter_core.utils import ensure_async
  12. from tornado import web
  13. from jupyter_server.auth.decorator import authorized
  14. from jupyter_server.utils import url_escape, url_path_join
  15. from ...base.handlers import APIHandler
  16. from .websocket import KernelWebsocketHandler
  17. AUTH_RESOURCE = "kernels"
  18. class KernelsAPIHandler(APIHandler):
  19. """A kernels API handler."""
  20. auth_resource = AUTH_RESOURCE
  21. class MainKernelHandler(KernelsAPIHandler):
  22. """The root kernel handler."""
  23. @web.authenticated
  24. @authorized
  25. async def get(self):
  26. """Get the list of running kernels."""
  27. km = self.kernel_manager
  28. kernels = await ensure_async(km.list_kernels())
  29. self.finish(json.dumps(kernels, default=json_default))
  30. @web.authenticated
  31. @authorized
  32. async def post(self):
  33. """Start a kernel."""
  34. km = self.kernel_manager
  35. model = self.get_json_body()
  36. if model is None:
  37. model = {"name": km.default_kernel_name}
  38. else:
  39. model.setdefault("name", km.default_kernel_name)
  40. kernel_id = await ensure_async(
  41. km.start_kernel( # type:ignore[has-type]
  42. kernel_name=model["name"], path=model.get("path")
  43. )
  44. )
  45. model = await ensure_async(km.kernel_model(kernel_id))
  46. location = url_path_join(self.base_url, "api", "kernels", url_escape(kernel_id))
  47. self.set_header("Location", location)
  48. self.set_status(201)
  49. self.finish(json.dumps(model, default=json_default))
  50. class KernelHandler(KernelsAPIHandler):
  51. """A kernel API handler."""
  52. @web.authenticated
  53. @authorized
  54. async def get(self, kernel_id):
  55. """Get a kernel model."""
  56. km = self.kernel_manager
  57. model = await ensure_async(km.kernel_model(kernel_id))
  58. self.finish(json.dumps(model, default=json_default))
  59. @web.authenticated
  60. @authorized
  61. async def delete(self, kernel_id):
  62. """Remove a kernel."""
  63. km = self.kernel_manager
  64. await ensure_async(km.shutdown_kernel(kernel_id))
  65. self.set_status(204)
  66. self.finish()
  67. class KernelActionHandler(KernelsAPIHandler):
  68. """A kernel action API handler."""
  69. @web.authenticated
  70. @authorized
  71. async def post(self, kernel_id, action):
  72. """Interrupt or restart a kernel."""
  73. km = self.kernel_manager
  74. if action == "interrupt":
  75. await ensure_async(km.interrupt_kernel(kernel_id)) # type:ignore[func-returns-value]
  76. self.set_status(204)
  77. if action == "restart":
  78. try:
  79. await km.restart_kernel(kernel_id)
  80. except Exception:
  81. message = "Exception restarting kernel"
  82. self.log.error(message, exc_info=True)
  83. self.write(json.dumps({"message": message, "traceback": ""}))
  84. self.set_status(500)
  85. else:
  86. model = await ensure_async(km.kernel_model(kernel_id))
  87. self.write(json.dumps(model, default=json_default))
  88. self.finish()
  89. # -----------------------------------------------------------------------------
  90. # URL to handler mappings
  91. # -----------------------------------------------------------------------------
  92. _kernel_id_regex = r"(?P<kernel_id>\w+-\w+-\w+-\w+-\w+)"
  93. _kernel_action_regex = r"(?P<action>restart|interrupt)"
  94. default_handlers = [
  95. (r"/api/kernels", MainKernelHandler),
  96. (r"/api/kernels/%s" % _kernel_id_regex, KernelHandler),
  97. (
  98. rf"/api/kernels/{_kernel_id_regex}/{_kernel_action_regex}",
  99. KernelActionHandler,
  100. ),
  101. (r"/api/kernels/%s/channels" % _kernel_id_regex, KernelWebsocketHandler),
  102. ]