~deryck/lpmedic/trunk

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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#!/usr/bin/env python
"""
A script to help triage Launchpad bugs.
"""

from optparse import OptionParser
import sys

from launchpadlib.launchpad import Launchpad, uris

def get_suggested_importance(result):
    scale = {
        (1, 6): u'Low',
        (7, 11): u'High',
    }
    for index in scale:
        if index[0] <= result <= index[1]:
            return scale[index]

questions = {
    1: {
        'Can this bug be confirmed? [yes, no, neither]':
            {'yes': 1, 'no': -1, 'neither': 0},
    },
    2: {
        'Is this bug new? [yes, no]':
            {'yes': 1, 'no': 0},
    },
    3: {
        'Is the area in scope for the next 6 months? [yes, no, neither]':
            {'yes': 1, 'no': -1, 'neither': 0},
    },
    4: {
        'How likely is a quick/easy fix? [very, somewhat, unsure, not]':
            {'very': 2, 'somewhat': 1, 'unsure': 0, 'not': -1},
    },
    5: {
        'How many people does this affect? [everyone, many, some, none]':
            {'everyone': 2, 'many': 1, 'some': 0, 'none': -1},
    },
    6: {
        'Are their workarounds? [always, sometimes, never]':
            {'always': -1, 'sometimes': 0, 'never': 1},
    },
    7: {
        'Is this an OOPS/Timeout? [yes, no]':
            {'yes': 1, 'no': 0},
    },
    8: {
        'How prominent is the affected feature? [very, somewhat, not]':
            {'very': 2, 'somewhat': 1, 'not': 0}
    },
}

def rank_bug():
    total = 0
    keys = questions.keys()
    keys.sort()
    for question_num in keys:
        question = questions[question_num]
        answer = raw_input('%s ' % question.keys()[0])
        val = question.values()[0][answer]
        print 'Adding %d to count' % val
        total += val
    return total

def main(argv=None):
    if argv is None:
        argv = sys.argv

    usage = """%s: [PROJECT]\n%s""" % (argv[0], __doc__)

    parser = OptionParser(usage=usage)
    parser.add_option(
        '-s', '--system', default='edge', dest='lpsystem',
        help=(
            "The Launchpad system to use.  Must be one of %s. "
            "Defaults to 'edge'." % sorted(uris.service_roots.keys())))
    parser.add_option(
        '-b', '--bug', dest='lpbug', metavar='BUG_ID', type='int',
        help='Triage a single bug instead of all open bugs.')
    parser.add_option(
        '-t', '--tag', dest='tag', metavar='TAG',
        help='Triage bugs with this tag.')
    options, args = parser.parse_args(args=argv)

    if len(args) != 2:
        parser.error('A project name must be supplied.')

    if options.lpbug and options.tag:
        parser.error('You can only specify either a bug ID or a tag.')

    project = args[1]

    launchpad = Launchpad.login_with('lpmedic', options.lpsystem)
    lp_project = launchpad.projects[project]

    if options.lpbug:
        new_bugs = [launchpad.bugs[options.lpbug]]
    elif options.tag:
        new_bugs = lp_project.searchTasks(
            tags=options.tag, order_by='-datecreated')
    else:
        new_bugs = lp_project.searchTasks(
            status='New', order_by='-datecreated')

    for item in new_bugs:
        # XXX: deryck
        # The logic should be refactored to not assume
        # this is a bugtask, but to get single bugs working,
        # work from the correct bugtask on a bug.
        if hasattr(item, 'bug'):
            task = item
        else:
            task = [
                bt for bt in item.bug_tasks
                if bt.bug_target_name == project][0]

        print 'Title: %s' % task.bug.title
        print 'Status: %s, Importance: %s' % (
            task.status, task.importance)
        if task.assignee:
            assignee = task.assignee.display_name
        else:
            assignee = task.assignee
        print 'Assignee: %s, Milestone: %s' % (assignee, task.milestone)
        print '%d affected users' % task.bug.users_affected_count
        print 'Reported by %s (%s) on %s:' % (
            task.bug.owner.display_name, task.bug.owner.name,
            task.bug.date_created)
        print 'Description:\n%s' % task.bug.description
        if task.bug.messages.total_size > 1:
            print 'Comments:'
            for message in task.bug.messages:
                if message.content != task.bug.description:
                    print '---------------------------------------------'
                    print '%s (%s) wrote on %s' % (
                        message.owner.display_name, message.owner.name,
                        message.date_created)
                    print message.content
        print 'Bug link: https://bugs.launchpad.net/bugs/%s/' % task.bug.id
        print
        do_bug = raw_input('Triage this bug? [Y/n] ')
        if do_bug.lower() == 'y' or do_bug == '':
            print
            rank = rank_bug()
            print 'This bug has been ranked at: %d' % rank
            suggested_importance = get_suggested_importance(rank)
            if suggested_importance is not None:
                do_importance = raw_input(
                    'Set this bug to %s? [y/N] ' % suggested_importance)
                if do_importance.lower() == 'y':
                    if task.status != u'Triaged':
                        task.status = u'Triaged'
                    task.importance = suggested_importance
                    task.lp_save()
                    print 'Set bug %d to (Triaged, %s)' % (
                        task.bug.id, suggested_importance)
                    go_again = raw_input('Continue triaging bugs? [Y/n] ')
                    if go_again == '' or go_again.lower() == 'y':
                        continue
                    else:
                        print 'Thanks for doing some bug triage!'
                        return 0
                else:
                    continue
            else:
                print 'Unable to rank importance for bug %s.' % task.bug.id
        else:
            print
            continue
    print 'Thanks for doing some bug triage bugs!'
    return 0

if __name__ == '__main__':
    try:
        sys.exit(main())
    except KeyboardInterrupt:
        print
        print 'Thanks for doing some bug triage!'