-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgraph.py
More file actions
140 lines (110 loc) · 4.26 KB
/
graph.py
File metadata and controls
140 lines (110 loc) · 4.26 KB
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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
def enum(**enums):
return type('Enum', (), enums)
def setToList(object):
if type(object) is list:
result = []
for item in object:
result.append(setToList(item))
return result
if type(object) is dict:
result = {}
for key, value in object.items():
result[key] = setToList(value)
return result
if type(object) is set:
result = []
for value in object:
result.append(setToList(value))
return result
return object
class GraphError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
class Node:
Type = enum(JIRA='JIRA', GIT='git', STASH='stash')
def __init__(self, id, _type, data):
self.id = id
self._type = _type
self.data = data
if not (_type == Node.Type.JIRA or _type == Node.Type.GIT or _type == Node.Type.STASH):
raise GraphError('Invalid node type: ' + _type)
if _type == Node.Type.JIRA:
if ((not 'type' in data)
or (not 'URL' in data)
or (not 'code' in data)
or (not 'summary' in data)
or (not 'assignee' in data)
or (not 'status' in data)
or (not 'statusColor' in data)
or (not 'completed' in data)
or (not 'estimated' in data)):
raise GraphError('Missing field in JIRA data node: ' + json.dumps(data, indent=4))
if _type == Node.Type.GIT:
if (not 'type' in data):
raise GraphError('Missing field in git data node: ' + json.dumps(data, indent=4))
if _type == Node.Type.STASH:
if ((not 'reviewers' in data)
or (not 'name' in data)
or (not 'URL' in data)):
raise GraphError('Missing field in stash data node: ' + json.dumps(data, indent=4))
def toObject(self):
return {
'id': self.id,
'type': self._type,
'data': setToList(self.data)
}
class Edge:
def __init__(self, source, target, _type=None):
self.source = source
self.target = target
self._type = _type
if source == target:
raise GraphError('Invalid edge - source and target same: ' + source)
def toObject(self):
object = {
'source': self.source,
'target': self.target
}
if self._type:
object['type'] = setToList(self._type)
return object
class Graph:
def __init__(self):
self.nodes = []
self.nodeIds = set()
self.edges = []
def hasNode(self, nodeId):
return nodeId in self.nodeIds
def addNode(self, node):
if not isinstance(node, Node):
raise GraphError('Not a node object: ' + repr(node))
if node.id in self.nodeIds:
raise GraphError('Node already added to graph: ' + node.id)
self.nodes.append(node)
self.nodeIds.add(node.id)
def addEdge(self, edge):
if not isinstance(edge, Edge):
raise GraphError('Not a edge object: ' + repr(edge))
self.edges.append(edge)
def saveGraphJson(self, filePath, additionalData=None):
import datetime
output = {
'nodes': [],
'edges': [],
'timestamp': datetime.datetime.now().strftime('%d.%m.%Y %X')
}
if additionalData:
for key, value in additionalData.items():
output[key] = value
for node in self.nodes:
output['nodes'].append(node.toObject())
for edge in self.edges:
if (edge.source in self.nodeIds) and (edge.target in self.nodeIds):
output['edges'].append(edge.toObject())
with open(filePath, 'w') as outfile:
outfile.write(json.dumps(output, indent=4, ensure_ascii=False).encode('utf-8'))