11# This module defines an image scraper for sphinx-gallery
22# https://sphinx-gallery.github.io/
33# which can be used by projects using plotly in their documentation.
4- from glob import glob
54import os
6- import shutil
75
86import plotly
7+ from plotly .io ._base_renderers import sphinx_gallery_figures
98
109plotly .io .renderers .default = "sphinx_gallery_png"
1110
@@ -14,11 +13,15 @@ def plotly_sg_scraper(block, block_vars, gallery_conf, **kwargs):
1413 """Scrape Plotly figures for galleries of examples using
1514 sphinx-gallery.
1615
17- Examples should use ``plotly.io.show()`` to display the figure with
18- the custom sphinx_gallery renderer.
16+ Examples should use ``plotly.io.show()`` (or the equivalent
17+ ``fig.show()``) to display the figure with the custom
18+ ``sphinx_gallery_png`` renderer, which is made the default renderer as a
19+ side effect of importing this module.
1920
20- Since the sphinx_gallery renderer generates both html and static png
21- files, we simply crawl these files and give them the appropriate path.
21+ Every figure shown that way is written to the gallery image directory
22+ twice: once as an interactive HTML file, which is embedded in the page,
23+ and once as a static image, which sphinx-gallery uses to generate the
24+ thumbnail of the example.
2225
2326 Parameters
2427 ----------
@@ -29,10 +32,9 @@ def plotly_sg_scraper(block, block_vars, gallery_conf, **kwargs):
2932 gallery_conf : dict
3033 Contains the configuration of Sphinx-Gallery
3134 **kwargs : dict
32- Additional keyword arguments to pass to
33- :meth:`~matplotlib.figure.Figure.savefig`, e.g. ``format='svg'``.
34- The ``format`` kwarg in particular is used to set the file extension
35- of the output file (currently only 'png' and 'svg' are supported).
35+ Additional keyword arguments.
36+ The ``format`` kwarg is used to set the file extension
37+ of the static images (currently only 'png' and 'svg' are supported).
3638
3739 Returns
3840 -------
@@ -44,54 +46,73 @@ def plotly_sg_scraper(block, block_vars, gallery_conf, **kwargs):
4446 -----
4547 Add this function to the image scrapers
4648 """
47- examples_dir = os . path . dirname ( block_vars [ "src_file" ] )
48- pngs = sorted ( glob ( os . path . join ( examples_dir , "*.png" )))
49- htmls = sorted ( glob ( os . path . join ( examples_dir , "*.html" )) )
49+ image_format = kwargs . get ( "format" , "png" )
50+ if image_format not in ( "png" , "svg" ):
51+ raise ValueError ( f"format must be one of 'png' or 'svg', got { image_format !r } " )
5052 image_path_iterator = block_vars ["image_path_iterator" ]
51- image_names = list ()
52- seen = set ()
53- for html , png in zip (htmls , pngs ):
54- if png not in seen :
55- seen |= set (png )
56- this_image_path_png = next (image_path_iterator )
57- this_image_path_html = os .path .splitext (this_image_path_png )[0 ] + ".html"
58- image_names .append (this_image_path_html )
59- shutil .move (png , this_image_path_png )
60- shutil .move (html , this_image_path_html )
53+ html_names = []
54+ try :
55+ for fig_dict , image_path in zip (sphinx_gallery_figures , image_path_iterator ):
56+ # sphinx-gallery hands out one path per image; the HTML file sits
57+ # next to the image it is the interactive counterpart of.
58+ path_root = os .path .splitext (image_path )[0 ]
59+ _write_image (fig_dict , f"{ path_root } .{ image_format } " , image_format )
60+ plotly .io .write_html (
61+ fig_dict ,
62+ file = f"{ path_root } .html" ,
63+ include_plotlyjs = "cdn" ,
64+ full_html = False ,
65+ default_width = "100%" ,
66+ default_height = 525 ,
67+ validate = False ,
68+ )
69+ html_names .append (f"{ path_root } .html" )
70+ finally :
71+ # Don't let figures leak into the next block if writing one failed.
72+ del sphinx_gallery_figures [:]
6173 # Use the `figure_rst` helper function to generate rST for image files
62- return figure_rst (image_names , gallery_conf ["src_dir" ])
74+ return figure_rst (html_names , gallery_conf ["src_dir" ])
75+
76+
77+ def _write_image (fig_dict , file , image_format ):
78+ """Write a static image, with a helpful message if that is not possible."""
79+ try :
80+ plotly .io .write_image (fig_dict , file , format = image_format , validate = False )
81+ except Exception as exc :
82+ raise RuntimeError (
83+ f"Kaleido and a compatible browser are required to use the "
84+ f"`sphinx_gallery_png` renderer, but writing { file } failed with: "
85+ f"{ type (exc ).__name__ } : { exc } \n "
86+ "See https://plotly.com/python/static-image-export/ for "
87+ "installation instructions. Alternatively, you can use the "
88+ "`sphinx_gallery` renderer without this scraper (note that "
89+ "thumbnails can only be generated with the `sphinx_gallery_png` "
90+ "renderer)."
91+ ) from exc
6392
6493
6594def figure_rst (figure_list , sources_dir ):
66- """Generate RST for a list of PNG filenames.
67-
68- Depending on whether we have one or more figures, we use a
69- single rst call to 'image' or a horizontal list.
95+ """Generate RST for a list of HTML filenames.
7096
7197 Parameters
7298 ----------
7399 figure_list : list
74100 List of strings of the figures' absolute paths.
75101 sources_dir : str
76- absolute path of Sphinx documentation sources
102+ absolute path of Sphinx documentation sources (unused, kept for
103+ compatibility with the equivalent sphinx-gallery helper)
77104
78105 Returns
79106 -------
80107 images_rst : str
81108 rst code to embed the images in the document
82109 """
83-
84- figure_paths = [
85- os .path .relpath (figure_path , sources_dir ).replace (os .sep , "/" ).lstrip ("/" )
110+ # The HTML files live in the "images" directory next to the document that
111+ # includes them, so the paths are relative to that document.
112+ return "" .join (
113+ SINGLE_HTML % ("images/" + os .path .basename (figure_path ))
86114 for figure_path in figure_list
87- ]
88- images_rst = ""
89- if not figure_paths :
90- return images_rst
91- figure_name = figure_paths [0 ]
92- figure_path = os .path .join ("images" , os .path .basename (figure_name ))
93- images_rst = SINGLE_HTML % figure_path
94- return images_rst
115+ )
95116
96117
97118SINGLE_HTML = """
0 commit comments