Merge pull request #3928 from yuvipanda/auto-backport-of-pr-3919-on-2.x

Auto backport of pr 3919 on 2.x
This commit is contained in:
Yuvi Panda
2022-06-06 18:40:16 +05:30
committed by GitHub
2 changed files with 43 additions and 9 deletions

View File

@@ -182,6 +182,7 @@ page_template = """
<span> <span>
<a href='{{hub_control_panel_url}}' <a href='{{hub_control_panel_url}}'
id='jupyterhub-control-panel-link'
class='btn btn-default btn-sm navbar-btn pull-right' class='btn btn-default btn-sm navbar-btn pull-right'
style='margin-right: 4px; margin-left: 2px;'> style='margin-right: 4px; margin-left: 2px;'>
Control Panel Control Panel
@@ -640,7 +641,8 @@ class SingleUserNotebookAppMixin(Configurable):
if default_url: if default_url:
self.config[self.__class__.__name__].default_url = default_url self.config[self.__class__.__name__].default_url = default_url
self._log_app_versions() self._log_app_versions()
return super().initialize(argv) super().initialize(argv)
self.patch_templates()
def start(self): def start(self):
self.log.info("Starting jupyterhub-singleuser server version %s", __version__) self.log.info("Starting jupyterhub-singleuser server version %s", __version__)
@@ -711,7 +713,6 @@ class SingleUserNotebookAppMixin(Configurable):
# apply X-JupyterHub-Version to *all* request handlers (even redirects) # apply X-JupyterHub-Version to *all* request handlers (even redirects)
self.patch_default_headers() self.patch_default_headers()
self.patch_templates()
def page_config_hook(self, handler, page_config): def page_config_hook(self, handler, page_config):
"""JupyterLab page config hook """JupyterLab page config hook
@@ -744,19 +745,30 @@ class SingleUserNotebookAppMixin(Configurable):
) )
self.jinja_template_vars['hub_host'] = self.hub_host self.jinja_template_vars['hub_host'] = self.hub_host
self.jinja_template_vars['hub_prefix'] = self.hub_prefix self.jinja_template_vars['hub_prefix'] = self.hub_prefix
env = self.web_app.settings['jinja2_env'] self.jinja_template_vars[
'hub_control_panel_url'
] = self.hub_host + url_path_join(self.hub_prefix, 'home')
env.globals['hub_control_panel_url'] = self.hub_host + url_path_join( settings = self.web_app.settings
self.hub_prefix, 'home' # patch classic notebook jinja env
) jinja_envs = []
if 'jinja2_env' in settings:
# default jinja env (should we do this on jupyter-server, or only notebook?)
jinja_envs.append(settings['jinja2_env'])
if 'notebook_jinja2_env' in settings:
# when running with jupyter-server, classic notebook (nbclassic server extension)
# gets its own jinja env, which needs the same patch
jinja_envs.append(settings['notebook_jinja2_env'])
# patch jinja env loading to modify page template # patch jinja env loading to get modified template, only for base page.html
def get_page(name): def get_page(name):
if name == 'page.html': if name == 'page.html':
return page_template return page_template
orig_loader = env.loader for jinja_env in jinja_envs:
env.loader = ChoiceLoader([FunctionLoader(get_page), orig_loader]) jinja_env.loader = ChoiceLoader(
[FunctionLoader(get_page), jinja_env.loader]
)
def load_server_extensions(self): def load_server_extensions(self):
# Loading LabApp sets $JUPYTERHUB_API_TOKEN on load, which is incorrect # Loading LabApp sets $JUPYTERHUB_API_TOKEN on load, which is incorrect

View File

@@ -5,9 +5,11 @@ from contextlib import contextmanager
from subprocess import CalledProcessError from subprocess import CalledProcessError
from subprocess import check_output from subprocess import check_output
from unittest import mock from unittest import mock
from urllib.parse import urlencode
from urllib.parse import urlparse from urllib.parse import urlparse
import pytest import pytest
from bs4 import BeautifulSoup
import jupyterhub import jupyterhub
from .. import orm from .. import orm
@@ -16,6 +18,7 @@ from .mocking import public_url
from .mocking import StubSingleUserSpawner from .mocking import StubSingleUserSpawner
from .utils import async_requests from .utils import async_requests
from .utils import AsyncSession from .utils import AsyncSession
from .utils import get_page
@contextmanager @contextmanager
@@ -225,3 +228,22 @@ def test_singleuser_app_class(JUPYTERHUB_SINGLEUSER_APP):
else: else:
assert '--ServerApp.' in out assert '--ServerApp.' in out
assert '--NotebookApp.' not in out assert '--NotebookApp.' not in out
async def test_nbclassic_control_panel(app, user):
# use StubSingleUserSpawner to launch a single-user app in a thread
app.spawner_class = StubSingleUserSpawner
app.tornado_settings['spawner_class'] = StubSingleUserSpawner
# login, start the server
await user.spawn()
cookies = await app.login_user(user.name)
next_url = url_path_join(user.url, "tree/")
url = '/?' + urlencode({'next': next_url})
r = await get_page(url, app, cookies=cookies)
r.raise_for_status()
assert urlparse(r.url).path == urlparse(next_url).path
page = BeautifulSoup(r.text, "html.parser")
link = page.find("a", id="jupyterhub-control-panel-link")
assert link, f"Missing jupyterhub-control-panel-link in {page}"
assert link["href"] == url_path_join(app.base_url, "hub/home")