@@ -2999,6 +2999,72 @@ def start_app(self) -> None:
2999
2999
)
3000
3000
self .exit (1 )
3001
3001
3002
+ self .write_server_info_file ()
3003
+
3004
+ if not self .no_browser_open_file :
3005
+ self .write_browser_open_files ()
3006
+
3007
+ # Handle the browser opening.
3008
+ if self .open_browser and not self .sock :
3009
+ self .launch_browser ()
3010
+
3011
+ async def _cleanup (self ) -> None :
3012
+ """General cleanup of files, extensions and kernels created
3013
+ by this instance ServerApp.
3014
+ """
3015
+ self .remove_server_info_file ()
3016
+ self .remove_browser_open_files ()
3017
+ await self .cleanup_extensions ()
3018
+ await self .cleanup_kernels ()
3019
+ try :
3020
+ await self .kernel_websocket_connection_class .close_all () # type:ignore[attr-defined]
3021
+ except AttributeError :
3022
+ # This can happen in two different scenarios:
3023
+ #
3024
+ # 1. During tests, where the _cleanup method is invoked without
3025
+ # the corresponding initialize method having been invoked.
3026
+ # 2. If the provided `kernel_websocket_connection_class` does not
3027
+ # implement the `close_all` class method.
3028
+ #
3029
+ # In either case, we don't need to do anything and just want to treat
3030
+ # the raised error as a no-op.
3031
+ pass
3032
+ if getattr (self , "kernel_manager" , None ):
3033
+ self .kernel_manager .__del__ ()
3034
+ if getattr (self , "session_manager" , None ):
3035
+ self .session_manager .close ()
3036
+ if hasattr (self , "http_server" ):
3037
+ # Stop a server if its set.
3038
+ self .http_server .stop ()
3039
+
3040
+ def start_ioloop (self ) -> None :
3041
+ """Start the IO Loop."""
3042
+ if sys .platform .startswith ("win" ):
3043
+ # add no-op to wake every 5s
3044
+ # to handle signals that may be ignored by the inner loop
3045
+ pc = ioloop .PeriodicCallback (lambda : None , 5000 )
3046
+ pc .start ()
3047
+ try :
3048
+ self .io_loop .add_callback (self ._post_start )
3049
+ self .io_loop .start ()
3050
+ except KeyboardInterrupt :
3051
+ self .log .info (_i18n ("Interrupted..." ))
3052
+
3053
+ def init_ioloop (self ) -> None :
3054
+ """init self.io_loop so that an extension can use it by io_loop.call_later() to create background tasks"""
3055
+ self .io_loop = ioloop .IOLoop .current ()
3056
+
3057
+ async def _post_start (self ):
3058
+ """Add an async hook to start tasks after the event loop is running.
3059
+
3060
+ This will also attempt to start all tasks found in
3061
+ the `start_extension` method in Extension Apps.
3062
+ """
3063
+ try :
3064
+ await self .extension_manager .start_all_extensions ()
3065
+ except Exception as err :
3066
+ self .log .error (err )
3067
+
3002
3068
info = self .log .info
3003
3069
for line in self .running_server_info (kernel_count = False ).split ("\n " ):
3004
3070
info (line )
@@ -3017,15 +3083,6 @@ def start_app(self) -> None:
3017
3083
)
3018
3084
)
3019
3085
3020
- self .write_server_info_file ()
3021
-
3022
- if not self .no_browser_open_file :
3023
- self .write_browser_open_files ()
3024
-
3025
- # Handle the browser opening.
3026
- if self .open_browser and not self .sock :
3027
- self .launch_browser ()
3028
-
3029
3086
if self .identity_provider .token and self .identity_provider .token_generated :
3030
3087
# log full URL with generated token, so there's a copy/pasteable link
3031
3088
# with auth info.
@@ -3066,51 +3123,6 @@ def start_app(self) -> None:
3066
3123
3067
3124
self .log .critical ("\n " .join (message ))
3068
3125
3069
- async def _cleanup (self ) -> None :
3070
- """General cleanup of files, extensions and kernels created
3071
- by this instance ServerApp.
3072
- """
3073
- self .remove_server_info_file ()
3074
- self .remove_browser_open_files ()
3075
- await self .cleanup_extensions ()
3076
- await self .cleanup_kernels ()
3077
- try :
3078
- await self .kernel_websocket_connection_class .close_all () # type:ignore[attr-defined]
3079
- except AttributeError :
3080
- # This can happen in two different scenarios:
3081
- #
3082
- # 1. During tests, where the _cleanup method is invoked without
3083
- # the corresponding initialize method having been invoked.
3084
- # 2. If the provided `kernel_websocket_connection_class` does not
3085
- # implement the `close_all` class method.
3086
- #
3087
- # In either case, we don't need to do anything and just want to treat
3088
- # the raised error as a no-op.
3089
- pass
3090
- if getattr (self , "kernel_manager" , None ):
3091
- self .kernel_manager .__del__ ()
3092
- if getattr (self , "session_manager" , None ):
3093
- self .session_manager .close ()
3094
- if hasattr (self , "http_server" ):
3095
- # Stop a server if its set.
3096
- self .http_server .stop ()
3097
-
3098
- def start_ioloop (self ) -> None :
3099
- """Start the IO Loop."""
3100
- if sys .platform .startswith ("win" ):
3101
- # add no-op to wake every 5s
3102
- # to handle signals that may be ignored by the inner loop
3103
- pc = ioloop .PeriodicCallback (lambda : None , 5000 )
3104
- pc .start ()
3105
- try :
3106
- self .io_loop .start ()
3107
- except KeyboardInterrupt :
3108
- self .log .info (_i18n ("Interrupted..." ))
3109
-
3110
- def init_ioloop (self ) -> None :
3111
- """init self.io_loop so that an extension can use it by io_loop.call_later() to create background tasks"""
3112
- self .io_loop = ioloop .IOLoop .current ()
3113
-
3114
3126
def start (self ) -> None :
3115
3127
"""Start the Jupyter server app, after initialization
3116
3128
0 commit comments