Skip to content

Commit

Permalink
Added a "bounceing ticket" view.
Browse files Browse the repository at this point in the history
This gives us some visibility into tickets that bounce back and forth between
closed and wontfix.
  • Loading branch information
jacobian committed May 16, 2013
1 parent 86bf580 commit 1c20f09
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 3 deletions.
4 changes: 4 additions & 0 deletions django_www/urls.py
Expand Up @@ -47,6 +47,10 @@
# django-push # django-push
url(r'^subscriber/', include('django_push.subscriber.urls')), url(r'^subscriber/', include('django_push.subscriber.urls')),


# Trac schtuff
url(r'^trac/', include('tracdb.urls')),


url(r'^sitemap\.xml$', cache_page(60 * 60 * 6)(sitemap_views.sitemap), {'sitemaps': sitemaps}), url(r'^sitemap\.xml$', cache_page(60 * 60 * 6)(sitemap_views.sitemap), {'sitemaps': sitemaps}),
url(r'^weblog/', include('blog.urls')), url(r'^weblog/', include('blog.urls')),
url(r'^download/', include('releases.urls')), url(r'^download/', include('releases.urls')),
Expand Down
7 changes: 4 additions & 3 deletions fabfile.py
Expand Up @@ -85,11 +85,12 @@ def update_docs():
""" """
managepy('update_docs -v2', site='docs') managepy('update_docs -v2', site='docs')


def copy_db(): def copy_dbs():
""" """
Copy the production DB locally for testing. Copy the production DBs locally for testing.
""" """
local('ssh %s pg_dump -U djangoproject -c djangoproject | psql djangoproject' % env.hosts[0]) for db in ('djangoproject', 'code.djangoproject'):
local('ssh %s pg_dump -U %s -c %s | psql %s' % (env.hosts[0], db, db, db))


def copy_docs(): def copy_docs():
""" """
Expand Down
32 changes: 32 additions & 0 deletions templates/tracdb/bouncing_tickets.html
@@ -0,0 +1,32 @@
{% extends "base_community.html" %}

{% block content-related %}{% endblock %}

{% block title %}Bouncing Tickets{% endblock %}

{% block content %}

<h1>Bouncing Tickets</h1>

<h2 class="deck">Tickets that have been repeatedly reopened.</h2>

<table width="90%" class="docutils">
<thead>
<tr>
<th>Ticket</th>
<th>Times reopened</th>
<th>Last reopened</th>
</tr>
</thead>
<tbody>
{% for t in tickets %}
<tr>
<td><a href="http://code.djangoproject.com/ticket/{{ t.id }}">#{{ t.id }}: {{ t.summary|truncatewords:10 }}</a></td>
<td>{{ t.times_reopened }}</td>
<td>{{ t.last_reopen_time|date:"F j, Y" }}</td>
</tr>
{% endfor %}
</tbody>
</table>

{% endblock %}
35 changes: 35 additions & 0 deletions tracdb/migrations/0002_bouncing_tickets_view.py
@@ -0,0 +1,35 @@
from south.db import dbs
from south.v2 import SchemaMigration

#
# Create a database view for "bouncing" tickets - tickets that change their
# state from closed back to open, possibly a number of times.
#

class Migration(SchemaMigration):
viewname = "bouncing_tickets"
viewquery = """
SELECT
ticket.id,
ticket.summary,
COUNT(*) AS times_reopened,
MAX(change.time) AS last_reopen_time
FROM ticket_change AS change
JOIN ticket ON change.ticket = ticket.id
WHERE
change.field = 'status'
AND change.oldvalue = 'closed'
AND change.newvalue != 'closed'
AND ticket.resolution = 'wontfix'
GROUP BY ticket.id;
"""

def forwards(self, orm):
db = dbs['trac']
db.execute("CREATE VIEW %s AS %s" % (self.viewname, self.viewquery))
db.execute('COMMIT')

def backwards(self, orm):
db = dbs['trac']
db.execute("DROP VIEW %s" % self.viewname)
db.execute('COMMIT')
10 changes: 10 additions & 0 deletions tracdb/urls.py
@@ -0,0 +1,10 @@
from django.conf.urls import patterns, url
from . import views

urlpatterns = patterns('',
url(
r'^bouncing/$',
views.bouncing_tickets,
name='bouncing_tickets',
),
)
31 changes: 31 additions & 0 deletions tracdb/views.py
@@ -0,0 +1,31 @@
import datetime
from django.shortcuts import render
from django import db
from django.utils.tzinfo import FixedOffset

def bouncing_tickets(request):
c = db.connections['trac'].cursor()
c.execute("""SELECT * FROM bouncing_tickets
WHERE times_reopened >= 3
ORDER BY last_reopen_time DESC""")
tickets = dictfetchall(c)

# Fix timestamps. LOLTrac.
for t in tickets:
t['last_reopen_time'] = ts2dt(t['last_reopen_time'])

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 [
dict(zip([col[0] for col in desc], row))
for row in cursor.fetchall()
]

0 comments on commit 1c20f09

Please sign in to comment.