Skip to content

Commit

Permalink
PR: Add a new preferred-dir traitlet (#549)
Browse files Browse the repository at this point in the history
* Add a new preferred-dir traitlet
  • Loading branch information
goanpeca authored Jul 8, 2021
1 parent 81d46e3 commit f7290dc
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 3 deletions.
33 changes: 30 additions & 3 deletions jupyter_server/serverapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,7 @@ def start(self):
'certfile': 'ServerApp.certfile',
'client-ca': 'ServerApp.client_ca',
'notebook-dir': 'ServerApp.root_dir',
'preferred-dir': 'ServerApp.preferred_dir',
'browser': 'ServerApp.browser',
'pylab': 'ServerApp.pylab',
'gateway-url': 'GatewayClient.url',
Expand Down Expand Up @@ -1355,9 +1356,7 @@ def _default_root_dir(self):
else:
return os.getcwd()

@validate('root_dir')
def _root_dir_validate(self, proposal):
value = proposal['value']
def _normalize_dir(self, value):
# Strip any trailing slashes
# *except* if it's root
_, path = os.path.splitdrive(value)
Expand All @@ -1367,13 +1366,41 @@ def _root_dir_validate(self, proposal):
if not os.path.isabs(value):
# If we receive a non-absolute path, make it absolute.
value = os.path.abspath(value)
return value

@validate('root_dir')
def _root_dir_validate(self, proposal):
value = self._normalize_dir(proposal['value'])
if not os.path.isdir(value):
raise TraitError(trans.gettext("No such directory: '%r'") % value)
return value

preferred_dir = Unicode(config=True,
help=trans.gettext("Preferred starting directory to use for notebooks and kernels.")
)

@default('preferred_dir')
def _default_prefered_dir(self):
return self.root_dir

@validate('preferred_dir')
def _preferred_dir_validate(self, proposal):
value = self._normalize_dir(proposal['value'])
if not os.path.isdir(value):
raise TraitError(trans.gettext("No such preferred dir: '%r'") % value)

# preferred_dir must be equal or a subdir of root_dir
if not value.startswith(self.root_dir):
raise TraitError(trans.gettext("preferred_dir must be equal or a subdir of root_dir: '%r'") % value)

return value

@observe('root_dir')
def _root_dir_changed(self, change):
self._root_dir_set = True
if not self.preferred_dir.startswith(change['new']):
self.log.warning(trans.gettext("Value of preferred_dir updated to use value of root_dir"))
self.preferred_dir = change['new']

@observe('server_extensions')
def _update_server_extensions(self, change):
Expand Down
90 changes: 90 additions & 0 deletions jupyter_server/tests/test_serverapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,3 +286,93 @@ def test_urls(config, public_url, local_url, connection_url):
assert serverapp.connection_url == connection_url
# Cleanup singleton after test.
ServerApp.clear_instance()


# Preferred dir tests
# ----------------------------------------------------------------------------
def test_valid_preferred_dir(tmp_path, jp_configurable_serverapp):
path = str(tmp_path)
app = jp_configurable_serverapp(root_dir=path, preferred_dir=path)
assert app.root_dir == path
assert app.preferred_dir == path
assert app.root_dir == app.preferred_dir


def test_valid_preferred_dir_is_root_subdir(tmp_path, jp_configurable_serverapp):
path = str(tmp_path)
path_subdir = str(tmp_path / 'subdir')
os.makedirs(path_subdir, exist_ok=True)
app = jp_configurable_serverapp(root_dir=path, preferred_dir=path_subdir)
assert app.root_dir == path
assert app.preferred_dir == path_subdir
assert app.preferred_dir.startswith(app.root_dir)


def test_valid_preferred_dir_does_not_exist(tmp_path, jp_configurable_serverapp):
path = str(tmp_path)
path_subdir = str(tmp_path / 'subdir')
with pytest.raises(TraitError) as error:
app = jp_configurable_serverapp(root_dir=path, preferred_dir=path_subdir)

assert "No such preferred dir:" in str(error)


def test_invalid_preferred_dir_does_not_exist(tmp_path, jp_configurable_serverapp):
path = str(tmp_path)
path_subdir = str(tmp_path / 'subdir')
with pytest.raises(TraitError) as error:
app = jp_configurable_serverapp(root_dir=path, preferred_dir=path_subdir)

assert "No such preferred dir:" in str(error)


def test_invalid_preferred_dir_does_not_exist_set(tmp_path, jp_configurable_serverapp):
path = str(tmp_path)
path_subdir = str(tmp_path / 'subdir')

app = jp_configurable_serverapp(root_dir=path)
with pytest.raises(TraitError) as error:
app.preferred_dir = path_subdir

assert "No such preferred dir:" in str(error)


def test_invalid_preferred_dir_not_root_subdir(tmp_path, jp_configurable_serverapp):
path = str(tmp_path / 'subdir')
os.makedirs(path, exist_ok=True)
not_subdir_path = str(tmp_path)

with pytest.raises(TraitError) as error:
app = jp_configurable_serverapp(root_dir=path, preferred_dir=not_subdir_path)

assert "preferred_dir must be equal or a subdir of root_dir:" in str(error)


def test_invalid_preferred_dir_not_root_subdir_set(tmp_path, jp_configurable_serverapp):
path = str(tmp_path / 'subdir')
os.makedirs(path, exist_ok=True)
not_subdir_path = str(tmp_path)

app = jp_configurable_serverapp(root_dir=path)
with pytest.raises(TraitError) as error:
app.preferred_dir = not_subdir_path

assert "preferred_dir must be equal or a subdir of root_dir:" in str(error)


def test_observed_root_dir_updates_preferred_dir(tmp_path, jp_configurable_serverapp):
path = str(tmp_path)
new_path = str(tmp_path / 'subdir')
os.makedirs(new_path, exist_ok=True)

app = jp_configurable_serverapp(root_dir=path, preferred_dir=path)
app.root_dir = new_path
assert app.preferred_dir == new_path


def test_observed_root_dir_does_not_update_preferred_dir(tmp_path, jp_configurable_serverapp):
path = str(tmp_path)
new_path = str(tmp_path.parent)
app = jp_configurable_serverapp(root_dir=path, preferred_dir=path)
app.root_dir = new_path
assert app.preferred_dir == path

0 comments on commit f7290dc

Please sign in to comment.