OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 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 about the review you done, or forgot to do. | 6 """Get rietveld stats about the review you done, or forgot to do. |
7 | 7 |
8 Example: | 8 Example: |
9 - my_reviews.py -r me@chromium.org -Q for stats for last quarter. | 9 - my_reviews.py -r me@chromium.org -Q for stats for last quarter. |
10 """ | 10 """ |
11 import datetime | 11 import datetime |
12 import math | 12 import math |
13 import optparse | 13 import optparse |
14 import os | 14 import os |
15 import sys | 15 import sys |
16 | 16 |
| 17 import auth |
17 import rietveld | 18 import rietveld |
18 | 19 |
19 | 20 |
20 def username(email): | 21 def username(email): |
21 """Keeps the username of an email address.""" | 22 """Keeps the username of an email address.""" |
22 return email.split('@', 1)[0] | 23 return email.split('@', 1)[0] |
23 | 24 |
24 | 25 |
25 def to_datetime(string): | 26 def to_datetime(string): |
26 """Load UTC time as a string into a datetime object.""" | 27 """Load UTC time as a string into a datetime object.""" |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 # More information is available, print issue.keys() to see them. | 208 # More information is available, print issue.keys() to see them. |
208 print '%7d %10s %3s %14s %-15s %s' % ( | 209 print '%7d %10s %3s %14s %-15s %s' % ( |
209 issue['issue'], | 210 issue['issue'], |
210 issue['created'][:10], | 211 issue['created'][:10], |
211 reviewed, | 212 reviewed, |
212 latency, | 213 latency, |
213 issue['owner_email'], | 214 issue['owner_email'], |
214 ', '.join(sorted(issue['reviewers']))) | 215 ', '.join(sorted(issue['reviewers']))) |
215 | 216 |
216 | 217 |
217 def print_reviews(reviewer, created_after, created_before, instance_url): | 218 def print_reviews( |
| 219 reviewer, created_after, created_before, instance_url, auth_config): |
218 """Prints issues |reviewer| received and potentially reviewed.""" | 220 """Prints issues |reviewer| received and potentially reviewed.""" |
219 remote = rietveld.Rietveld(instance_url, None, None) | 221 remote = rietveld.Rietveld(instance_url, auth_config) |
220 | 222 |
221 # The stats we gather. Feel free to send me a CL to get more stats. | 223 # The stats we gather. Feel free to send me a CL to get more stats. |
222 stats = Stats() | 224 stats = Stats() |
223 | 225 |
224 # Column sizes need to match print_issue() output. | 226 # Column sizes need to match print_issue() output. |
225 print >> sys.stderr, ( | 227 print >> sys.stderr, ( |
226 'Issue Creation Did Latency Owner Reviewers') | 228 'Issue Creation Did Latency Owner Reviewers') |
227 | 229 |
228 # See def search() in rietveld.py to see all the filters you can use. | 230 # See def search() in rietveld.py to see all the filters you can use. |
229 issues = [] | 231 issues = [] |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 ' gave multiple LGTMs on %d issues.') % ( | 263 ' gave multiple LGTMs on %d issues.') % ( |
262 stats.lgtms, stats.percent_lgtm, stats.multiple_lgtms)) | 264 stats.lgtms, stats.percent_lgtm, stats.multiple_lgtms)) |
263 print >> sys.stderr, ( | 265 print >> sys.stderr, ( |
264 'Average latency from request to first comment is %s.' % | 266 'Average latency from request to first comment is %s.' % |
265 to_time(stats.average_latency)) | 267 to_time(stats.average_latency)) |
266 print >> sys.stderr, ( | 268 print >> sys.stderr, ( |
267 'Median latency from request to first comment is %s.' % | 269 'Median latency from request to first comment is %s.' % |
268 to_time(stats.median_latency)) | 270 to_time(stats.median_latency)) |
269 | 271 |
270 | 272 |
271 def print_count(reviewer, created_after, created_before, instance_url): | 273 def print_count( |
272 remote = rietveld.Rietveld(instance_url, None, None) | 274 reviewer, created_after, created_before, instance_url, auth_config): |
| 275 remote = rietveld.Rietveld(instance_url, auth_config) |
273 print len(list(remote.search( | 276 print len(list(remote.search( |
274 reviewer=reviewer, | 277 reviewer=reviewer, |
275 created_after=created_after, | 278 created_after=created_after, |
276 created_before=created_before, | 279 created_before=created_before, |
277 keys_only=True))) | 280 keys_only=True))) |
278 | 281 |
279 | 282 |
280 def get_previous_quarter(today): | 283 def get_previous_quarter(today): |
281 """There are four quarters, 01-03, 04-06, 07-09, 10-12. | 284 """There are four quarters, 01-03, 04-06, 07-09, 10-12. |
282 | 285 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 parser.add_option( | 328 parser.add_option( |
326 '-e', '--end', metavar='<date>', | 329 '-e', '--end', metavar='<date>', |
327 help='Filter issues created before the date') | 330 help='Filter issues created before the date') |
328 parser.add_option( | 331 parser.add_option( |
329 '-Q', '--last_quarter', action='store_true', | 332 '-Q', '--last_quarter', action='store_true', |
330 help='Use last quarter\'s dates, e.g. %s to %s' % (begin, end)) | 333 help='Use last quarter\'s dates, e.g. %s to %s' % (begin, end)) |
331 parser.add_option( | 334 parser.add_option( |
332 '-i', '--instance_url', metavar='<host>', | 335 '-i', '--instance_url', metavar='<host>', |
333 default='http://codereview.chromium.org', | 336 default='http://codereview.chromium.org', |
334 help='Host to use, default is %default') | 337 help='Host to use, default is %default') |
| 338 auth.add_auth_options(parser) |
335 # Remove description formatting | 339 # Remove description formatting |
336 parser.format_description = ( | 340 parser.format_description = ( |
337 lambda _: parser.description) # pylint: disable=E1101 | 341 lambda _: parser.description) # pylint: disable=E1101 |
338 options, args = parser.parse_args() | 342 options, args = parser.parse_args() |
| 343 auth_config = auth.extract_auth_config_from_options(options) |
339 if args: | 344 if args: |
340 parser.error('Args unsupported') | 345 parser.error('Args unsupported') |
341 if options.reviewer is None: | 346 if options.reviewer is None: |
342 parser.error('$EMAIL_ADDRESS and $USER are not set, please use -r') | 347 parser.error('$EMAIL_ADDRESS and $USER are not set, please use -r') |
343 | 348 |
344 print >> sys.stderr, 'Searching for reviews by %s' % options.reviewer | 349 print >> sys.stderr, 'Searching for reviews by %s' % options.reviewer |
345 if options.last_quarter: | 350 if options.last_quarter: |
346 options.begin = begin | 351 options.begin = begin |
347 options.end = end | 352 options.end = end |
348 print >> sys.stderr, 'Using range %s to %s' % ( | 353 print >> sys.stderr, 'Using range %s to %s' % ( |
349 options.begin, options.end) | 354 options.begin, options.end) |
350 else: | 355 else: |
351 if options.begin is None or options.end is None: | 356 if options.begin is None or options.end is None: |
352 parser.error('Please specify either --last_quarter or --begin and --end') | 357 parser.error('Please specify either --last_quarter or --begin and --end') |
353 | 358 |
354 # Validate dates. | 359 # Validate dates. |
355 try: | 360 try: |
356 to_datetime(options.begin) | 361 to_datetime(options.begin) |
357 to_datetime(options.end) | 362 to_datetime(options.end) |
358 except ValueError as e: | 363 except ValueError as e: |
359 parser.error('%s: %s - %s' % (e, options.begin, options.end)) | 364 parser.error('%s: %s - %s' % (e, options.begin, options.end)) |
360 | 365 |
361 if options.count: | 366 if options.count: |
362 print_count( | 367 print_count( |
363 options.reviewer, | 368 options.reviewer, |
364 options.begin, | 369 options.begin, |
365 options.end, | 370 options.end, |
366 options.instance_url) | 371 options.instance_url, |
| 372 auth_config) |
367 else: | 373 else: |
368 print_reviews( | 374 print_reviews( |
369 options.reviewer, | 375 options.reviewer, |
370 options.begin, | 376 options.begin, |
371 options.end, | 377 options.end, |
372 options.instance_url) | 378 options.instance_url, |
| 379 auth_config) |
373 return 0 | 380 return 0 |
374 | 381 |
375 | 382 |
376 if __name__ == '__main__': | 383 if __name__ == '__main__': |
377 try: | 384 try: |
378 sys.exit(main()) | 385 sys.exit(main()) |
379 except KeyboardInterrupt: | 386 except KeyboardInterrupt: |
380 sys.stderr.write('interrupted\n') | 387 sys.stderr.write('interrupted\n') |
381 sys.exit(1) | 388 sys.exit(1) |
OLD | NEW |