Skip to content

Commit ec6217e

Browse files
authored
Merge pull request #375 from afshin/open-browser
Handle open_browser trait in ServerApp and ExtensionApp differently
2 parents 72ee66b + ebbcbb7 commit ec6217e

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
@@ -903,6 +903,28 @@ def _default_allow_remote(self):
903903
"""
904904
)
905905

906+
# The name of the app that started this server (if not started directly).
907+
# It is sometimes important to know if + which another app (say a server extension)
908+
# started the serverapp to properly configure some traits.
909+
# This trait should not be configured by users. It will likely be set by ExtensionApp.
910+
_starter_app_name = Unicode(None, allow_none=True)
911+
912+
@validate('_starter_app_name')
913+
def _validate_starter_app(self, proposal):
914+
# Check that a previous server extension isn't named yet
915+
value = proposal["value"]
916+
if self._starter_app_name != None:
917+
raise TraitError("Another extension was already named as the starter_server_extension.")
918+
return value
919+
920+
@property
921+
def starter_app(self):
922+
"""Get the Extension that started this server."""
923+
name = self._starter_app_name
924+
if name is None:
925+
return
926+
return self.extension_manager.extension_points.get(name, None).app
927+
906928
open_browser = Bool(False, config=True,
907929
help="""Whether to open in a browser after starting.
908930
The specific browser used is platform dependent and
@@ -911,6 +933,31 @@ def _default_allow_remote(self):
911933
(ServerApp.browser) configuration option.
912934
""")
913935

936+
937+
def _handle_browser_opening(self):
938+
"""This method handles whether a browser should be opened.
939+
By default, Jupyter Server doesn't try to open an browser. However,
940+
it's many server extensions might want to open the browser by default.
941+
This essentially toggles the default value for open_browser.
942+
943+
From a UX perspective, this needs to be surfaced to the user. The default
944+
behavior of Jupyter Server switches, which can be confusing.
945+
"""
946+
# If the server was started by another application, use that applications
947+
# trait for the open_browser trait. If that trait is not given, ignore
948+
if self.starter_app:
949+
try:
950+
if self.starter_app.open_browser:
951+
self.launch_browser()
952+
# If the starter_app doesn't have an open_browser trait, ignore
953+
# move on and don't start a browser.
954+
except AttributeError:
955+
pass
956+
else:
957+
if self.open_browser:
958+
self.launch_browser()
959+
960+
914961
browser = Unicode(u'', config=True,
915962
help="""Specify what command to use to invoke a web
916963
browser when starting the server. If not specified, the
@@ -1832,8 +1879,8 @@ def start_app(self):
18321879
self.write_server_info_file()
18331880
self.write_browser_open_file()
18341881

1835-
if self.open_browser:
1836-
self.launch_browser()
1882+
# Handle the browser opening.
1883+
self._handle_browser_opening()
18371884

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

0 commit comments

Comments
 (0)