Giter Site home page Giter Site logo

gographviz's Introduction

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

gographviz's People

Contributors

ansd avatar awalterschulze avatar bobinette avatar fenollp avatar gouthamve avatar jmrtt avatar jpreese avatar mewmew avatar moul avatar myitcv avatar nkitchen avatar ruudk avatar saheienko avatar skius avatar temoto avatar tormath1 avatar x-cli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gographviz's Issues

How to set some properties?

How can I change the shape from ellipse to diamond or square or other pattern?How can I add a comment on the line between two graphics?

escaping rules, Is period escaped?

are periods escaped using the escape API?

given the following code https://play.golang.org/p/G_8QqcEn9yO i'd expect these nodes to be escaped. Running them through dot causes a syntax error.

sig@desktop2:~$ dot -Tsvg graph.dot 
Error: graph.dot: syntax error in line 3 near '.'
sig@desktop2:~$ dot -Tsvg graph.dot ^C
sig@desktop2:~$ cat graph.dot 

digraph G {
        a.b->a.c;
        a.b;
        a.c;
}

used the following code from playground to generate the graph

package main

import (
	"fmt"
	graph "github.com/awalterschulze/gographviz"
)

func main() {
n := "G"
	g := graph.NewEscape()
	g.SetDir(true)
	g.SetName(n)
	g.AddNode(n, "a.b", nil)
	g.AddNode(n, "a.c", nil)
	g.AddEdge("a.b", "a.c", true, nil)
	fmt.Printf("%s\n", g.String())
}

Escape graph is not intuitive

I only stumbled on this feature because of #10 .

Whilst I understand the rationale, I think it makes the API a little untidy to have a second struct type. As this is a failure case with the dot tool, is it worth escaping as default?

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

Documentation is needed

What steps will reproduce the problem?
1.
2.
3.

What is the expected output? What do you see instead?


Please use labels and text to provide additional information.


Original issue reported on code.google.com by awalterschulze on 11 Jan 2013 at 7:39

Attribute values are not quoted

What steps will reproduce the problem?
Compile:
    a := make(map[string]string)
    a["label"] = "a b"
    g := graphviz.NewGraph()
    g.SetName("g")
    g.AddNode("g", "n", a)
    fmt.Printf("%s\n", g.String())

What is the expected output?
graph g {
    n [ label="a b" ];

}

What do you see instead?
graph g {
    n [ label=a b ];

}

What version of the product are you using? On what operating system?
454bc64fdfa20468f637d99162e1edc60c1a6677, Arch Linux x86_64, go 1.3.3

Please provide any additional information below.
The actual output is not valid DOT (crashes when fed to DOT with "Error: 
<stdin>: syntax error in line 2 near ']'"). Quoting of attribute values is 
tricky, but necessary.

Original issue reported on code.google.com by [email protected] on 20 Oct 2014 at 10:25

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.

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 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)
	}
}

Escaping seems to be not complete

While testing escaped graphs (NewEscape), I discovered that most probably in 
non-HTML strings all HTML (XML) control characters should be escaped. 

http://www.graphviz.org/doc/info/lang.html:

"In addition, the content must be legal XML, so that the special XML escape 
sequences for ", &, <, and > may be necessary in order to embed these 
characters in attribute values or raw text."

I've attached the patch.

Original issue reported on code.google.com by [email protected] on 28 May 2014 at 8:44

Attachments:

Gographviz shown as an incompatible package when imported

I'm using Gographviz in our project, and Gographviz is shown as an incompatible package in go.mod:

	github.com/awalterschulze/gographviz v2.0.1+incompatible

It's because Gographviz has not opted in to go modules but has been tagged with v2+ SemVer tags.

It would be better if Gographviz starts to use go modules to manage its dependencies, which is recommended by Golang officials.

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

Proposal: move gocc generated packages to internal

The generated gocc packages should not be needed by anyone using gographviz and thus they should not need to be exposed.

Here is a list of the packages that are propsed to move to an internal package:

  • errors
  • lexer
  • parser
  • token
  • util

If anyone has any objections please let me know asap.

Add more encapsulations

I need to access the Edges internal data:

type Edges struct {
    SrcToDsts map[string]map[string]*Edge
    DstToSrcs map[string]map[string]*Edge
    Edges     []*Edge
}

but I don't want to dip directly into the above data structure, but would like to access them through encapsulations instead. So, I'd like to propose the following access methods:

// EdgesToParents returns all the edges linked to its parents of the given nodeName.
EdgesToParents(nodeName string) map[string]... => return DstToSrcs[nodeName]

// EdgesToChildren returns all the edges linked to its children of the given nodeName.
EdgesToChildren(nodeName string) map[string]... => return SrcToDsts[nodeName]

Or something similar. Would that be OK? I don't mind patch myself and send in the pull request.

Moreover, I also need the access method of NodesAll for all the nodes within the given Graph:

// NodesAll returns all the nodes within the given Graph.

Would that be OK to have such encapsulations? Again, I don't mind patch myself and send in the pull request.

Thanks

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
...

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?

ast.NewSubGraph data race due to rand.NewSource

Hello.

Thank you very much for great library. I try to use dot as storage format for user defined graphs.

Found this with parallel tests:

g := &SubGraph{ID: ID(fmt.Sprintf("anon%d", r.Int63()))}

produces data race in math/rand.(*Rand).Int63() because you create new rand source in

r = rand.New(rand.NewSource(1234))

which is not thread-safe, as docs say:

https://golang.org/pkg/math/rand/#NewSource
Unlike the default Source used by top-level functions, this source is not safe for concurrent use by multiple goroutines.

I can imagine you had best intentions for fast or reproducible PRNG. Maybe what was required for testing leaked into production code. I'm not sure how to fix this without breaking API.

IMHO this could be a start:

func NewSubGraph(id, l Attrib) (*SubGraph, error) {
	g := &SubGraph{}
	if id == nil {
		g.ID = ID(fmt.Sprintf("anon%d", r.Int63()))
	} else if len(id.(ID)) > 0 {
		g.ID = id.(ID)
	}
	if l != nil {
		g.StmtList = l.(StmtList)
	}
	return g, nil
}

So "anon%d" generation could be moved into (hopefully stateful) ProdTabEntry.

It also removes unconditional allocation to relax GC worried people.

Of course, just using thread-safe rand.Int63() function fixes data race.

What you think?

Dead links for documentation

I was reading through the source code about attributes and found some URLs to GraphViz's webpage that are now dead. It looks like they have migrated. I don't have time right now to do a PR, but here's the new url:

/* Old */
// Damping http://www.graphviz.org/content/attrs#dDamping

/* New */
// Damping http://graphviz.gitlab.io/_pages/doc/info/attrs.html#d:Damping

Hope that helps a little bit. :) Thanks for the work you've already done! Super helpful!

setup github action

Would love to replace travis job with github action, if anyone is interested in helping?

isNode accepts "node_name:port_name"

I expected the output like this...

digraph {
  source [
    label="<f0> left |<f1> middle |<f2> right"
    shape=record
  ];

  target [
    label="<f0> left |<f1> middle |<f2> right"
    shape=record
  ];

  source:f1 -> target:f2
}

but returns

error: source:f1 is not a node or a subgraph

Escape API doesn't properly escape nodes with file names

A minimal example:

package main

import (
        "fmt"
        gv "github.com/awalterschulze/gographviz"
)

func main() {
        graph := gv.NewEscape()
        graph.SetName("G")
        graph.AddNode("G", "a.txt", nil)
        graph.AddNode("G", "b.txt", nil)
        fmt.Println(graph.String())
}

Output:

$ go run main.go
graph G {
        a.txt;
        b.txt;

}

$ go run main.go | dot -Tpng -o out.png
Error: <stdin>: syntax error in line 2 near '.'

How to implement an anonymous subgraph

Hello, many thanks for this library!

I have a question which is duplicate of this issue here:

#9 (comment)

In a manual graphviz chart I have the following setup.

At the top of my graph I have defined:

  newrank=true;

As part of my graph I have the following anonymous graph:

{ rank=same; some_node_1; some_node_2; }  # How to inject this line?

This works, however similar to the issue linked above, how do I accomplish this in gographviz?

gographviz in production - a short review

Hi,

just wanted to let you know, that we are using gographviz in production for now almost two weeks. It's really a pleasure to work with the library - the API is intuitive and nicely documented and the library is stable. Awesome work!

What are we using gographviz for?

Currently we use the the library to build up a interactive label graph for our public image dataset. gographviz parses our label graph dot file and creates the nodes and edge information which will be rendered with d3.js. In case you want to have a look: https://imagemonkey.io/graph

There is also a online label graph editor (https://imagemonkey.io/graph?editor=true) which uses gographviz to parse and validate the input.

label_graph_editor

I hope it's okay to post that here, as it's not really a bug. You can close that issue...just wanted to let you know that are successfully using your library. ;-)

Have a nice day,
Bernhard

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!

[Question] How to delete Edges properly?

Hi,

I have loaded graph from DOT file and would like to remove Edge from the graph. I implement Kahn's algorithm for topological sorting and it requires removing edges from graph.

I understand that I can probably delete element from maps Graph.Edges.DstToSrcs and Graph.Edges.SrcToDsts but I wonder if it's not more involved so that graph stays valid.

Thanks for pointers!

Time for a release?

Hi,

There have been 27 commits since the last release, perhaps time for another release? :)

Cluster getting included as a node

I am trying to generate a graph from this dot file. Here is the code I have right now:

graphAst, error := parser.ParseBytes(dotText)
dag := ggv.NewGraph()
ggv.Analyse(graphAst, dag)

dag.Nodes includes a Node called L even though there is no node L in the .dot input. I suspect that there is a bug where the cluster_L cluster is being parsed as a node.

Expose DOT-specific keywords

A user shouldn't manually construct DOT keywords before adding them in the attributes of a graph object. All the names mentioned in here should be exposed by this package.

Attributes of nodes are ignored when they are declared after their edges

I found an issue with the fix to #26: If an edge statement refers to a node, and then the statement for the node appears later with attributes, those attributes are ignored.

The man page for dot is arguably ambiguous on this, but its output clearly differs from gographviz.

I'll post an example as soon as I can.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.