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