process_app.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. # Copyright (c) Jupyter Development Team.
  2. # Distributed under the terms of the Modified BSD License.
  3. """A lab app that runs a sub process for a demo or a test."""
  4. from __future__ import annotations
  5. import sys
  6. from typing import Any
  7. from jupyter_server.extension.application import ExtensionApp, ExtensionAppJinjaMixin
  8. from tornado.ioloop import IOLoop
  9. from .handlers import LabConfig, add_handlers
  10. from .process import Process
  11. class ProcessApp(ExtensionAppJinjaMixin, LabConfig, ExtensionApp):
  12. """A jupyterlab app that runs a separate process and exits on completion."""
  13. load_other_extensions = True
  14. # Do not open a browser for process apps
  15. open_browser = False # type:ignore[assignment]
  16. def get_command(self) -> tuple[list[str], dict[str, Any]]:
  17. """Get the command and kwargs to run with `Process`.
  18. This is intended to be overridden.
  19. """
  20. return [sys.executable, "--version"], {}
  21. def initialize_settings(self) -> None:
  22. """Start the application."""
  23. IOLoop.current().add_callback(self._run_command)
  24. def initialize_handlers(self) -> None:
  25. """Initialize the handlers."""
  26. add_handlers(self.handlers, self) # type:ignore[arg-type]
  27. def _run_command(self) -> None:
  28. command, kwargs = self.get_command()
  29. kwargs.setdefault("logger", self.log)
  30. future = Process(command, **kwargs).wait_async()
  31. IOLoop.current().add_future(future, self._process_finished)
  32. def _process_finished(self, future: Any) -> None:
  33. try:
  34. IOLoop.current().stop()
  35. sys.exit(future.result())
  36. except Exception as e:
  37. self.log.error(str(e))
  38. sys.exit(1)