forked from BlueBrain/eFEL
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathefel_graph_dependency
executable file
·142 lines (112 loc) · 4.95 KB
/
efel_graph_dependency
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/env python
'''graph the dependency graph'''
import argparse
import logging
import os
from collections import namedtuple, defaultdict
Feature = namedtuple('Feature', 'library name dependencies')
Dependency = namedtuple('Dependency', 'feature wildcard')
def create_feature(line):
'''Convert a line from the Dependency.txt to a feature
LibV2:AP_duration_half_width_change #LibV2:AP_duration_half_width
LibV2:E6 #LibV1:AP_amplitude;APWaveForm
'''
tokenized_line = line.strip().split()
library, name = '', tokenized_line[0]
if ':' in name:
library, name = name.strip().split(':')
dependencies = []
if len(tokenized_line) > 1:
dependencies.extend(create_dependency(d) for d in tokenized_line[1:])
return Feature(library=library, name=name, dependencies=dependencies)
def create_dependency(line):
'''parse a dependency, and create a Dependency'''
line = line.strip()
assert line[0] == '#', '"%s": Not a feature dependency, must start w/ #' % line
feature, wildcard = line[1:], ''
if ';' in feature:
feature, wildcard = feature.split(';')
return Dependency(feature=feature, wildcard=wildcard)
def get_feature_library(dependency_file):
'''parse the `dependency_file` and gather all the features and their dependencies'''
feature_library = defaultdict(dict)
with open(dependency_file) as fd:
for line in fd:
feature = create_feature(line)
feature_library[feature.library][feature.name] = feature
# defaults are the last to be loaded
feature_library['Default'][feature.name] = feature
def find_feature(dependency):
'''find the feature in the current feature_library'''
if ':' in dependency.feature:
library, name = dependency.feature.split(':')
else:
library, name = 'Default', dependency.feature
feature = feature_library[library][name]
return Dependency(feature=feature, wildcard=dependency.wildcard)
# resolve features pointers
for library in feature_library.keys():
if 'Default' == library:
continue
for feature in feature_library[library].values():
for i in range(len(feature.dependencies)):
feature.dependencies[i] = find_feature(feature.dependencies[i])
return feature_library
COLORS = ('blue', 'crimson', 'forestgreen', 'dodgerblue3', 'aquamarine4',
)
def output_graphivz(feature_library, filename, draw_dependencies=False,
output_dot=False):
'''create a PNG at filename of the dependencies'''
try:
import pygraphviz
except ImportError:
import sys
sys.exit('Need to have the "pygraphviz" package installed')
G = pygraphviz.AGraph(name='Dependencies', directed=True)
G.graph_attr['overlap'] = 'false'
G.graph_attr['rankdir'] = 'TB'
for library, color in zip(sorted(feature_library.keys()), COLORS):
if 'Default' == library:
continue
G.add_node(library, shape='circle', color=color)
sg = G.add_subgraph(name=library, style="")
for name, feature in feature_library[library].iteritems():
full_name = library + ':' + name
sg.add_node(full_name, label=name, shape='box', color=color)
sg.add_edge(library, full_name, color=color)
if draw_dependencies:
for dep in feature.dependencies:
target = dep.feature.library + ':' + dep.feature.name
G.add_edge(full_name, target, color='yellowgreen')
if output_dot:
G.write(os.path.splitext(filename)[0] + '.dot')
G.draw(filename, prog='dot')
def get_parser():
'''return the argument parser'''
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input', required=True,
help='Input Dependency.txt file')
parser.add_argument('-g', '--graph',
help='Output graph png file location')
parser.add_argument('--graph-deps', action='store_true',
help='If graphing, draw the links to the dependencies')
parser.add_argument('--dot', action='store_true',
help='If graphing, output the dot file')
parser.add_argument('-d', '--dump', action='store_true',
help='Dump the resolved dependency tree')
parser.add_argument('-v', '--verbose', action='count', default=0,
help='-v for INFO, -vv for DEBUG')
return parser
def main(args):
'''main'''
logging.basicConfig(level=(
logging.WARNING, logging.INFO, logging.DEBUG)[min(args.verbose, 2)])
feature_library = get_feature_library(args.input)
if args.dump:
from pprint import pprint
pprint(dict(feature_library))
if args.graph:
output_graphivz(feature_library, args.graph, args.graph_deps, args.dot)
if __name__ == '__main__':
PARSER = get_parser()
main(PARSER.parse_args())