1 |
"""This is probably overkill for packages.gentoo.org, but perhaps it can be |
2 |
used elsewhere""" |
3 |
|
4 |
__version__ = '$Revision: $' |
5 |
# $Source: $ |
6 |
|
7 |
# importers may want to override this. This is the current(?) |
8 |
# bugs.gentoo.org settings |
9 |
STATUS = {'UNCONFIRMED': 'UNCONFIRMED', |
10 |
'NEW': 'NEW', |
11 |
'ASSIGNED': 'ASSIGNED', |
12 |
'REOPENED': 'REOPENED', |
13 |
'RESOLVED': 'RESOLVED', |
14 |
'VERIFIED': 'VERIFIED', |
15 |
'CLOSED': 'CLOSED'} |
16 |
|
17 |
def parse_csv(line): |
18 |
"""parse a line of CSV""" |
19 |
data = [] |
20 |
indata = 0 |
21 |
inquote = 0 |
22 |
line = line.strip() |
23 |
cdata = '' |
24 |
prev_char = '' |
25 |
for char in line: |
26 |
if char == ',': |
27 |
if indata: |
28 |
if not inquote: |
29 |
data.append(cdata) |
30 |
cdata = '' |
31 |
indata = 0 |
32 |
else: |
33 |
cdata = cdata + char |
34 |
elif prev_char == '' or prev_char == ',': |
35 |
data.append('') |
36 |
elif char == '"': |
37 |
if indata: |
38 |
data.append(cdata) |
39 |
indata = 0 |
40 |
cdata = '' |
41 |
inquote = 0 |
42 |
else: |
43 |
indata = 1 |
44 |
inquote = 1 |
45 |
elif indata: |
46 |
cdata = cdata + char |
47 |
else: |
48 |
indata = 1 |
49 |
cdata = cdata = char |
50 |
prev_char = char |
51 |
if prev_char != '"': |
52 |
data.append(cdata) |
53 |
return data |
54 |
|
55 |
class Bug: |
56 |
"""a bugzilla bug""" |
57 |
def __init__(self, bug_id, severity, priority, rep_platform, assigned_to, |
58 |
status, resolution, short_desc): |
59 |
self.bug_id = bug_id |
60 |
self.severity = severity |
61 |
self.priority = priority |
62 |
self.rep_platform = rep_platform |
63 |
self.assigned_to = assigned_to |
64 |
self.status = status |
65 |
self.resolution = resolution |
66 |
self.short_desc = short_desc |
67 |
|
68 |
def to_dict(self): |
69 |
"""convert to dict""" |
70 |
return {'bug_id': self.bug_id, |
71 |
'severity': self.severity, |
72 |
'priority': self.priority, |
73 |
'rep_platform': self.rep_platform, |
74 |
'assigned_to': self.assigned_to, |
75 |
'status': self.status, |
76 |
'resolution': self.resolution, |
77 |
'short_desc': self.short_desc} |
78 |
|
79 |
def to_tuple(self): |
80 |
"""convert to tuple""" |
81 |
return [self.bug_id, self.severity, self.priority, self.rep_platform, |
82 |
self.assigned_to, self.status, self.resolution, self.short_desc] |
83 |
|
84 |
class BugFactory: |
85 |
"""create bugs from dict data""" |
86 |
def __init__(self): |
87 |
"""to shut pylint up""" |
88 |
pass |
89 |
|
90 |
def fromDict(self, mapping): |
91 |
"""from dict => BugFactory.fromDict(mapping).to_dict() == mapping""" |
92 |
bug_id = mapping.get("bug_id", "unknown") |
93 |
severity = mapping.get("severity") |
94 |
priority = mapping.get("priority") |
95 |
rep_platform = mapping.get("rep_platform") |
96 |
assigned_to = mapping.get("assigned_to") |
97 |
status = mapping.get("status") |
98 |
resolution = mapping.get("resolution") |
99 |
short_desc = mapping.get("short_desc") |
100 |
|
101 |
return Bug(bug_id, severity, priority, rep_platform, assigned_to, |
102 |
status, resolution, short_desc) |
103 |
|
104 |
def fromListOfDicts(self, buglist): |
105 |
"""when you have a list of dicts""" |
106 |
all = [] |
107 |
for mapping in buglist: |
108 |
all.append(self.fromDict(mapping)) |
109 |
return all |
110 |
|
111 |
def fromCSV(self, csv_file): |
112 |
"""fp should be a file object with CSV data in the format as returned |
113 |
by bugzlla""" |
114 |
|
115 |
all = [] |
116 |
for line in csv_file.readlines()[1:]: |
117 |
mapping = {} |
118 |
fields = parse_csv(line) |
119 |
if len(fields) < 7: |
120 |
continue # wtf? |
121 |
#print fields |
122 |
(mapping['bug_id'], mapping['severity'], mapping['priority'], |
123 |
mapping['rep_platform'], mapping['assigned_to'], |
124 |
mapping['status'], mapping['resolution'], |
125 |
mapping['short_desc']) = fields[:8] |
126 |
all.append(self.fromDict(mapping)) |
127 |
|
128 |
return all |
129 |
|
130 |
|
131 |
class HTMLWriter: |
132 |
"""convert list of bugs to HTML""" |
133 |
def __init__(self, bugs, bugzilla_site=None): |
134 |
"""where <bugs> is a list of Bugs""" |
135 |
html = '<table class="buglist">\n' |
136 |
html = ('%s<tr class="heading"><th class="bug_id">Bug ID</th>' |
137 |
'<th class="severity">Severity</th><th class="priority">' |
138 |
'Priority</th><th class="platform">Platform</th>' |
139 |
#'<th class="assigned_to">Assigned To</th>' |
140 |
'<th class="status">Status</th>' |
141 |
#'<th class="resolution">Resolution</th>' |
142 |
'<th class="description">Description</th>' |
143 |
'</tr>\n' % html) |
144 |
for bug in bugs: |
145 |
bug_dict = bug.to_dict() |
146 |
html = html + '<tr class="bug">' |
147 |
if bugzilla_site: |
148 |
html = html + ('<td class="bug_id">' |
149 |
'<a href="http://%s/show_bug.cgi?id=%s">' |
150 |
'%s</td>' % (bugzilla_site, bug_dict['bug_id'], |
151 |
bug_dict['bug_id'])) |
152 |
else: |
153 |
html = html + '<td class="bug_id">%(bug_id)s</td>' % bug_dict |
154 |
|
155 |
html = html + ('<td class="severity">%(severity)s</td>' |
156 |
'<td class="priority">%(priority)s</td>' |
157 |
'<td class="platform">%(rep_platform)s' |
158 |
#'<td class="assigned_to">%(assigned_to)s</td>' |
159 |
'<td class="status">%(status)s</td>' |
160 |
#'<td class="resolution">%(resolution)s</td>' |
161 |
'<td class="description">%(short_desc)s</td>' |
162 |
'</tr>\n' % bug_dict) |
163 |
html = html + '</table>\n' |
164 |
self.html = html |
165 |
|
166 |
def __str__(self): |
167 |
return self.html |