From 5055e00d45b5329f4c214cf277c943d76b9156ba Mon Sep 17 00:00:00 2001 From: gabriel-tessier Date: Wed, 9 Feb 2022 22:21:53 +0900 Subject: [PATCH] feat(output): Generate dot file and support multi outformat.(#441) Re (#592) * feat(output): Generate dot file and support multi outformat.(#441) * [fix] forget to clean the dot generated file. * [fix] indentation * [fix] Review + add more cases in unittest * [fix] Add dot in the test --- diagrams/__init__.py | 40 ++++++++++++++++++---------------------- docs/guides/diagram.md | 12 +++++++++++- tests/test_diagram.py | 18 +++++++++++++++--- 3 files changed, 44 insertions(+), 26 deletions(-) diff --git a/diagrams/__init__.py b/diagrams/__init__.py index 6968bc4a..1fb33db7 100644 --- a/diagrams/__init__.py +++ b/diagrams/__init__.py @@ -40,7 +40,7 @@ def setcluster(cluster): class Diagram: __directions = ("TB", "BT", "LR", "RL") __curvestyles = ("ortho", "curved") - __outformats = ("png", "jpg", "svg", "pdf") + __outformats = ("png", "jpg", "svg", "pdf", "dot") # fmt: off _default_graph_attrs = { @@ -127,8 +127,13 @@ class Diagram: raise ValueError(f'"{curvestyle}" is not a valid curvestyle') self.dot.graph_attr["splines"] = curvestyle - if not self._validate_outformat(outformat): - raise ValueError(f'"{outformat}" is not a valid output format') + if isinstance(outformat, list): + for one_format in outformat: + if not self._validate_outformat(one_format): + raise ValueError(f'"{one_format}" is not a valid output format') + else: + if not self._validate_outformat(outformat): + raise ValueError(f'"{outformat}" is not a valid output format') self.outformat = outformat # Merge passed in attributes @@ -155,25 +160,13 @@ class Diagram: return self.dot.pipe(format="png") def _validate_direction(self, direction: str) -> bool: - direction = direction.upper() - for v in self.__directions: - if v == direction: - return True - return False + return direction.upper() in self.__directions def _validate_curvestyle(self, curvestyle: str) -> bool: - curvestyle = curvestyle.lower() - for v in self.__curvestyles: - if v == curvestyle: - return True - return False + return curvestyle.lower() in self.__curvestyles def _validate_outformat(self, outformat: str) -> bool: - outformat = outformat.lower() - for v in self.__outformats: - if v == outformat: - return True - return False + return outformat.lower() in self.__outformats def node(self, nodeid: str, label: str, **attrs) -> None: """Create a new node.""" @@ -188,7 +181,11 @@ class Diagram: self.dot.subgraph(dot) def render(self) -> None: - self.dot.render(format=self.outformat, view=self.show, quiet=True) + if isinstance(self.outformat, list): + for one_format in self.outformat: + self.dot.render(format=one_format, view=self.show, quiet=True) + else: + self.dot.render(format=self.outformat, view=self.show, quiet=True) class Cluster: @@ -263,9 +260,8 @@ class Cluster: def _validate_direction(self, direction: str): direction = direction.upper() - for v in self.__directions: - if v == direction: - return True + if direction in self.__directions: + return True return False def node(self, nodeid: str, label: str, **attrs) -> None: diff --git a/docs/guides/diagram.md b/docs/guides/diagram.md index 8420e361..de7f59c0 100644 --- a/docs/guides/diagram.md +++ b/docs/guides/diagram.md @@ -44,7 +44,7 @@ diag You can specify the output file format with `outformat` parameter. Default is **png**. -> (png, jpg, svg, and pdf) are allowed. +> (png, jpg, svg, pdf and dot) are allowed. ```python from diagrams import Diagram @@ -54,6 +54,16 @@ with Diagram("Simple Diagram", outformat="jpg"): EC2("web") ``` +The `outformat` parameter also support list to output all the defined output in one call. + +```python +from diagrams import Diagram +from diagrams.aws.compute import EC2 + +with Diagram("Simple Diagram Multi Output", outformat=["jpg", "png", "dot"]): + EC2("web") +``` + You can specify the output filename with `filename` parameter. The extension shouldn't be included, it's determined by the `outformat` parameter. ```python diff --git a/tests/test_diagram.py b/tests/test_diagram.py index cc5567b0..dc0b6029 100644 --- a/tests/test_diagram.py +++ b/tests/test_diagram.py @@ -26,7 +26,7 @@ class DiagramTest(unittest.TestCase): def test_validate_direction(self): # Normal directions. - for dir in ("TB", "BT", "LR", "RL"): + for dir in ("TB", "BT", "LR", "RL", "tb"): Diagram(direction=dir) # Invalid directions. @@ -36,7 +36,7 @@ class DiagramTest(unittest.TestCase): def test_validate_curvestyle(self): # Normal directions. - for cvs in ("ortho", "curved"): + for cvs in ("ortho", "curved", "CURVED"): Diagram(curvestyle=cvs) # Invalid directions. @@ -46,7 +46,7 @@ class DiagramTest(unittest.TestCase): def test_validate_outformat(self): # Normal output formats. - for fmt in ("png", "jpg", "svg", "pdf"): + for fmt in ("png", "jpg", "svg", "pdf", "PNG", "dot"): Diagram(outformat=fmt) # Invalid output formats. @@ -108,6 +108,18 @@ class DiagramTest(unittest.TestCase): Node("node1") self.assertTrue(os.path.exists(f"{self.name}.png")) + def test_outformat_list(self): + """Check that outformat render all the files from the list.""" + self.name = 'diagrams_image' + with Diagram(show=False, outformat=["dot", "png"]): + Node("node1") + # both files must exist + self.assertTrue(os.path.exists(f"{self.name}.png")) + self.assertTrue(os.path.exists(f"{self.name}.dot")) + + # clean the dot file as it only generated here + os.remove(self.name + ".dot") + class ClusterTest(unittest.TestCase): def setUp(self):