diff --git a/pytential/symbolic/compiler.py b/pytential/symbolic/compiler.py index e17a2589f..9847f6d2d 100644 --- a/pytential/symbolic/compiler.py +++ b/pytential/symbolic/compiler.py @@ -333,8 +333,9 @@ def dot_dataflow_graph( node_names: dict[Statement, str] = {} result = [ - 'initial [label="initial"]' - 'result [label="result"]'] + 'initial [label="initial"];', + 'result [label="result"];', + ] for num, insn in enumerate(code.statements): node_name = f"node{num}" @@ -380,7 +381,7 @@ def gen_expr_arrow(expr: Expression, target_node: str) -> None: else: gen_expr_arrow(code_res, "result") - return "digraph dataflow {\n%s\n}\n" % "\n".join(result) + return "digraph dataflow {\n %s\n}\n" % "\n ".join(result) # }}} diff --git a/test/test_tools.py b/test/test_tools.py index bbe85ce0e..5761015ee 100644 --- a/test/test_tools.py +++ b/test/test_tools.py @@ -288,6 +288,48 @@ def test_add_geometry_to_collection(actx_factory: ArrayContextFactory): # }}} +# {{{ test_dot_dataflow_graph + +def test_dot_dataflow_graph() -> None: + from pymbolic.primitives import Variable + + from pytential.symbolic.compiler import Assign, Code, dot_dataflow_graph + from pytential.symbolic.mappers import DependencyMapper + + dep_mapper = DependencyMapper(composite_leaves=False) + + x = Variable("x") + y = Variable("y") + z = Variable("z") + + stmt = Assign(names=("w",), exprs=(x + y,), priority=0) + code = Code( + inputs={"x", "y"}, + schedule=[(stmt, set())], + result=z, + ) + + dot = dot_dataflow_graph(dep_mapper, code) + logger.info("dot graph:\n%s", dot) + assert "digraph dataflow" in dot + + import shutil + if shutil.which("dot") is None: + return + + import subprocess + + result = subprocess.run( # ruff: ignore[subprocess-run-without-check] + ["dot", "-Tsvg"], + input=dot, + capture_output=True, + text=True, + ) + assert result.returncode == 0 + +# }}} + + # You can test individual routines by typing # $ python test_tools.py 'test_routine()'