Skip to content

Commit a4029cd

Browse files
committed
Repeat graphviz errors on subsequent builds
1 parent cc7c6f4 commit a4029cd

2 files changed

Lines changed: 37 additions & 1 deletion

File tree

sphinx/ext/graphviz.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,16 @@ def render_dot(
351351
return relfn, outfn
352352

353353

354+
def _mark_graphviz_error_for_reread(
355+
self: HTML5Translator | LaTeXTranslator | TexinfoTranslator,
356+
options: dict[str, Any],
357+
) -> None:
358+
"""Force the source document to be re-read on the next build."""
359+
docname = options.get('docname', getattr(self.builder, 'current_docname', None))
360+
if isinstance(docname, str):
361+
self.builder.env.reread_always.add(docname)
362+
363+
354364
def render_dot_html(
355365
self: HTML5Translator,
356366
node: graphviz,
@@ -370,6 +380,7 @@ def render_dot_html(
370380
try:
371381
fname, outfn = render_dot(self, code, options, format, prefix, filename)
372382
except GraphvizError as exc:
383+
_mark_graphviz_error_for_reread(self, options)
373384
logger.warning(__('dot code %r: %s'), code, exc)
374385
raise nodes.SkipNode from exc
375386

@@ -433,6 +444,7 @@ def render_dot_latex(
433444
try:
434445
fname, _outfn = render_dot(self, code, options, 'pdf', prefix, filename)
435446
except GraphvizError as exc:
447+
_mark_graphviz_error_for_reread(self, options)
436448
logger.warning(__('dot code %r: %s'), code, exc)
437449
raise nodes.SkipNode from exc
438450

@@ -477,6 +489,7 @@ def render_dot_texinfo(
477489
try:
478490
fname, _outfn = render_dot(self, code, options, 'png', prefix)
479491
except GraphvizError as exc:
492+
_mark_graphviz_error_for_reread(self, options)
480493
logger.warning(__('dot code %r: %s'), code, exc)
481494
raise nodes.SkipNode from exc
482495
if fname is not None:

tests/test_extensions/test_ext_graphviz.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
import pytest
1010

11-
from sphinx.ext.graphviz import ClickableMapDefinition
11+
from sphinx.ext import graphviz as graphviz_ext
12+
from sphinx.ext.graphviz import ClickableMapDefinition, GraphvizError
1213

1314
if TYPE_CHECKING:
1415
from sphinx.testing.util import SphinxTestApp
@@ -163,6 +164,28 @@ def test_graphviz_i18n(app: SphinxTestApp) -> None:
163164
assert re.search(html, content, re.MULTILINE)
164165

165166

167+
@pytest.mark.sphinx('html', testroot='ext-graphviz')
168+
def test_graphviz_error_is_reported_on_next_build(
169+
app: SphinxTestApp, monkeypatch: pytest.MonkeyPatch
170+
) -> None:
171+
def render_dot_with_error(*args: object, **kwargs: object) -> None:
172+
msg = 'broken graph'
173+
raise GraphvizError(msg)
174+
175+
monkeypatch.setattr(graphviz_ext, 'render_dot', render_dot_with_error)
176+
177+
app.build(force_all=True)
178+
assert 'broken graph' in app.warning.getvalue()
179+
assert app.env.reread_always == {'index'}
180+
181+
app.warning.seek(0)
182+
app.warning.truncate(0)
183+
app.build()
184+
185+
assert 'broken graph' in app.warning.getvalue()
186+
assert app.env.reread_always == {'index'}
187+
188+
166189
def test_graphviz_parse_mapfile() -> None:
167190
# empty graph
168191
code = '# digraph {\n# }\n'

0 commit comments

Comments
 (0)