diff --git a/CHANGELOGS.rst b/CHANGELOGS.rst index 08cc2f9..5ab7192 100644 --- a/CHANGELOGS.rst +++ b/CHANGELOGS.rst @@ -4,6 +4,9 @@ Change Logs 0.4.2 +++++ +* :pr:`53`: Disable gdot call to graphviz if ``UNITTEST_GOING=1`` +* :pr:`51`: Uses GitHub actions for CI +* :pr:`49`: Cache gdot script execution results in Sphinx environment` * :pr:`47`: use svg by default with gdot 0.4.1 diff --git a/_unittests/ut_gdot/test_gdot_extension.py b/_unittests/ut_gdot/test_gdot_extension.py index dea0ff4..41f9393 100644 --- a/_unittests/ut_gdot/test_gdot_extension.py +++ b/_unittests/ut_gdot/test_gdot_extension.py @@ -163,6 +163,35 @@ 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}" + ) + def test_gdot_unittest_going_svg(self): """When UNITTEST_GOING=1, a dummy SVG containing 'DISABLED FOR TESTS' is rendered.""" content = """ diff --git a/sphinx_runpython/gdot/sphinx_gdot_extension.py b/sphinx_runpython/gdot/sphinx_gdot_extension.py index da1905b..285551c 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 @@ -153,7 +154,25 @@ 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") + 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 = {} + 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 = [