Skip to content
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Fixed
- Fix `hex_to_rgb` parsing of 3-digit shorthand hexadecimal colors such as `#FFF` [[#5662](https://github.com/plotly/plotly.py/pull/5662)], with thanks to @genrichez for the contribution!
- Add `<!doctype html>` to the `to_html()` template to comply with modern web standards [[#5693](https://github.com/plotly/plotly.py/pull/5693)], with thanks to @mishrakushal for the contribution!
- Fix the sphinx-gallery scraper so that it generates thumbnails for figures shown with `fig.show()` or displayed as the last expression of a code block, warns once (instead of failing the build) when static image export is unavailable, and no longer scrapes files belonging to other examples during parallel builds [[#4722](https://github.com/plotly/plotly.py/issues/4722), [#4959](https://github.com/plotly/plotly.py/issues/4959)], with thanks to @larsoner for the contribution!


## [6.9.0] - 2026-07-09
Expand Down
14 changes: 14 additions & 0 deletions plotly/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,20 @@ def hist_series(data_frame, **kwargs):
return histogram(data_frame, **new_kwargs)


def _get_sg_image_scraper():
"""Called by sphinx-gallery when ``"plotly"`` is listed in ``image_scrapers``.

See https://sphinx-gallery.github.io/stable/advanced.html#integrate-custom-scrapers-with-sphinx-gallery
"""
import plotly.io as pio
from plotly.io._sg_scraper import plotly_sg_scraper

# Not left to the import side effect: sphinx-gallery resolves the scraper
# repeatedly, so this also undoes any later renderer change.
pio.renderers.default = "sphinx_gallery_png"
return plotly_sg_scraper


def _jupyter_labextension_paths():
"""Called by Jupyter Lab Server to detect if it is a valid labextension and
to install the extension.
Expand Down
9 changes: 8 additions & 1 deletion plotly/basedatatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,14 @@ def _repr_html_(self):
if "text/html" in bundle:
return bundle["text/html"]
else:
return self.to_html(full_html=False, include_plotlyjs="cdn")
# Size like the html renderers do: "100%" height collapses or
# overflows in plain-HTML consumers such as sphinx-gallery.
return self.to_html(
full_html=False,
include_plotlyjs="cdn",
default_width="100%",
default_height=525,
)

def _repr_mimebundle_(self, include=None, exclude=None, validate=True, **kwargs):
"""
Expand Down
40 changes: 17 additions & 23 deletions plotly/io/_base_renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
from os.path import isdir

from plotly import optional_imports
from plotly.io import to_json, to_image, write_image, write_html
from plotly.io import to_json, to_image
from plotly.io._utils import plotly_cdn_url
from plotly.offline.offline import _get_jconfig, get_plotlyjs
from plotly.tools import return_figure_from_figure_or_data

ipython_display = optional_imports.get_module("IPython.display")
IPython = optional_imports.get_module("IPython")
Expand Down Expand Up @@ -821,26 +820,21 @@ def to_mimebundle(self, fig_dict):
return {"text/html": html}


# Figures shown with the "sphinx_gallery_png" renderer are queued here until
# plotly.io._sg_scraper.plotly_sg_scraper collects them, so the renderer itself
# does not need to know where sphinx-gallery wants the files to be written.
sphinx_gallery_figures = []


class SphinxGalleryOrcaRenderer(ExternalRenderer):
"""Renderer used together with the sphinx-gallery image scraper.

Instead of displaying the figure, this renderer queues it in
``plotly.io._base_renderers.sphinx_gallery_figures``;
:func:`plotly.io._sg_scraper.plotly_sg_scraper` then writes each queued
figure to the gallery's image directory, both as an interactive HTML file
and as a static image used for the gallery thumbnail.
"""

def render(self, fig_dict):
stack = inspect.stack()
# Name of script from which plot function was called is retrieved
try:
filename = stack[3].filename # let's hope this is robust...
except Exception: # python 2
filename = stack[3][1]
filename_root, _ = os.path.splitext(filename)
filename_html = filename_root + ".html"
filename_png = filename_root + ".png"
figure = return_figure_from_figure_or_data(fig_dict, True)
_ = write_html(fig_dict, file=filename_html, include_plotlyjs="cdn")
try:
write_image(figure, filename_png)
except (ValueError, ImportError):
raise ImportError(
"orca and psutil are required to use the `sphinx-gallery-orca` renderer. "
"See https://plotly.com/python/static-image-export/ for instructions on "
"how to install orca. Alternatively, you can use the `sphinx-gallery` "
"renderer (note that png thumbnails can only be generated with "
"the `sphinx-gallery-orca` renderer)."
)
sphinx_gallery_figures.append(fig_dict)
Loading