mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-09 02:54:09 +00:00
Merge pull request #4528 from meeseeksmachine/auto-backport-of-pr-4503-on-4.x
Backport PR #4503 on branch 4.x (set root_dir when using singleuser extension)
This commit is contained in:
@@ -483,6 +483,11 @@ class JupyterHubSingleUser(ExtensionApp):
|
|||||||
cfg.answer_yes = True
|
cfg.answer_yes = True
|
||||||
self.config.FileContentsManager.delete_to_trash = False
|
self.config.FileContentsManager.delete_to_trash = False
|
||||||
|
|
||||||
|
# load Spawner.notebook_dir configuration, if given
|
||||||
|
root_dir = os.getenv("JUPYTERHUB_ROOT_DIR", None)
|
||||||
|
if root_dir:
|
||||||
|
cfg.root_dir = os.path.expanduser(root_dir)
|
||||||
|
|
||||||
# load http server config from environment
|
# load http server config from environment
|
||||||
url = urlparse(os.environ['JUPYTERHUB_SERVICE_URL'])
|
url = urlparse(os.environ['JUPYTERHUB_SERVICE_URL'])
|
||||||
if url.port:
|
if url.port:
|
||||||
|
@@ -30,6 +30,7 @@ class JupyterHubTestHandler(JupyterHandler):
|
|||||||
info = {
|
info = {
|
||||||
"current_user": self.current_user,
|
"current_user": self.current_user,
|
||||||
"config": self.app.config,
|
"config": self.app.config,
|
||||||
|
"root_dir": self.contents_manager.root_dir,
|
||||||
"disable_user_config": getattr(self.app, "disable_user_config", None),
|
"disable_user_config": getattr(self.app, "disable_user_config", None),
|
||||||
"settings": self.settings,
|
"settings": self.settings,
|
||||||
"config_file_paths": self.app.config_file_paths,
|
"config_file_paths": self.app.config_file_paths,
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from contextlib import nullcontext
|
from contextlib import nullcontext
|
||||||
|
from pprint import pprint
|
||||||
from subprocess import CalledProcessError, check_output
|
from subprocess import CalledProcessError, check_output
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
from urllib.parse import urlencode, urlparse
|
from urllib.parse import urlencode, urlparse
|
||||||
@@ -171,9 +172,7 @@ async def test_disable_user_config(request, app, tmpdir, full_spawn):
|
|||||||
)
|
)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
info = r.json()
|
info = r.json()
|
||||||
import pprint
|
pprint(info)
|
||||||
|
|
||||||
pprint.pprint(info)
|
|
||||||
assert info['disable_user_config']
|
assert info['disable_user_config']
|
||||||
server_config = info['config']
|
server_config = info['config']
|
||||||
settings = info['settings']
|
settings = info['settings']
|
||||||
@@ -198,6 +197,79 @@ async def test_disable_user_config(request, app, tmpdir, full_spawn):
|
|||||||
assert_not_in_home(path, key)
|
assert_not_in_home(path, key)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("extension", [True, False])
|
||||||
|
@pytest.mark.parametrize("notebook_dir", ["", "~", "~/sub", "ABS"])
|
||||||
|
async def test_notebook_dir(
|
||||||
|
request, app, tmpdir, user, full_spawn, extension, notebook_dir
|
||||||
|
):
|
||||||
|
if extension:
|
||||||
|
try:
|
||||||
|
import jupyter_server # noqa
|
||||||
|
except ImportError:
|
||||||
|
pytest.skip("needs jupyter-server 2")
|
||||||
|
else:
|
||||||
|
if jupyter_server.version_info < (2,):
|
||||||
|
pytest.skip("needs jupyter-server 2")
|
||||||
|
|
||||||
|
token = user.new_api_token(scopes=["access:servers!user"])
|
||||||
|
headers = {"Authorization": f"Bearer {token}"}
|
||||||
|
|
||||||
|
spawner = user.spawner
|
||||||
|
if extension:
|
||||||
|
user.spawner.environment["JUPYTERHUB_SINGLEUSER_EXTENSION"] = "1"
|
||||||
|
else:
|
||||||
|
user.spawner.environment["JUPYTERHUB_SINGLEUSER_EXTENSION"] = "0"
|
||||||
|
|
||||||
|
home_dir = tmpdir.join("home").mkdir()
|
||||||
|
sub_dir = home_dir.join("sub").mkdir()
|
||||||
|
with sub_dir.join("subfile.txt").open("w") as f:
|
||||||
|
f.write("txt\n")
|
||||||
|
abs_dir = tmpdir.join("abs").mkdir()
|
||||||
|
with abs_dir.join("absfile.txt").open("w") as f:
|
||||||
|
f.write("absfile\n")
|
||||||
|
|
||||||
|
if notebook_dir:
|
||||||
|
expected_root_dir = notebook_dir.replace("ABS", str(abs_dir)).replace(
|
||||||
|
"~", str(home_dir)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
expected_root_dir = str(home_dir)
|
||||||
|
|
||||||
|
spawner.notebook_dir = notebook_dir.replace("ABS", str(abs_dir))
|
||||||
|
|
||||||
|
# home_dir is defined on SimpleSpawner
|
||||||
|
user.spawner.home_dir = home = str(home_dir)
|
||||||
|
spawner.environment["HOME"] = home
|
||||||
|
await user.spawn()
|
||||||
|
await app.proxy.add_user(user)
|
||||||
|
url = public_url(app, user)
|
||||||
|
r = await async_requests.get(
|
||||||
|
url_path_join(public_url(app, user), 'jupyterhub-test-info'), headers=headers
|
||||||
|
)
|
||||||
|
r.raise_for_status()
|
||||||
|
info = r.json()
|
||||||
|
pprint(info)
|
||||||
|
|
||||||
|
assert info["root_dir"] == expected_root_dir
|
||||||
|
# secondary check: make sure it has the intended effect on root_dir
|
||||||
|
r = await async_requests.get(
|
||||||
|
url_path_join(public_url(app, user), 'api/contents/'), headers=headers
|
||||||
|
)
|
||||||
|
r.raise_for_status()
|
||||||
|
root_contents = sorted(item['name'] for item in r.json()['content'])
|
||||||
|
|
||||||
|
# check contents
|
||||||
|
if not notebook_dir or notebook_dir == "~":
|
||||||
|
# use any to avoid counting possible automatically created files in $HOME
|
||||||
|
assert 'sub' in root_contents
|
||||||
|
elif notebook_dir == "ABS":
|
||||||
|
assert 'absfile.txt' in root_contents
|
||||||
|
elif notebook_dir == "~/sub":
|
||||||
|
assert 'subfile.txt' in root_contents
|
||||||
|
else:
|
||||||
|
raise ValueError(f"No contents check for {notebook_dir}")
|
||||||
|
|
||||||
|
|
||||||
def test_help_output():
|
def test_help_output():
|
||||||
out = check_output(
|
out = check_output(
|
||||||
[sys.executable, '-m', 'jupyterhub.singleuser', '--help-all']
|
[sys.executable, '-m', 'jupyterhub.singleuser', '--help-all']
|
||||||
|
Reference in New Issue
Block a user