Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Branch 0.12.6 #2992

Merged
merged 13 commits into from
Dec 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# Releases

## Version 0.12.6

Date: 2021-12-08

The 0.12.6 release fixes a major regression introduced in the last release along with a small number of pre-existing bugs.

Regressions:

- Always load imported bokeh extensions ([#2957](https://github.com/holoviz/panel/pull/2957))
- Fix regression rendering `HoloViews` plotly backend ([#2961](https://github.com/holoviz/panel/pull/2961))

Bug fixes:

- Do not run `Ace` import on initialization ([#2959](https://github.com/holoviz/panel/pull/2959))
- Improve handling of `ReactiveHTML` cleanup ([#2974](https://github.com/holoviz/panel/pull/2974), [#2993](https://github.com/holoviz/panel/pull/2993))
- Ensure empty `Str` has same height as non-empty ([#2981](https://github.com/holoviz/panel/pull/2981))
- Ensure `Tabulator` supports grouping on numeric columns ([#2987](https://github.com/holoviz/panel/pull/2987))
- Fix `Tabulator` with multi-index and pagination ([#2989](https://github.com/holoviz/panel/pull/2989))
- Allow index as column name in table widgets ([#2990](https://github.com/holoviz/panel/pull/2990))
- Ensure TemplateActions component does not have height ([#2997](https://github.com/holoviz/panel/pull/2997))

## Version 0.12.5

Date: 2021-11-23
Expand All @@ -13,7 +34,7 @@ Compatibility:

Enhancements:

- Add 'light' to list of button types ([#2814, [#2816](https://github.com/holoviz/panel/pull/2816))
- Add 'light' to list of button types ([#2814](https://github.com/holoviz/panel/pull/2814), [#2816](https://github.com/holoviz/panel/pull/2816))
- Make OAuth cookie expiry configurable ([#2724](https://github.com/holoviz/panel/pull/2724))
- Run `onload` callbacks with `--warm` option ([#2844](https://github.com/holoviz/panel/pull/2844))
- Improve Plotly responsive sizing behavior ([#2838](https://github.com/holoviz/panel/pull/2838))
Expand Down
23 changes: 22 additions & 1 deletion doc/releases.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# Releases

## Version 0.12.6

Date: 2021-12-07

The 0.12.6 release fixes a major regression introduced in the last release along with a small number of pre-existing bugs.

Regressions:

- Always load imported bokeh extensions ([#2957](https://github.com/holoviz/panel/pull/2957))
- Fix regression rendering `HoloViews` plotly backend ([#2961](https://github.com/holoviz/panel/pull/2961))

Bug fixes:

- Do not run `Ace` import on initialization ([#2959](https://github.com/holoviz/panel/pull/2959))
- Improve handling of `ReactiveHTML` cleanup ([#2974](https://github.com/holoviz/panel/pull/2974), [#2993](https://github.com/holoviz/panel/pull/2993))
- Ensure empty `Str` has same height as non-empty ([#2981](https://github.com/holoviz/panel/pull/2981))
- Ensure `Tabulator` supports grouping on numeric columns ([#2987](https://github.com/holoviz/panel/pull/2987))
- Fix `Tabulator` with multi-index and pagination ([#2989](https://github.com/holoviz/panel/pull/2989))
- Allow index as column name in table widgets ([#2990](https://github.com/holoviz/panel/pull/2990))
- Ensure TemplateActions component does not have height ([#2997](https://github.com/holoviz/panel/pull/2997))

## Version 0.12.5

Date: 2021-11-23
Expand All @@ -13,7 +34,7 @@ Compatibility:

Enhancements:

- Add 'light' to list of button types ([#2814, [#2816](https://github.com/holoviz/panel/pull/2816))
- Add 'light' to list of button types ([#2814](https://github.com/holoviz/panel/pull/2814), [#2816](https://github.com/holoviz/panel/pull/2816))
- Make OAuth cookie expiry configurable ([#2724](https://github.com/holoviz/panel/pull/2724))
- Run `onload` callbacks with `--warm` option ([#2844](https://github.com/holoviz/panel/pull/2844))
- Improve Plotly responsive sizing behavior ([#2838](https://github.com/holoviz/panel/pull/2838))
Expand Down
2 changes: 1 addition & 1 deletion panel/io/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def bundle_resources(roots, resources):
css_files.extend(css_resources.css_files)
css_raw.extend(css_resources.css_raw)

extensions = _bundle_extensions(roots, js_resources)
extensions = _bundle_extensions(None, js_resources)
if mode == "inline":
js_raw.extend([ Resources._inline(bundle.artifact_path) for bundle in extensions ])
elif mode == "server":
Expand Down
8 changes: 3 additions & 5 deletions panel/models/ace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,13 @@ function ID() {

export class AcePlotView extends PanelHTMLBoxView {
model: AcePlot
protected _ace: any
protected _editor: any
protected _langTools: any
protected _modelist: any
protected _container: HTMLDivElement

initialize(): void {
super.initialize()
this._ace = (window as any).ace
this._container = div({
id: ID(),
style: {
Expand Down Expand Up @@ -51,9 +49,9 @@ export class AcePlotView extends PanelHTMLBoxView {
if (!(this._container === this.el.childNodes[0]))
this.el.appendChild(this._container)
this._container.textContent = this.model.code
this._editor = this._ace.edit(this._container.id)
this._langTools = this._ace.require('ace/ext/language_tools')
this._modelist = this._ace.require("ace/ext/modelist")
this._editor = (window as any).ace.edit(this._container.id)
this._langTools = (window as any).ace.require('ace/ext/language_tools')
this._modelist = (window as any).ace.require("ace/ext/modelist")
this._editor.setOptions({
enableBasicAutocompletion: true,
enableSnippets: true,
Expand Down
11 changes: 7 additions & 4 deletions panel/pane/holoviews.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,7 @@ def _get_model(self, doc, root=None, parent=None, comm=None):

kwargs = {p: v for p, v in self.param.get_param_values()
if p in Layoutable.param and p != 'name'}
pane_type = self._panes.get(backend, Pane)
if 'tight' in pane_type.param:
kwargs['tight'] = True
child_pane = pane_type(state, **kwargs)
child_pane = self._get_pane(backend, state, **kwargs)
self._update_plot(plot, child_pane)
model = child_pane._get_model(doc, root, parent, comm)
if ref in self._plots:
Expand All @@ -273,6 +270,12 @@ def _get_model(self, doc, root=None, parent=None, comm=None):
self._models[ref] = (model, parent)
return model

def _get_pane(self, backend, state, **kwargs):
pane_type = self._panes.get(backend, Pane)
if isinstance(pane_type, type) and issubclass(pane_type, Matplotlib):
kwargs['tight'] = True
return pane_type(state, **kwargs)

def _render(self, doc, comm, root):
import holoviews as hv
from holoviews import Store, renderer as load_renderer
Expand Down
4 changes: 2 additions & 2 deletions panel/pane/markup.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,8 @@ def applies(cls, obj):

def _get_properties(self):
properties = super()._get_properties()
if self.object is None:
text = ''
if self.object is None or (isinstance(self.object, str) and self.object == ''):
text = '<pre> </pre>'
else:
text = '<pre>'+str(self.object)+'</pre>'
return dict(properties, text=escape(text))
Expand Down
47 changes: 15 additions & 32 deletions panel/reactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -1262,20 +1262,13 @@ def __init__(self, **params):
else:
params[children_param] = panel(child_value)
super().__init__(**params)
self._panes = {}
self._event_callbacks = defaultdict(lambda: defaultdict(list))

def _cleanup(self, root):
for children_param in self._parser.children.values():
children = getattr(self, children_param)
mode = self._child_config.get(children_param)
if mode != 'model':
continue
if isinstance(children, dict):
children = children.values()
elif not isinstance(children, list):
children = [children]
for child in children:
child._cleanup(root)
for child, panes in self._panes.items():
for pane in panes:
pane._cleanup(root)
super()._cleanup(root)

@property
Expand Down Expand Up @@ -1341,12 +1334,11 @@ def _get_events(self):
node_events[e] = False
return events

def _get_children(self, doc, root, model, comm, old_children=None):
def _get_children(self, doc, root, model, comm):
from .pane import panel
old_children = old_children or {}
old_models = model.children
new_models = {parent: [] for parent in self._parser.children}
new_panes = {}
new_panes, internal_panes = {}, {}

for parent, children_param in self._parser.children.items():
mode = self._child_config.get(children_param, 'model')
Expand All @@ -1363,20 +1355,13 @@ def _get_children(self, doc, root, model, comm, old_children=None):
else:
panes = [panel(panes)]
new_panes[parent] = panes
if isinstance(panes, dict):
panes = list(panes.values())
internal_panes[children_param] = panes

for children_param, old_panes in old_children.items():
mode = self._child_config.get(children_param, 'model')
if mode == 'literal':
continue
panes = getattr(self, children_param)
if not isinstance(panes, (list, dict)):
panes = [panes]
old_panes = [old_panes]
elif isinstance(panes, dict):
panes = panes.values()
old_panes = old_panes.values()
for children_param, old_panes in self._panes.items():
for old_pane in old_panes:
if old_pane not in panes and hasattr(old_pane, '_cleanup'):
if old_pane not in internal_panes.get(children_param, []):
old_pane._cleanup(root)

for parent, child_panes in new_panes.items():
Expand All @@ -1386,11 +1371,9 @@ def _get_children(self, doc, root, model, comm, old_children=None):
mode = self._child_config.get(children_param, 'model')
if mode == 'literal':
new_models[parent] = children_param
elif children_param in old_children:
elif children_param in self._panes:
# Find existing models
old_panes = old_children[children_param]
if not isinstance(old_panes, (list, dict)):
old_panes = [old_panes]
old_panes = self._panes[children_param]
for i, pane in enumerate(child_panes):
if pane in old_panes and root.ref['id'] in pane._models:
child, _ = pane._models[root.ref['id']]
Expand All @@ -1405,6 +1388,7 @@ def _get_children(self, doc, root, model, comm, old_children=None):
pane._get_model(doc, root, model, comm)
for pane in child_panes
]
self._panes = internal_panes
return self._process_children(doc, root, model, comm, new_models)

def _get_template(self):
Expand Down Expand Up @@ -1556,10 +1540,9 @@ def _update_model(self, events, msg, root, model, doc, comm):
else:
data_msg[prop] = v
if new_children:
old_children = {key: events[key].old for key in new_children}
if self._parser.looped:
model_msg['html'] = escape(self._get_template())
children = self._get_children(doc, root, model, comm, old_children)
children = self._get_children(doc, root, model, comm)
else:
children = None
if children is not None:
Expand Down
4 changes: 3 additions & 1 deletion panel/template/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,9 @@ class TemplateActions(ReactiveHTML):

close_modal = param.Integer(default=0)

_template = "<div></div>"
margin = param.Integer(default=0)

_template = ""

_scripts = {
'open_modal': ["document.getElementById('pn-Modal').style.display = 'block'"],
Expand Down
49 changes: 47 additions & 2 deletions panel/tests/test_reactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,13 +291,19 @@ class TestChildren(ReactiveHTML):
test = TestChildren(children=[widget])
root = test.get_root()
assert root.children == {'div': [widget._models[root.ref['id']][0]]}
assert len(widget._models) == 1
assert test._panes == {'children': [widget]}

widget_new = TextInput()
test.children = [widget_new]
assert len(widget._models) == 0
assert root.children == {'div': [widget_new._models[root.ref['id']][0]]}
assert test._panes == {'children': [widget_new]}


test._cleanup(root)
assert len(test._models) == 0
assert len(widget_new._models) == 0


def test_reactive_html_templated_children():

Expand All @@ -323,12 +329,52 @@ class TestTemplatedChildren(ReactiveHTML):
root = test.get_root()
assert root.looped == ['option']
assert root.children == {'option': [widget._models[root.ref['id']][0]]}
assert test._panes == {'children': [widget]}

widget_new = TextInput()
test.children = [widget_new]
assert len(widget._models) == 0
assert root.children == {'option': [widget_new._models[root.ref['id']][0]]}
assert test._panes == {'children': [widget_new]}


def test_reactive_html_templated_dict_children():

class TestTemplatedChildren(ReactiveHTML):

children = param.Dict(default={})

_template = """
<select id="select">
{% for key, option in children.items() %}
<option id="option-{{ loop.index0 }}">${children[{{ key }}]}</option>
{% endfor %}
</div>
"""

assert TestTemplatedChildren._attrs == {}
assert TestTemplatedChildren._node_callbacks == {}
assert TestTemplatedChildren._inline_callbacks == []
assert TestTemplatedChildren._parser.children == {'option': 'children'}

widget = TextInput()
test = TestTemplatedChildren(children={'test': widget})
root = test.get_root()
assert root.looped == ['option']
assert root.children == {'option': [widget._models[root.ref['id']][0]]}
assert test._panes == {'children': [widget]}
widget_model = widget._models[root.ref['id']][0]

widget_new = TextInput()
test.children = {'test': widget_new, 'test2': widget}
assert len(widget._models) == 1
assert root.children == {
'option': [
widget_new._models[root.ref['id']][0],
widget_model
]
}
assert test._panes == {'children': [widget_new, widget]}


def test_reactive_html_templated_children_add_loop_id():
Expand Down Expand Up @@ -368,7 +414,6 @@ class TestTemplatedChildren(ReactiveHTML):
assert model.looped == ['option']



def test_reactive_html_templated_children_add_loop_id_and_for_loop_var():

class TestTemplatedChildren(ReactiveHTML):
Expand Down
Loading