Parses the Graphviz DOT language in golang

Parses the Graphviz DOT language and creates an interface, in golang, with which to easily create new and manipulate existing graphs which can be written back to the DOT format.

This parser has been created using gocc.

Example (Parse and Edit)

graphAst, _ := gographviz.ParseString(`digraph G {}`)
graph := gographviz.NewGraph()
if err := gographviz.Analyse(graphAst, graph); err != nil {
    panic(err)
}
graph.AddNode("G", "a", nil)
graph.AddNode("G", "b", nil)
graph.AddEdge("a", "b", true, nil)
output := graph.String()

Documentation

Installation

go get github.com/awalterschulze/gographviz

Build and Tests

Build Status

Users

  • aptly - Debian repository management tool
  • gorgonia - A Library that helps facilitate machine learning in Go
  • imagemonkey - Let's create our own image dataset
  • depviz - GitHub dependency visualizer (auto-roadmap)
  • kustomize-graph - A tool to visualize Kustomize dependencies
  • inframap - Read your tfstate or HCL to generate a graph specific for each Terraform provider
  • Antrea Traceflow supports using Traceflow for network diagnosis for Antrea, a Kubernetes networking solution intended to be Kubernetes native

Mentions

Using Golang and GraphViz to Visualize Complex Grails Applications

Owner
Walter Schulze
Pair programmer with an interest in language design.
Walter Schulze
Comments
  • Typesafe (kinda) Attributes now available

    Typesafe (kinda) Attributes now available

    So, the attributes is now a static set (found in common/attributes.go). The API still takes a map[string]string but all public methods (AddNode, AddAttr etc) will call FromStringMap(), which will create a Attrs from the string map, and then pass them into private methods (addNode, addAttr, etc)

    This way, the API stays the same, per #4 .

    Caveat: I have also silenced the panic(err) in almost all of them because the test cases themselves are wrong/have wrong attributes. I'll probably leave that to someone else to fix. (grep for the below:)

    if err != nil {
        // panic(err)  // TODO: Fix...
    }```
    
  • Fix Go module name

    Fix Go module name

    From https://blog.golang.org/using-go-modules:

    Each different major version (v1, v2, and so on) of a Go module uses a different module path: starting at v2, the path must end in the major version. In the example, v3 of rsc.io/quote is no longer rsc.io/quote: instead, it is identified by the module path rsc.io/quote/v3. This convention is called semantic import versioning

    Currently running go mod download in a module using github.com/awalterschulze/gographviz in version v2.0.2 results in the following error:

    github.com/awalterschulze/[email protected]+incompatible: invalid version: +incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required

  • Attributes and Errors

    Attributes and Errors

    This pull request contains backwards incompatible changes:

    1. Some methods now return errors, instead of panicing.
    2. Attributes are checked to be valid attributes.
  • [Question] Is there any way to get the Node in a Graph?

    [Question] Is there any way to get the Node in a Graph?

    I want to edit a node attributes inside a graph. Is there any way to get the node by name of node and edit it? Like in nodejs package JNXnetwork we can do that by

    G.node.get(0).foo = 'bar';
    

    Is there anyway in this package to do that?

    Thanks

  • Default attributes are not inherited by nodes or edges in subgraphs

    Default attributes are not inherited by nodes or edges in subgraphs

    Given an input graph with default node/edge attributes and a subgraph, like this one:

    digraph g {
        node [shape=record];
        edge [style=dashed];
        subgraph cluster_key {
            graph [label=KEY];
            key_user [fontcolor=red];
            key_dep  [fontcolor=blue];
            key_user -> key_dep;
        }
        A [fontcolor=red];
        B [fontcolor=blue];
        A -> B;
    }
    

    In the rendering from dot, the default attributes are inherited by the objects in the subgraph:

    image

    but gographviz only applies the attributes to the top-level objects, not the ones in the subgraph:

    image

  • how to set `node[shape=box style=rounded labelloc=b]` global attribute?

    how to set `node[shape=box style=rounded labelloc=b]` global attribute?

    image

    it's not allowed use like this:

    graph.AddAttr(workflowName, "node", "shape=rect style=rounded, labelloc=b")
    

    but if set attribute one by one, it will not take affect.

    graph.AddAttr(workflowName, "shape", "rect")
    graph.AddAttr(workflowName, "style", "rounded")
    graph.AddAttr(workflowName, "labelloc", "b")
    

    image

  • Nesting cluster subgraphs doesn't work

    Nesting cluster subgraphs doesn't work

    What I am trying to achive:

    pic

    Code I used:

    g := gographviz.NewGraph()
    g.SetName("G")
    g.SetDir(true)
    
    g.AddNode("G", "Ga", nil)
    g.AddNode("G", "Gb", nil)
    g.AddEdge("Ga", "Gb", true, nil)
    
    g.AddSubGraph("G", "clusterone", map[string]string{
        "style": "filled", 
        "fillcolor": "red",
    })
    g.AddNode("clusterone", "sA", nil)
    g.AddNode("clusterone", "sB", nil)
    g.AddEdge("sA", "sB", true, nil)
    
    g.AddSubGraph("clusterone", "clustertwo", map[string]string{
        "style": "filled", 
        "fillcolor": "blue",
    })
    g.AddNode("clustertwo", "ssA", nil)
    g.AddNode("clustertwo", "ssB", nil)
    g.AddEdge("ssA", "ssB", true, nil)
    
    fmt.Println(g.String())
    

    However this is what the result looked like:

    pic2

    Am I doing something wrong?

  • Quote node IDs and attributes

    Quote node IDs and attributes

    Hi there, thanks for this package.

    My node IDs and attribute values disagree strongly with the DOT schema, and I've found that I have to quote them in order for tools like Gephi to parse them as they all are of type "ID".

    Could gographviz detect the need to quote/escape anything that it needs to write out as type ID and do so automatically so I don't have to add the quotes myself? Here's an example that produces an unreadable file:

    graph := gographviz.NewGraph()
    graph.SetName("G")
    graph.AddNode("G", "331fb1985e8884cfaaae65be7f8cfe5b", gographviz.Attrs{"label": "1:6:1w/w/PYqH7d1+6Fg"})
    graph.AddEdge("331fb1985e8884cfaaae65be7f8cfe5b", "ec2f3d34a4f4c4f82dd1d0b2f1a581e", gographviz.Attrs{"label": "FOO_BAR"})
    os.Stdout.Write(gographviz.WriteAst().String())
    

    Thanks!

  • How to get subtree based on parent node?

    How to get subtree based on parent node?

    Hi,

    first of all, many thanks for the great library - it's really a pleasure to use!

    I am currently evaluating gographviz for another project (https://github.com/bbernhard/imagemonkey-core) and would be glad if I could use it there.

    One thing I am currently struggling with is, the possibility to extract a subtree based on a given label. If I understood the documentation correctly, then that's what SortedChildren is meant to be for. However, for some obscure reason it doesn't seem to work - it looks like I have messed something up here.

    Here is a small code snippet which illustrates my problem. truck, bike, motorbike and car are all children of vehicle. When asking gographviz for the label vehicle I would like to get a list of all its children. I tried to accomplish that with graph.Relations.SortedChildren("vehicle") but that returns an empty list.

    I am pretty sure that I have missed something here and would be glad, if you could point me in the right direction.

    Thanks a lot, Bernhard

    package main
    
    import (
    	"bytes"
    	"os"
    	"fmt"
    	"github.com/awalterschulze/gographviz"
    )
    
    func main() {
    	graphAst, _ := gographviz.ParseString(`
    		digraph G { 
    			{ 
    				car [label="car" id="94bbd2ff-8a8e-4d1c-9ac5-f9506aa20e43"] 
    				vehicle [color=green style=filled label="vehicle"] 
    				truck [label="truck"] 
    			} 
    			
    		   vehicle -> truck
    		    vehicle -> car
    		    vehicle -> motorbike
    		    vehicle -> bike
    		}
    	`)
    	graph := gographviz.NewGraph()
    	graph.SetDir(true)
    	if err := gographviz.Analyse(graphAst, graph); err != nil {
        	panic(err)
    	}
    
    	childrens := graph.Relations.SortedChildren("vehicle")
    	for _, child := range childrens {
    		fmt.Printf("%s\n", child)
    	}
    }
    
  • Make cluster subgraphs as nodes for edges

    Make cluster subgraphs as nodes for edges

    There's an issue where making edges between cluster subgraphs (which are useful with fdp) would double subgraphs in output string.

    Consider this code:

    g := gographviz.NewEscape()
    g.SetName("G")
    g.SetDir(false)
    g.AddSubGraph("G", "cluster0", map[string]string{"label": "root"})
    g.AddSubGraph("cluster0", "cluster_1", map[string]string{"label": "child 1"})
    g.AddSubGraph("cluster0", "cluster_2", map[string]string{"label": "child 2"})
    nodeStyle := map[string]string{"style": "rounded"}
    g.AddNode("cluster_1", "1", nodeStyle)
    g.AddNode("cluster_1", "2", nodeStyle)
    g.AddNode("cluster_2", "3", nodeStyle)
    g.AddNode("cluster_2", "4", nodeStyle)
    g.AddNode("G", "Code deployment", map[string]string{"style": "dotted"})
    g.AddPortEdge("cluster_2", "", "cluster_1", "", false, nil)
    s := g.String()
    fmt.Println(s)
    

    It currently renders such code, which is incorrect and would not render:

    graph G { subgraph cluster_2 { label="child 2"; 3 [ style=rounded ]; 4 [ style=rounded ];

    } --subgraph cluster_1 { label="child 1"; 1 [ style=rounded ]; 2 [ style=rounded ];

    }; subgraph cluster0 { label=root; subgraph cluster_1 { label="child 1"; 1 [ style=rounded ]; 2 [ style=rounded ];

    } ; subgraph cluster_2 { label="child 2"; 3 [ style=rounded ]; 4 [ style=rounded ];

    } ;

    } ; "Code deployment" [ style=dotted ];

    }

    After the patch applied it would make such code (subgraphs starting with cluster would be rendered as nodes for edges): graph G { cluster_2--cluster_1; subgraph cluster0 { label=root; subgraph cluster_1 { label="child 1"; 1 [ style=rounded ]; 2 [ style=rounded ];

    } ; subgraph cluster_2 { label="child 2"; 3 [ style=rounded ]; 4 [ style=rounded ];

    } ;

    } ; "Code deployment" [ style=dotted ];

    }

  • Replace travis job with github action.

    Replace travis job with github action.

    Created github action that performs the same tasks as travis job.

    Note that the badge in Readme.md is already pointing to https://github.com/awalterschulze/gographviz to work correctly when merged.

  • Extend does not escape attributes

    Extend does not escape attributes

    I am using the following to update node labels in an Escape

    graph.Nodes.Lookup[id].Attrs.Extend(attrs)
    

    but the new label is not automatically escaped. Maybe there is a better way to update node attributes that I'm missing.

    On the other hand, if this is a bug, I'd happy to try to fix it. At a first glance at the implementation, it does not look like the escaping logic is executed for any Attrs method.

    Thanks!

  • How to define default attributes for node, edge, or graph

    How to define default attributes for node, edge, or graph

    Hi, all.

    I am trying to use the node, edge, and graph statement from the Lexical and Semantic Notes. However, since this library always sorts and prints nodes, the order is changed. How can I always define it first?

    Output:

    digraph G {
    	rank=LR;
    	Hello->World[ headlabel="head", taillabel="tail" ];
    	Hello->World:f0;
    	Hello->World:f1;
    	Hello->World:f2;
    	Hello [ label="Hi\nStart", shape=Mrecord ];
    	World [ label="<f0>one|<f1>two|<f2>three", shape=Mrecord ];
    	node [ shape=Mrecord ];
    }
    

    You can see that the node line is defined last.

    Expected:

    digraph G {
    	node [ shape=Mrecord ];  <-------------- This line
    	rank=LR;
    	Hello->World[ headlabel="head", taillabel="tail" ];
    	Hello->World:f0;
    	Hello->World:f1;
    	Hello->World:f2;
    	Hello [ label="Hi\nStart", shape=Mrecord ];
    	World [ label="<f0>one|<f1>two|<f2>three", shape=Mrecord ];
    }
    

    Only when defined like this, the output I want is completed.

    Looking at the source code, there seem to be no solutions. For now, is the only way to add properties to each node?

    ...
    go 1.14
    
    require github.com/awalterschulze/gographviz v2.0.1+incompatible
    ...
    
  • quoted string and its quirks

    quoted string and its quirks

    From the spec http://www.graphviz.org/content/dot-language

    As another aid for readability, dot allows double-quoted strings to span
    multiple physical lines using the standard C convention of a backslash
    immediately preceding a newline character.
    
    In addition, double-quoted strings can be concatenated using a '+' operator.
    
  • isNumber accepts non-numbers

    isNumber accepts non-numbers

    isNumber in escape.go is supposed to return true if it is passed a string that represents a number. However, it accepts "127.0.0.1" as a number but dot does not accept that. More generally it allows an arbitrary number of "."s in a number. This causes strings to not be escaped when they should be.

Go language bindings for the COIN-OR Linear Programming library

clp Description The clp package provides a Go interface to the COIN-OR Linear Programming (CLP) library, part of the COIN-OR (COmputational INfrastruc

Nov 9, 2022
Naive Bayesian Classification for Golang.

Naive Bayesian Classification Perform naive Bayesian classification into an arbitrary number of classes on sets of strings. bayesian also supports ter

Dec 20, 2022
Implements a simple floating point arithmetic expression evaluator in Go (golang).

evaler https://github.com/soniah/evaler Package evaler implements a simple floating point arithmetic expression evaluator. Evaler uses Dijkstra's Shun

Sep 27, 2022
Golang RServe client. Use R from Go

Roger Roger is a Go RServe client, allowing the capabilities of R to be used from Go applications. The communication between Go and R is via TCP. It i

Dec 22, 2022
A well tested and comprehensive Golang statistics library package with no dependencies.

Stats - Golang Statistics Package A well tested and comprehensive Golang statistics library / package / module with no dependencies. If you have any s

Dec 27, 2022
Parses the Graphviz DOT language in golang

Parses the Graphviz DOT language and creates an interface, in golang, with which to easily create new and manipulate existing graphs which can be writ

Dec 25, 2022
Ltree Visualizer - A golang library to visualize postgres ltree type data using DOT language and Graphviz
Ltree Visualizer - A golang library to visualize postgres ltree type data using DOT language and Graphviz

Ltree Visualizer A golang library to visualize postgres ltree type data using DOT language and Graphviz What is Ltree? Ltree is a data type which is u

Jun 12, 2022
Converts 'go mod graph' output into Graphviz's DOT language
Converts 'go mod graph' output into Graphviz's DOT language

modgv Converts 'go mod graph' output into GraphViz's DOT language. takes no options or arguments it reads the output generated by “go mod graph” on st

Dec 22, 2022
Go package for writing descriptions using the Graphviz DOT language
Go package for writing descriptions using the Graphviz DOT language

dot - little helper package in Go for the graphviz dot language

Nov 30, 2022
An ease to use finit state machine golang implementation.Turn any struct to a fsm with graphviz visualization supported.

go-fsm An ease to use finit state machine golang implementation.Turn any struct to a fsm with graphviz visualization supported. usage import github.co

Dec 26, 2021
Visualize call graph of a Go program using Graphviz
Visualize call graph of a Go program using Graphviz

go-callvis go-callvis is a development tool to help visualize call graph of a Go program using interactive view. Introduction The purpose of this tool

Jan 1, 2023
Visualize call graph of a Go program using Graphviz
Visualize call graph of a Go program using Graphviz

go-callvis go-callvis is a development tool to help visualize call graph of a Go program using interactive view. Introduction The purpose of this tool

Dec 31, 2022
Slice graph uses graphviz in order to pretty print slices for you.

slicegraph Slice graph uses graphviz in order to make you understand what happens underneath your slices.

Sep 22, 2022
Visualize your Go data structures using graphviz

memviz How would you rather debug a data structure? "Pretty" printed Visual graph (*test.fib)(0xc04204a5a0)({ index: (int) 5, prev: (*test.fib)(0xc0

Dec 22, 2022
🛠 A configuration library for Go that parses environment variables, JSON files, and reloads automatically on SIGHUP
🛠 A configuration library for Go that parses environment variables, JSON files, and reloads automatically on SIGHUP

config A small configuration library for Go that parses environment variables, JSON files, and reloads automatically on SIGHUP. Example func main() {

Dec 11, 2022
:evergreen_tree: Parses indented code and returns a tree structure.

codetree Parses indented code (Python, Pug, Stylus, Pixy, codetree, etc.) and returns a tree structure. Installation go get github.com/aerogo/codetree

Sep 27, 2022
Parses Go tracebacks and finds possible deadlocks

findlock Parses Go tracebacks and finds possible deadlocks This works by checking how many locks have the same memory address. If there are multiple g

Nov 19, 2022
Package gostackparse parses goroutines stack traces as produced by panic() or debug.Stack() at ~300 MiB/s.

gostackparse Package gostackparse parses goroutines stack traces as produced by panic() or debug.Stack() at ~300 MiB/s. Parsing this data can be usefu

Dec 1, 2022
Parses a file and associate SQL queries to a map. Useful for separating SQL from code logic

goyesql This package is based on nleof/goyesql but is not compatible with it any more. This package introduces support for arbitrary tag types and cha

Oct 20, 2021
This utility parses stackoverflow data and pushes it to Zinc/Elasticsearch

Gostack This utility parses stackoverflow data and pushes it to Zinc/Elasticsear

Jun 8, 2022