[Collab-qa-commits] r2040 - udd/web/cgi-bin
Stefano Rivera
stefanor at alioth.debian.org
Thu Sep 29 16:15:55 UTC 2011
Author: stefanor
Date: 2011-09-29 16:15:54 +0000 (Thu, 29 Sep 2011)
New Revision: 2040
Added:
udd/web/cgi-bin/bts-usertags.cgi
Log:
BTS Usertag browser
Added: udd/web/cgi-bin/bts-usertags.cgi
===================================================================
--- udd/web/cgi-bin/bts-usertags.cgi (rev 0)
+++ udd/web/cgi-bin/bts-usertags.cgi 2011-09-29 16:15:54 UTC (rev 2040)
@@ -0,0 +1,279 @@
+#!/usr/bin/env python
+# Browse usertags on the BTS
+# Copyright (C) 2011, Stefano Rivera <stefanor at debian.org>
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+
+import cgi
+import cgitb
+import re
+import urllib
+
+import psycopg2
+
+DATABASE = {'database': 'udd',
+ 'port': 5441,
+ 'host': 'localhost',
+ 'user': 'guest',
+ }
+
+
+class AttrDict(dict):
+ def __init__(self, **kwargs):
+ for key, value in kwargs.iteritems():
+ self[key] = value
+
+ def __getattr__(self, name):
+ try:
+ return self[name]
+ except KeyError, e:
+ raise AttributeError(e)
+
+
+def query(query, cols, *parameters):
+ conn = psycopg2.connect(**DATABASE)
+ cursor = conn.cursor()
+ cursor.execute(query, parameters)
+ for row in cursor.fetchall():
+ yield AttrDict(**dict(zip(cols, row)))
+ cursor.close()
+ conn.close()
+
+
+def strip_tags(soup):
+ return re.sub(r'<[^>]*?>', '', soup)
+
+
+def urlencode(params):
+ s = urllib.urlencode(params)
+ return re.sub(r'&(?!(\w+|#\d+);)', '&', s)
+
+
+def head(title):
+ head_title = 'Debian BTS Usertag Browser'
+ if title != 'Home':
+ head_title = title + ' — ' + head_title
+ print("""
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <style type="text/css">
+ label {
+ display: inline-block;
+ width: 5ex;
+ }
+ table {
+ border-collapse: collapse;
+ }
+ table, th, td {
+ border: 1px solid gray;
+ padding: 3px;
+ }
+ tr.done td {
+ text-decoration: line-through;
+ }
+ </style>
+ <title>%(head_title)s</title>
+</head>
+<body>
+<h1>%(title)s</h1>
+""".lstrip() % {
+ 'head_title': head_title,
+ 'title': title,
+ })
+
+
+def foot(linkhome=True):
+ if linkhome:
+ print '<p><a href="?">Home</a></p>'
+ print """<script type="text/javascript" src="../static/sorttable.js"></script>
+</body>
+</html>
+""".strip()
+
+
+def thead(*cols):
+ print '<table class="sortable">'
+ print ' <thead><tr>'
+ for col in cols:
+ print ' <th>%s</th>' % col
+ print ' </tr></thead>'
+
+
+def tr(*cols, **kwargs):
+ attrs = ['%s=%s' for attr in kwargs.get('attrs', {}).iteritems()]
+ print ' <tr%s>' % ' '.join(attrs)
+ for col in cols:
+ print ' <td>%s</td>' % col
+ print ' </tr>'
+
+
+def tfoot():
+ print '</table>'
+
+
+def index():
+ head("Home")
+ print("""
+<h2>Search</h2>
+<form action="?" accept-charset="UTF-8">
+ <label for="user">User:</label>
+ <input type="email" name="user" id="user"><br />
+ <label for="tag">Tag:</label>
+ <input type="text" name="tag" id="tag"><br />
+ <input type="submit" formnovalidate value="Search">
+</form>
+<h2>By Bug</h2>
+<form action="?" accept-charset="UTF-8">
+ <label for="bug">Bug:</label>
+ <input type="number" name="bug" id="bug" placeholder="Bug #"><br />
+ <input type="submit" value="Search">
+</form>
+<h2>Browse</h2>
+<ul>
+ <li><a href="?browse=users">By user</a></li>
+</ul>
+""".lstrip())
+ foot(False)
+
+
+def by_user(user):
+ r = query("""SELECT tag, COUNT(*) AS count
+ FROM bugs_usertags INNER JOIN bugs USING (id)
+ WHERE email = %s GROUP BY tag
+ """, ('tag', 'count'), user)
+ head('User %s' % strip_tags(user))
+ thead('Tag', 'Bugs')
+ for result in r:
+ tr('<a href="?%(params)s">%(tag)s</a>' % {
+ 'tag': result.tag,
+ 'params': urlencode({'user': user,
+ 'tag': result.tag}),
+ },
+ result.count)
+ tfoot()
+ foot()
+
+
+def tagged_bugs(user, tag):
+ r = query("""SELECT id, package, source, title, done != '' AS done
+ FROM bugs INNER JOIN bugs_usertags USING (id)
+ WHERE bugs_usertags.email = %s AND bugs_usertags.tag = %s
+ """, ('id', 'package', 'source', 'title', 'done'), user, tag)
+ head('Tagged %(tag)s by <a href="?%(params)s">%(user)s</a>'
+ % {
+ 'tag': strip_tags(tag),
+ 'user': strip_tags(user),
+ 'params': urlencode({'user': user}),
+ })
+ thead('Bug', 'Package', 'Title', 'Other tags')
+ for result in r:
+ attrs = {}
+ if result.done:
+ attrs['class'] = 'done'
+ tr('<a href="http://bugs.debian.org/%(id)s">#%(id)s</a>'
+ % {'id': result.id},
+ '<a href="http://packages.qa.debian.org/%(source)s">%(target)s</a>'
+ % {'source': result.source,
+ 'target': ('src:' if result.source == result.package else '')
+ + result.package,
+ },
+ result.title,
+ '<a href="?bug=%s">list usertags</a>' % result.id,
+ attrs=attrs)
+ tfoot()
+ foot()
+
+
+def search_result(user, tag):
+ r = query("""SELECT email, tag, COUNT(*) AS count
+ FROM bugs_usertags INNER JOIN bugs USING (id)
+ WHERE email LIKE %s AND tag LIKE %s GROUP BY email, tag
+ """, ('email', 'tag', 'count'), user, tag)
+ head('Search Result')
+ thead('User', 'Tag', 'Bugs')
+ for result in r:
+ tr('<a href="?%(params)s">%(email)s</a>' % {
+ 'email': result.email,
+ 'params': urlencode({'user': result.email}),
+ },
+ '<a href="?%(params)s">%(tag)s</a>' % {
+ 'tag': result.tag,
+ 'params': urlencode({'user': result.email,
+ 'tag': result.tag}),
+ },
+ result.count)
+ tfoot()
+ foot()
+
+
+def by_bug(bug):
+ r = query("SELECT email, tag FROM bugs_usertags WHERE id = %s",
+ ('email', 'tag'), bug)
+ head('Bug <a href="http://bugs.debian.org/%(bug)i">#%(bug)i</a>'
+ % {'bug': bug})
+ thead('User', 'Tag')
+ for result in r:
+ tr('<a href="?%(params)s">%(email)s</a>' % {
+ 'email': result.email,
+ 'params': urlencode({'user': result.email}),
+ },
+ '<a href="?%(params)s">%(tag)s</a>' % {
+ 'tag': result.tag,
+ 'params': urlencode({'user': result.email, 'tag': result.tag}),
+ })
+ tfoot()
+ foot()
+
+
+def user_list():
+ r = query("""SELECT email, COUNT(*) AS count
+ FROM bugs_usertags INNER JOIN bugs USING (id)
+ GROUP BY email""",
+ ('email', 'count'))
+ head('User List')
+ thead('User', 'Bugs')
+ for result in r:
+ tr('<a href="?%(params)s">%(email)s</a>' % {
+ 'email': result.email,
+ 'params': urlencode({'user': result.email}),
+ },
+ result.count)
+ tfoot()
+ foot()
+
+
+def main():
+ print 'Content-Type: text/html; charset=utf-8'
+ print ''
+ cgitb.enable()
+ form = cgi.FieldStorage()
+ if 'browse' in form and form.getfirst('browse', '') == 'users':
+ user_list()
+ elif 'user' in form or 'tag' in form:
+ user = form.getfirst('user', '*').replace('*', '%')
+ tag = form.getfirst('tag', '*').replace('*', '%')
+ if '%' not in user and tag == '%':
+ by_user(user)
+ elif '%' not in user and '%' not in tag:
+ tagged_bugs(user, tag)
+ else:
+ search_result(user, tag)
+ elif 'bug' in form and form.getfirst('bug', ''):
+ by_bug(int(form.getfirst('bug', '')))
+ else:
+ index()
+
+
+if __name__ == '__main__':
+ main()
Property changes on: udd/web/cgi-bin/bts-usertags.cgi
___________________________________________________________________
Added: svn:executable
+ *
More information about the Collab-qa-commits
mailing list