@@ -3060,6 +3060,72 @@ def start_app(self) -> None:
3060
3060
)
3061
3061
self .exit (1 )
3062
3062
3063
+ self .write_server_info_file ()
3064
+
3065
+ if not self .no_browser_open_file :
3066
+ self .write_browser_open_files ()
3067
+
3068
+ # Handle the browser opening.
3069
+ if self .open_browser and not self .sock :
3070
+ self .launch_browser ()
3071
+
3072
+ async def _cleanup (self ) -> None :
3073
+ """General cleanup of files, extensions and kernels created
3074
+ by this instance ServerApp.
3075
+ """
3076
+ self .remove_server_info_file ()
3077
+ self .remove_browser_open_files ()
3078
+ await self .cleanup_extensions ()
3079
+ await self .cleanup_kernels ()
3080
+ try :
3081
+ await self .kernel_websocket_connection_class .close_all () # type:ignore[attr-defined]
3082
+ except AttributeError :
3083
+ # This can happen in two different scenarios:
3084
+ #
3085
+ # 1. During tests, where the _cleanup method is invoked without
3086
+ # the corresponding initialize method having been invoked.
3087
+ # 2. If the provided `kernel_websocket_connection_class` does not
3088
+ # implement the `close_all` class method.
3089
+ #
3090
+ # In either case, we don't need to do anything and just want to treat
3091
+ # the raised error as a no-op.
3092
+ pass
3093
+ if getattr (self , "kernel_manager" , None ):
3094
+ self .kernel_manager .__del__ ()
3095
+ if getattr (self , "session_manager" , None ):
3096
+ self .session_manager .close ()
3097
+ if hasattr (self , "http_server" ):
3098
+ # Stop a server if its set.
3099
+ self .http_server .stop ()
3100
+
3101
+ def start_ioloop (self ) -> None :
3102
+ """Start the IO Loop."""
3103
+ if sys .platform .startswith ("win" ):
3104
+ # add no-op to wake every 5s
3105
+ # to handle signals that may be ignored by the inner loop
3106
+ pc = ioloop .PeriodicCallback (lambda : None , 5000 )
3107
+ pc .start ()
3108
+ try :
3109
+ self .io_loop .add_callback (self ._post_start )
3110
+ self .io_loop .start ()
3111
+ except KeyboardInterrupt :
3112
+ self .log .info (_i18n ("Interrupted..." ))
3113
+
3114
+ def init_ioloop (self ) -> None :
3115
+ """init self.io_loop so that an extension can use it by io_loop.call_later() to create background tasks"""
3116
+ self .io_loop = ioloop .IOLoop .current ()
3117
+
3118
+ async def _post_start (self ):
3119
+ """Add an async hook to start tasks after the event loop is running.
3120
+
3121
+ This will also attempt to start all tasks found in
3122
+ the `start_extension` method in Extension Apps.
3123
+ """
3124
+ try :
3125
+ await self .extension_manager .start_all_extensions ()
3126
+ except Exception as err :
3127
+ self .log .error (err )
3128
+
3063
3129
info = self .log .info
3064
3130
for line in self .running_server_info (kernel_count = False ).split ("\n " ):
3065
3131
info (line )
@@ -3078,15 +3144,6 @@ def start_app(self) -> None:
3078
3144
)
3079
3145
)
3080
3146
3081
- self .write_server_info_file ()
3082
-
3083
- if not self .no_browser_open_file :
3084
- self .write_browser_open_files ()
3085
-
3086
- # Handle the browser opening.
3087
- if self .open_browser and not self .sock :
3088
- self .launch_browser ()
3089
-
3090
3147
if self .identity_provider .token and self .identity_provider .token_generated :
3091
3148
# log full URL with generated token, so there's a copy/pasteable link
3092
3149
# with auth info.
@@ -3127,51 +3184,6 @@ def start_app(self) -> None:
3127
3184
3128
3185
self .log .critical ("\n " .join (message ))
3129
3186
3130
- async def _cleanup (self ) -> None :
3131
- """General cleanup of files, extensions and kernels created
3132
- by this instance ServerApp.
3133
- """
3134
- self .remove_server_info_file ()
3135
- self .remove_browser_open_files ()
3136
- await self .cleanup_extensions ()
3137
- await self .cleanup_kernels ()
3138
- try :
3139
- await self .kernel_websocket_connection_class .close_all () # type:ignore[attr-defined]
3140
- except AttributeError :
3141
- # This can happen in two different scenarios:
3142
- #
3143
- # 1. During tests, where the _cleanup method is invoked without
3144
- # the corresponding initialize method having been invoked.
3145
- # 2. If the provided `kernel_websocket_connection_class` does not
3146
- # implement the `close_all` class method.
3147
- #
3148
- # In either case, we don't need to do anything and just want to treat
3149
- # the raised error as a no-op.
3150
- pass
3151
- if getattr (self , "kernel_manager" , None ):
3152
- self .kernel_manager .__del__ ()
3153
- if getattr (self , "session_manager" , None ):
3154
- self .session_manager .close ()
3155
- if hasattr (self , "http_server" ):
3156
- # Stop a server if its set.
3157
- self .http_server .stop ()
3158
-
3159
- def start_ioloop (self ) -> None :
3160
- """Start the IO Loop."""
3161
- if sys .platform .startswith ("win" ):
3162
- # add no-op to wake every 5s
3163
- # to handle signals that may be ignored by the inner loop
3164
- pc = ioloop .PeriodicCallback (lambda : None , 5000 )
3165
- pc .start ()
3166
- try :
3167
- self .io_loop .start ()
3168
- except KeyboardInterrupt :
3169
- self .log .info (_i18n ("Interrupted..." ))
3170
-
3171
- def init_ioloop (self ) -> None :
3172
- """init self.io_loop so that an extension can use it by io_loop.call_later() to create background tasks"""
3173
- self .io_loop = ioloop .IOLoop .current ()
3174
-
3175
3187
def start (self ) -> None :
3176
3188
"""Start the Jupyter server app, after initialization
3177
3189
0 commit comments