From 38b23c297fd74720cdd8bb0f7f6eb8d2edd5c1a2 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Wed, 9 Mar 2022 09:48:59 +0100 Subject: [PATCH 1/4] Improve error handling - Add theme handling to error pages - Center error message --- share/jupyter/voila/templates/base/error.html | 12 ++++++++- share/jupyter/voila/templates/lab/error.html | 12 +++++++++ voila/handler.py | 26 ++++++++++++++++++- 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 share/jupyter/voila/templates/lab/error.html diff --git a/share/jupyter/voila/templates/base/error.html b/share/jupyter/voila/templates/base/error.html index 21cbd9142..0af6fdcd5 100644 --- a/share/jupyter/voila/templates/base/error.html +++ b/share/jupyter/voila/templates/base/error.html @@ -1,7 +1,17 @@ {% extends "page.html" %} +{% block stylesheets %} + {{ super() }} + + +{% endblock %} + {% block body %} -
+

{{ status_code }}: {{ status_message }}

{% block error_detail %} diff --git a/share/jupyter/voila/templates/lab/error.html b/share/jupyter/voila/templates/lab/error.html new file mode 100644 index 000000000..8a132454e --- /dev/null +++ b/share/jupyter/voila/templates/lab/error.html @@ -0,0 +1,12 @@ +{% extends "voila/templates/base/error.html" %} + +{% block stylesheets %} + {{ super() }} + + +{% endblock %} diff --git a/voila/handler.py b/voila/handler.py index 172611706..f7a3d019e 100644 --- a/voila/handler.py +++ b/voila/handler.py @@ -23,7 +23,7 @@ from ._version import __version__ from .notebook_renderer import NotebookRenderer from .query_parameters_handler import QueryStringSocketHandler -from .utils import ENV_VARIABLE +from .utils import ENV_VARIABLE, create_include_assets_functions class VoilaHandler(JupyterHandler): @@ -192,6 +192,30 @@ async def get(self, path=None): self.write(html) self.flush() + def render_template(self, name, **ns): + template_arg = ( + self.get_argument("voila-template", self.voila_configuration.template) + if self.voila_configuration.allow_template_override == "YES" + else self.voila_configuration.template + ) + theme_arg = ( + self.get_argument("voila-theme", self.voila_configuration.theme) + if self.voila_configuration.allow_theme_override == "YES" + else self.voila_configuration.theme + ) + + ns = { + **ns, + **self.template_namespace, + **create_include_assets_functions( + template_arg, self.base_url + ), + "theme": theme_arg + } + + template = self.get_template(name) + return template.render(**ns) + def redirect_to_file(self, path): self.redirect(url_path_join(self.base_url, 'voila', 'files', path)) From e62daccc1975c5080b55cf220ce55ca7fce9c256 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Wed, 9 Mar 2022 09:53:42 +0100 Subject: [PATCH 2/4] Add ui-tests for error handling --- ui-tests/tests/voila.test.ts | 21 ++++++++++++++++++ .../404-classic-linux.png | Bin 0 -> 5204 bytes .../404-dark-linux.png | Bin 0 -> 5114 bytes .../voila.test.ts-snapshots/404-linux.png | Bin 0 -> 5154 bytes 4 files changed, 21 insertions(+) create mode 100644 ui-tests/tests/voila.test.ts-snapshots/404-classic-linux.png create mode 100644 ui-tests/tests/voila.test.ts-snapshots/404-dark-linux.png create mode 100644 ui-tests/tests/voila.test.ts-snapshots/404-linux.png diff --git a/ui-tests/tests/voila.test.ts b/ui-tests/tests/voila.test.ts index ddaca1412..d9a9ab0e6 100644 --- a/ui-tests/tests/voila.test.ts +++ b/ui-tests/tests/voila.test.ts @@ -161,6 +161,27 @@ test.describe('Voila performance Tests', () => { ); }); + test('Render 404 error', async ({ page }) => { + await page.goto('/voila/render/unknown.ipynb'); + await page.waitForSelector('.voila-error'); + + expect(await page.screenshot()).toMatchSnapshot('404.png'); + }); + + test('Render 404 error with classic template', async ({ page }) => { + await page.goto('/voila/render/unknown.ipynb?voila-template=classic'); + await page.waitForSelector('.voila-error'); + + expect(await page.screenshot()).toMatchSnapshot('404-classic.png'); + }); + + test('Render 404 error with dark theme', async ({ page }) => { + await page.goto('/voila/render/unknown.ipynb?voila-theme=dark'); + await page.waitForSelector('.voila-error'); + + expect(await page.screenshot()).toMatchSnapshot('404-dark.png'); + }); + test('Render and benchmark bqplot.ipynb', async ({ page, browserName diff --git a/ui-tests/tests/voila.test.ts-snapshots/404-classic-linux.png b/ui-tests/tests/voila.test.ts-snapshots/404-classic-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..9cfb1959ae849282b8e2a0c37889fd7e680e7d7b GIT binary patch literal 5204 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 literal 0 HcmV?d00001 diff --git a/ui-tests/tests/voila.test.ts-snapshots/404-dark-linux.png b/ui-tests/tests/voila.test.ts-snapshots/404-dark-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..b81e5d451131b6854cb66477f7d1102e4b4c7a3d GIT binary patch literal 5114 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 literal 0 HcmV?d00001 diff --git a/ui-tests/tests/voila.test.ts-snapshots/404-linux.png b/ui-tests/tests/voila.test.ts-snapshots/404-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..7ac9b6054079068d16bb95bbb844cc87a52798e3 GIT binary patch literal 5154 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 Date: Wed, 9 Mar 2022 12:14:20 +0100 Subject: [PATCH 3/4] Do not fail if include_css is not defined --- share/jupyter/voila/templates/lab/page.html | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/share/jupyter/voila/templates/lab/page.html b/share/jupyter/voila/templates/lab/page.html index a3148cdb8..7152c925f 100644 --- a/share/jupyter/voila/templates/lab/page.html +++ b/share/jupyter/voila/templates/lab/page.html @@ -1,14 +1,16 @@ {%- extends 'voila/templates/base/page.html' -%} {% block stylesheets %} -{% if theme == 'dark' %} - {{ include_css("static/index.css") }} - {{ include_css("static/theme-dark.css") }} -{% elif theme == 'light' %} - {{ include_css("static/index.css") }} - {{ include_css("static/theme-light.css") }} -{% else %} - {{ include_css("static/index.css") }} - {{ include_lab_theme(theme) }} +{% if include_css %} + {% if theme == 'dark' %} + {{ include_css("static/index.css") }} + {{ include_css("static/theme-dark.css") }} + {% elif theme == 'light' %} + {{ include_css("static/index.css") }} + {{ include_css("static/theme-light.css") }} + {% else %} + {{ include_css("static/index.css") }} + {{ include_lab_theme(theme) }} + {% endif %} {% endif %} {% endblock %} From 483606838f52befd7c6a381f250cbd6f76817638 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Thu, 10 Mar 2022 13:56:38 +0100 Subject: [PATCH 4/4] Refactor code --- voila/handler.py | 61 +++++++++++++++++++++++++------------------- voila/treehandler.py | 42 +++++++++++------------------- 2 files changed, 50 insertions(+), 53 deletions(-) diff --git a/voila/handler.py b/voila/handler.py index f7a3d019e..93de9f1dc 100644 --- a/voila/handler.py +++ b/voila/handler.py @@ -26,12 +26,45 @@ from .utils import ENV_VARIABLE, create_include_assets_functions -class VoilaHandler(JupyterHandler): +class BaseVoilaHandler(JupyterHandler): + def initialize(self, **kwargs): + self.voila_configuration = kwargs['voila_configuration'] + + def render_template(self, name, **ns): + """ Render the Voila HTML template, respecting the theme and nbconvert template. + """ + template_arg = ( + self.get_argument("voila-template", self.voila_configuration.template) + if self.voila_configuration.allow_template_override == "YES" + else self.voila_configuration.template + ) + theme_arg = ( + self.get_argument("voila-theme", self.voila_configuration.theme) + if self.voila_configuration.allow_theme_override == "YES" + else self.voila_configuration.theme + ) + + ns = { + **ns, + **self.template_namespace, + **create_include_assets_functions( + template_arg, self.base_url + ), + "theme": theme_arg + } + + template = self.get_template(name) + return template.render(**ns) + + +class VoilaHandler(BaseVoilaHandler): + + def initialize(self, **kwargs): + super().initialize(**kwargs) self.notebook_path = kwargs.pop('notebook_path', []) # should it be [] self.template_paths = kwargs.pop('template_paths', []) self.traitlet_config = kwargs.pop('config', None) - self.voila_configuration = kwargs['voila_configuration'] # we want to avoid starting multiple kernels due to template mistakes self.kernel_started = False @@ -192,30 +225,6 @@ async def get(self, path=None): self.write(html) self.flush() - def render_template(self, name, **ns): - template_arg = ( - self.get_argument("voila-template", self.voila_configuration.template) - if self.voila_configuration.allow_template_override == "YES" - else self.voila_configuration.template - ) - theme_arg = ( - self.get_argument("voila-theme", self.voila_configuration.theme) - if self.voila_configuration.allow_theme_override == "YES" - else self.voila_configuration.theme - ) - - ns = { - **ns, - **self.template_namespace, - **create_include_assets_functions( - template_arg, self.base_url - ), - "theme": theme_arg - } - - template = self.get_template(name) - return template.render(**ns) - def redirect_to_file(self, path): self.redirect(url_path_join(self.base_url, 'voila', 'files', path)) diff --git a/voila/treehandler.py b/voila/treehandler.py index deb8e93bc..a8f99c1cd 100644 --- a/voila/treehandler.py +++ b/voila/treehandler.py @@ -10,15 +10,16 @@ from tornado import web -from jupyter_server.base.handlers import JupyterHandler from jupyter_server.utils import url_path_join, url_escape -from .utils import get_server_root_dir, create_include_assets_functions +from .utils import get_server_root_dir +from .handler import BaseVoilaHandler -class VoilaTreeHandler(JupyterHandler): +class VoilaTreeHandler(BaseVoilaHandler): + def initialize(self, **kwargs): - self.voila_configuration = kwargs['voila_configuration'] + super().initialize(**kwargs) self.allowed_extensions = list(self.voila_configuration.extension_language_mapping.keys()) + ['.ipynb'] def get_template(self, name): @@ -58,17 +59,6 @@ def get(self, path=''): page_title = self.generate_page_title(path) contents = cm.get(path) - template_arg = ( - self.get_argument("voila-template", self.voila_configuration.template) - if self.voila_configuration.allow_template_override == "YES" - else self.voila_configuration.template - ) - theme_arg = ( - self.get_argument("voila-theme", self.voila_configuration.theme) - if self.voila_configuration.allow_theme_override == "YES" - else self.voila_configuration.theme - ) - def allowed_content(content): if content['type'] in ['directory', 'notebook']: return True @@ -78,18 +68,16 @@ def allowed_content(content): contents['content'] = sorted(contents['content'], key=lambda i: i['name']) contents['content'] = filter(allowed_content, contents['content']) - include_assets_functions = create_include_assets_functions(template_arg, self.base_url) - - self.write(self.render_template('tree.html', - page_title=page_title, - notebook_path=path, - breadcrumbs=breadcrumbs, - contents=contents, - terminals_available=False, - server_root=get_server_root_dir(self.settings), - theme=theme_arg, - query=self.request.query, - **include_assets_functions)) + self.write(self.render_template( + 'tree.html', + page_title=page_title, + notebook_path=path, + breadcrumbs=breadcrumbs, + contents=contents, + terminals_available=False, + server_root=get_server_root_dir(self.settings), + query=self.request.query, + )) elif cm.file_exists(path): # it's not a directory, we have redirecting to do model = cm.get(path, content=False)