Skip to content

Commit ebbcbb7

Browse files
committed
Handle open_browser trait in ServerApp and ExtensionApp differently
1 parent 60c66b6 commit ebbcbb7

File tree

2 files changed

+66
-5
lines changed

2 files changed

+66
-5
lines changed

jupyter_server/extension/application.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
Unicode,
1010
List,
1111
Dict,
12+
Bool,
1213
default
1314
)
1415
from traitlets.config import Config
@@ -147,9 +148,20 @@ class method. This method can be set as a entry_point in
147148
# A useful class property that subclasses can override to
148149
# configure the underlying Jupyter Server when this extension
149150
# is launched directly (using its `launch_instance` method).
150-
serverapp_config = {
151-
"open_browser": True
152-
}
151+
serverapp_config = {}
152+
153+
# Some subclasses will likely ovrride this trait to flip
154+
# the default value to True if they offer a browser
155+
# based frontend.
156+
open_browser = Bool(
157+
False,
158+
help="""Whether to open in a browser after starting.
159+
The specific browser used is platform dependent and
160+
determined by the python standard library `webbrowser`
161+
module, unless it is overridden using the --browser
162+
(ServerApp.browser) configuration option.
163+
"""
164+
).tag(config=True)
153165

154166
# The extension name used to name the jupyter config
155167
# file, jupyter_{name}_config.
@@ -365,6 +377,8 @@ def initialize_server(cls, argv=[], load_other_extensions=True, **kwargs):
365377
config = Config(cls._jupyter_server_config())
366378
serverapp = ServerApp.instance(**kwargs, argv=[], config=config)
367379
serverapp.initialize(argv=argv, find_extensions=load_other_extensions)
380+
# Inform the serverapp that this extension app started the app.
381+
serverapp._starter_app_name = cls.name
368382
return serverapp
369383

370384
def initialize(self):

jupyter_server/serverapp.py

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,28 @@ def _default_allow_remote(self):
887887
"""
888888
)
889889

890+
# The name of the app that started this server (if not started directly).
891+
# It is sometimes important to know if + which another app (say a server extension)
892+
# started the serverapp to properly configure some traits.
893+
# This trait should not be configured by users. It will likely be set by ExtensionApp.
894+
_starter_app_name = Unicode(None, allow_none=True)
895+
896+
@validate('_starter_app_name')
897+
def _validate_starter_app(self, proposal):
898+
# Check that a previous server extension isn't named yet
899+
value = proposal["value"]
900+
if self._starter_app_name != None:
901+
raise TraitError("Another extension was already named as the starter_server_extension.")
902+
return value
903+
904+
@property
905+
def starter_app(self):
906+
"""Get the Extension that started this server."""
907+
name = self._starter_app_name
908+
if name is None:
909+
return
910+
return self.extension_manager.extension_points.get(name, None).app
911+
890912
open_browser = Bool(False, config=True,
891913
help="""Whether to open in a browser after starting.
892914
The specific browser used is platform dependent and
@@ -895,6 +917,31 @@ def _default_allow_remote(self):
895917
(ServerApp.browser) configuration option.
896918
""")
897919

920+
921+
def _handle_browser_opening(self):
922+
"""This method handles whether a browser should be opened.
923+
By default, Jupyter Server doesn't try to open an browser. However,
924+
it's many server extensions might want to open the browser by default.
925+
This essentially toggles the default value for open_browser.
926+
927+
From a UX perspective, this needs to be surfaced to the user. The default
928+
behavior of Jupyter Server switches, which can be confusing.
929+
"""
930+
# If the server was started by another application, use that applications
931+
# trait for the open_browser trait. If that trait is not given, ignore
932+
if self.starter_app:
933+
try:
934+
if self.starter_app.open_browser:
935+
self.launch_browser()
936+
# If the starter_app doesn't have an open_browser trait, ignore
937+
# move on and don't start a browser.
938+
except AttributeError:
939+
pass
940+
else:
941+
if self.open_browser:
942+
self.launch_browser()
943+
944+
898945
browser = Unicode(u'', config=True,
899946
help="""Specify what command to use to invoke a web
900947
browser when starting the server. If not specified, the
@@ -1807,8 +1854,8 @@ def start_app(self):
18071854
self.write_server_info_file()
18081855
self.write_browser_open_file()
18091856

1810-
if self.open_browser:
1811-
self.launch_browser()
1857+
# Handle the browser opening.
1858+
self._handle_browser_opening()
18121859

18131860
if self.token and self._token_generated:
18141861
# log full URL with generated token, so there's a copy/pasteable link

0 commit comments

Comments
 (0)