summaryrefslogtreecommitdiff
path: root/tracdb
diff options
context:
space:
mode:
authorTim Graham <timograham@gmail.com>2014-08-25 10:14:24 -0400
committerTim Graham <timograham@gmail.com>2014-08-25 10:14:24 -0400
commita49a59ab78d5aa446feae8fe6c03bb9a150d41ef (patch)
tree5c3e39b8d36c038ed7922ba71c046adcb2c0bf18 /tracdb
parentb5a49087236453829f7bfddf572def606518c7af (diff)
Added flake8.cfg and cleaned up code.
Diffstat (limited to 'tracdb')
-rw-r--r--tracdb/db_router.py3
-rw-r--r--tracdb/models.py46
-rw-r--r--tracdb/stats.py12
-rw-r--r--tracdb/views.py13
4 files changed, 50 insertions, 24 deletions
diff --git a/tracdb/db_router.py b/tracdb/db_router.py
index c85ded89..61e578cc 100644
--- a/tracdb/db_router.py
+++ b/tracdb/db_router.py
@@ -5,11 +5,11 @@ queries against the "trac" DB alias.
It's very simplistic, leaving off allow_relation and allow_syncdb since all
the Trac apps are unmanaged.
"""
-
from unipath import FSPath as Path
THIS_APP = Path(__file__).parent.name
+
class TracRouter(object):
def db_for_read(self, model, **hints):
return 'trac' if app_label(model) == THIS_APP else None
@@ -20,5 +20,6 @@ class TracRouter(object):
def allow_syncdb(self, db, model):
return False if db == 'trac' else None
+
def app_label(model):
return model._meta.app_label
diff --git a/tracdb/models.py b/tracdb/models.py
index d993b7b9..d81049c2 100644
--- a/tracdb/models.py
+++ b/tracdb/models.py
@@ -43,14 +43,17 @@ And a few notes on tables that're left out and why:
* NodeChange: Ditto.
"""
+from __future__ import unicode_literals
-from __future__ import absolute_import
import datetime
+
from django.db import models
from django.utils.tzinfo import FixedOffset
+
_epoc = datetime.datetime(1970, 1, 1, tzinfo=FixedOffset(0))
+
class time_property(object):
"""
Convert Trac timestamps into UTC datetimes.
@@ -70,6 +73,7 @@ class time_property(object):
timestamp = getattr(instance, self.fieldname)
return _epoc + datetime.timedelta(microseconds=timestamp)
+
class Ticket(models.Model):
id = models.IntegerField(primary_key=True)
type = models.TextField()
@@ -95,11 +99,11 @@ class Ticket(models.Model):
keywords = models.TextField()
class Meta(object):
- db_table = u'ticket'
+ db_table = 'ticket'
managed = False
def __unicode__(self):
- return u"#%s: %s" % (self.id, self.summary)
+ return "#%s: %s" % (self.id, self.summary)
def __init__(self, *args, **kwargs):
super(Ticket, self).__init__(*args, **kwargs)
@@ -114,17 +118,19 @@ class Ticket(models.Model):
value = bool(int(value))
setattr(self, name, value)
+
class TicketCustom(models.Model):
ticket = models.ForeignKey(Ticket, related_name='custom_fields', db_column='ticket', primary_key=True)
name = models.TextField()
value = models.TextField()
class Meta(object):
- db_table = u'ticket_custom'
+ db_table = 'ticket_custom'
managed = False
def __unicode__(self):
- return u"%s: %s" % (self.name, self.value)
+ return "%s: %s" % (self.name, self.value)
+
class TicketChange(models.Model):
ticket = models.ForeignKey(Ticket, related_name='changes', db_column='ticket', primary_key=True)
@@ -137,39 +143,42 @@ class TicketChange(models.Model):
time = time_property('_time')
class Meta(object):
- db_table = u'ticket_change'
+ db_table = 'ticket_change'
managed = False
ordering = ['_time']
def __unicode__(self):
return "#%s: changed %s" % (self.ticket.id, self.field)
+
class Component(models.Model):
name = models.TextField(primary_key=True)
owner = models.TextField()
description = models.TextField()
class Meta(object):
- db_table = u'component'
+ db_table = 'component'
managed = False
def __unicode__(self):
return self.name
+
class Version(models.Model):
name = models.TextField(primary_key=True)
description = models.TextField()
- _time = models.BigIntegerField(db_column ='time')
+ _time = models.BigIntegerField(db_column='time')
time = time_property('_time')
class Meta(object):
- db_table = u'version'
+ db_table = 'version'
managed = False
def __unicode__(self):
return self.name
+
class Milestone(models.Model):
name = models.TextField(primary_key=True)
description = models.TextField()
@@ -181,12 +190,13 @@ class Milestone(models.Model):
completed = time_property('completed')
class Meta(object):
- db_table = u'milestone'
+ db_table = 'milestone'
managed = False
def __unicode__(self):
return self.name
+
class SingleRepoRevisionManager(models.Manager):
"""
Forces Revision to only query against a single repo, thus making
@@ -200,8 +210,10 @@ class SingleRepoRevisionManager(models.Manager):
qs = super(SingleRepoRevisionManager, self).get_queryset()
return qs.filter(repos=self.repo_id)
+
SINGLE_REPO_ID = 1
+
class Revision(models.Model):
repos = models.IntegerField()
rev = models.TextField(primary_key=True)
@@ -215,12 +227,13 @@ class Revision(models.Model):
objects = SingleRepoRevisionManager(repo_id=SINGLE_REPO_ID)
class Meta(object):
- db_table = u'revision'
+ db_table = 'revision'
managed = False
def __unicode__(self):
return '[%s] %s' % (self.rev, self.message.split('\n', 1)[0])
+
# The Wiki table uses a composite primary key (name, version). Since
# Django doesn't support this, this model sits on top of a simple view.
class Wiki(models.Model):
@@ -236,11 +249,12 @@ class Wiki(models.Model):
readonly = models.IntegerField()
class Meta:
- db_table = u'wiki_django_view'
+ db_table = 'wiki_django_view'
managed = False
def __unicode__(self):
- return u'%s (v%s)' % (self.name, self.version)
+ return '%s (v%s)' % (self.name, self.version)
+
# Same story as for Wiki: attachment's PK is (type, id, filename), so again
# there's a simple view this is on top of.
@@ -257,9 +271,9 @@ class Attachment(models.Model):
ipnr = models.TextField()
class Meta:
- db_table = u'attachment_django_view'
+ db_table = 'attachment_django_view'
managed = False
def __unicode__(self):
- attached_to = (u'#%s' % self.id) if self.type == 'ticket' else self.id
- return u'%s (on %s)' % (self.filename, attached_to)
+ attached_to = ('#%s' % self.id) if self.type == 'ticket' else self.id
+ return '%s (on %s)' % (self.filename, attached_to)
diff --git a/tracdb/stats.py b/tracdb/stats.py
index 478d35da..ed3ac2a3 100644
--- a/tracdb/stats.py
+++ b/tracdb/stats.py
@@ -1,15 +1,16 @@
"""
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"
@@ -23,16 +24,19 @@ def stat(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).
@@ -40,10 +44,12 @@ def tickets_closed(username):
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
@@ -52,10 +58,12 @@ def new_tickets_reviewed(username):
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.
diff --git a/tracdb/views.py b/tracdb/views.py
index c2fba15a..6dd07907 100644
--- a/tracdb/views.py
+++ b/tracdb/views.py
@@ -1,8 +1,10 @@
import datetime
-from django.shortcuts import render
+
from django import db
+from django.shortcuts import render
from django.utils.tzinfo import FixedOffset
+
def bouncing_tickets(request):
c = db.connections['trac'].cursor()
c.execute("""SELECT * FROM bouncing_tickets
@@ -14,15 +16,16 @@ def bouncing_tickets(request):
for t in tickets:
t['last_reopen_time'] = ts2dt(t['last_reopen_time'])
- return render(request,
- 'tracdb/bouncing_tickets.html',
- {'tickets': tickets}
- )
+ return render(request, 'tracdb/bouncing_tickets.html', {
+ 'tickets': tickets,
+ })
+
def ts2dt(ts):
epoc = datetime.datetime(1970, 1, 1, tzinfo=FixedOffset(0))
return epoc + datetime.timedelta(microseconds=ts)
+
def dictfetchall(cursor):
desc = cursor.description
return [