Source code for pyGHDL.dom.formatting.GraphML
from enum import Flag
from pathlib import Path
from textwrap import dedent
from typing import Dict, List, ClassVar
from pyTooling.Decorators import export
from pyTooling.Graph import Graph, Vertex
from pyTooling.MetaClasses import abstractmethod, ExtendedType
from pyVHDLModel import (
DependencyGraphVertexKind,
DependencyGraphEdgeKind,
Library as VHDLModel_Library,
Document as VHDLModel_Document,
)
[docs]
@export
class Formatter: # (metaclass=ExtendedType):
_graph: Graph
NODE_COLORS: ClassVar[Dict[Flag, str]]
EDGE_COLORS: ClassVar[Dict[Flag, str]]
@abstractmethod
def WriteGraphML(self, path: Path):
pass
[docs]
@export
class DependencyGraphFormatter(Formatter):
NODE_COLORS = {
DependencyGraphVertexKind.Document: "#999999",
DependencyGraphVertexKind.Library: "#99ccff",
DependencyGraphVertexKind.Package: "#ff9900",
DependencyGraphVertexKind.PackageBody: "#ff9900",
DependencyGraphVertexKind.Context: "#cc99ff",
DependencyGraphVertexKind.Entity: "#ffff99",
DependencyGraphVertexKind.Architecture: "#ff99cc",
DependencyGraphVertexKind.Configuration: "#ff9900",
}
EDGE_COLORS = {
DependencyGraphEdgeKind.SourceFile: "#000000",
DependencyGraphEdgeKind.CompileOrder: "#ff0000",
DependencyGraphEdgeKind.LibraryClause: "#000000",
DependencyGraphEdgeKind.UseClause: "#000000",
DependencyGraphEdgeKind.ContextReference: "#000000",
DependencyGraphEdgeKind.EntityImplementation: "#99ccff",
DependencyGraphEdgeKind.PackageImplementation: "#99ccff",
DependencyGraphEdgeKind.EntityInstantiation: "#000000",
DependencyGraphEdgeKind.ComponentInstantiation: "#000000",
DependencyGraphEdgeKind.ConfigurationInstantiation: "#000000",
DependencyGraphEdgeKind.PackageInstantiation: "#000000",
}
def WriteGraphML(self, path: Path):
with path.open("w") as file:
file.write(dedent(f"""\
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="nd1" for="node" attr.name="id" attr.type="string"/>
<key id="nd2" for="node" attr.name="value" attr.type="string"/>
<key id="nd3" for="node" attr.name="kind" attr.type="string"/>
<key id="nd4" for="node" attr.name="color" attr.type="string"/>
<key id="ed3" for="edge" attr.name="kind" attr.type="string"/>
<key id="ed4" for="edge" attr.name="color" attr.type="string"/>
<graph id="DependencyGraph"
edgedefault="directed"
parse.nodes="{len(self._graph._verticesWithID)}"
parse.edges="{len(self._graph._edgesWithoutID)}"
parse.order="nodesfirst">
"""))
groups: Dict[str, List[Vertex]] = {}
for vertex in self._graph._verticesWithID.values():
if isinstance(vertex.Value, VHDLModel_Library):
identifier = vertex.Value.NormalizedIdentifier
elif isinstance(vertex.Value, VHDLModel_Document):
identifier = vertex.Value.DesignUnits[0].Library.NormalizedIdentifier
else:
identifier = vertex.Value.Library.NormalizedIdentifier
if identifier in groups:
groups[identifier].append(vertex)
else:
groups[identifier] = [vertex]
for group, vertices in groups.items():
file.write(dedent("""\
{prefix}<node id="grp_{id}">
{prefix} <data key="nd2">{value}</data>
{prefix} <graph id="{id}" edgedefault="directed">
""").format(prefix=" ", id=group, value=group))
for vertex in vertices:
if vertex["kind"] is DependencyGraphVertexKind.Architecture:
value = f"{vertex.Value.Entity.Name.Identifier}({vertex.Value.Identifier})"
elif vertex["kind"] is DependencyGraphVertexKind.Document:
value = f"{vertex.ID}"
else:
value = f"{vertex.Value.Identifier}"
file.write(dedent("""\
{prefix}<node id="{vertex.ID}">
{prefix} <data key="nd1">{vertex.ID}</data>
{prefix} <data key="nd2">{value}</data>
{prefix} <data key="nd3">{vertex[kind].name}</data>
{prefix} <data key="nd4">{color}</data>
{prefix}</node>
""").format(prefix=" ", vertex=vertex, value=value, color=self.NODE_COLORS[vertex["kind"]]))
file.write(dedent("""\
{prefix} </graph>
{prefix}</node>
""").format(prefix=" "))
edgeCount = 1
for edge in self._graph._edgesWithoutID:
file.write(dedent("""\
{prefix}<edge id="e{edgeCount}" source="{edge.Source.ID}" target="{edge.Destination.ID}">
{prefix} <data key="ed3">{edge[kind].name}</data>
{prefix} <data key="ed4">{color}</data>
{prefix}</edge>
""").format(prefix=" ", edgeCount=edgeCount, edge=edge, color=self.EDGE_COLORS[edge["kind"]]))
edgeCount += 1
file.write(dedent("""\
</graph>
</graphml>
"""))
[docs]
@export
class HierarchyGraphFormatter(Formatter):
NODE_COLORS = {
DependencyGraphVertexKind.Document: "#999999",
DependencyGraphVertexKind.Library: "#99ccff",
DependencyGraphVertexKind.Package: "#ff9900",
DependencyGraphVertexKind.PackageBody: "#ff9900",
DependencyGraphVertexKind.Context: "#cc99ff",
DependencyGraphVertexKind.Entity: "#ffff99",
DependencyGraphVertexKind.Architecture: "#ff99cc",
DependencyGraphVertexKind.Configuration: "#ff9900",
}
EDGE_COLORS = {
DependencyGraphEdgeKind.SourceFile: "#000000",
DependencyGraphEdgeKind.CompileOrder: "#ff0000",
DependencyGraphEdgeKind.LibraryClause: "#000000",
DependencyGraphEdgeKind.UseClause: "#000000",
DependencyGraphEdgeKind.ContextReference: "#000000",
DependencyGraphEdgeKind.EntityImplementation: "#99ccff",
DependencyGraphEdgeKind.PackageImplementation: "#99ccff",
DependencyGraphEdgeKind.EntityInstantiation: "#000000",
DependencyGraphEdgeKind.ComponentInstantiation: "#000000",
DependencyGraphEdgeKind.ConfigurationInstantiation: "#000000",
}
def WriteGraphML(self, path: Path):
with path.open("w") as file:
file.write(dedent(f"""\
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="nd1" for="node" attr.name="id" attr.type="string"/>
<key id="nd2" for="node" attr.name="value" attr.type="string"/>
<key id="nd3" for="node" attr.name="kind" attr.type="string"/>
<key id="nd4" for="node" attr.name="color" attr.type="string"/>
<key id="ed3" for="edge" attr.name="kind" attr.type="string"/>
<key id="ed4" for="edge" attr.name="color" attr.type="string"/>
<graph id="HierarchyGraph"
edgedefault="directed"
parse.nodes="{len(self._graph._verticesWithID)}"
parse.edges="{len(self._graph._edgesWithoutID)}"
parse.order="nodesfirst">
"""))
for vertex in self._graph._verticesWithID.values():
if vertex["kind"] is DependencyGraphVertexKind.Entity:
file.write(dedent("""\
{prefix}<node id="{vertex.ID}">
{prefix} <data key="nd1">{vertex.ID}</data>
{prefix} <data key="nd2">{vertex.Value.Identifier}</data>
{prefix} <data key="nd3">{vertex[kind].name}</data>
{prefix} <data key="nd4">{color}</data>
{prefix}</node>
""").format(prefix=" ", vertex=vertex, color=self.NODE_COLORS[vertex["kind"]]))
elif vertex["kind"] is DependencyGraphVertexKind.Architecture:
file.write(dedent("""\
{prefix}<node id="{vertex.ID}">
{prefix} <data key="nd1">{vertex.ID}</data>
{prefix} <data key="nd2">{vertex.Value.Identifier}</data>
{prefix} <data key="nd3">{vertex[kind].name}</data>
{prefix} <data key="nd4">{color}</data>
{prefix}</node>
""").format(prefix=" ", vertex=vertex, color=self.NODE_COLORS[vertex["kind"]]))
edgeCount = 1
for edge in self._graph._edgesWithoutID:
file.write(dedent("""\
{prefix}<edge id="e{edgeCount}" source="{edge.Source.ID}" target="{edge.Destination.ID}">
{prefix} <data key="ed3">{edge[kind].name}</data>
{prefix} <data key="ed4">{color}</data>
{prefix}</edge>
""").format(prefix=" ", edgeCount=edgeCount, edge=edge, color=self.EDGE_COLORS[edge["kind"]]))
edgeCount += 1
file.write(dedent("""\
</graph>
</graphml>
"""))
[docs]
@export
class CompileOrderGraphFormatter(Formatter):
NODE_COLORS = {
DependencyGraphVertexKind.Document: "#999999",
DependencyGraphVertexKind.Library: "#99ccff",
DependencyGraphVertexKind.Package: "#ff9900",
DependencyGraphVertexKind.PackageBody: "#ff9900",
DependencyGraphVertexKind.Context: "#cc99ff",
DependencyGraphVertexKind.Entity: "#ffff99",
DependencyGraphVertexKind.Architecture: "#ff99cc",
DependencyGraphVertexKind.Configuration: "#ff9900",
}
EDGE_COLORS = {
DependencyGraphEdgeKind.SourceFile: "#000000",
DependencyGraphEdgeKind.CompileOrder: "#ff0000",
DependencyGraphEdgeKind.LibraryClause: "#000000",
DependencyGraphEdgeKind.UseClause: "#000000",
DependencyGraphEdgeKind.ContextReference: "#000000",
DependencyGraphEdgeKind.EntityImplementation: "#99ccff",
DependencyGraphEdgeKind.PackageImplementation: "#99ccff",
DependencyGraphEdgeKind.EntityInstantiation: "#000000",
DependencyGraphEdgeKind.ComponentInstantiation: "#000000",
DependencyGraphEdgeKind.ConfigurationInstantiation: "#000000",
}
def WriteGraphML(self, path: Path):
with path.open("w") as file:
file.write(dedent(f"""\
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="nd1" for="node" attr.name="id" attr.type="string"/>
<key id="nd2" for="node" attr.name="value" attr.type="string"/>
<key id="nd3" for="node" attr.name="kind" attr.type="string"/>
<key id="nd4" for="node" attr.name="color" attr.type="string"/>
<key id="ed3" for="edge" attr.name="kind" attr.type="string"/>
<key id="ed4" for="edge" attr.name="color" attr.type="string"/>
<graph id="CompileOrderGraph"
edgedefault="directed"
parse.nodes="{len(self._graph._verticesWithID)}"
parse.edges="{len(self._graph._edgesWithoutID)}"
parse.order="nodesfirst">
"""))
for vertex in self._graph._verticesWithID.values():
if vertex["kind"] is DependencyGraphVertexKind.Document:
file.write(dedent("""\
{prefix}<node id="{vertex.ID}">
{prefix} <data key="nd1">{vertex.ID}</data>
{prefix} <data key="nd2">{vertex.Value.Path.name}</data>
{prefix} <data key="nd3">{vertex[kind].name}</data>
{prefix} <data key="nd4">{color}</data>
{prefix}</node>
""").format(prefix=" ", vertex=vertex, color=self.NODE_COLORS[vertex["kind"]]))
edgeCount = 1
for edge in self._graph._edgesWithoutID:
file.write(dedent("""\
{prefix}<edge id="e{edgeCount}" source="{edge.Source.ID}" target="{edge.Destination.ID}">
{prefix} <data key="ed3">{edge[kind].name}</data>
{prefix} <data key="ed4">{color}</data>
{prefix}</edge>
""").format(prefix=" ", edgeCount=edgeCount, edge=edge, color=self.EDGE_COLORS[edge["kind"]]))
edgeCount += 1
file.write(dedent("""\
</graph>
</graphml>
"""))