python: render <svg> via _repr_html_

Work around a recent decision in Jupyter Lab and Notebook to render
<svg> is inline <img>, breaking tooltips or text selection.

(Rerendering all notebooks was painful.)

* NEWS: Mention the change.
* python/spot/__init__.py: Add a _repr_html_ method to all
classes that had a _repr_svg_.  It seems Jupyter will use
_repr_html_ by default.
* python/spot/jupyter.py: SVG replace the _repr_svg_ method
by a _repr_html.
* tests/python/_altscc.ipynb, tests/python/_autparserr.ipynb,
tests/python/_aux.ipynb, tests/python/_mealy.ipynb,
tests/python/_partitioned_relabel.ipynb,
tests/python/_product_susp.ipynb, tests/python/_product_weak.ipynb,
tests/python/_synthesis.ipynb, tests/python/aliases.ipynb,
tests/python/alternation.ipynb, tests/python/atva16-fig2a.ipynb,
tests/python/atva16-fig2b.ipynb, tests/python/automata-io.ipynb,
tests/python/automata.ipynb, tests/python/cav22-figs.ipynb,
tests/python/contains.ipynb, tests/python/decompose.ipynb,
tests/python/formulas.ipynb, tests/python/games.ipynb,
tests/python/gen.ipynb, tests/python/highlighting.ipynb,
tests/python/ltsmin-dve.ipynb, tests/python/ltsmin-pml.ipynb,
tests/python/parity.ipynb, tests/python/product.ipynb,
tests/python/randaut.ipynb, tests/python/satmin.ipynb,
tests/python/stutter-inv.ipynb, tests/python/synthesis.ipynb,
tests/python/testingaut.ipynb, tests/python/twagraph-internals.ipynb,
tests/python/word.ipynb, tests/python/zlktree.ipynb: Update all
notebooks.
This commit is contained in:
Alexandre Duret-Lutz 2024-02-09 15:06:07 +01:00
parent 4cf7503fff
commit 3034e8fcc3
36 changed files with 43249 additions and 8585 deletions

View file

@ -145,6 +145,10 @@ class aig:
print_dot(ostr, self, opt)
return _ostream_to_svg(ostr)
# see spot.jupyter.SVG for why we need _repr_html_ instead of _repr_svg_
def _repr_html_(self):
return self._repr_svg_()
def show(self, opt=None):
from spot.jupyter import SVG
return SVG(self._repr_svg_(opt))
@ -210,6 +214,10 @@ class twa:
print_dot(ostr, self, opt)
return _ostream_to_svg(ostr)
# see spot.jupyter.SVG for why we need _repr_html_ instead of _repr_svg_
def _repr_html_(self):
return self._repr_svg_()
def show(self, opt=None):
"""Display the automaton as SVG, in the IPython/Jupyter notebook"""
if opt is None:
@ -479,6 +487,10 @@ class zielonka_tree:
self.dot(ostr)
return _ostream_to_svg(ostr)
# see spot.jupyter.SVG for why we need _repr_html_ instead of _repr_svg_
def _repr_html_(self):
return self._repr_svg_()
_acdnum = 0
@_extend(acd)

View file

@ -23,19 +23,24 @@ Auxiliary functions for Spot's Python bindings.
from IPython.display import display, HTML, DisplayObject
class SVG(DisplayObject):
"""
Replacement for IPython.display.SVG that does not use
"""Replacement for IPython.display.SVG that does not use
minidom to extract the <svg> element.
We need that because prior to Python 3.8, minidom used
sort all attributes, and in Python 3.8 this was changed
to keep the same order, causing test failures in our
diff-based test suite.
We need that because prior to Python 3.8, minidom used sort all
attributes, and in Python 3.8 this was changed to keep the same
order, causing test failures in our diff-based test suite.
We do not need the <svg> extraction when processing
GraphViz output.
Also nowadays Jupyter Notebook 7 started to render <svg> as inline
<img> instead of inlining the <svg> directly, breaking many useful
usages of SVG in the name of easier copy/paste.
https://github.com/jupyter/notebook/issues/7114
https://github.com/jupyterlab/jupyterlab/issues/10464
"""
def _repr_svg_(self):
def _repr_html_(self):
return self.data
def display_inline(*args, per_row=None, show=None):
@ -52,11 +57,11 @@ def display_inline(*args, per_row=None, show=None):
for arg in args:
dpy = 'inline-block'
if show is not None and hasattr(arg, 'show'):
rep = arg.show(show)._repr_svg_()
arg = arg.show(show)
if hasattr(arg, '_repr_html_'):
rep = arg._repr_html_()
elif hasattr(arg, '_repr_svg_'):
rep = arg._repr_svg_()
elif hasattr(arg, '_repr_html_'):
rep = arg._repr_html_()
elif hasattr(arg, '_repr_latex_'):
rep = arg._repr_latex_()
if not per_row: