From a96f83303478bfcc51ffa977e1cbeb2d4df8d7f6 Mon Sep 17 00:00:00 2001 From: Allen Downey Date: Mon, 2 Nov 2026 16:37:49 -0500 Subject: [PATCH 1/2] Redraw a figure in JupyterLab when its output is updated The mime renderer's renderModel returned early whenever it already had a graph, so update_display_data (for example IPython's DisplayHandle.update) never changed the figure. Redraw when the figure in the new model differs from the one drawn; keep returning early when it's the same, as when createGraph stores the PNG in the model. Co-Authored-By: Claude Opus 5.5 --- js/src/mimeExtension.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/js/src/mimeExtension.ts b/js/src/mimeExtension.ts index b49d0de86df..ddee3a57d0b 100644 --- a/js/src/mimeExtension.ts +++ b/js/src/mimeExtension.ts @@ -54,8 +54,16 @@ export class RenderedPlotly extends Widget implements IRenderMime.IRenderer { */ renderModel(model: IRenderMime.IMimeModel): Promise { if (this.hasGraphElement()) { - // We already have a graph, don't overwrite it - return Promise.resolve(); + // We already have a graph. Redraw it only if the figure has changed, + // as it does when a kernel sends update_display_data. (createGraph + // stores a PNG of the figure in the model, which calls renderModel + // again with the same figure.) + const previous = this._model?.data[this._mimeType]; + if (JSON.stringify(previous) === JSON.stringify(model.data[this._mimeType])) { + return Promise.resolve(); + } + this._model = model; + return this.createGraph(model); } // Save off reference to model so that we can regenerate the plot later From ae2f1968130464adbffac85a2ef63acfaadae720 Mon Sep 17 00:00:00 2001 From: Allen Downey Date: Mon, 2 Nov 2026 17:39:09 -0500 Subject: [PATCH 2/2] Changelog entry for #5865 Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1632f922032..ee01fe41702 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Add support for converting matplotlib reference lines (`axhline`, `axvline`, and horizontal/vertical `axline`) as well as axes-coordinate lines into Plotly layout shapes in `mpl_to_plotly`, including support for date axes [[#5719](https://github.com/plotly/plotly.py/pull/5719)], with thanks to @robertoffmoura for the contribution! ### Fixed +- Fix figures in JupyterLab not redrawing when their output is updated with `update_display_data` (for example `DisplayHandle.update`), which also kept animations in other kernels on their first frame [[#5865](https://github.com/plotly/plotly.py/pull/5865)] - Fix `mpl_to_plotly` tick marker mirroring, axis positioning, and trace visibility for twinned and overlaid subplots (such as `twinx` and `twiny`) [[#5310](https://github.com/plotly/plotly.py/pull/5310)], with thanks to @robertoffmoura for the contribution! - Fix `mpl_to_plotly` losing matplotlib axis line colors by exporting the color of each axis's displayed spine to the plotly x and y axis `linecolor` [[#5311](https://github.com/plotly/plotly.py/pull/5311)], with thanks to @robertoffmoura for the contribution! - Fix concurrent first access to lazily initialized graph object properties, which could raise `ValueError("Invalid value")` [[#5691](https://github.com/plotly/plotly.py/pull/5691)], with thanks to @hb1915 for the contribution!