OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Get rietveld stats. | 6 """Get rietveld stats about the review you done, or forgot to do. |
7 | 7 |
8 Example: | 8 Example: |
9 - my_reviews.py -o me@chromium.org -Q for stats for last quarter. | 9 - my_reviews.py -o me@chromium.org -Q for stats for last quarter. |
10 """ | 10 """ |
11 import datetime | 11 import datetime |
12 import optparse | 12 import optparse |
13 import os | 13 import os |
14 import sys | 14 import sys |
15 | 15 |
16 import rietveld | 16 import rietveld |
17 | 17 |
18 | 18 |
19 def print_reviews(owner, reviewer, created_after, created_before, instance_url): | 19 def username(email): |
20 """Prints issues with the filter. | 20 return email.split('@', 1)[0] |
21 | 21 |
22 Set with_messages=True to search() call bellow if you want each message too. | 22 |
23 If you only want issue numbers, use keys_only=True in the search() call. | 23 def print_reviews(reviewer, created_after, created_before, instance_url): |
24 You can then use remote.get_issue_properties(issue, True) to get the data per | 24 """Prints issues the dude reviewed.""" |
25 issue. | |
26 """ | |
27 remote = rietveld.Rietveld(instance_url, None, None) | 25 remote = rietveld.Rietveld(instance_url, None, None) |
| 26 total = 0 |
| 27 actually_reviewed = 0 |
28 | 28 |
29 # See def search() in rietveld.py to see all the filters you can use. | 29 # See def search() in rietveld.py to see all the filters you can use. |
30 for issue in remote.search( | 30 for issue in remote.search( |
31 owner=owner, | |
32 reviewer=reviewer, | 31 reviewer=reviewer, |
33 created_after=created_after, | 32 created_after=created_after, |
34 created_before=created_before, | 33 created_before=created_before, |
35 keys_only=False, | 34 with_messages=True, |
36 with_messages=False, | |
37 ): | 35 ): |
| 36 total += 1 |
38 # By default, hide commit-bot and the domain. | 37 # By default, hide commit-bot and the domain. |
39 reviewers = set(r.split('@', 1)[0] for r in issue['reviewers']) | 38 reviewers = set(username(r) for r in issue['reviewers']) |
40 reviewers -= set(('commit-bot',)) | 39 reviewers -= set(['commit-bot']) |
41 # Strip time. | 40 # Strip time. |
42 timestamp = issue['created'][:10] | 41 timestamp = issue['created'][:10] |
| 42 if any( |
| 43 username(msg['sender']) == username(reviewer) |
| 44 for msg in issue['messages']): |
| 45 reviewed = ' x ' |
| 46 actually_reviewed += 1 |
| 47 else: |
| 48 reviewed = ' ' |
43 | 49 |
44 # More information is available, print issue.keys() to see them. | 50 # More information is available, print issue.keys() to see them. |
45 print '%d: %s %s' % (issue['issue'], timestamp, ', '.join(reviewers)) | 51 print '%7d %s %s O:%-15s R:%s' % ( |
| 52 issue['issue'], |
| 53 timestamp, |
| 54 reviewed, |
| 55 username(issue['owner_email']), |
| 56 ', '.join(reviewers)) |
| 57 percent = 0. |
| 58 if total: |
| 59 percent = (actually_reviewed * 100. / total) |
| 60 print 'You actually reviewed %d issues out of %d (%1.1f%%)' % ( |
| 61 actually_reviewed, total, percent) |
46 | 62 |
47 | 63 |
48 def print_count(owner, reviewer, created_after, created_before, instance_url): | 64 def print_count(reviewer, created_after, created_before, instance_url): |
49 remote = rietveld.Rietveld(instance_url, None, None) | 65 remote = rietveld.Rietveld(instance_url, None, None) |
50 print len(list(remote.search( | 66 print len(list(remote.search( |
51 owner=owner, | |
52 reviewer=reviewer, | 67 reviewer=reviewer, |
53 created_after=created_after, | 68 created_after=created_after, |
54 created_before=created_before, | 69 created_before=created_before, |
55 keys_only=False))) | 70 keys_only=True))) |
56 | 71 |
57 | 72 |
58 def get_previous_quarter(today): | 73 def get_previous_quarter(today): |
59 """There are four quarters, 01-03, 04-06, 07-09, 10-12. | 74 """There are four quarters, 01-03, 04-06, 07-09, 10-12. |
60 | 75 |
61 If today is in the last month of a quarter, assume it's the current quarter | 76 If today is in the last month of a quarter, assume it's the current quarter |
62 that is requested. | 77 that is requested. |
63 """ | 78 """ |
64 year = today.year | 79 year = today.year |
65 month = today.month - (today.month % 3) + 1 | 80 month = today.month - (today.month % 3) + 1 |
(...skipping 16 matching lines...) Expand all Loading... |
82 def main(): | 97 def main(): |
83 # Silence upload.py. | 98 # Silence upload.py. |
84 rietveld.upload.verbosity = 0 | 99 rietveld.upload.verbosity = 0 |
85 today = datetime.date.today() | 100 today = datetime.date.today() |
86 created_after, created_before = get_previous_quarter(today) | 101 created_after, created_before = get_previous_quarter(today) |
87 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__) | 102 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__) |
88 parser.add_option( | 103 parser.add_option( |
89 '--count', action='store_true', | 104 '--count', action='store_true', |
90 help='Just count instead of printing individual issues') | 105 help='Just count instead of printing individual issues') |
91 parser.add_option( | 106 parser.add_option( |
92 '-o', '--owner', metavar='<email>', help='Filter on issue owner') | 107 '-r', '--reviewer', metavar='<email>', |
93 parser.add_option( | 108 default=os.environ.get('EMAIL_ADDRESS'), |
94 '-r', '--reviewer', metavar='<email>', help='Filter on issue reviewer') | 109 help='Filter on issue reviewer, default=%default') |
95 parser.add_option( | 110 parser.add_option( |
96 '-c', '--created_after', metavar='<date>', | 111 '-c', '--created_after', metavar='<date>', |
97 help='Filter issues created after the date') | 112 help='Filter issues created after the date') |
98 parser.add_option( | 113 parser.add_option( |
99 '-C', '--created_before', metavar='<date>', | 114 '-C', '--created_before', metavar='<date>', |
100 help='Filter issues create before the date') | 115 help='Filter issues create before the date') |
101 parser.add_option( | 116 parser.add_option( |
102 '-Q', '--last_quarter', action='store_true', | 117 '-Q', '--last_quarter', action='store_true', |
103 help='Use last quarter\'s dates, e.g. %s to %s' % ( | 118 help='Use last quarter\'s dates, e.g. %s to %s' % ( |
104 created_after, created_before)) | 119 created_after, created_before)) |
105 parser.add_option( | 120 parser.add_option( |
106 '-i', '--instance_url', metavar='<host>', | 121 '-i', '--instance_url', metavar='<host>', |
107 default='http://codereview.chromium.org', | 122 default='http://codereview.chromium.org', |
108 help='Host to use, default is %default') | 123 help='Host to use, default is %default') |
109 # Remove description formatting | 124 # Remove description formatting |
110 parser.format_description = lambda x: parser.description | 125 parser.format_description = lambda x: parser.description |
111 options, args = parser.parse_args() | 126 options, args = parser.parse_args() |
112 if args: | 127 if args: |
113 parser.error('Args unsupported') | 128 parser.error('Args unsupported') |
114 if not options.owner and not options.reviewer: | 129 |
115 options.owner = os.environ['EMAIL_ADDRESS'] | 130 print >> sys.stderr, 'Searching for reviews by %s' % options.reviewer |
116 if '@' not in options.owner: | |
117 parser.error('Please specify at least -o or -r') | |
118 print >> sys.stderr, 'Defaulting to owner=%s' % options.owner | |
119 if options.last_quarter: | 131 if options.last_quarter: |
120 options.created_after = created_after | 132 options.created_after = created_after |
121 options.created_before = created_before | 133 options.created_before = created_before |
122 print >> sys.stderr, 'Using range %s to %s' % ( | 134 print >> sys.stderr, 'Using range %s to %s' % ( |
123 options.created_after, options.created_before) | 135 options.created_after, options.created_before) |
124 if options.count: | 136 if options.count: |
125 print_count( | 137 print_count( |
126 options.owner, options.reviewer, | 138 options.reviewer, |
127 options.created_after, options.created_before, | 139 options.created_after, |
| 140 options.created_before, |
128 options.instance_url) | 141 options.instance_url) |
129 else: | 142 else: |
130 print_reviews( | 143 print_reviews( |
131 options.owner, options.reviewer, | 144 options.reviewer, |
132 options.created_after, options.created_before, | 145 options.created_after, |
| 146 options.created_before, |
133 options.instance_url) | 147 options.instance_url) |
134 return 0 | 148 return 0 |
135 | 149 |
136 | 150 |
137 if __name__ == '__main__': | 151 if __name__ == '__main__': |
138 sys.exit(main()) | 152 sys.exit(main()) |
OLD | NEW |