From f955878bc775903a66a3886c24fd4eafe951c962 Mon Sep 17 00:00:00 2001 From: Min RK Date: Mon, 14 Mar 2022 16:45:49 +0100 Subject: [PATCH 1/2] Revert "Revert "Server extension paths (#730)" (#732)" This reverts commit 93b1c838957c4f29d2bcdbaae1721f55fe8b4f27. --- jupyter_server/extension/application.py | 21 +++++++++++++++++++-- jupyter_server/serverapp.py | 7 +------ tests/extension/test_app.py | 8 ++++++++ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/jupyter_server/extension/application.py b/jupyter_server/extension/application.py index ea18d687d4..932263e702 100644 --- a/jupyter_server/extension/application.py +++ b/jupyter_server/extension/application.py @@ -12,6 +12,7 @@ from traitlets import default from traitlets import Dict from traitlets import HasTraits +from traitlets import Instance from traitlets import List from traitlets import Unicode from traitlets.config import Config @@ -103,7 +104,7 @@ def _prepare_templates(self): loader=FileSystemLoader(self.template_paths), extensions=["jinja2.ext.i18n"], autoescape=True, - **self.jinja2_options + **self.jinja2_options, ) # Add the jinja2 environment for this extension to the tornado settings. @@ -162,6 +163,12 @@ class method. This method can be set as a entry_point in def _default_open_browser(self): return self.serverapp.config["ServerApp"].get("open_browser", True) + @property + def config_file_paths(self): + """Look on the same path as our parent for config files""" + # rely on parent serverapp, which should control all config loading + return self.serverapp.config_file_paths + # The extension name used to name the jupyter config # file, jupyter_{name}_config. # This should also match the jupyter subcommand used to launch @@ -200,7 +207,17 @@ def _default_url(self): ] # A ServerApp is not defined yet, but will be initialized below. - serverapp = None + serverapp = Instance(ServerApp) + + @default("serverapp") + def _default_serverapp(self): + # load the current global instance, if any + if ServerApp.initialized(): + return ServerApp.instance() + else: + # serverapp accessed before it was defined, + # declare an empty one + return ServerApp() _log_formatter_cls = LogFormatter diff --git a/jupyter_server/serverapp.py b/jupyter_server/serverapp.py index 1ee4cf64b4..422f4ffb13 100644 --- a/jupyter_server/serverapp.py +++ b/jupyter_server/serverapp.py @@ -104,7 +104,6 @@ base_flags, base_aliases, ) -from jupyter_core.paths import jupyter_config_path from jupyter_client import KernelManager from jupyter_client.kernelspec import KernelSpecManager from jupyter_client.session import Session @@ -2154,11 +2153,7 @@ def find_server_extensions(self): # This enables merging on keys, which we want for extension enabling. # Regular config loading only merges at the class level, # so each level clobbers the previous. - config_paths = jupyter_config_path() - if self.config_dir not in config_paths: - # add self.config_dir to the front, if set manually - config_paths.insert(0, self.config_dir) - manager = ExtensionConfigManager(read_config_path=config_paths) + manager = ExtensionConfigManager(read_config_path=self.config_file_paths) extensions = manager.get_jpserver_extensions() for modulename, enabled in sorted(extensions.items()): diff --git a/tests/extension/test_app.py b/tests/extension/test_app.py index dc045631a2..c550e4c75e 100644 --- a/tests/extension/test_app.py +++ b/tests/extension/test_app.py @@ -69,6 +69,14 @@ def test_extensionapp_load_config_file( assert mock_extension.mock_trait == "config from file" +def test_extensionapp_no_parent(): + # make sure we can load config files, even when serverapp is not passed + # relevant for e.g. shortcuts to config-loading + app = MockExtensionApp() + assert isinstance(app.config_file_paths, list) + assert app.serverapp is not None + + OPEN_BROWSER_COMBINATIONS = ( (True, {}), (True, {"ServerApp": {"open_browser": True}}), From acf2fc6be21044943a8b34dbe5dac6d79dac9647 Mon Sep 17 00:00:00 2001 From: Min RK Date: Mon, 14 Mar 2022 16:47:36 +0100 Subject: [PATCH 2/2] handle non-ServerApp global instance --- jupyter_server/extension/application.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/jupyter_server/extension/application.py b/jupyter_server/extension/application.py index 932263e702..108b270670 100644 --- a/jupyter_server/extension/application.py +++ b/jupyter_server/extension/application.py @@ -213,11 +213,15 @@ def _default_url(self): def _default_serverapp(self): # load the current global instance, if any if ServerApp.initialized(): - return ServerApp.instance() - else: - # serverapp accessed before it was defined, - # declare an empty one - return ServerApp() + try: + return ServerApp.instance() + except Exception: + # error retrieving instance, e.g. MultipleInstanceError + pass + + # serverapp accessed before it was defined, + # declare an empty one + return ServerApp() _log_formatter_cls = LogFormatter