xflr6 / graphviz

Simple Python interface for Graphviz
https://graphviz.readthedocs.io
MIT License
1.63k stars 211 forks source link

Convert graphviz.files.Source to graphviz.dot.Digraph #130

Closed clayms closed 3 years ago

clayms commented 3 years ago

Is there a way to convert the graphviz.files.Source type to graphviz.dot.Digraph type?

I would like to import a .gv file and use it as a subgraph in another graph.

However, the following fails.


from graphviz import Digraph, Source

g1 = Digraph('G', filename='hello.gv')
g1.edge('Hello', 'Earth')
g1.save("g1.gv")
g1

image

g2 = Digraph('G', filename='hi.gv')
g2.edge('Hi', 'Moon')
g2

image

g2.subgraph(g1)
g2

image

type(g1)
graphviz.dot.Digraph

g1_file = Source.from_file(filename="g1.gv")
g1_file

image

type(g1_file)
graphviz.files.Source

However, even though the imported Source file (g1_file) can be rendered the same as the in-memory Digraph (g1), it cannot be added as a subgraph as it is a Source object, not a Digraph object.

g2 = Digraph('G', filename='hi.gv')
g2.edge('Hi', 'Moon')

g2.subgraph(g1_file)

g2.subgraph(g1_file)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
o:\_Projects\ArchitectureDiagrams\code\github_answers6.py in ()
----> 861 g2.subgraph(g1_file)

/home/user/.local/lib/python3.6/site-packages/graphviz/dot.py in subgraph(self, graph, name, comment, graph_attr, node_attr, edge_attr, body)
    215             raise ValueError('graph must be sole argument of subgraph()')
    216 
--> 217         if graph.directed != self.directed:
    218             raise ValueError('%r cannot add subgraph of different kind:'
    219                              ' %r' % (self, graph))

AttributeError: 'Source' object has no attribute 'directed'
clayms commented 3 years ago

Ok, figured it out

from graphviz import Digraph, Source

g1_body = Source.from_file(filename="g1.gv").source.split('\n')[1:-2]
g1_digraph = Digraph(body=g1_body) 
g2.subgraph(g1_digraph)
g2

image

xflr6 commented 3 years ago

Thanks for documenting.

Source only loads (does not parse) the file, but as the body of (Di)Graph is a list of lines you can get away with operations on the list strings in simple cases.

See https://graphviz.readthedocs.io/en/stable/#see-also for libraries that parse DOT.

We could make Source iterable so one could do list(<Source instance>)[1:-2].