Skip to content

Commit ffb0744

Browse files
authored
Merge pull request #159 from Zsailer/extension-app-config
allow extensions to read config from file
2 parents e1b4ce4 + 3fbb285 commit ffb0744

File tree

4 files changed

+41
-10
lines changed

4 files changed

+41
-10
lines changed

jupyter_server/extension/application.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,21 +95,20 @@ class method. This method can be set as a entry_point in
9595

9696
# Name of the extension
9797
extension_name = Unicode(
98-
"",
9998
help="Name of extension."
10099
)
101100

102-
@default("extension_name")
103-
def _default_extension_name(self):
101+
def _extension_name_default(self):
104102
try:
105103
return self.name
106104
except AttributeError:
107105
raise ValueError("The extension must be given a `name`.")
108106

109107
INVALID_EXTENSION_NAME_CHARS = [' ', '.', '+', '/']
110108

111-
def _validate_extension_name(self):
112-
value = self.extension_name
109+
@validate('extension_name')
110+
def _validate_extension_name(self, value):
111+
#value = self.extension_name
113112
if isinstance(value, str):
114113
# Validate that extension_name doesn't contain any invalid characters.
115114
for c in ExtensionApp.INVALID_EXTENSION_NAME_CHARS:
@@ -157,6 +156,22 @@ def static_url_prefix(self):
157156
help=_("""Handlers appended to the server.""")
158157
).tag(config=True)
159158

159+
def _config_dir_default(self):
160+
"""Point the config directory at the server's config_dir by default."""
161+
try:
162+
return self.serverapp.config_dir
163+
except AttributeError:
164+
raise AttributeError(
165+
"The ExtensionApp has not ServerApp "
166+
"initialized. Try `.initialize_server()`."
167+
)
168+
169+
def _config_file_name_default(self):
170+
"""The default config file name."""
171+
if not self.extension_name:
172+
return ''
173+
return 'jupyter_{}_config'.format(self.extension_name.replace('-','_'))
174+
160175
default_url = Unicode('/', config=True,
161176
help=_("The default URL to redirect to from `/`")
162177
)
@@ -298,10 +313,11 @@ def initialize(self, serverapp, argv=[]):
298313
- Passes settings to webapp
299314
- Appends handlers to webapp.
300315
"""
301-
self._validate_extension_name()
316+
# Initialize ServerApp.
317+
self.serverapp = serverapp
318+
302319
# Initialize the extension application
303320
super(ExtensionApp, self).initialize(argv=argv)
304-
self.serverapp = serverapp
305321

306322
# Initialize config, settings, templates, and handlers.
307323
self._prepare_config()

jupyter_server/serverapp.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,7 @@ def _update_server_extensions(self, change):
12091209
"""))
12101210

12111211
def parse_command_line(self, argv=None):
1212+
12121213
super(ServerApp, self).parse_command_line(argv)
12131214

12141215
if self.extra_args:
@@ -1504,7 +1505,7 @@ def init_server_extensions(self):
15041505
# Add debug log for loaded extensions.
15051506
self.log.debug("%s is enabled and loaded." % modulename)
15061507
else:
1507-
self.log.warning("%s is enabled but no `load_jupyter_server_extension` function was found")
1508+
self.log.warning("%s is enabled but no `load_jupyter_server_extension` function was found" % modulename)
15081509
except Exception:
15091510
if self.reraise_server_extension_failures:
15101511
raise

tests/extension/conftest.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ def initialize_handlers(self):
2020
self.handlers.append(('/mock', MockExtensionHandler))
2121

2222

23+
@pytest.fixture
24+
def config_file(config_dir):
25+
f = config_dir.joinpath('jupyter_mock_config.py')
26+
f.write_text("c.MockExtension.mock_trait ='config from file'")
27+
return f
28+
29+
2330
@pytest.fixture
2431
def extended_serverapp(serverapp):
2532
m = MockExtension()

tests/extension/test_app.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,18 @@ def test_instance_creation_with_instance_args(trait_name, trait_value):
4949
def test_instance_creation_with_argv(serverapp, trait_name, trait_value):
5050
kwarg = {}
5151
kwarg.setdefault(trait_name, trait_value)
52-
5352
argv = [
5453
'--MockExtension.{name}={value}'.format(name=trait_name, value=trait_value)
5554
]
56-
5755
mock_extension = MockExtension()
5856
mock_extension.initialize(serverapp, argv=argv)
5957
assert getattr(mock_extension, trait_name) == trait_value
58+
59+
60+
def test_extensionapp_load_config_file(config_file, serverapp, extended_serverapp):
61+
# Assert default config_file_paths is the same in the app and extension.
62+
assert extended_serverapp.config_file_paths == serverapp.config_file_paths
63+
assert extended_serverapp.config_file_name == 'jupyter_mock_config'
64+
assert extended_serverapp.config_dir == serverapp.config_dir
65+
# Assert that the trait is updated by config file
66+
assert extended_serverapp.mock_trait == 'config from file'

0 commit comments

Comments
 (0)