Revamp needsponsor report.

Now includes names or addresses if names not set.
Includes submission date of oldest ticket.
Names are clickable to find all review commentary.
This commit is contained in:
Jason Tibbitts 2012-08-20 11:42:14 -05:00
parent 8789303caf
commit 66eaae6702
2 changed files with 165 additions and 24 deletions

View file

@ -99,7 +99,8 @@ def parse_config(file):
def nobody(str):
'''Shorten the long "nobody's working on it" string.'''
if str == "Nobody's working on this, feel free to take it":
if (str == "Nobody's working on this, feel free to take it"
or str == "nobody@fedoraproject.org"):
return "(Nobody)"
return str
@ -107,9 +108,14 @@ def nosec(str):
'''Remove the seconds from an hh:mm:ss format string.'''
return str[0:str.rfind(':')]
def human_time(t):
def human_date(t):
'''Turn an ISO date into something more human-friendly.'''
t = str(t)
return t[0:4] + '-' + t[4:6] + '-' + t[6:8]
def human_time(t):
'''Turn an ISO date into something more human-friendly, with time.'''
t = str(t)
return t[0:4] + '-' + t[4:6] + '-' + t[6:8] + ' ' + t[9:]
def to_unicode(object, encoding='utf8', errors='replace'):
@ -156,20 +162,23 @@ def seq_max_split(seq, max_entries):
def run_query(bz):
querydata = {}
bugdata = {}
interesting = {}
alldeps = set([])
closeddeps = set([])
needinfo = set([])
usermap = {}
querydata['include_fields'] = ['id', 'creation_time', 'last_change_time', 'bug_severity',
'alias', 'assigned_to', 'product', 'creator', 'creator_id', 'status', 'resolution',
'component', 'blocks', 'depends_on', 'summary',
'whiteboard', 'flags']
querydata['extra_values'] = []
#querydata['extra_values'] = []
querydata['bug_status'] = ['NEW', 'ASSIGNED', 'MODIFIED']
querydata['product'] = ['Fedora', 'Fedora EPEL']
querydata['component'] = ['Package Review']
querydata['query_format'] = 'advanced'
# Look up tickets with no flag set
# Look up tickets with no fedora-review flag set
querydata['f1'] = 'flagtypes.name'
querydata['o1'] = 'notregexp'
querydata['v1'] = 'fedora-review[-+?]'
@ -178,21 +187,40 @@ def run_query(bz):
for bug in bugs:
bugdata[bug.id] = {}
bugdata[bug.id]['hidden'] = 0
bugdata[bug.id]['needinfo'] = 0
bugdata[bug.id]['blocks'] = bug.blocks
bugdata[bug.id]['depends'] = bug.depends_on
bugdata[bug.id]['reviewflag'] = ' '
# Keep track of dependencies in unflagged tickets
# Keep track of "interesting" bugs for which we'll need to do complete
# lookups. We want anything with
if bug.depends_on:
alldeps.update(bug.depends_on)
# Get the status of each dependency
for i in seq_max_split(alldeps, 500):
for bug in bz.getbugssimple(i):
if bug.status == 'CLOSED':
closeddeps.add(bug.id)
if bug.flags.find('needinfo?') >= 0:
needinfo.add(bug.id)
# Some special processing for those unflagged tickets
# Get the status of each "interesting" bug
for i in seq_max_split(alldeps.union(needinfo), 500):
for bug in filter(None, bz._proxy.Bug.get_bugs({'ids':i, 'permissive': 1, 'extra_fields': ['flags']})['bugs']):
interesting[bug['id']] = bug
# Note the dependencies which are closed
for i in alldeps:
if interesting[i]['status'] == 'CLOSED':
closeddeps.add(i)
# Note the ones flagged needinfo->reporter
for i in needinfo:
for j in interesting[i]['flags']:
if (j['name'] == 'needinfo'
and j['status'] == '?'
and j['requestee'] == interesting[i]['creator']):
bugdata[i]['needinfo'] = 1
bugdata[i]['hidden'] = 1
# Hide tickets blocked by other bugs or whose with various blockers and
# statuses.
def opendep(id): return id not in closeddeps
for bug in bugs:
wb = string.lower(bug.whiteboard)
@ -206,6 +234,14 @@ def run_query(bz):
or filter(opendep, bugdata[bug.id]['depends']))):
bugdata[bug.id]['hidden'] = 1
# Now we need to look up the names of the users
for i in bugs:
if select_needsponsor(i, bugdata[i.id]):
usermap[i.reporter] = ''
for i in bz._proxy.User.get({'names': usermap.keys()})['users']:
usermap[i['name']] = i['real_name']
# Now process the other three flags; not much special processing for them
querydata['o1'] = 'equals'
# for i in ['-', '+', '?']:
@ -222,7 +258,7 @@ def run_query(bz):
bugs.sort(key=operator.attrgetter('id'))
return [bugs, bugdata]
return [bugs, bugdata, usermap]
# Need to generate reports:
# "Accepted" and closed
@ -267,6 +303,7 @@ def select_merge(bug, bugd):
def select_needsponsor(bug, bugd):
wb = string.lower(bug.whiteboard)
if (bugd['reviewflag'] == ' '
and bugd['needinfo'] == 0
and NEEDSPONSOR in bugd['blocks']
and LEGAL not in bugd['blocks']
and bug.bug_status != 'CLOSED'
@ -403,13 +440,13 @@ def report_merge(bugs, bugdata, loader, tmpdir, subs):
return data['count']
def report_needsponsor(bugs, bugdata, loader, tmpdir, subs):
# Note that this abuses the "month" view to group by reporter instead of month.
def report_needsponsor(bugs, bugdata, loader, usermap, tmpdir, subs):
data = deepcopy(subs)
data['description'] = 'This page lists all new NEEDSPONSOR tickets (those without the fedora-revlew flag set)'
data['description'] = 'This page lists all new NEEDSPONSOR tickets (those without the fedora-revlew flag set).'
data['title'] = 'NEEDSPONSOR tickets'
curreporter = ''
curcount = 0
oldest = {}
selected = []
for i in bugs:
@ -417,19 +454,31 @@ def report_needsponsor(bugs, bugdata, loader, tmpdir, subs):
selected.append(i)
selected.sort(key=reporter)
# Determine the oldest reported bug
for i in selected:
if i.reporter not in oldest:
oldest[i.reporter] = i.creation_time
elif i.creation_time < oldest[i.reporter]:
oldest[i.reporter] = i.creation_time
for i in selected:
rowclass = rowclass_plain(data['count'])
r = i.reporter;
if curreporter != reporter(i):
data['months'].append({'month': reporter(i), 'bugs': []})
curreporter = reporter(i)
if curreporter != r:
if (r in usermap and len(usermap[r])):
name = usermap[r]
else:
name = r
data['packagers'].append({'email': r, 'name': name, 'oldest': human_date(oldest[r]), 'bugs': []})
curreporter = r
curcount = 0
data['months'][-1]['bugs'].append(std_row(i, rowclass))
data['packagers'][-1]['bugs'].append(std_row(i, rowclass))
data['count'] +=1
curcount +=1
write_html(loader, 'bymonth.html', data, tmpdir, 'NEEDSPONSOR.html')
write_html(loader, 'needsponsor.html', data, tmpdir, 'NEEDSPONSOR.html')
return data['count']
@ -494,10 +543,10 @@ def report_new(bugs, bugdata, loader, tmpdir, subs):
if __name__ == '__main__':
options = parse_commandline()
config = parse_config(options.configfile)
#bz = bugzilla.Bugzilla(url=config['url'], cookiefile=None, user=config['username'], password=config['password'])
bz = bugzilla.Bugzilla(url=config['url'], cookiefile=None)
bz = bugzilla.RHBugzilla(url=config['url'], cookiefile=None, user=config['username'], password=config['password'])
#bz = bugzilla.RHBugzilla(url=config['url'], cookiefile=None)
t = time.time()
(bugs, bugdata) = run_query(bz)
(bugs, bugdata, usermap) = run_query(bz)
querytime = time.time() - t
# Don't bother running this stuff until the query completes, since it fails
@ -512,6 +561,7 @@ if __name__ == '__main__':
'version': VERSION,
'count': 0,
'months': [],
'packagers': [],
'bugs': [],
}
args = {'bugs':bugs, 'bugdata':bugdata, 'loader':loader, 'tmpdir':tmpdir, 'subs':subs}
@ -522,7 +572,7 @@ if __name__ == '__main__':
subs['epel'] = report_epel(**args)
subs['hidden'] = report_hidden(**args)
subs['merge'] = report_merge(**args)
subs['needsponsor'] = report_needsponsor(**args)
subs['needsponsor'] = report_needsponsor(usermap=usermap, **args)
subs['review'] = report_review(**args)
subs['trivial'] = report_trivial(**args)
# data['accepted_closed'] = report_accepted_closed(bugs, bugdata, loader, tmpdir)

View file

@ -0,0 +1,91 @@
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/"
xmlns:xi="http://www.w3.org/2001/XInclude">
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<base href="https://bugzilla.redhat.com/bugzilla/"/>
<title>$title</title>
<style type="text/css" media="screen">
.bz_state_NEEDSPONSOR {background-color: #AAFFAA}
.bz_state_FEATURE {background-color: #FFAAAA}
.bz_row_even {background-color: #FFFFFF}
.bz_row_odd {background-color: #EEEEEE}
#content
{
margin-left: 0ex!important;
}
td, th
{
border: none!important;
padding: 0.5ex 2ex!important;
}
</style>
<link rel="stylesheet" type="text/css" media="all"
href="http://fedoraproject.org/static/css/fedora.css" />
</head>
<body>
<div id="wrapper">
<div id="head">
<h1><a href="http://fedoraproject.org/index.html">Fedora</a></h1>
</div>
<div id="content">
<h2>$description</h2>
Click the name to find all comments made in any review tickets.<br/>
In parentheses is the date their oldest submission was made.<br/>
Last Update: $update (v$version)<br/>
There are $count tickets in this category<br/>
<table class="buglist" cellspacing="0" cellpadding="4" width="100%">
<thead>
<tr align="left">
<th>ID</th>
<th>Alias</th>
<th>Last Change</th>
<th>Summary</th>
</tr>
</thead>
<py:for each="packager in packagers">
<tr><td colspan="5"><b>
<a href="buglist.cgi?emaillongdesc1=1&amp;emailtype1=substring&amp;component=Package%20Review&amp;query_format=advanced&amp;email1=${packager['email']}">${packager['name']}</a> (${packager['oldest']})
</b></td></tr>
<py:for each="bug in packager['bugs']">
<tr class="${bug['class']}">
<td>
<a href="show_bug.cgi?id=${bug['id']}">${bug['id']}</a>
</td>
<td>${bug['alias']} </td>
<td>${bug['lastchange']}</td>
<td>${bug['summary']}</td>
</tr>
</py:for>
</py:for>
</table>
</div>
</div>
<div id="bottom">
<div id="footer">
<p class="copy">
&copy; 2012 Red Hat, Inc. and others.
Currently maintained by Jason Tibbitts; please send comments or questions to him or file tickets on <a href="https://fedorahosted.org/fedora-infrastructure/">the infrastructure trac</a>.
</p>
<p class="disclaimer">
The Fedora Project is maintained and driven by the community and sponsored by Red Hat. This is a community maintained site. Red Hat is not responsible for content.
</p>
<ul>
<li class="first"><a href="http://fedoraproject.org/wiki/Legal:Main">Legal</a></li>
<li><a href="http://fedoraproject.org/wiki/Legal:Trademark_guidelines">Trademark Guidelines</a></li>
</ul>
</div>
</div>
</body>
</html>