New submission from R David Murray <rdmur...@bitdance.com>:
I propose to alter the weekly roundup-summary email by breaking down the 'open'
category in the header issue summary into the subcategories 'enhancements' and
'bugs'. The idea is that you get what you measure, and if we see how many bugs
we are fixing versus enhancements we are committing, we might get a few more
bugs fixed.
The attached patch treats 'enhancment' and 'performance' as enhancements (yes,
I know performance issues can be bugs, but ones that really are bugs tend to
get fixed quickly), and everything else (including uncategorized) as bugs.
I'm sure we can make some progress on our bug count just by categorizing
uncategorized issues, but that will give us a better idea of how many unfixed
bugs we really have, which I think is useful info.
----------
files: bugs.patch
messages: 2419
nosy: ezio.melotti, r.david.murray
priority: feature
status: unread
title: Break down 'open' into 'enhancements' vs 'bugs' in roundup-summary
_______________________________________________________
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue446>
_______________________________________________________
--- /home/roundup/bin/roundup-summary 2010-11-02 16:58:22.000000000 +0100
+++ roundup-summary 2012-04-01 04:50:09.000000000 +0200
@@ -24,6 +24,10 @@
-r RESOLVED, --resolved=RESOLVED
Comma-delimited list of statuses that corresponds to
resolved (default: resolved,done,done-cbb,closed,faq).
+ -n ENHANCEMENT, --not-bug=ENHANCEMENT
+ Comma-delimited list of types that correspond to
+ issues that are enhancemnts, not bugs (default:
+ enhancement)
-o FILENAME, --output=FILENAME
File name for output; default is stdout.
-e FILENAME, --errors=FILENAME
@@ -60,9 +64,11 @@
Do NOT respond to this message.
Issues counts and deltas:
- open %(open)5d (%(open_delta)+3d)
- closed %(closed)5d (%(closed_delta)+3d)
- total %(total)5d (%(total_delta)+3d)
+ open %(open)5d (%(open_delta)+3d)
+ enhancements %(enhancements)5d (%(enhancements_delta)+3d)
+ bugs %(bugs)5d (%(bugs_delta)+3d)
+ closed %(closed)5d (%(closed_delta)+3d)
+ total %(total)5d (%(total_delta)+3d)
Open issues with patches: %(patches)-5d"""
@@ -79,6 +85,8 @@
<p>Issues stats:</p>
<table border="1">
<tr><th>open</th><td>%(open)5d (%(open_new)+3d)</td></tr>
+ <tr><th> enhancements</th></td>%s(enhancements)5d
(%s(enhancements_delta)+3d)</td></tr>
+ <tr><th>  ;bugs</th></td>%s(bugs)5d (%s(bugs_delta)+3d)</td></tr>
<tr><th>closed</th><td>%(closed)5d (%(closed_new)+3d)</td></tr>
<tr><th>total</th><td>%(total)5d (%(total_new)+3d)</td></tr>
</table>
@@ -93,6 +101,8 @@
"""
# list of statuses to treat as closed -- these don't have to all exist.
resolved_status_def = 'resolved,done,done-cbb,closed,faq'
+ # similar list of types to treat as enhancements, not bugs.
+ enhancement_type_def = 'enhancement,performance'
# period of time for report. Uses roundup syntax for ranges.
default_dates = '-1w;' # last week
# email address of recipient of report, if any.
@@ -120,6 +130,10 @@
help='Comma-delimited list of statuses that corresponds to resolved '
'(default: %default).')
advanced.add_option(
+ '-n', '--not-bug', dest='enhancements', default=enhancement_type_def,
+ help='Comma-delmited list of types that correspond to issues that '
+ 'are enhancements, not bugs (default: %default).')
+ advanced.add_option(
'-o', '--output', dest='output', metavar='FILENAME', default='',
help='File name for output; default is stdout.')
advanced.add_option(
@@ -144,6 +158,7 @@
'you must supply the path to a tracker home.')
options.dates = get_dates(options.dates)
options.resolved = [s.strip() for s in options.resolved.split(',')]
+ options.enhancements = [s.strip() for s in options.enhancements.split(',')]
instance_home = args[0]
return options, instance_home
@@ -208,9 +223,9 @@
start_str = start_date.pretty(format='%F') # %F -> yyyy-mm-dd
end_str = end_date.pretty(format='%F')
# counters for current values
- open_tot = closed_tot = all_tot = 0
+ open_tot = enhance_tot = closed_tot = all_tot = 0
# counters for previous values
- open_old = closed_old = all_old = 0
+ open_old = enhance_old = closed_old = all_old = 0
with_patch = 0
patch_id = DB.keyword.lookup('patch')
for id, issue in self.issues.iteritems():
@@ -218,6 +233,8 @@
if issue['creation'] > end_date:
continue
all_tot += 1
+ was_enhance = issue['last_period_type'] in OPTIONS.enhancements
+ is_enhance = issue['type'] in OPTIONS.enhancements
if issue['creation'] < start_date:
all_old += 1
# check if the issue was closed at the end of the previous
@@ -226,6 +243,9 @@
closed_old += 1
else:
open_old += 1
+ if was_enhance:
+ enhance_old += 1
+
# check if the issue is closed now
if issue['closed']:
closed_tot += 1
@@ -233,10 +253,16 @@
open_tot += 1
if patch_id in issue['keyword_ids']:
with_patch += 1
+ if is_enhance:
+ enhance_tot += 1
all_delta = all_tot - all_old
open_delta = open_tot - open_old
closed_delta = closed_tot - closed_old
assert all_delta == open_delta + closed_delta
+ enhance_delta = enhance_tot - enhance_old
+ bugs_tot = open_tot - enhance_tot
+ bugs_old = open_old - enhance_old
+ bugs_delta = bugs_tot - bugs_old
# save the values in an attribute to avoid calculating it twice
# when both the txt and the HTML header are needed (i.e. when sending
# HTML mails)
@@ -246,6 +272,8 @@
tracker_name=DB.config.TRACKER_NAME,
open=open_tot, open_delta=open_delta,
closed=closed_tot, closed_delta=closed_delta,
+ bugs=bugs_tot, bugs_delta=bugs_delta,
+ enhancements=enhance_tot, enhancements_delta=enhance_delta,
total=all_tot, total_delta=all_delta,
patches=with_patch,
)
@@ -505,6 +533,9 @@
status = None,
real_status = sid2name(attrs['status']), # Avoid a bug in
get_issue_attrs
last_period_status = None, # the status of the issue before start_date
+ type = '',
+ real_type = tid2name(attrs['type']),
+ last_period_type = None, # the type of the issue before start_date
actor = None,
activity = None,
keyword_ids = kwds,
@@ -524,6 +555,8 @@
status1 = sid2name(attrs['status']),
actor2 = attrs['actor'],
activity2 = attrs['activity'],
+ type2 = tid2name(attrs['type']),
+ type1 = tid2name(attrs['type']),
journal = journal
)
return issue, helper
@@ -545,13 +578,14 @@
return dates.to_value > issue['creation'] <= dates.from_value
def update(issue, helper):
- for key in ('status', 'actor', 'activity'):
+ for key in ('status', 'actor', 'activity', 'type'):
issue[key] = issue[key] or helper[key + '2']
# I'm not sure all this stuff is necessary, but it seems to work...
# this trick catches the first time we are in the interval of interest
if helper['activity2'] < dates.to_value:
update(issue, helper)
status_changes = []
+ type_changes = []
old_time = issue['creation']
for _, time, userid, act, data in helper['journal']:
in_period = dates.to_value > time >= dates.from_value
@@ -585,7 +619,12 @@
issue['real_status'] in OPTIONS.resolved):
issue['closer'] = userid
issue['closed_date'] = time
+ if 'type' in data:
+ helper['type1'] = tid2name(data['type'])
+ type_changes.append((old_time, helper['type1']))
+ old_time = time
status_changes.append((old_time, issue['real_status']))
+ type_changes.append((old_time, issue['real_type']))
# if the status didn't change and this is still None set it to 'open',
# leave it to None for new issues
if issue['creation'] < dates.from_value:
@@ -594,6 +633,11 @@
issue['last_period_status'] = status
if issue['last_period_status'] is None:
issue['last_period_status'] = 'open'
+ for time, type in type_changes:
+ if time < dates.from_value:
+ issue['last_period_type'] = type
+ if issue['last_period_type'] is None:
+ issue['last_period_type'] = issue['type']
# get these set if not done before
update(issue, helper)
last_opened = issue['reopened_date'] or issue['creation']
@@ -657,6 +701,13 @@
cache[status_id] = name
return name
+def tid2name(issue_type_id, cache={None:'none'}):
+ if issue_type_id in cache:
+ return cache[issue_type_id]
+ name = DB.issue_type.get(issue_type_id, 'name')
+ cache[issue_type_id] = name
+ return name
+
def uid2name(user_id, cache={None:'none'}):
if user_id in cache:
return cache[user_id]
_______________________________________________
Tracker-discuss mailing list
Tracker-discuss@python.org
http://mail.python.org/mailman/listinfo/tracker-discuss