|
83 | 83 | from .auth.login import LoginHandler
|
84 | 84 | from .auth.logout import LogoutHandler
|
85 | 85 | from .base.handlers import FileFindHandler
|
86 |
| -from .terminal import TerminalManager |
87 | 86 |
|
88 | 87 | from traitlets.config import Config
|
89 | 88 | from traitlets.config.application import catch_config_error, boolean_flag
|
|
117 | 116 | from jupyter_server.extension.config import ExtensionConfigManager
|
118 | 117 | from jupyter_server.traittypes import TypeFromClasses
|
119 | 118 |
|
| 119 | +# Tolerate missing terminado package. |
| 120 | +try: |
| 121 | + from .terminal import TerminalManager |
| 122 | + terminado_available = True |
| 123 | +except ImportError: |
| 124 | + terminado_available = False |
| 125 | + |
120 | 126 | #-----------------------------------------------------------------------------
|
121 | 127 | # Module globals
|
122 | 128 | #-----------------------------------------------------------------------------
|
@@ -285,7 +291,7 @@ def init_settings(self, jupyter_app, kernel_manager, contents_manager,
|
285 | 291 | allow_password_change=jupyter_app.allow_password_change,
|
286 | 292 | server_root_dir=root_dir,
|
287 | 293 | jinja2_env=env,
|
288 |
| - terminals_available=False, # Set later if terminals are available |
| 294 | + terminals_available=terminado_available and jupyter_app.terminals_enabled, |
289 | 295 | serverapp=jupyter_app
|
290 | 296 | )
|
291 | 297 |
|
@@ -588,8 +594,10 @@ class ServerApp(JupyterApp):
|
588 | 594 | classes = [
|
589 | 595 | KernelManager, Session, MappingKernelManager, KernelSpecManager, AsyncMappingKernelManager,
|
590 | 596 | ContentsManager, FileContentsManager, AsyncContentsManager, AsyncFileContentsManager, NotebookNotary,
|
591 |
| - TerminalManager, GatewayKernelSpecManager, GatewaySessionManager, GatewayClient |
| 597 | + GatewayKernelManager, GatewayKernelSpecManager, GatewaySessionManager, GatewayClient |
592 | 598 | ]
|
| 599 | + if terminado_available: # Only necessary when terminado is available |
| 600 | + classes.append(TerminalManager) |
593 | 601 |
|
594 | 602 | subcommands = dict(
|
595 | 603 | list=(JupyterServerListApp, JupyterServerListApp.description.splitlines()[0]),
|
@@ -1330,6 +1338,15 @@ def _update_server_extensions(self, change):
|
1330 | 1338 | is not available.
|
1331 | 1339 | """))
|
1332 | 1340 |
|
| 1341 | + # Since use of terminals is also a function of whether the terminado package is |
| 1342 | + # available, this variable holds the "final indication" of whether terminal functionality |
| 1343 | + # should be considered (particularly during shutdown/cleanup). It is enabled only |
| 1344 | + # once both the terminals "service" can be initialized and terminals_enabled is True. |
| 1345 | + # Note: this variable is slightly different from 'terminals_available' in the web settings |
| 1346 | + # in that this variable *could* remain false if terminado is available, yet the terminal |
| 1347 | + # service's initialization still fails. As a result, this variable holds the truth. |
| 1348 | + terminals_available = False |
| 1349 | + |
1333 | 1350 | authenticate_prometheus = Bool(
|
1334 | 1351 | True,
|
1335 | 1352 | help=""""
|
@@ -1548,7 +1565,7 @@ def init_terminals(self):
|
1548 | 1565 | try:
|
1549 | 1566 | from .terminal import initialize
|
1550 | 1567 | initialize(server_app=self)
|
1551 |
| - self.web_app.settings['terminals_available'] = True |
| 1568 | + self.terminals_available = True |
1552 | 1569 | except ImportError as e:
|
1553 | 1570 | self.log.warning(_i18n("Terminals not available (error was %s)"), e)
|
1554 | 1571 |
|
@@ -1694,11 +1711,8 @@ def shutdown_no_activity(self):
|
1694 | 1711 | if len(km) != 0:
|
1695 | 1712 | return # Kernels still running
|
1696 | 1713 |
|
1697 |
| - try: |
| 1714 | + if self.terminals_available: |
1698 | 1715 | term_mgr = self.web_app.settings['terminal_manager']
|
1699 |
| - except KeyError: |
1700 |
| - pass # Terminals not enabled |
1701 |
| - else: |
1702 | 1716 | if term_mgr.terminals:
|
1703 | 1717 | return # Terminals still running
|
1704 | 1718 |
|
@@ -1853,11 +1867,10 @@ def cleanup_terminals(self):
|
1853 | 1867 | The terminals will shutdown themselves when this process no longer exists,
|
1854 | 1868 | but explicit shutdown allows the TerminalManager to cleanup.
|
1855 | 1869 | """
|
1856 |
| - try: |
1857 |
| - terminal_manager = self.web_app.settings['terminal_manager'] |
1858 |
| - except KeyError: |
1859 |
| - return # Terminals not enabled |
| 1870 | + if not self.terminals_available: |
| 1871 | + return |
1860 | 1872 |
|
| 1873 | + terminal_manager = self.web_app.settings['terminal_manager'] |
1861 | 1874 | n_terminals = len(terminal_manager.list())
|
1862 | 1875 | terminal_msg = trans.ngettext('Shutting down %d terminal', 'Shutting down %d terminals', n_terminals)
|
1863 | 1876 | self.log.info(terminal_msg % n_terminals)
|
|
0 commit comments