/
stats.py
65 lines (53 loc) · 1.89 KB
/
stats.py
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
"""
Various queries for grabbing interesting user stats from Trac.
"""
from __future__ import absolute_import
import operator
import django.db
from django.utils.datastructures import SortedDict
from .models import Revision, Ticket, TicketChange, Attachment
_statfuncs = []
def stat(title):
"""
Register a function as a "stat"
The function should take a username and return a number.
"""
def _inner(f):
_statfuncs.append(f)
f.title = title
return f
return _inner
def get_user_stats(username):
stats = SortedDict()
for func in sorted(_statfuncs, key=operator.attrgetter('title')):
stats[func.title] = func(username)
return stats
@stat('Commits')
def commit_count(username):
return Revision.objects.filter(author=username).count()
@stat('Tickets closed')
def tickets_closed(username):
# Raw query so that we can do COUNT(DISTINCT ticket).
q = """SELECT COUNT(DISTINCT ticket) FROM ticket_change
WHERE author = %s AND field = 'status' AND newvalue = 'closed';"""
return run_single_value_query(q, username)
@stat('Tickets opened')
def tickets_opened(username):
return Ticket.objects.filter(reporter=username).count()
@stat('New tickets reviewed')
def new_tickets_reviewed(username):
# We don't want to de-dup as for tickets_closed: multiple reviews of the
# same ticket should "count" as a review.
qs = TicketChange.objects.filter(author=username, field='stage', oldvalue='Unreviewed')
qs = qs.exclude(newvalue='Unreviewed')
return qs.count()
@stat('Patches submitted')
def patches_submitted(username):
return Attachment.objects.filter(author=username).count()
def run_single_value_query(query, *params):
"""
Helper: run a query returning a single value (e.g. a COUNT) and return the value.
"""
c = django.db.connections['trac'].cursor()
c.execute(query, params)
return c.fetchone()[0]