134
134
urlencode_unix_socket_path ,
135
135
)
136
136
137
- # Tolerate missing terminado package.
138
- try :
139
- from jupyter_server .terminal import TerminalManager
140
-
141
- terminado_available = True
142
- except ImportError :
143
- terminado_available = False
144
-
145
137
# -----------------------------------------------------------------------------
146
138
# Module globals
147
139
# -----------------------------------------------------------------------------
@@ -292,7 +284,7 @@ def init_settings(
292
284
env .install_gettext_translations (nbui , newstyle = False )
293
285
294
286
if sys_info ["commit_source" ] == "repository" :
295
- # don't cache (rely on 304) when working from default branch
287
+ # don't cache (rely on 304) when working from master
296
288
version_hash = ""
297
289
else :
298
290
# reset the cache on server restart
@@ -361,7 +353,6 @@ def init_settings(
361
353
allow_password_change = jupyter_app .allow_password_change ,
362
354
server_root_dir = root_dir ,
363
355
jinja2_env = env ,
364
- terminals_available = terminado_available and jupyter_app .terminals_enabled ,
365
356
serverapp = jupyter_app ,
366
357
)
367
358
@@ -454,14 +445,12 @@ def last_activity(self):
454
445
self .settings ["started" ],
455
446
self .settings ["kernel_manager" ].last_kernel_activity ,
456
447
]
457
- try :
458
- sources .append (self .settings ["api_last_activity" ])
459
- except KeyError :
460
- pass
461
- try :
462
- sources .append (self .settings ["terminal_last_activity" ])
463
- except KeyError :
464
- pass
448
+ # Any setting that ends with a key that ends with `_last_activity` is
449
+ # counted here. This provides a hook for extensions to add a last activity
450
+ # setting to the server.
451
+ sources .extend (
452
+ [key for key , val in self .settings .items () if key .endswith ("_last_activity" )]
453
+ )
465
454
sources .extend (self .settings ["last_activity_times" ].values ())
466
455
return max (sources )
467
456
@@ -744,8 +733,6 @@ class ServerApp(JupyterApp):
744
733
GatewayClient ,
745
734
Authorizer ,
746
735
]
747
- if terminado_available : # Only necessary when terminado is available
748
- classes .append (TerminalManager )
749
736
750
737
subcommands = dict (
751
738
list = (JupyterServerListApp , JupyterServerListApp .description .splitlines ()[0 ]),
@@ -1713,8 +1700,8 @@ def _update_server_extensions(self, change):
1713
1700
0 ,
1714
1701
config = True ,
1715
1702
help = (
1716
- "Shut down the server after N seconds with no kernels or "
1717
- "terminals running and no activity. "
1703
+ "Shut down the server after N seconds with no kernels"
1704
+ "running and no activity. "
1718
1705
"This can be used together with culling idle kernels "
1719
1706
"(MappingKernelManager.cull_idle_timeout) to "
1720
1707
"shutdown the Jupyter server when it's not in use. This is not "
@@ -1724,7 +1711,6 @@ def _update_server_extensions(self, change):
1724
1711
)
1725
1712
1726
1713
terminals_enabled = Bool (
1727
- True ,
1728
1714
config = True ,
1729
1715
help = _i18n (
1730
1716
"""Set to False to disable terminals.
@@ -1738,14 +1724,10 @@ def _update_server_extensions(self, change):
1738
1724
),
1739
1725
)
1740
1726
1741
- # Since use of terminals is also a function of whether the terminado package is
1742
- # available, this variable holds the "final indication" of whether terminal functionality
1743
- # should be considered (particularly during shutdown/cleanup). It is enabled only
1744
- # once both the terminals "service" can be initialized and terminals_enabled is True.
1745
- # Note: this variable is slightly different from 'terminals_available' in the web settings
1746
- # in that this variable *could* remain false if terminado is available, yet the terminal
1747
- # service's initialization still fails. As a result, this variable holds the truth.
1748
- terminals_available = False
1727
+ @default ("terminals_enabled" )
1728
+ def _default_terminals_enabled (self ):
1729
+
1730
+ return True
1749
1731
1750
1732
authenticate_prometheus = Bool (
1751
1733
True ,
@@ -2032,23 +2014,6 @@ def connection_url(self):
2032
2014
urlparts = self ._get_urlparts (path = self .base_url )
2033
2015
return urlparts .geturl ()
2034
2016
2035
- def init_terminals (self ):
2036
- if not self .terminals_enabled :
2037
- return
2038
-
2039
- try :
2040
- from jupyter_server .terminal import initialize
2041
-
2042
- initialize (
2043
- self .web_app ,
2044
- self .root_dir ,
2045
- self .connection_url ,
2046
- self .terminado_settings ,
2047
- )
2048
- self .terminals_available = True
2049
- except ImportError as e :
2050
- self .log .warning (_i18n ("Terminals not available (error was %s)" ), e )
2051
-
2052
2017
def init_signal (self ):
2053
2018
if not sys .platform .startswith ("win" ) and sys .stdin and sys .stdin .isatty ():
2054
2019
signal .signal (signal .SIGINT , self ._handle_sigint )
@@ -2194,24 +2159,22 @@ def shutdown_no_activity(self):
2194
2159
if len (km ) != 0 :
2195
2160
return # Kernels still running
2196
2161
2197
- if self .terminals_available :
2198
- term_mgr = self .web_app .settings ["terminal_manager" ]
2199
- if term_mgr .terminals :
2200
- return # Terminals still running
2162
+ if self .extension_manager .any_activity :
2163
+ return
2201
2164
2202
2165
seconds_since_active = (utcnow () - self .web_app .last_activity ()).total_seconds ()
2203
2166
self .log .debug ("No activity for %d seconds." , seconds_since_active )
2204
2167
if seconds_since_active > self .shutdown_no_activity_timeout :
2205
2168
self .log .info (
2206
- "No kernels or terminals for %d seconds; shutting down." ,
2169
+ "No kernels for %d seconds; shutting down." ,
2207
2170
seconds_since_active ,
2208
2171
)
2209
2172
self .stop ()
2210
2173
2211
2174
def init_shutdown_no_activity (self ):
2212
2175
if self .shutdown_no_activity_timeout > 0 :
2213
2176
self .log .info (
2214
- "Will shut down after %d seconds with no kernels or terminals ." ,
2177
+ "Will shut down after %d seconds with no kernels." ,
2215
2178
self .shutdown_no_activity_timeout ,
2216
2179
)
2217
2180
pc = ioloop .PeriodicCallback (self .shutdown_no_activity , 60000 )
@@ -2409,7 +2372,6 @@ def initialize(
2409
2372
self .init_configurables ()
2410
2373
self .init_components ()
2411
2374
self .init_webapp ()
2412
- self .init_terminals ()
2413
2375
self .init_signal ()
2414
2376
self .init_ioloop ()
2415
2377
self .load_server_extensions ()
@@ -2431,23 +2393,6 @@ async def cleanup_kernels(self):
2431
2393
self .log .info (kernel_msg % n_kernels )
2432
2394
await run_sync_in_loop (self .kernel_manager .shutdown_all ())
2433
2395
2434
- async def cleanup_terminals (self ):
2435
- """Shutdown all terminals.
2436
-
2437
- The terminals will shutdown themselves when this process no longer exists,
2438
- but explicit shutdown allows the TerminalManager to cleanup.
2439
- """
2440
- if not self .terminals_available :
2441
- return
2442
-
2443
- terminal_manager = self .web_app .settings ["terminal_manager" ]
2444
- n_terminals = len (terminal_manager .list ())
2445
- terminal_msg = trans .ngettext (
2446
- "Shutting down %d terminal" , "Shutting down %d terminals" , n_terminals
2447
- )
2448
- self .log .info (terminal_msg % n_terminals )
2449
- await run_sync_in_loop (terminal_manager .terminate_all ())
2450
-
2451
2396
async def cleanup_extensions (self ):
2452
2397
"""Call shutdown hooks in all extensions."""
2453
2398
n_extensions = len (self .extension_manager .extension_apps )
@@ -2728,7 +2673,6 @@ async def _cleanup(self):
2728
2673
self .remove_browser_open_files ()
2729
2674
await self .cleanup_extensions ()
2730
2675
await self .cleanup_kernels ()
2731
- await self .cleanup_terminals ()
2732
2676
2733
2677
def start_ioloop (self ):
2734
2678
"""Start the IO Loop."""
0 commit comments