From ec87a384352699bd7666a0a391ef61698ef6c81a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 22:37:23 +0000 Subject: [PATCH 1/7] Initial plan From 77468b7bb292f30c526c386c0f08c34c4370eb03 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 22:46:20 +0000 Subject: [PATCH 2/7] speedup runpython execution for graphviz: cache script results in Sphinx env Co-authored-by: xadupre <22452781+xadupre@users.noreply.github.com> --- _unittests/ut_gdot/test_gdot_extension.py | 29 +++++++++++++++++++ .../gdot/sphinx_gdot_extension.py | 19 +++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/_unittests/ut_gdot/test_gdot_extension.py b/_unittests/ut_gdot/test_gdot_extension.py index 39bee87..9e62f59 100644 --- a/_unittests/ut_gdot/test_gdot_extension.py +++ b/_unittests/ut_gdot/test_gdot_extension.py @@ -137,5 +137,34 @@ def test_gdot4_png(self): self.assertIn("png", content) + @ignore_warnings(PendingDeprecationWarning) + def test_gdot_script_cache(self): + """Test that identical scripts are cached and produce the same output.""" + script = "print('digraph foo { HbarH -> HbazH; }')".replace("H", '\"') + content = f""" +before + +.. gdot:: + :script: + + {script} + +middle + +.. gdot:: + :script: + + {script} + +after +""" + content = rst2html( + content, writer_name="rst", new_extensions=["sphinx_runpython.gdot"] + ) + # Both gdot directives should produce the same DOT output + count = content.count('digraph foo { "bar" -> "baz"; }') + self.assertEqual(count, 2, f"Expected the DOT code to appear twice, got {count}") + + if __name__ == "__main__": unittest.main(verbosity=2) diff --git a/sphinx_runpython/gdot/sphinx_gdot_extension.py b/sphinx_runpython/gdot/sphinx_gdot_extension.py index b9b7083..3273233 100644 --- a/sphinx_runpython/gdot/sphinx_gdot_extension.py +++ b/sphinx_runpython/gdot/sphinx_gdot_extension.py @@ -1,3 +1,4 @@ +import hashlib import os import logging from docutils import nodes @@ -147,7 +148,23 @@ def run(self): # executes script if any content = "\n".join(self.content) if script or script == "": - stdout, stderr, _ = run_python_script(content, process=process) + env = info.get("env") + cache_key = hashlib.sha256( + f"{content}:{process}".encode("utf-8") + ).hexdigest() + if env is not None: + if not hasattr(env, "gdot_script_cache"): + env.gdot_script_cache = {} + cached = env.gdot_script_cache.get(cache_key, None) + else: + cached = None + + if cached is not None: + stdout, stderr = cached + else: + stdout, stderr, _ = run_python_script(content, process=process) + if env is not None: + env.gdot_script_cache[cache_key] = (stdout, stderr) if stderr: out = [ From a9d09902e146627d6d02272fb4736d5ec9ae20bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Dupr=C3=A9?= Date: Fri, 6 Mar 2026 15:21:18 +0100 Subject: [PATCH 3/7] fix --- _unittests/ut_gdot/test_gdot_extension.py | 7 ++++--- sphinx_runpython/gdot/sphinx_gdot_extension.py | 4 +--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/_unittests/ut_gdot/test_gdot_extension.py b/_unittests/ut_gdot/test_gdot_extension.py index 9e62f59..0b85359 100644 --- a/_unittests/ut_gdot/test_gdot_extension.py +++ b/_unittests/ut_gdot/test_gdot_extension.py @@ -136,11 +136,10 @@ def test_gdot4_png(self): return self.assertIn("png", content) - @ignore_warnings(PendingDeprecationWarning) def test_gdot_script_cache(self): """Test that identical scripts are cached and produce the same output.""" - script = "print('digraph foo { HbarH -> HbazH; }')".replace("H", '\"') + script = "print('digraph foo { HbarH -> HbazH; }')".replace("H", '"') content = f""" before @@ -163,7 +162,9 @@ def test_gdot_script_cache(self): ) # Both gdot directives should produce the same DOT output count = content.count('digraph foo { "bar" -> "baz"; }') - self.assertEqual(count, 2, f"Expected the DOT code to appear twice, got {count}") + self.assertEqual( + count, 2, f"Expected the DOT code to appear twice, got {count}" + ) if __name__ == "__main__": diff --git a/sphinx_runpython/gdot/sphinx_gdot_extension.py b/sphinx_runpython/gdot/sphinx_gdot_extension.py index 3273233..04641e9 100644 --- a/sphinx_runpython/gdot/sphinx_gdot_extension.py +++ b/sphinx_runpython/gdot/sphinx_gdot_extension.py @@ -149,9 +149,7 @@ def run(self): content = "\n".join(self.content) if script or script == "": env = info.get("env") - cache_key = hashlib.sha256( - f"{content}:{process}".encode("utf-8") - ).hexdigest() + cache_key = hashlib.sha256(f"{content}:{process}".encode()).hexdigest() if env is not None: if not hasattr(env, "gdot_script_cache"): env.gdot_script_cache = {} From 9aa3ec35c70b9b8559d1d00b3e02361eae2f8227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Dupr=C3=A9?= Date: Fri, 6 Mar 2026 15:26:31 +0100 Subject: [PATCH 4/7] fix --- CHANGELOGS.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOGS.rst b/CHANGELOGS.rst index 08cc2f9..378e050 100644 --- a/CHANGELOGS.rst +++ b/CHANGELOGS.rst @@ -4,6 +4,7 @@ Change Logs 0.4.2 +++++ +* :pr:`48`: Cache gdot script execution results in Sphinx environment` * :pr:`47`: use svg by default with gdot 0.4.1 From d2672930ed1f15e54a1f2ed39ffafc8d57e510b5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:41:02 +0000 Subject: [PATCH 5/7] gdot: prefix cache key with last segment of docname Co-authored-by: xadupre <22452781+xadupre@users.noreply.github.com> --- sphinx_runpython/gdot/sphinx_gdot_extension.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sphinx_runpython/gdot/sphinx_gdot_extension.py b/sphinx_runpython/gdot/sphinx_gdot_extension.py index e30f1e8..ad915c9 100644 --- a/sphinx_runpython/gdot/sphinx_gdot_extension.py +++ b/sphinx_runpython/gdot/sphinx_gdot_extension.py @@ -155,7 +155,11 @@ def run(self): content = "\n".join(self.content) if script or script == "": env = info.get("env") - cache_key = hashlib.sha256(f"{content}:{process}".encode()).hexdigest() + doc_prefix = docname.split("/")[-1] if docname else "" + cache_key = ( + f"{doc_prefix}:" + + hashlib.sha256(f"{content}:{process}".encode()).hexdigest() + ) if env is not None: if not hasattr(env, "gdot_script_cache"): env.gdot_script_cache = {} From cd379240b9ff6364bd01bf41ce86d9460b11bd06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Dupr=C3=A9?= Date: Fri, 6 Mar 2026 15:43:20 +0100 Subject: [PATCH 6/7] change --- CHANGELOGS.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOGS.rst b/CHANGELOGS.rst index 378e050..b76ab51 100644 --- a/CHANGELOGS.rst +++ b/CHANGELOGS.rst @@ -4,6 +4,7 @@ Change Logs 0.4.2 +++++ +* :pr:`51`: Uses GitHub actions for CI * :pr:`48`: Cache gdot script execution results in Sphinx environment` * :pr:`47`: use svg by default with gdot From 1ce73028450b62c2a72231e22077226c71577e33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Dupr=C3=A9?= Date: Fri, 6 Mar 2026 15:44:03 +0100 Subject: [PATCH 7/7] changes --- CHANGELOGS.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOGS.rst b/CHANGELOGS.rst index b76ab51..cc417f8 100644 --- a/CHANGELOGS.rst +++ b/CHANGELOGS.rst @@ -5,7 +5,7 @@ Change Logs +++++ * :pr:`51`: Uses GitHub actions for CI -* :pr:`48`: Cache gdot script execution results in Sphinx environment` +* :pr:`49`: Cache gdot script execution results in Sphinx environment` * :pr:`47`: use svg by default with gdot 0.4.1