diff options
| author | Tim Graham <timograham@gmail.com> | 2014-08-25 10:14:24 -0400 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2014-08-25 10:14:24 -0400 |
| commit | a49a59ab78d5aa446feae8fe6c03bb9a150d41ef (patch) | |
| tree | 5c3e39b8d36c038ed7922ba71c046adcb2c0bf18 /tracdb | |
| parent | b5a49087236453829f7bfddf572def606518c7af (diff) | |
Added flake8.cfg and cleaned up code.
Diffstat (limited to 'tracdb')
| -rw-r--r-- | tracdb/db_router.py | 3 | ||||
| -rw-r--r-- | tracdb/models.py | 46 | ||||
| -rw-r--r-- | tracdb/stats.py | 12 | ||||
| -rw-r--r-- | tracdb/views.py | 13 |
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 [ |
