Skip to content

Commit 9711822

Browse files
authored
Server extension paths (#730)
1 parent 0d8227a commit 9711822

File tree

3 files changed

+28
-8
lines changed

3 files changed

+28
-8
lines changed

jupyter_server/extension/application.py

+19-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from traitlets import default
1313
from traitlets import Dict
1414
from traitlets import HasTraits
15+
from traitlets import Instance
1516
from traitlets import List
1617
from traitlets import Unicode
1718
from traitlets.config import Config
@@ -103,7 +104,7 @@ def _prepare_templates(self):
103104
loader=FileSystemLoader(self.template_paths),
104105
extensions=["jinja2.ext.i18n"],
105106
autoescape=True,
106-
**self.jinja2_options
107+
**self.jinja2_options,
107108
)
108109

109110
# 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
162163
def _default_open_browser(self):
163164
return self.serverapp.config["ServerApp"].get("open_browser", True)
164165

166+
@property
167+
def config_file_paths(self):
168+
"""Look on the same path as our parent for config files"""
169+
# rely on parent serverapp, which should control all config loading
170+
return self.serverapp.config_file_paths
171+
165172
# The extension name used to name the jupyter config
166173
# file, jupyter_{name}_config.
167174
# This should also match the jupyter subcommand used to launch
@@ -200,7 +207,17 @@ def _default_url(self):
200207
]
201208

202209
# A ServerApp is not defined yet, but will be initialized below.
203-
serverapp = None
210+
serverapp = Instance(ServerApp)
211+
212+
@default("serverapp")
213+
def _default_serverapp(self):
214+
# load the current global instance, if any
215+
if ServerApp.initialized():
216+
return ServerApp.instance()
217+
else:
218+
# serverapp accessed before it was defined,
219+
# declare an empty one
220+
return ServerApp()
204221

205222
_log_formatter_cls = LogFormatter
206223

jupyter_server/serverapp.py

+1-6
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@
104104
base_flags,
105105
base_aliases,
106106
)
107-
from jupyter_core.paths import jupyter_config_path
108107
from jupyter_client import KernelManager
109108
from jupyter_client.kernelspec import KernelSpecManager
110109
from jupyter_client.session import Session
@@ -2154,11 +2153,7 @@ def find_server_extensions(self):
21542153
# This enables merging on keys, which we want for extension enabling.
21552154
# Regular config loading only merges at the class level,
21562155
# so each level clobbers the previous.
2157-
config_paths = jupyter_config_path()
2158-
if self.config_dir not in config_paths:
2159-
# add self.config_dir to the front, if set manually
2160-
config_paths.insert(0, self.config_dir)
2161-
manager = ExtensionConfigManager(read_config_path=config_paths)
2156+
manager = ExtensionConfigManager(read_config_path=self.config_file_paths)
21622157
extensions = manager.get_jpserver_extensions()
21632158

21642159
for modulename, enabled in sorted(extensions.items()):

tests/extension/test_app.py

+8
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ def test_extensionapp_load_config_file(
6969
assert mock_extension.mock_trait == "config from file"
7070

7171

72+
def test_extensionapp_no_parent():
73+
# make sure we can load config files, even when serverapp is not passed
74+
# relevant for e.g. shortcuts to config-loading
75+
app = MockExtensionApp()
76+
assert isinstance(app.config_file_paths, list)
77+
assert app.serverapp is not None
78+
79+
7280
OPEN_BROWSER_COMBINATIONS = (
7381
(True, {}),
7482
(True, {"ServerApp": {"open_browser": True}}),

0 commit comments

Comments
 (0)