From 4b0051164962dca99176c3d167f6f062b5339aed Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Wed, 14 Nov 2018 20:43:26 +0000
Subject: [PATCH] Improved Param and HoloViews pane cleanup
---
panel/holoviews.py | 32 +++++++++++++++++++++++---------
panel/pane.py | 1 -
panel/param.py | 2 +-
3 files changed, 24 insertions(+), 11 deletions(-)
diff --git a/panel/holoviews.py b/panel/holoviews.py
index bb835a50ef..0711e98147 100644
--- a/panel/holoviews.py
+++ b/panel/holoviews.py
@@ -51,6 +51,15 @@ def _update_widgets(self):
widgets, values = self.widgets_from_dimensions(self.object, self.widgets,
self.widget_type)
self._values = values
+
+ # Clean up anything models listening to the previous widgets
+ for _, cbs in self._callbacks.items():
+ for cb in list(cbs):
+ if cb.inst in self.widget_box.objects:
+ print(cb)
+ cb.inst.param.unwatch(cb)
+ cbs.remove(cb)
+
self.widget_box.objects = widgets
if widgets and not self.widget_box in self.layout.objects:
self.layout.append(self.widget_box)
@@ -89,6 +98,11 @@ def _render(self, doc, comm, root):
if comm:
kwargs['comm'] = comm
plot = renderer.get_plot(self.object, **kwargs)
+ ref = root.ref['id']
+ if ref in self._plots:
+ old_plot = self._plots[ref]
+ old_plot.comm = None
+ old_plot.cleanup()
self._plots[root.ref['id']] = plot
return plot
@@ -96,20 +110,21 @@ def _get_model(self, doc, root=None, parent=None, comm=None):
"""
Should return the Bokeh model to be rendered.
"""
+ ref = root.ref['id']
plot = self._render(doc, comm, root)
child_pane = Pane(plot.state, _temporary=True)
model = child_pane._get_model(doc, root, parent, comm)
+ self._models[ref] = model
+ self._link_object(doc, root, parent, comm)
if self.widget_box.objects:
self._link_widgets(child_pane, root, comm)
- self._models[root.ref['id']] = model
- self._link_object(doc, root, parent, comm)
return model
def _link_widgets(self, pane, root, comm):
- from holoviews.core.util import cross_index
-
def update_plot(change):
+ from holoviews.core.util import cross_index
from holoviews.plotting.bokeh.plot import BokehPlot
+
widgets = self.widget_box.objects
if self.widget_type == 'scrubber':
key = cross_index([v for v in self._values.values()], widgets[0].value)
@@ -130,10 +145,9 @@ def update_plot():
pane.object = plot.state
ref = root.ref['id']
- if ref not in self._callbacks:
- for w in self.widget_box.objects:
- watcher = w.param.watch(update_plot, 'value')
- self._callbacks[ref].append(watcher)
+ for w in self.widget_box.objects:
+ watcher = w.param.watch(update_plot, 'value')
+ self._callbacks[ref].append(watcher)
@classmethod
def widgets_from_dimensions(cls, object, widget_types={}, widgets_type='individual'):
@@ -200,7 +214,7 @@ def is_bokeh_element_plot(plot):
Checks whether plotting instance is a HoloViews ElementPlot rendered
with the bokeh backend.
"""
- from holoviews.plotting.plot import GenericElementPlot, GenericOverlayPlot
+ from holoviews.plotting.plot import GenericElementPlot, GenericOverlayPlot
return (plot.renderer.backend == 'bokeh' and isinstance(plot, GenericElementPlot)
and not isinstance(plot, GenericOverlayPlot))
diff --git a/panel/pane.py b/panel/pane.py
index 24f593c4f5..6eb90d134c 100644
--- a/panel/pane.py
+++ b/panel/pane.py
@@ -185,7 +185,6 @@ def update_models():
(type(self).__name__, old_model, new_model))
else:
parent.children[index] = new_model
- self._models[root.ref['id']] = new_model
if comm:
update_models()
diff --git a/panel/param.py b/panel/param.py
index c0ddf2e59f..76367dfd53 100644
--- a/panel/param.py
+++ b/panel/param.py
@@ -445,7 +445,7 @@ def update_pane(*events):
def _get_model(self, doc, root=None, parent=None, comm=None):
ref = root.ref['id']
if ref in self._callbacks:
- self._cleanup(ref)
+ self._cleanup(root)
model = self._inner_layout._get_model(doc, root, parent, comm)
self._link_object_params(doc, root, parent, comm)
self._models[ref] = model