panel
panel copied to clipboard
UndefinedError while saving a panel object to html file
ALL software version info
OS: Ubuntu 22.04 Python: 3.10.12 Panel: 1.4.0 Bokeh: 3.4.0
Description of expected behavior and the observed behavior
I developed a package that creates interactive plots. Considering the great number of examples in the documentation, these are the steps I use to build it (on a headless server):
- create and populate a panel template.
- Save the template to an html file.
- Load the html file with selenium, take a screenshot and save it.
- Include the screenshot in the docs.
With panel 1.4.0 I'm getting an error in step 2, saving the template to an html file. Previous versions worked fine.
Complete, minimal, self-contained example code that reproduces the issue
from bokeh.plotting import figure, show
from bokeh.io import output_notebook
import numpy as np
import panel as pn
x = np.linspace(-np.pi, np.pi)
y = np.cos(x)
f = figure()
f.line(x, y)
p = pn.template.BootstrapTemplate(
title="Hello World",
sidebar=["# Hello Sidebar", "This is text for the *sidebar*"],
main=[pn.pane.panel(f)],
)
p.save("test_panel.html")
Stack traceback and/or browser JavaScript console output
---------------------------------------------------------------------------
UndefinedError Traceback (most recent call last)
Cell In[1], line 17
11 p = pn.template.BootstrapTemplate(
12 title="Hello World",
13 sidebar=["# Hello Sidebar", "This is text for the *sidebar*"],
14 main=[pn.pane.panel(f)],
15 )
16 # p.servable().show()
---> 17 p.save("test_panel.html")
File ~/Documents/Development/envs/plot/lib/python3.10/site-packages/panel/template/base.py:473, in BaseTemplate.save(self, filename, title, resources, embed, max_states, max_opts, embed_json, json_prefix, save_path, load_path)
470 if embed:
471 raise ValueError("Embedding is not yet supported on Template.")
--> 473 return save(
474 self, filename, title, resources, self.template,
475 self._render_variables, embed, max_states, max_opts,
476 embed_json, json_prefix, save_path, load_path
477 )
File ~/Documents/Development/envs/plot/lib/python3.10/site-packages/panel/io/save.py:290, in save(panel, filename, title, resources, template, template_variables, embed, max_states, max_opts, embed_json, json_prefix, save_path, load_path, progress, embed_states, as_png, **kwargs)
288 # Set resource mode
289 with set_resource_mode(resources):
--> 290 html = file_html(doc, resources, title, **kwargs)
291 if hasattr(filename, 'write'):
292 if isinstance(filename, io.BytesIO):
File ~/Documents/Development/envs/plot/lib/python3.10/site-packages/panel/io/save.py:164, in file_html(models, resources, title, template, template_variables, theme, _always_new)
162 title = _title_from_models(models_seq, title)
163 bundle = bundle_resources(models_seq, resources)
--> 164 return html_page_for_render_items(
165 bundle, docs_json, render_items, title=title, template=template,
166 template_variables=template_variables
167 )
File ~/Documents/Development/envs/plot/lib/python3.10/site-packages/bokeh/embed/elements.py:150, in html_page_for_render_items(bundle, docs_json, render_items, title, template, template_variables)
147 elif isinstance(template, str):
148 template = get_env().from_string("{% extends base %}\n" + template)
--> 150 html = template.render(context)
151 return html
File ~/Documents/Development/envs/plot/lib/python3.10/site-packages/jinja2/environment.py:1301, in Template.render(self, *args, **kwargs)
1299 return self.environment.concat(self.root_render_func(ctx)) # type: ignore
1300 except Exception:
-> 1301 self.environment.handle_exception()
File ~/Documents/Development/envs/plot/lib/python3.10/site-packages/jinja2/environment.py:936, in Environment.handle_exception(self, source)
931 """Exception handling helper. This is used internally to either raise
932 rewritten exceptions or return a rendered traceback for the template.
933 """
934 from .debug import rewrite_traceback_stack
--> 936 raise rewrite_traceback_stack(source=source)
File ~/Documents/Development/envs/plot/lib/python3.10/site-packages/panel/template/bootstrap/bootstrap.html:1, in top-level template code()
----> 1 {% extends "base/base.html" %}
2
3 {% block preamble %}
File ~/Documents/Development/envs/plot/lib/python3.10/site-packages/panel/template/base/base.html:1, in top-level template code()
----> 1 {% extends "base.html" %}
2
3 <!-- goes in body -->
File ~/Documents/Development/envs/plot/lib/python3.10/site-packages/panel/_templates/base.html:20, in top-level template code()
18 <!DOCTYPE html>
19 <html lang="en" {{ html_attrs | default("", true) }}>
---> 20 {% block head %}
21 <head>
22 {% block inner_head %}
File ~/Documents/Development/envs/plot/lib/python3.10/site-packages/panel/_templates/base.html:22, in block 'head'()
20 {% block head %}
21 <head>
---> 22 {% block inner_head %}
23 <meta charset="utf-8">
24 <title>{% block title %}{{ title | e if title else "Panel App" }}{% endblock %}</title>
File ~/Documents/Development/envs/plot/lib/python3.10/site-packages/panel/_templates/base.html:29, in block 'inner_head'()
27 {% if manifest_url %}<link rel="manifest" href="{{ manifest_url }}">{% endif %}
28 {% if theme_name == "dark"%}<style>html { background-color: #121212 }</style>{% endif %}
---> 29 {% block preamble -%}{%- endblock %}
30 {% block resources %}
31 <style>
File ~/Documents/Development/envs/plot/lib/python3.10/site-packages/panel/template/bootstrap/bootstrap.html:6, in block 'preamble'()
4 {{ super() }}
5 <!-- Template JS -->
----> 6 {% for src in template_resources['js'].values() %}
7 <script src="{{ src }}"></script>
8 {% endfor %}
File ~/Documents/Development/envs/plot/lib/python3.10/site-packages/jinja2/environment.py:466, in Environment.getitem(self, obj, argument)
464 """Get an item or attribute of an object but prefer the item."""
465 try:
--> 466 return obj[argument]
467 except (AttributeError, TypeError, LookupError):
468 if isinstance(argument, str):
UndefinedError: 'template_resources' is undefined
Screenshots or screencasts of the bug in action
- [ ] I may be interested in making a pull request to address this
I am having the same issue in my application. I was able to reproduce with the code example above. If I set the panel version to 1.3.8 the sample runs without error. Any version >= 1.4.0 reproduces the issue.
Can confirm it is an issue with MaterialTemplate
on Panel 1.4.2
Confirmed also here. An active issue with on Panel 1.4.2. Okay if downloaded to 1.3.8. Would love to have this bug fixed.
The issue seemed to be resolved if the following one-line code is restored from panel/template/base.py at line number 146 @philippjfr
self._render_variables['template_resources'] = self.resolve_resources()
I have noticed the commit here: https://github.com/holoviz/panel/commit/d6f5117b06da92c127585b29b03da9b71c6260ab
Can confirm it is an issue with MaterialTemplate on Panel 1.4.5
I tried with ressources='CDN'
and ressources='INLINE'
.