Browse Source

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
tags/v0.21.1
gabriel-tessier 2 years ago
committed by GitHub
parent
commit
5055e00d45
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 26 deletions
  1. +18
    -22
      diagrams/__init__.py
  2. +11
    -1
      docs/guides/diagram.md
  3. +15
    -3
      tests/test_diagram.py

+ 18
- 22
diagrams/__init__.py View File

@@ -40,7 +40,7 @@ def setcluster(cluster):
class Diagram: class Diagram:
__directions = ("TB", "BT", "LR", "RL") __directions = ("TB", "BT", "LR", "RL")
__curvestyles = ("ortho", "curved") __curvestyles = ("ortho", "curved")
__outformats = ("png", "jpg", "svg", "pdf")
__outformats = ("png", "jpg", "svg", "pdf", "dot")


# fmt: off # fmt: off
_default_graph_attrs = { _default_graph_attrs = {
@@ -127,8 +127,13 @@ class Diagram:
raise ValueError(f'"{curvestyle}" is not a valid curvestyle') raise ValueError(f'"{curvestyle}" is not a valid curvestyle')
self.dot.graph_attr["splines"] = 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 self.outformat = outformat


# Merge passed in attributes # Merge passed in attributes
@@ -155,25 +160,13 @@ class Diagram:
return self.dot.pipe(format="png") return self.dot.pipe(format="png")


def _validate_direction(self, direction: str) -> bool: 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: 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: 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: def node(self, nodeid: str, label: str, **attrs) -> None:
"""Create a new node.""" """Create a new node."""
@@ -188,7 +181,11 @@ class Diagram:
self.dot.subgraph(dot) self.dot.subgraph(dot)


def render(self) -> None: 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: class Cluster:
@@ -263,9 +260,8 @@ class Cluster:


def _validate_direction(self, direction: str): def _validate_direction(self, direction: str):
direction = direction.upper() direction = direction.upper()
for v in self.__directions:
if v == direction:
return True
if direction in self.__directions:
return True
return False return False


def node(self, nodeid: str, label: str, **attrs) -> None: def node(self, nodeid: str, label: str, **attrs) -> None:


+ 11
- 1
docs/guides/diagram.md View File

@@ -44,7 +44,7 @@ diag


You can specify the output file format with `outformat` parameter. Default is **png**. 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 ```python
from diagrams import Diagram from diagrams import Diagram
@@ -54,6 +54,16 @@ with Diagram("Simple Diagram", outformat="jpg"):
EC2("web") 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. You can specify the output filename with `filename` parameter. The extension shouldn't be included, it's determined by the `outformat` parameter.


```python ```python


+ 15
- 3
tests/test_diagram.py View File

@@ -26,7 +26,7 @@ class DiagramTest(unittest.TestCase):


def test_validate_direction(self): def test_validate_direction(self):
# Normal directions. # Normal directions.
for dir in ("TB", "BT", "LR", "RL"):
for dir in ("TB", "BT", "LR", "RL", "tb"):
Diagram(direction=dir) Diagram(direction=dir)


# Invalid directions. # Invalid directions.
@@ -36,7 +36,7 @@ class DiagramTest(unittest.TestCase):


def test_validate_curvestyle(self): def test_validate_curvestyle(self):
# Normal directions. # Normal directions.
for cvs in ("ortho", "curved"):
for cvs in ("ortho", "curved", "CURVED"):
Diagram(curvestyle=cvs) Diagram(curvestyle=cvs)


# Invalid directions. # Invalid directions.
@@ -46,7 +46,7 @@ class DiagramTest(unittest.TestCase):


def test_validate_outformat(self): def test_validate_outformat(self):
# Normal output formats. # Normal output formats.
for fmt in ("png", "jpg", "svg", "pdf"):
for fmt in ("png", "jpg", "svg", "pdf", "PNG", "dot"):
Diagram(outformat=fmt) Diagram(outformat=fmt)


# Invalid output formats. # Invalid output formats.
@@ -108,6 +108,18 @@ class DiagramTest(unittest.TestCase):
Node("node1") Node("node1")
self.assertTrue(os.path.exists(f"{self.name}.png")) 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): class ClusterTest(unittest.TestCase):
def setUp(self): def setUp(self):


Loading…
Cancel
Save