diff --git a/packages/python/plotly/plotly/basedatatypes.py b/packages/python/plotly/plotly/basedatatypes.py index ee9ce457451..dcdce077a8e 100644 --- a/packages/python/plotly/plotly/basedatatypes.py +++ b/packages/python/plotly/plotly/basedatatypes.py @@ -418,6 +418,37 @@ def __repr__(self): return repr_str + def _repr_html_(self): + """ + Customize html representation + """ + bundle = self._repr_mimebundle_() + if "text/html" in bundle: + return bundle["text/html"] + else: + return self.to_html(full_html=False, include_plotlyjs="cdn") + + def _repr_mimebundle_(self, include=None, exclude=None, validate=True, **kwargs): + """ + Return mimebundle corresponding to default renderer. + """ + import plotly.io as pio + + renderer_str = pio.renderers.default + renderers = pio._renderers.renderers + renderer_names = renderers._validate_coerce_renderers(renderer_str) + renderers_list = [renderers[name] for name in renderer_names] + from plotly.io._utils import validate_coerce_fig_to_dict + from plotly.io._renderers import MimetypeRenderer + + fig_dict = validate_coerce_fig_to_dict(self, validate) + # Mimetype renderers + bundle = {} + for renderer in renderers_list: + if isinstance(renderer, MimetypeRenderer): + bundle.update(renderer.to_mimebundle(fig_dict)) + return bundle + def _ipython_display_(self): """ Handle rich display of figures in ipython contexts diff --git a/packages/python/plotly/plotly/io/_base_renderers.py b/packages/python/plotly/plotly/io/_base_renderers.py index f0642c7a3f5..9cd7fbfb72b 100644 --- a/packages/python/plotly/plotly/io/_base_renderers.py +++ b/packages/python/plotly/plotly/io/_base_renderers.py @@ -796,7 +796,57 @@ def render(self, fig_dict): self.displayHTML(html) -class SphinxGalleryRenderer(ExternalRenderer): +class SphinxGalleryHtmlRenderer(HtmlRenderer): + def __init__( + self, + connected=True, + config=None, + auto_play=False, + post_script=None, + animation_opts=None, + ): + super(SphinxGalleryHtmlRenderer, self).__init__( + connected=connected, + full_html=False, + requirejs=False, + global_init=False, + config=config, + auto_play=auto_play, + post_script=post_script, + animation_opts=animation_opts, + ) + + def to_mimebundle(self, fig_dict): + + from plotly.io import to_html + + if self.requirejs: + include_plotlyjs = "require" + include_mathjax = False + elif self.connected: + include_plotlyjs = "cdn" + include_mathjax = "cdn" + else: + include_plotlyjs = True + include_mathjax = "cdn" + + html = to_html( + fig_dict, + config=self.config, + auto_play=self.auto_play, + include_plotlyjs=include_plotlyjs, + include_mathjax=include_mathjax, + full_html=self.full_html, + animation_opts=self.animation_opts, + default_width="100%", + default_height=525, + validate=False, + ) + + return {"text/html": html} + + +class SphinxGalleryOrcaRenderer(ExternalRenderer): def render(self, fig_dict): stack = inspect.stack() # Name of script from which plot function was called is retrieved @@ -809,4 +859,13 @@ def render(self, fig_dict): filename_png = filename_root + ".png" figure = return_figure_from_figure_or_data(fig_dict, True) _ = write_html(fig_dict, file=filename_html) - write_image(figure, filename_png) + 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)." + ) diff --git a/packages/python/plotly/plotly/io/_renderers.py b/packages/python/plotly/plotly/io/_renderers.py index 5277c9efec7..22b0f92c394 100644 --- a/packages/python/plotly/plotly/io/_renderers.py +++ b/packages/python/plotly/plotly/io/_renderers.py @@ -24,7 +24,8 @@ PdfRenderer, BrowserRenderer, IFrameRenderer, - SphinxGalleryRenderer, + SphinxGalleryHtmlRenderer, + SphinxGalleryOrcaRenderer, CoCalcRenderer, DatabricksRenderer, ) @@ -430,7 +431,8 @@ def show(fig, renderer=None, validate=True, **kwargs): renderers["chromium"] = BrowserRenderer(config=config, using="chromium") renderers["iframe"] = IFrameRenderer(config=config, include_plotlyjs=True) renderers["iframe_connected"] = IFrameRenderer(config=config, include_plotlyjs="cdn") -renderers["sphinx_gallery"] = SphinxGalleryRenderer() +renderers["sphinx_gallery"] = SphinxGalleryHtmlRenderer() +renderers["sphinx_gallery_png"] = SphinxGalleryOrcaRenderer() # Set default renderer # -------------------- diff --git a/packages/python/plotly/plotly/io/_sg_scraper.py b/packages/python/plotly/plotly/io/_sg_scraper.py index bec587d0ff6..18defd11671 100644 --- a/packages/python/plotly/plotly/io/_sg_scraper.py +++ b/packages/python/plotly/plotly/io/_sg_scraper.py @@ -7,7 +7,7 @@ from glob import glob import shutil -plotly.io.renderers.default = "sphinx_gallery" +plotly.io.renderers.default = "sphinx_gallery_png" def plotly_sg_scraper(block, block_vars, gallery_conf, **kwargs): diff --git a/packages/python/plotly/plotly/tests/test_io/test_renderers.py b/packages/python/plotly/plotly/tests/test_io/test_renderers.py index 692c4efc696..2d51792721b 100644 --- a/packages/python/plotly/plotly/tests/test_io/test_renderers.py +++ b/packages/python/plotly/plotly/tests/test_io/test_renderers.py @@ -287,3 +287,90 @@ def test_reject_invalid_renderer(renderer): ) def test_accept_valid_renderer(renderer): pio.renderers.default = renderer + + +@pytest.mark.parametrize( + "renderer", + plotly_mimetype_renderers + + ["notebook", "notebook_connected", "browser", "notebook+plotly_mimetype"], +) +def test_repr_html(renderer): + pio.renderers.default = renderer + fig = go.Figure() + fig.update_layout(template=None) + str_html = fig._repr_html_() + bundle = fig._repr_mimebundle_() + # id number of figure + id_html = str_html.split('document.getElementById("')[1].split('")')[0] + id_pattern = "cd462b94-79ce-42a2-887f-2650a761a144" + template = ( + '