Skip to content

Repr html #2421

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 20, 2020
Merged
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
31 changes: 31 additions & 0 deletions packages/python/plotly/plotly/basedatatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, I like the fallback here.


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
Expand Down
63 changes: 61 additions & 2 deletions packages/python/plotly/plotly/io/_base_renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)."
)
6 changes: 4 additions & 2 deletions packages/python/plotly/plotly/io/_renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
PdfRenderer,
BrowserRenderer,
IFrameRenderer,
SphinxGalleryRenderer,
SphinxGalleryHtmlRenderer,
SphinxGalleryOrcaRenderer,
CoCalcRenderer,
DatabricksRenderer,
)
Expand Down Expand Up @@ -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
# --------------------
Expand Down
2 changes: 1 addition & 1 deletion packages/python/plotly/plotly/io/_sg_scraper.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
87 changes: 87 additions & 0 deletions packages/python/plotly/plotly/tests/test_io/test_renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = (
'<div>\n \n <script type="text/javascript">'
"window.PlotlyConfig = {MathJaxConfig: 'local'};</script>\n "
'<script src="https://cdn.plot.ly/plotly-latest.min.js"></script> \n '
'<div id="cd462b94-79ce-42a2-887f-2650a761a144" class="plotly-graph-div" '
'style="height:100%; width:100%;"></div>\n <script type="text/javascript">'
"\n \n window.PLOTLYENV=window.PLOTLYENV || {};"
'\n \n if (document.getElementById("cd462b94-79ce-42a2-887f-2650a761a144"))'
" {\n Plotly.newPlot(\n 'cd462b94-79ce-42a2-887f-2650a761a144',"
'\n [],\n {"template": {}},'
'\n {"responsive": true}\n )\n };'
"\n \n </script>\n </div>"
)
if "text/html" in bundle:
str_bundle = bundle["text/html"]
id_bundle = str_bundle.split('document.getElementById("')[1].split('")')[0]
assert str_html.replace(id_html, "") == str_bundle.replace(id_bundle, "")
else:
assert str_html.replace(id_html, "") == template.replace(id_pattern, "")


all_renderers_without_orca = [
"plotly_mimetype",
"jupyterlab",
"nteract",
"vscode",
"notebook",
"notebook_connected",
"kaggle",
"azure",
"colab",
"cocalc",
"databricks",
"json",
"browser",
"firefox",
"chrome",
"chromium",
"iframe",
"iframe_connected",
"sphinx_gallery",
]


@pytest.mark.parametrize("renderer_str", all_renderers_without_orca)
def test_repr_mimebundle(renderer_str):
pio.renderers.default = renderer_str
fig = go.Figure()
fig.update_layout(template=None)
bundle = fig._repr_mimebundle_()
renderer = pio.renderers[renderer_str]
from plotly.io._renderers import MimetypeRenderer

if isinstance(renderer, MimetypeRenderer):
ref_bundle = renderer.to_mimebundle(fig.to_dict())
for key in bundle:
if "getElementById" in bundle[key]:
id1 = bundle[key].split('document.getElementById("')[1].split('")')[0]
id2 = (
ref_bundle[key].split('document.getElementById("')[1].split('")')[0]
)
assert bundle[key].replace(id1, "") == ref_bundle[key].replace(id2, "")
else:
assert bundle == {}


def test_repr_mimebundle_mixed_renderer(fig1):
pio.renderers.default = "notebook+plotly_mimetype"
assert set(fig1._repr_mimebundle_().keys()) == set(
{"application/vnd.plotly.v1+json", "text/html"}
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks for the tests!

Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def test_scraper():
from plotly.io._sg_scraper import plotly_sg_scraper

# test that monkey-patching worked ok
assert plotly.io.renderers.default == "sphinx_gallery"
assert plotly.io.renderers.default == "sphinx_gallery_png"
# Use dummy values for arguments of plotly_sg_scraper
block = "" # we don't need actually code
import tempfile
Expand Down