Add support for in-memory diagram generation using BytesIO

pull/999/head
rithvikgrandhi 1 year ago
parent 4c2d8a3795
commit 29a56bc359

@ -3,7 +3,7 @@ import os
import uuid
from pathlib import Path
from typing import Dict, List, Optional, Union
from io import BytesIO
from graphviz import Digraph
# Global contexts for a diagrams and a cluster.
@ -42,7 +42,7 @@ class Diagram:
__curvestyles = ("ortho", "curved")
__outformats = ("png", "jpg", "svg", "pdf", "dot")
# fmt: off
# Default graph attributes
_default_graph_attrs = {
"pad": "2.0",
"splines": "ortho",
@ -59,10 +59,6 @@ class Diagram:
"width": "1.4",
"height": "1.4",
"labelloc": "b",
# imagepos attribute is not backward compatible
# TODO: check graphviz version to see if "imagepos" is available >= 2.40
# https://github.com/xflr6/graphviz/blob/master/graphviz/backend.py#L248
# "imagepos": "tc",
"imagescale": "true",
"fontname": "Sans-Serif",
"fontsize": "13",
@ -72,10 +68,6 @@ class Diagram:
"color": "#7B8894",
}
# fmt: on
# TODO: Label position option
# TODO: Save directory option (filename + directory?)
def __init__(
self,
name: str = "",
@ -89,6 +81,7 @@ class Diagram:
graph_attr: Optional[dict] = None,
node_attr: Optional[dict] = None,
edge_attr: Optional[dict] = None,
output_buffer: Optional[BytesIO] = None # New parameter
):
"""Diagram represents a global diagrams context.
@ -103,7 +96,7 @@ class Diagram:
:param graph_attr: Provide graph_attr dot config attributes.
:param node_attr: Provide node_attr dot config attributes.
:param edge_attr: Provide edge_attr dot config attributes.
:param strict: Rendering should merge multi-edges.
:param output_buffer: Optional in-memory buffer to write the output to.
"""
if graph_attr is None:
graph_attr = {}
@ -152,9 +145,7 @@ class Diagram:
self.show = show
self.autolabel = autolabel
def __str__(self) -> str:
return str(self.dot)
self.output_buffer = output_buffer # Store the buffer
def __enter__(self):
setdiagram(self)
@ -162,8 +153,8 @@ class Diagram:
def __exit__(self, exc_type, exc_value, traceback):
self.render()
# Remove the graphviz file leaving only the image.
os.remove(self.filename)
if not self.output_buffer:
os.remove(self.filename)
setdiagram(None)
def _repr_png_(self):
@ -193,9 +184,15 @@ class Diagram:
def render(self) -> None:
if isinstance(self.outformat, list):
for one_format in self.outformat:
self.dot.render(format=one_format, view=self.show, quiet=True)
if self.output_buffer:
self.output_buffer.write(self.dot.pipe(format=one_format))
else:
self.dot.render(format=one_format, view=self.show, quiet=True)
else:
self.dot.render(format=self.outformat, view=self.show, quiet=True)
if self.output_buffer:
self.output_buffer.write(self.dot.pipe(format=self.outformat))
else:
self.dot.render(format=self.outformat, view=self.show, quiet=True)
class Cluster:

Loading…
Cancel
Save