summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagnus Hagander2019-02-05 22:55:23 +0000
committerMagnus Hagander2019-02-06 09:29:00 +0000
commit463b3c1fe2e5bea061269ed9eea4b876a9eab213 (patch)
treec7f6f057b238434b4865129e2a4f61312be4d274
parenta32f4007670330d05a834db1b67687ab8b8c3b34 (diff)
Fixes for pep8 compatibility
-rw-r--r--pgcommitfest/auth.py29
-rw-r--r--pgcommitfest/commitfest/admin.py8
-rw-r--r--pgcommitfest/commitfest/ajax.py62
-rw-r--r--pgcommitfest/commitfest/feeds.py3
-rw-r--r--pgcommitfest/commitfest/forms.py16
-rw-r--r--pgcommitfest/commitfest/lookups.py1
-rw-r--r--pgcommitfest/commitfest/management/commands/send_notifications.py5
-rw-r--r--pgcommitfest/commitfest/models.py59
-rw-r--r--pgcommitfest/commitfest/reports.py13
-rw-r--r--pgcommitfest/commitfest/templatetags/commitfest.py10
-rw-r--r--pgcommitfest/commitfest/util.py7
-rw-r--r--pgcommitfest/commitfest/views.py89
-rw-r--r--pgcommitfest/commitfest/widgets.py1
-rw-r--r--pgcommitfest/mailqueue/models.py1
-rw-r--r--pgcommitfest/mailqueue/util.py8
-rw-r--r--pgcommitfest/settings.py27
-rw-r--r--pgcommitfest/urls.py9
-rw-r--r--pgcommitfest/userprofile/admin.py2
-rw-r--r--pgcommitfest/userprofile/forms.py12
-rw-r--r--pgcommitfest/userprofile/models.py1
-rw-r--r--pgcommitfest/userprofile/util.py1
-rw-r--r--pgcommitfest/userprofile/views.py5
-rwxr-xr-xtools/commitfest/check_patches_in_archives.py100
-rwxr-xr-xtools/commitfest/oneoff/update_attachment_filenames.py100
-rwxr-xr-xtools/commitfest/update_archive_threads.py22
-rwxr-xr-xtools/mail/send_queued_mail.py38
26 files changed, 352 insertions, 277 deletions
diff --git a/pgcommitfest/auth.py b/pgcommitfest/auth.py
index 1073b5e..f9e72e2 100644
--- a/pgcommitfest/auth.py
+++ b/pgcommitfest/auth.py
@@ -35,6 +35,7 @@ from Crypto.Hash import SHA
from Crypto import Random
import time
+
class AuthBackend(ModelBackend):
# We declare a fake backend that always fails direct authentication -
# since we should never be using direct authentication in the first place!
@@ -48,7 +49,7 @@ class AuthBackend(ModelBackend):
# Handle login requests by sending them off to the main site
def login(request):
- if request.GET.has_key('next'):
+ if 'next' in request.GET:
# Put together an url-encoded dict of parameters we're getting back,
# including a small nonce at the beginning to make sure it doesn't
# encrypt the same way every time.
@@ -57,16 +58,17 @@ def login(request):
r = Random.new()
iv = r.read(16)
encryptor = AES.new(SHA.new(settings.SECRET_KEY).digest()[:16], AES.MODE_CBC, iv)
- cipher = encryptor.encrypt(s + ' ' * (16-(len(s) % 16))) # pad to 16 bytes
+ cipher = encryptor.encrypt(s + ' ' * (16 - (len(s) % 16))) # pad to 16 bytes
return HttpResponseRedirect("%s?d=%s$%s" % (
- settings.PGAUTH_REDIRECT,
- base64.b64encode(iv, "-_"),
- base64.b64encode(cipher, "-_"),
- ))
+ settings.PGAUTH_REDIRECT,
+ base64.b64encode(iv, "-_"),
+ base64.b64encode(cipher, "-_"),
+ ))
else:
return HttpResponseRedirect(settings.PGAUTH_REDIRECT)
+
# Handle logout requests by logging out of this site and then
# redirecting to log out from the main site as well.
def logout(request):
@@ -74,16 +76,17 @@ def logout(request):
django_logout(request)
return HttpResponseRedirect("%slogout/" % settings.PGAUTH_REDIRECT)
+
# Receive an authentication response from the main website and try
# to log the user in.
def auth_receive(request):
- if request.GET.has_key('s') and request.GET['s'] == "logout":
+ if request.GET.get('s', '') == 'logout':
# This was a logout request
return HttpResponseRedirect('/')
- if not request.GET.has_key('i'):
+ if 'i' not in request.GET:
return HttpResponse("Missing IV in url!", status=400)
- if not request.GET.has_key('d'):
+ if 'd' not in request.GET:
return HttpResponse("Missing data in url!", status=400)
# Set up an AES object and decrypt the data we received
@@ -115,7 +118,7 @@ def auth_receive(request):
changed = True
if user.email != data['e'][0]:
user.email = data['e'][0]
- changed= True
+ changed = True
if changed:
user.save()
except User.DoesNotExist:
@@ -153,7 +156,7 @@ We apologize for the inconvenience.
# Finally, check of we have a data package that tells us where to
# redirect the user.
- if data.has_key('d'):
+ if 'd' in data:
(ivs, datas) = data['d'][0].split('$')
decryptor = AES.new(SHA.new(settings.SECRET_KEY).digest()[:16],
AES.MODE_CBC,
@@ -163,7 +166,7 @@ We apologize for the inconvenience.
rdata = urlparse.parse_qs(s, strict_parsing=True)
except ValueError:
return HttpResponse("Invalid encrypted data received.", status=400)
- if rdata.has_key('r'):
+ if 'r' in rdata:
# Redirect address
return HttpResponseRedirect(rdata['r'][0])
# No redirect specified, see if we have it in our settings
@@ -191,7 +194,7 @@ def user_search(searchterm=None, userid=None):
u = urllib.urlopen('%ssearch/?%s' % (
settings.PGAUTH_REDIRECT,
urllib.urlencode(q),
- ))
+ ))
(ivs, datas) = u.read().split('&')
u.close()
diff --git a/pgcommitfest/commitfest/admin.py b/pgcommitfest/commitfest/admin.py
index 232ba30..3ac72a0 100644
--- a/pgcommitfest/commitfest/admin.py
+++ b/pgcommitfest/commitfest/admin.py
@@ -2,21 +2,25 @@ from django.contrib import admin
from models import *
+
class CommitterAdmin(admin.ModelAdmin):
list_display = ('user', 'active')
+
class PatchOnCommitFestInline(admin.TabularInline):
model = PatchOnCommitFest
- extra=1
+ extra = 1
+
class PatchAdmin(admin.ModelAdmin):
inlines = (PatchOnCommitFestInline,)
list_display = ('name', )
-# list_filter = ('commitfests_set__commitfest__name',)
+
class MailThreadAttachmentAdmin(admin.ModelAdmin):
list_display = ('date', 'author', 'messageid', 'mailthread',)
+
admin.site.register(Committer, CommitterAdmin)
admin.site.register(CommitFest)
admin.site.register(Topic)
diff --git a/pgcommitfest/commitfest/ajax.py b/pgcommitfest/commitfest/ajax.py
index b8317f5..71b3ee8 100644
--- a/pgcommitfest/commitfest/ajax.py
+++ b/pgcommitfest/commitfest/ajax.py
@@ -10,27 +10,30 @@ import requests
import json
from pgcommitfest.auth import user_search
+from models import CommitFest, Patch, MailThread, MailThreadAttachment
+from models import MailThreadAnnotation, PatchHistory
+
-class HttpResponseServiceUnavailable(HttpResponse):
+class HttpResponseServiceUnavailable(HttpResponse):
status_code = 503
+
class Http503(Exception):
pass
-from models import CommitFest, Patch, MailThread, MailThreadAttachment
-from models import MailThreadAnnotation, PatchHistory
def _archivesAPI(suburl, params=None):
try:
- resp = requests.get("http{0}://{1}:{2}{3}".format(settings.ARCHIVES_PORT == 443 and 's' or '',
- settings.ARCHIVES_SERVER,
- settings.ARCHIVES_PORT,
- suburl),
- params=params,
- headers={
- 'Host': settings.ARCHIVES_HOST,
- },
- timeout=settings.ARCHIVES_TIMEOUT,
+ resp = requests.get(
+ "http{0}://{1}:{2}{3}".format(settings.ARCHIVES_PORT == 443 and 's' or '',
+ settings.ARCHIVES_SERVER,
+ settings.ARCHIVES_PORT,
+ suburl),
+ params=params,
+ headers={
+ 'Host': settings.ARCHIVES_HOST,
+ },
+ timeout=settings.ARCHIVES_TIMEOUT,
)
if resp.status_code != 200:
if resp.status_code == 404:
@@ -43,9 +46,10 @@ def _archivesAPI(suburl, params=None):
except Exception as e:
raise Http503("Failed to communicate with archives backend: %s" % e)
+
def getThreads(request):
- search = request.GET.has_key('s') and request.GET['s'] or None
- if request.GET.has_key('a') and request.GET['a'] == "1":
+ search = request.GET.get('s', None)
+ if request.GET.get('a', '0') == '1':
attachonly = 1
else:
attachonly = 0
@@ -58,6 +62,7 @@ def getThreads(request):
r = _archivesAPI('/list/pgsql-hackers/latest.json', params)
return sorted(r, key=lambda x: x['date'], reverse=True)
+
def getMessages(request):
threadid = request.GET['t']
@@ -67,6 +72,7 @@ def getMessages(request):
r = _archivesAPI('/message-id.json/%s' % thread.messageid)
return sorted(r, key=lambda x: x['date'], reverse=True)
+
def refresh_single_thread(thread):
r = sorted(_archivesAPI('/message-id.json/%s' % thread.messageid), key=lambda x: x['date'])
if thread.latestmsgid != r[-1]['msgid']:
@@ -83,6 +89,7 @@ def refresh_single_thread(thread):
p.lastmail = thread.latestmessage
p.save()
+
@transaction.atomic
def annotateMessage(request):
thread = get_object_or_404(MailThread, pk=int(request.POST['t']))
@@ -112,6 +119,7 @@ def annotateMessage(request):
return 'OK'
return 'Message not found in thread!'
+
@transaction.atomic
def deleteAnnotation(request):
annotation = get_object_or_404(MailThreadAnnotation, pk=request.POST['id'])
@@ -125,6 +133,7 @@ def deleteAnnotation(request):
return 'OK'
+
def parse_and_add_attachments(threadinfo, mailthread):
for t in threadinfo:
if len(t['atts']):
@@ -142,6 +151,7 @@ def parse_and_add_attachments(threadinfo, mailthread):
# In theory we should remove objects if they don't have an
# attachment, but how could that ever happen? Ignore for now.
+
@transaction.atomic
def attachThread(request):
cf = get_object_or_404(CommitFest, pk=int(request.POST['cf']))
@@ -150,6 +160,7 @@ def attachThread(request):
return doAttachThread(cf, patch, msgid, request.user)
+
def doAttachThread(cf, patch, msgid, user):
# Note! Must be called in an open transaction!
r = sorted(_archivesAPI('/message-id.json/%s' % msgid), key=lambda x: x['date'])
@@ -166,10 +177,10 @@ def doAttachThread(cf, patch, msgid, user):
# While at it, we update the thread entry with the latest data from the
# archives.
thread.patches.add(patch)
- thread.latestmessage=r[-1]['date']
- thread.latestauthor=r[-1]['from']
- thread.latestsubject=r[-1]['subj']
- thread.latestmsgid=r[-1]['msgid']
+ thread.latestmessage = r[-1]['date']
+ thread.latestauthor = r[-1]['from']
+ thread.latestsubject = r[-1]['subj']
+ thread.latestmsgid = r[-1]['msgid']
thread.save()
else:
# No existing thread existed, so create it
@@ -195,6 +206,7 @@ def doAttachThread(cf, patch, msgid, user):
return 'OK'
+
@transaction.atomic
def detachThread(request):
cf = get_object_or_404(CommitFest, pk=int(request.POST['cf']))
@@ -209,16 +221,18 @@ def detachThread(request):
return 'OK'
+
def searchUsers(request):
- if request.GET.has_key('s') and request.GET['s']:
+ if request.GET.get('s', ''):
return user_search(request.GET['s'])
else:
return []
+
def importUser(request):
- if request.GET.has_key('u') and request.GET['u']:
+ if request.GET.get('u', ''):
u = user_search(userid=request.GET['u'])
- if len (u) != 1:
+ if len(u) != 1:
return "Internal error, duplicate user found"
u = u[0]
@@ -235,7 +249,8 @@ def importUser(request):
else:
raise Http404()
-_ajax_map={
+
+_ajax_map = {
'getThreads': getThreads,
'getMessages': getMessages,
'attachThread': attachThread,
@@ -246,11 +261,12 @@ _ajax_map={
'importUser': importUser,
}
+
# Main entrypoint for /ajax/<command>/
@csrf_exempt
@login_required
def main(request, command):
- if not _ajax_map.has_key(command):
+ if command not in _ajax_map:
raise Http404
try:
resp = HttpResponse(content_type='application/json')
diff --git a/pgcommitfest/commitfest/feeds.py b/pgcommitfest/commitfest/feeds.py
index d858703..cd206ac 100644
--- a/pgcommitfest/commitfest/feeds.py
+++ b/pgcommitfest/commitfest/feeds.py
@@ -1,5 +1,6 @@
from django.contrib.syndication.views import Feed
+
class ActivityFeed(Feed):
title = description = 'Commitfest Activity Log'
link = 'https://commitfest.postgresql.org/'
@@ -30,7 +31,7 @@ class ActivityFeed(Feed):
def item_link(self, item):
if self.cfid:
- return 'https://commitfest.postgresql.org/{cfid}/{patchid}/'.format(cfid=self.cfid,**item)
+ return 'https://commitfest.postgresql.org/{cfid}/{patchid}/'.format(cfid=self.cfid, **item)
else:
return 'https://commitfest.postgresql.org/{cfid}/{patchid}/'.format(**item)
diff --git a/pgcommitfest/commitfest/forms.py b/pgcommitfest/commitfest/forms.py
index a341f99..ab8a14f 100644
--- a/pgcommitfest/commitfest/forms.py
+++ b/pgcommitfest/commitfest/forms.py
@@ -12,6 +12,7 @@ from lookups import UserLookup
from widgets import ThreadPickWidget
from ajax import _archivesAPI
+
class CommitFestFilterForm(forms.Form):
text = forms.CharField(max_length=50, required=False)
status = forms.ChoiceField(required=False)
@@ -28,13 +29,14 @@ class CommitFestFilterForm(forms.Form):
self.fields['status'] = forms.ChoiceField(choices=c, required=False)
q = Q(patch_author__commitfests=cf) | Q(patch_reviewer__commitfests=cf)
- userchoices = [(-1, '* All'), (-2, '* None'), (-3, '* Yourself') ] + [(u.id, '%s %s (%s)' % (u.first_name, u.last_name, u.username)) for u in User.objects.filter(q).distinct().order_by('first_name', 'last_name')]
+ userchoices = [(-1, '* All'), (-2, '* None'), (-3, '* Yourself')] + [(u.id, '%s %s (%s)' % (u.first_name, u.last_name, u.username)) for u in User.objects.filter(q).distinct().order_by('first_name', 'last_name')]
self.fields['author'] = forms.ChoiceField(choices=userchoices, required=False)
self.fields['reviewer'] = forms.ChoiceField(choices=userchoices, required=False)
for f in ('status', 'author', 'reviewer',):
self.fields[f].widget.attrs = {'class': 'input-medium'}
+
class PatchForm(forms.ModelForm):
class Meta:
model = Patch
@@ -68,11 +70,12 @@ class NewPatchForm(forms.ModelForm):
raise ValidationError("Error in API call to validate thread")
return self.cleaned_data['threadmsgid']
+
def _fetch_thread_choices(patch):
for mt in patch.mailthread_set.order_by('-latestmessage'):
ti = sorted(_archivesAPI('/message-id.json/%s' % mt.messageid), key=lambda x: x['date'], reverse=True)
yield [mt.subject,
- [('%s,%s' % (mt.messageid, t['msgid']),'From %s at %s' % (t['from'], t['date'])) for t in ti]]
+ [('%s,%s' % (mt.messageid, t['msgid']), 'From %s at %s' % (t['from'], t['date'])) for t in ti]]
review_state_choices = (
@@ -80,9 +83,11 @@ review_state_choices = (
(1, 'Passed'),
)
+
def reviewfield(label):
return forms.MultipleChoiceField(choices=review_state_choices, label=label, widget=forms.CheckboxSelectMultiple, required=False)
+
class CommentForm(forms.Form):
responseto = forms.ChoiceField(choices=[], required=True, label='In response to')
@@ -120,12 +125,13 @@ class CommentForm(forms.Form):
def clean(self):
if self.is_review:
- for fn,f in self.fields.items():
- if fn.startswith('review_') and self.cleaned_data.has_key(fn):
- if '1' in self.cleaned_data[fn] and not '0' in self.cleaned_data[fn]:
+ for fn, f in self.fields.items():
+ if fn.startswith('review_') and fn in self.cleaned_data:
+ if '1' in self.cleaned_data[fn] and '0' not in self.cleaned_data[fn]:
self.errors[fn] = (('Cannot pass a test without performing it!'),)
return self.cleaned_data
+
class BulkEmailForm(forms.Form):
reviewers = forms.CharField(required=False, widget=HiddenInput())
authors = forms.CharField(required=False, widget=HiddenInput())
diff --git a/pgcommitfest/commitfest/lookups.py b/pgcommitfest/commitfest/lookups.py
index 1cb567f..7297ccc 100644
--- a/pgcommitfest/commitfest/lookups.py
+++ b/pgcommitfest/commitfest/lookups.py
@@ -22,4 +22,5 @@ class UserLookup(ModelLookup):
# Display for choice listings
return u"%s (%s)" % (item.username, item.get_full_name())
+
registry.register(UserLookup)
diff --git a/pgcommitfest/commitfest/management/commands/send_notifications.py b/pgcommitfest/commitfest/management/commands/send_notifications.py
index be8cd90..d181712 100644
--- a/pgcommitfest/commitfest/management/commands/send_notifications.py
+++ b/pgcommitfest/commitfest/management/commands/send_notifications.py
@@ -8,6 +8,7 @@ from pgcommitfest.commitfest.models import PendingNotification
from pgcommitfest.userprofile.models import UserProfile
from pgcommitfest.mailqueue.util import send_template_mail
+
class Command(BaseCommand):
help = "Send queued notifications"
@@ -17,9 +18,9 @@ class Command(BaseCommand):
# build our own.
matches = {}
for n in PendingNotification.objects.all().order_by('user', 'history__patch__id', 'history__id'):
- if not matches.has_key(n.user.id):
+ if n.user.id not in matches:
matches[n.user.id] = {'user': n.user, 'patches': {}}
- if not matches[n.user.id]['patches'].has_key(n.history.patch.id):
+ if n.history.patch.id not in matches[n.user.id]['patches']:
matches[n.user.id]['patches'][n.history.patch.id] = {'patch': n.history.patch, 'entries': []}
matches[n.user.id]['patches'][n.history.patch.id]['entries'].append(n.history)
n.delete()
diff --git a/pgcommitfest/commitfest/models.py b/pgcommitfest/commitfest/models.py
index 1cc694e..5687561 100644
--- a/pgcommitfest/commitfest/models.py
+++ b/pgcommitfest/commitfest/models.py
@@ -7,6 +7,7 @@ from util import DiffableModel
from pgcommitfest.userprofile.models import UserProfile
+
# We have few enough of these, and it's really the only thing we
# need to extend from the user model, so just create a separate
# class.
@@ -24,17 +25,18 @@ class Committer(models.Model):
class Meta:
ordering = ('user__last_name', 'user__first_name')
+
class CommitFest(models.Model):
- STATUS_FUTURE=1
- STATUS_OPEN=2
- STATUS_INPROGRESS=3
- STATUS_CLOSED=4
+ STATUS_FUTURE = 1
+ STATUS_OPEN = 2
+ STATUS_INPROGRESS = 3
+ STATUS_CLOSED = 4
_STATUS_CHOICES = (
(STATUS_FUTURE, 'Future'),
(STATUS_OPEN, 'Open'),
(STATUS_INPROGRESS, 'In Progress'),
(STATUS_CLOSED, 'Closed'),
- )
+ )
name = models.CharField(max_length=100, blank=False, null=False, unique=True)
status = models.IntegerField(null=False, blank=False, default=1, choices=_STATUS_CHOICES)
startdate = models.DateField(blank=True, null=True)
@@ -42,7 +44,7 @@ class CommitFest(models.Model):
@property
def statusstring(self):
- return [v for k,v in self._STATUS_CHOICES if k==self.status][0]
+ return [v for k, v in self._STATUS_CHOICES if k == self.status][0]
@property
def periodstring(self):
@@ -62,9 +64,10 @@ class CommitFest(models.Model):
return self.name
class Meta:
- verbose_name_plural='Commitfests'
+ verbose_name_plural = 'Commitfests'
ordering = ('-startdate',)
+
class Topic(models.Model):
topic = models.CharField(max_length=100, blank=False, null=False)
@@ -85,9 +88,6 @@ class Patch(models.Model, DiffableModel):
# If there is a git repo about this patch
gitlink = models.URLField(blank=True, null=False, default='')
- # Mailthreads are ManyToMany in the other direction
- #mailthreads_set = ...
-
authors = models.ManyToManyField(User, related_name='patch_author', blank=True)
reviewers = models.ManyToManyField(User, related_name='patch_reviewer', blank=True)
@@ -107,7 +107,8 @@ class Patch(models.Model, DiffableModel):
map_manytomany_for_diff = {
'authors': 'authors_string',
'reviewers': 'reviewers_string',
- }
+ }
+
# Some accessors
@property
def authors_string(self):
@@ -139,7 +140,7 @@ class Patch(models.Model, DiffableModel):
if len(threads) == 0:
self.lastmail = None
else:
- self.lastmail = max(threads, key=lambda t:t.latestmessage).latestmessage
+ self.lastmail = max(threads, key=lambda t: t.latestmessage).latestmessage
def __unicode__(self):
return self.name
@@ -147,20 +148,21 @@ class Patch(models.Model, DiffableModel):
class Meta:
verbose_name_plural = 'patches'
+
class PatchOnCommitFest(models.Model):
# NOTE! This is also matched by the commitfest_patchstatus table,
# but we hardcoded it in here simply for performance reasons since
# the data should be entirely static. (Yes, that's something we
# might re-evaluate in the future)
- STATUS_REVIEW=1
- STATUS_AUTHOR=2
- STATUS_COMMITTER=3
- STATUS_COMMITTED=4
- STATUS_NEXT=5
- STATUS_REJECTED=6
- STATUS_RETURNED=7
- STATUS_WITHDRAWN=8
- _STATUS_CHOICES=(
+ STATUS_REVIEW = 1
+ STATUS_AUTHOR = 2
+ STATUS_COMMITTER = 3
+ STATUS_COMMITTED = 4
+ STATUS_NEXT = 5
+ STATUS_REJECTED = 6
+ STATUS_RETURNED = 7
+ STATUS_WITHDRAWN = 8
+ _STATUS_CHOICES = (
(STATUS_REVIEW, 'Needs review'),
(STATUS_AUTHOR, 'Waiting on Author'),
(STATUS_COMMITTER, 'Ready for Committer'),
@@ -170,7 +172,7 @@ class PatchOnCommitFest(models.Model):
(STATUS_RETURNED, 'Returned with feedback'),
(STATUS_WITHDRAWN, 'Withdrawn'),
)
- _STATUS_LABELS=(
+ _STATUS_LABELS = (
(STATUS_REVIEW, 'default'),
(STATUS_AUTHOR, 'primary'),
(STATUS_COMMITTER, 'info'),
@@ -180,8 +182,8 @@ class PatchOnCommitFest(models.Model):
(STATUS_RETURNED, 'danger'),
(STATUS_WITHDRAWN, 'danger'),
)
- OPEN_STATUSES=[STATUS_REVIEW, STATUS_AUTHOR, STATUS_COMMITTER]
- OPEN_STATUS_CHOICES=[x for x in _STATUS_CHOICES if x[0] in OPEN_STATUSES]
+ OPEN_STATUSES = [STATUS_REVIEW, STATUS_AUTHOR, STATUS_COMMITTER]
+ OPEN_STATUS_CHOICES = [x for x in _STATUS_CHOICES if x[0] in OPEN_STATUSES]
patch = models.ForeignKey(Patch, blank=False, null=False)
commitfest = models.ForeignKey(CommitFest, blank=False, null=False)
@@ -196,12 +198,13 @@ class PatchOnCommitFest(models.Model):
@property
def statusstring(self):
- return [v for k,v in self._STATUS_CHOICES if k==self.status][0]
+ return [v for k, v in self._STATUS_CHOICES if k == self.status][0]
class Meta:
unique_together = (('patch', 'commitfest',),)
ordering = ('-commitfest__startdate', )
+
class PatchHistory(models.Model):
patch = models.ForeignKey(Patch, blank=False, null=False)
date = models.DateTimeField(blank=False, null=False, auto_now_add=True)
@@ -250,9 +253,10 @@ class PatchHistory(models.Model):
recipients.extend(self.patch.authors.filter(userprofile__notify_all_author=True))
for u in set(recipients):
- if u != self.by: # Don't notify for changes we make ourselves
+ if u != self.by: # Don't notify for changes we make ourselves
PendingNotification(history=self, user=u).save()
+
class MailThread(models.Model):
# This class tracks mail threads from the main postgresql.org
# mailinglist archives. For each thread, we store *one* messageid.
@@ -279,6 +283,7 @@ class MailThread(models.Model):
class Meta:
ordering = ('firstmessage', )
+
class MailThreadAttachment(models.Model):
mailthread = models.ForeignKey(MailThread, null=False, blank=False)
messageid = models.CharField(max_length=1000, null=False, blank=False)
@@ -292,6 +297,7 @@ class MailThreadAttachment(models.Model):
ordering = ('-date',)
unique_together = (('mailthread', 'messageid',), )
+
class MailThreadAnnotation(models.Model):
mailthread = models.ForeignKey(MailThread, null=False, blank=False)
date = models.DateTimeField(null=False, blank=False, auto_now_add=True)
@@ -309,6 +315,7 @@ class MailThreadAnnotation(models.Model):
class Meta:
ordering = ('date', )
+
class PatchStatus(models.Model):
status = models.IntegerField(null=False, blank=False, primary_key=True)
statusstring = models.TextField(max_length=50, null=False, blank=False)
diff --git a/pgcommitfest/commitfest/reports.py b/pgcommitfest/commitfest/reports.py
index 4645856..aae1bba 100644
--- a/pgcommitfest/commitfest/reports.py
+++ b/pgcommitfest/commitfest/reports.py
@@ -6,6 +6,7 @@ from django.db import connection
from models import CommitFest
+
@login_required
def authorstats(request, cfid):
cf = get_object_or_404(CommitFest, pk=cfid)
@@ -13,7 +14,8 @@ def authorstats(request, cfid):
raise Http404("Only CF Managers can do that.")
cursor = connection.cursor()
- cursor.execute("""WITH patches(id,name) AS (
+ cursor.execute("""
+WITH patches(id,name) AS (
SELECT p.id, name
FROM commitfest_patch p
INNER JOIN commitfest_patchoncommitfest poc ON poc.patch_id=p.id AND poc.commitfest_id=%(cid)s
@@ -34,13 +36,14 @@ SELECT first_name || ' ' || last_name || ' (' || username ||')', authorpatches,
FROM (authors FULL OUTER JOIN reviewers ON authors.userid=reviewers.userid)
INNER JOIN auth_user u ON u.id=COALESCE(authors.userid, reviewers.userid)
ORDER BY last_name, first_name
-""", {
- 'cid': cf.id,
-})
+""",
+ {
+ 'cid': cf.id,
+ })
return render(request, 'report_authors.html', {
'cf': cf,
'report': cursor.fetchall(),
'title': 'Author stats',
- 'breadcrumbs': [{'title': cf.title, 'href': '/%s/' % cf.pk},],
+ 'breadcrumbs': [{'title': cf.title, 'href': '/%s/' % cf.pk}, ],
})
diff --git a/pgcommitfest/commitfest/templatetags/commitfest.py b/pgcommitfest/commitfest/templatetags/commitfest.py
index bde7d07..c51765d 100644
--- a/pgcommitfest/commitfest/templatetags/commitfest.py
+++ b/pgcommitfest/commitfest/templatetags/commitfest.py
@@ -5,26 +5,31 @@ from pgcommitfest.commitfest.models import PatchOnCommitFest
register = template.Library()
+
@register.filter(name='patchstatusstring')
@stringfilter
def patchstatusstring(value):
i = int(value)
- return [v for k,v in PatchOnCommitFest._STATUS_CHOICES if k==i][0]
+ return [v for k, v in PatchOnCommitFest._STATUS_CHOICES if k == i][0]
+
@register.filter(name='patchstatuslabel')
@stringfilter
def patchstatuslabel(value):
i = int(value)
- return [v for k,v in PatchOnCommitFest._STATUS_LABELS if k==i][0]
+ return [v for k, v in PatchOnCommitFest._STATUS_LABELS if k == i][0]
+
@register.filter(is_safe=True)
def label_class(value, arg):
return value.label_tag(attrs={'class': arg})
+
@register.filter(is_safe=True)
def field_class(value, arg):
return value.as_widget(attrs={"class": arg})
+
@register.filter(name='alertmap')
@stringfilter
def alertmap(value):
@@ -37,6 +42,7 @@ def alertmap(value):
else:
return 'alert-info'
+
@register.filter(name='hidemail')
@stringfilter
def hidemail(value):
diff --git a/pgcommitfest/commitfest/util.py b/pgcommitfest/commitfest/util.py
index 4698879..94ad3e5 100644
--- a/pgcommitfest/commitfest/util.py
+++ b/pgcommitfest/commitfest/util.py
@@ -18,15 +18,15 @@ class DiffableModel(object):
d2 = self._dict
diffs = dict([(k, (v, d2[k])) for k, v in d1.items() if v != d2[k]])
# Foreign key lookups
- for k,v in diffs.items():
+ for k, v in diffs.items():
if type(self._meta.get_field(k)) is django.db.models.fields.related.ForeignKey:
# If it's a foreign key, look up the name again on ourselves.
# Since we only care about the *new* value, it's easy enough.
diffs[k] = (v[0], getattr(self, k))
# Many to many lookups
if hasattr(self, 'map_manytomany_for_diff'):
- for k,v in diffs.items():
- if k in manytomanyfieldnames and self.map_manytomany_for_diff.has_key(k):
+ for k, v in diffs.items():
+ if k in manytomanyfieldnames and k in self.map_manytomany_for_diff:
# Try to show the display name instead here
newvalue = getattr(self, self.map_manytomany_for_diff[k])
diffs[k] = (v[0], newvalue)
@@ -41,4 +41,3 @@ class DiffableModel(object):
fields = [field.name for field in self._meta.fields]
fields.extend([field.name for field in self._meta.many_to_many])
return model_to_dict(self, fields=fields)
-
diff --git a/pgcommitfest/commitfest/views.py b/pgcommitfest/commitfest/views.py
index 705b172..7835f5e 100644
--- a/pgcommitfest/commitfest/views.py
+++ b/pgcommitfest/commitfest/views.py
@@ -26,6 +26,7 @@ from forms import BulkEmailForm
from ajax import doAttachThread, refresh_single_thread
from feeds import ActivityFeed
+
def home(request):
commitfests = list(CommitFest.objects.all())
opencf = next((c for c in commitfests if c.status == CommitFest.STATUS_OPEN), None)
@@ -38,7 +39,7 @@ def home(request):
'title': 'Commitfests',
'header_activity': 'Activity log',
'header_activity_link': '/activity/',
- })
+ })
def activity(request, cfid=None, rss=None):
@@ -62,11 +63,11 @@ def activity(request, cfid=None, rss=None):
extrafields = ',poc.commitfest_id AS cfid,cf.name AS cfname'
where = ' INNER JOIN commitfest_commitfest cf ON cf.id=poc.commitfest_id'
- sql = "SELECT ph.date, auth_user.username AS by, ph.what, p.id AS patchid, p.name{0} FROM commitfest_patchhistory ph INNER JOIN commitfest_patch p ON ph.patch_id=p.id INNER JOIN auth_user on auth_user.id=ph.by_id INNER JOIN commitfest_patchoncommitfest poc ON poc.patch_id=p.id {1} ORDER BY ph.date DESC LIMIT {2}".format(extrafields,where, num)
+ sql = "SELECT ph.date, auth_user.username AS by, ph.what, p.id AS patchid, p.name{0} FROM commitfest_patchhistory ph INNER JOIN commitfest_patch p ON ph.patch_id=p.id INNER JOIN auth_user on auth_user.id=ph.by_id INNER JOIN commitfest_patchoncommitfest poc ON poc.patch_id=p.id {1} ORDER BY ph.date DESC LIMIT {2}".format(extrafields, where, num)
curs = connection.cursor()
curs.execute(sql)
- activity = [dict(zip([c[0] for c in curs.description],r)) for r in curs.fetchall()]
+ activity = [dict(zip([c[0] for c in curs.description], r)) for r in curs.fetchall()]
if rss:
# Return RSS feed with these objects
@@ -79,9 +80,10 @@ def activity(request, cfid=None, rss=None):
'title': cf and 'Commitfest activity' or 'Global Commitfest activity',
'rss_alternate': cf and '/{0}/activity.rss/'.format(cf.id) or '/activity.rss/',
'rss_alternate_title': 'PostgreSQL Commitfest Activity Log',
- 'breadcrumbs': cf and [{'title': cf.title, 'href': '/%s/' % cf.pk},] or None,
+ 'breadcrumbs': cf and [{'title': cf.title, 'href': '/%s/' % cf.pk}, ] or None,
})
+
def redir(request, what):
if what == 'open':
cfs = list(CommitFest.objects.filter(status=CommitFest.STATUS_OPEN))
@@ -99,6 +101,7 @@ def redir(request, what):
return HttpResponseRedirect("/%s/" % cfs[0].id)
+
def commitfest(request, cfid):
# Find ourselves
cf = get_object_or_404(CommitFest, pk=cfid)
@@ -106,7 +109,7 @@ def commitfest(request, cfid):
# Build a dynamic filter based on the filtering options entered
whereclauses = []
whereparams = {}
- if request.GET.has_key('status') and request.GET['status'] != "-1":
+ if request.GET.get('status', '-1') != '-1':
try:
whereparams['status'] = int(request.GET['status'])
whereclauses.append("poc.status=%(status)s")
@@ -114,7 +117,7 @@ def commitfest(request, cfid):
# int() failed -- so just ignore this filter
pass
- if request.GET.has_key('author') and request.GET['author'] != "-1":
+ if request.GET.get('author', '-1') != '-1':
if request.GET['author'] == '-2':
whereclauses.append("NOT EXISTS (SELECT 1 FROM commitfest_patch_authors cpa WHERE cpa.patch_id=p.id)")
elif request.GET['author'] == '-3':
@@ -131,7 +134,7 @@ def commitfest(request, cfid):
# int() failed -- so just ignore this filter
pass
- if request.GET.has_key('reviewer') and request.GET['reviewer'] != "-1":
+ if request.GET.get('reviewer', '-1') != '-1':
if request.GET['reviewer'] == '-2':
whereclauses.append("NOT EXISTS (SELECT 1 FROM commitfest_patch_reviewers cpr WHERE cpr.patch_id=p.id)")
elif request.GET['reviewer'] == '-3':
@@ -148,33 +151,33 @@ def commitfest(request, cfid):
# int() failed -- so just ignore this filter
pass
- if request.GET.has_key('text') and request.GET['text'] != '':
+ if request.GET.get('text', '') != '':
whereclauses.append("p.name ILIKE '%%' || %(txt)s || '%%'")
whereparams['txt'] = request.GET['text']
has_filter = len(whereclauses) > 0
# Figure out custom ordering
- if request.GET.has_key('sortkey') and request.GET['sortkey']!='':
+ if request.GET.get('sortkey', '') != '':
try:
- sortkey=int(request.GET['sortkey'])
+ sortkey = int(request.GET['sortkey'])
except ValueError:
- sortkey=0
+ sortkey = 0
- if sortkey==1:
+ if sortkey == 1:
orderby_str = 'modified, created'
- elif sortkey==2:
+ elif sortkey == 2:
orderby_str = 'lastmail, created'
- elif sortkey==3:
+ elif sortkey == 3:
orderby_str = 'num_cfs DESC, modified, created'
else:
orderby_str = 'p.id'
- sortkey=0
+ sortkey = 0
else:
orderby_str = 'topic, created'
sortkey = 0
- if not has_filter and sortkey==0 and request.GET:
+ if not has_filter and sortkey == 0 and request.GET:
# Redirect to get rid of the ugly url
return HttpResponseRedirect('/%s/' % cf.id)
@@ -208,7 +211,7 @@ ORDER BY is_open DESC, {1}""".format(where_str, orderby_str), params)
curs = connection.cursor()
curs.execute("SELECT ps.status, ps.statusstring, count(*) FROM commitfest_patchoncommitfest poc INNER JOIN commitfest_patchstatus ps ON ps.status=poc.status WHERE commitfest_id=%(id)s GROUP BY ps.status ORDER BY ps.sortkey", {
'id': cf.id,
- })
+ })
statussummary = curs.fetchall()
statussummary.append([-1, 'Total', sum((r[2] for r in statussummary))])
@@ -223,15 +226,16 @@ ORDER BY is_open DESC, {1}""".format(where_str, orderby_str), params)
'statussummary': statussummary,
'has_filter': has_filter,
'title': cf.title,
- 'grouping': sortkey==0,
+ 'grouping': sortkey == 0,
'sortkey': sortkey,
'openpatchids': [p['id'] for p in patches if p['is_open']],
'header_activity': 'Activity log',
'header_activity_link': 'activity/',
- })
+ })
+
def global_search(request):
- if not request.GET.has_key('searchterm'):
+ if 'searchterm' not in request.GET:
return HttpResponseRedirect('/')
searchterm = request.GET['searchterm']
@@ -240,7 +244,8 @@ def global_search(request):
return render(request, 'patchsearch.html', {
'patches': patches,
'title': 'Patch search results',
- })
+ })
+
def patch(request, cfid, patchid):
cf = get_object_or_404(CommitFest, pk=cfid)
@@ -248,12 +253,12 @@ def patch(request, cfid, patchid):
patch_commitfests = PatchOnCommitFest.objects.select_related('commitfest').filter(patch=patch).order_by('-commitfest__startdate')
committers = Committer.objects.filter(active=True).order_by('user__last_name', 'user__first_name')
- #XXX: this creates a session, so find a smarter way. Probably handle
- #it in the callback and just ask the user then?
+ # XXX: this creates a session, so find a smarter way. Probably handle
+ # it in the callback and just ask the user then?
if request.user.is_authenticated():
- committer = [c for c in committers if c.user==request.user]
+ committer = [c for c in committers if c.user == request.user]
if len(committer) > 0:
- is_committer= True
+ is_committer = True
is_this_committer = committer[0] == patch.committer
else:
is_committer = is_this_committer = False
@@ -275,10 +280,11 @@ def patch(request, cfid, patchid):
'is_reviewer': is_reviewer,
'is_subscribed': is_subscribed,
'committers': committers,
- 'attachnow': request.GET.has_key('attachthreadnow'),
+ 'attachnow': 'attachthreadnow' in request.GET,
'title': patch.name,
- 'breadcrumbs': [{'title': cf.title, 'href': '/%s/' % cf.pk},],
- })
+ 'breadcrumbs': [{'title': cf.title, 'href': '/%s/' % cf.pk}, ],
+ })
+
@login_required
@transaction.atomic
@@ -318,6 +324,7 @@ def patchform(request, cfid, patchid):
{'title': 'View patch', 'href': '/%s/%s/' % (cf.pk, patch.pk)}],
})
+
@login_required
@transaction.atomic
def newpatch(request, cfid):
@@ -354,11 +361,12 @@ def newpatch(request, cfid):
return render(request, 'base_form.html', {
'form': form,
'title': 'New patch',
- 'breadcrumbs': [{'title': cf.title, 'href': '/%s/' % cf.pk},],
+ 'breadcrumbs': [{'title': cf.title, 'href': '/%s/' % cf.pk}, ],
'savebutton': 'Create patch',
'threadbrowse': True,
})
+
def _review_status_string(reviewstatus):
if '0' in reviewstatus:
if '1' in reviewstatus:
@@ -368,13 +376,14 @@ def _review_status_string(reviewstatus):
else:
return "not tested"
+
@login_required
@transaction.atomic
def comment(request, cfid, patchid, what):
cf = get_object_or_404(CommitFest, pk=cfid)
patch = get_object_or_404(Patch, pk=patchid)
poc = get_object_or_404(PatchOnCommitFest, patch=patch, commitfest=cf)
- is_review = (what=='review')
+ is_review = (what == 'review')
if poc.is_closed:
# We allow modification of patches in closed CFs *only* if it's the
@@ -464,6 +473,7 @@ def comment(request, cfid, patchid, what):
'savebutton': 'Send %s' % what,
})
+
@login_required
@transaction.atomic
def status(request, cfid, patchid, status):
@@ -551,7 +561,7 @@ def close(request, cfid, patchid, status):
# future one.
newcf = CommitFest.objects.filter(status=CommitFest.STATUS_FUTURE)
if len(newcf) == 0:
- messages.error(request,"No open and no future commitfest exists!")
+ messages.error(request, "No open and no future commitfest exists!")
return HttpResponseRedirect('/%s/%s/' % (poc.commitfest.id, poc.patch.id))
elif len(newcf) != 1:
messages.error(request, "No open and multiple future commitfests exist!")
@@ -596,6 +606,7 @@ def close(request, cfid, patchid, status):
return HttpResponseRedirect('/%s/%s/' % (poc.commitfest.id, poc.patch.id))
+
@login_required
@transaction.atomic
def reviewer(request, cfid, patchid, status):
@@ -604,16 +615,17 @@ def reviewer(request, cfid, patchid, status):
is_reviewer = request.user in patch.reviewers.all()
- if status=='become' and not is_reviewer:
+ if status == 'become' and not is_reviewer:
patch.reviewers.add(request.user)
patch.set_modified()
PatchHistory(patch=patch, by=request.user, what='Added %s as reviewer' % request.user.username).save_and_notify()
- elif status=='remove' and is_reviewer:
+ elif status == 'remove' and is_reviewer:
patch.reviewers.remove(request.user)
patch.set_modified()
PatchHistory(patch=patch, by=request.user, what='Removed %s from reviewers' % request.user.username).save_and_notify()
return HttpResponseRedirect('../../')
+
@login_required
@transaction.atomic
def committer(request, cfid, patchid, status):
@@ -628,17 +640,18 @@ def committer(request, cfid, patchid, status):
is_committer = committer == patch.committer
prevcommitter = patch.committer
- if status=='become' and not is_committer:
+ if status == 'become' and not is_committer:
patch.committer = committer
patch.set_modified()
PatchHistory(patch=patch, by=request.user, what='Added %s as committer' % request.user.username).save_and_notify(prevcommitter=prevcommitter)
- elif status=='remove' and is_committer:
+ elif status == 'remove' and is_committer:
patch.committer = None
patch.set_modified()
PatchHistory(patch=patch, by=request.user, what='Removed %s from committers' % request.user.username).save_and_notify(prevcommitter=prevcommitter)
patch.save()
return HttpResponseRedirect('../../')
+
@login_required
@transaction.atomic
def subscribe(request, cfid, patchid, sub):
@@ -654,6 +667,7 @@ def subscribe(request, cfid, patchid, sub):
patch.save()
return HttpResponseRedirect("../")
+
@login_required
@transaction.atomic
def send_email(request, cfid):
@@ -692,11 +706,12 @@ def send_email(request, cfid):
else:
reviewers = []
- if len(authors)==0 and len(reviewers)==0:
+ if len(authors) == 0 and len(reviewers) == 0:
messages.add_message(request, messages.WARNING, "No recipients specified, cannot send email")
return HttpResponseRedirect('..')
messages.add_message(request, messages.INFO, "Email will be sent from: %s" % UserWrapper(request.user).email)
+
def _user_and_mail(u):
return "%s %s (%s)" % (u.first_name, u.last_name, u.email)
@@ -709,7 +724,7 @@ def send_email(request, cfid):
'cf': cf,
'form': form,
'title': 'Send email',
- 'breadcrumbs': [{'title': cf.title, 'href': '/%s/' % cf.pk},],
+ 'breadcrumbs': [{'title': cf.title, 'href': '/%s/' % cf.pk}, ],
'savebutton': 'Send email',
})
diff --git a/pgcommitfest/commitfest/widgets.py b/pgcommitfest/commitfest/widgets.py
index ee2df3d..fbce50d 100644
--- a/pgcommitfest/commitfest/widgets.py
+++ b/pgcommitfest/commitfest/widgets.py
@@ -1,6 +1,7 @@
from django.forms import TextInput
from django.utils.safestring import mark_safe
+
class ThreadPickWidget(TextInput):
def render(self, name, value, attrs=None):
attrs['class'] += ' threadpick-input'
diff --git a/pgcommitfest/mailqueue/models.py b/pgcommitfest/mailqueue/models.py
index f75ca37..1a0642a 100644
--- a/pgcommitfest/mailqueue/models.py
+++ b/pgcommitfest/mailqueue/models.py
@@ -1,5 +1,6 @@
from django.db import models
+
class QueuedMail(models.Model):
sender = models.EmailField(max_length=100, null=False, blank=False)
receiver = models.EmailField(max_length=100, null=False, blank=False)
diff --git a/pgcommitfest/mailqueue/util.py b/pgcommitfest/mailqueue/util.py
index 9abea53..7faab0f 100644
--- a/pgcommitfest/mailqueue/util.py
+++ b/pgcommitfest/mailqueue/util.py
@@ -8,6 +8,7 @@ from email import encoders
from models import QueuedMail
+
def send_simple_mail(sender, receiver, subject, msgtxt, sending_username, attachments=None):
# attachment format, each is a tuple of (name, mimetype,contents)
# content should already be base64 encoded
@@ -24,21 +25,22 @@ def send_simple_mail(sender, receiver, subject, msgtxt, sending_username, attach
if attachments:
for filename, contenttype, content in attachments:
- main,sub = contenttype.split('/')
- part = MIMENonMultipart(main,sub)
+ main, sub = contenttype.split('/')
+ part = MIMENonMultipart(main, sub)
part.set_payload(content)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % filename)
encoders.encode_base64(part)
msg.attach(part)
-
# Just write it to the queue, so it will be transactionally rolled back
QueuedMail(sender=sender, receiver=receiver, fullmsg=msg.as_string()).save()
+
def send_mail(sender, receiver, fullmsg):
# Send an email, prepared as the full MIME encoded mail already
QueuedMail(sender=sender, receiver=receiver, fullmsg=fullmsg).save()
+
def send_template_mail(sender, senderaccountname, receiver, subject, templatename, templateattr={}, usergenerated=False):
send_simple_mail(sender, receiver, subject,
get_template(templatename).render(templateattr),
diff --git a/pgcommitfest/settings.py b/pgcommitfest/settings.py
index 575d90f..bab70eb 100644
--- a/pgcommitfest/settings.py
+++ b/pgcommitfest/settings.py
@@ -13,7 +13,7 @@ MANAGERS = ADMINS
DATABASES = {
'default': {
- 'ENGINE': 'django.db.backends.postgresql_psycopg2', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+ 'ENGINE': 'django.db.backends.postgresql_psycopg2', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'NAME': 'pgcommitfest', # Or path to database file if using sqlite3.
'USER': '', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
@@ -81,7 +81,6 @@ STATICFILES_DIRS = (
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
-# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
# Make this unique, and don't share it with anybody.
@@ -157,25 +156,25 @@ LOGGING = {
}
}
-DATE_FORMAT='Y-m-d'
-DATETIME_FORMAT='Y-m-d H:i:s'
+DATE_FORMAT = 'Y-m-d'
+DATETIME_FORMAT = 'Y-m-d H:i:s'
-LOGIN_URL='/account/login/'
+LOGIN_URL = '/account/login/'
-ARCHIVES_TIMEOUT=10 # Seconds to wait for calls to the archives
-ARCHIVES_SERVER="localhost"
-ARCHIVES_PORT="8001"
-ARCHIVES_HOST="archives.postgresql.org" # Host: header to send
-ARCHIVES_APIKEY=None
+ARCHIVES_TIMEOUT = 10 # Seconds to wait for calls to the archives
+ARCHIVES_SERVER = "localhost"
+ARCHIVES_PORT = "8001"
+ARCHIVES_HOST = "archives.postgresql.org" # Host: header to send
+ARCHIVES_APIKEY = None
# Email address to pgsql-hackers. Set to something local to test maybe?
-HACKERS_EMAIL="pgsql-hackers-testing@localhost"
+HACKERS_EMAIL = "pgsql-hackers-testing@localhost"
# Email address for outgoing system messages
-NOTIFICATION_FROM="[email protected]"
+NOTIFICATION_FROM = "[email protected]"
# Load local settings overrides
try:
- from local_settings import *
+ from local_settings import *
except ImportError:
- pass
+ pass
diff --git a/pgcommitfest/urls.py b/pgcommitfest/urls.py
index 109a341..71b1306 100644
--- a/pgcommitfest/urls.py
+++ b/pgcommitfest/urls.py
@@ -1,16 +1,17 @@
from django.conf.urls import include, url
from django.contrib import admin
-# Uncomment the next two lines to enable the admin:
-# from django.contrib import admin
-admin.autodiscover()
-
import pgcommitfest.commitfest.views as views
import pgcommitfest.commitfest.reports as reports
import pgcommitfest.commitfest.ajax as ajax
import pgcommitfest.auth
import pgcommitfest.userprofile.views
+# Uncomment the next two lines to enable the admin:
+# from django.contrib import admin
+admin.autodiscover()
+
+
urlpatterns = [
url(r'^$', views.home),
url(r'^activity(?P<rss>\.rss)?/', views.activity),
diff --git a/pgcommitfest/userprofile/admin.py b/pgcommitfest/userprofile/admin.py
index 4b73d1f..bef236d 100644
--- a/pgcommitfest/userprofile/admin.py
+++ b/pgcommitfest/userprofile/admin.py
@@ -2,7 +2,9 @@ from django.contrib import admin
from models import UserProfile
+
class UserProfileAdmin(admin.ModelAdmin):
list_display = ('user', )
+
admin.site.register(UserProfile, UserProfileAdmin)
diff --git a/pgcommitfest/userprofile/forms.py b/pgcommitfest/userprofile/forms.py
index 400a068..8fc687f 100644
--- a/pgcommitfest/userprofile/forms.py
+++ b/pgcommitfest/userprofile/forms.py
@@ -3,6 +3,7 @@ from django.contrib.auth.models import User
from models import UserProfile, UserExtraEmail
+
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
@@ -12,10 +13,11 @@ class UserProfileForm(forms.ModelForm):
super(UserProfileForm, self).__init__(*args, **kwargs)
self.user = user
- self.fields['selectedemail'].empty_label=self.user.email
- self.fields['selectedemail'].queryset=UserExtraEmail.objects.filter(user=self.user, confirmed=True)
- self.fields['notifyemail'].empty_label=self.user.email
- self.fields['notifyemail'].queryset=UserExtraEmail.objects.filter(user=self.user, confirmed=True)
+ self.fields['selectedemail'].empty_label = self.user.email
+ self.fields['selectedemail'].queryset = UserExtraEmail.objects.filter(user=self.user, confirmed=True)
+ self.fields['notifyemail'].empty_label = self.user.email
+ self.fields['notifyemail'].queryset = UserExtraEmail.objects.filter(user=self.user, confirmed=True)
+
class MailForm(forms.Form):
email = forms.EmailField()
@@ -32,7 +34,7 @@ class MailForm(forms.Form):
def clean_email2(self):
# If the primary email checker had an exception, the data will be gone
# from the cleaned_data structure
- if not self.cleaned_data.has_key('email'):
+ if 'email' not in self.cleaned_data:
return self.cleaned_data['email2']
email1 = self.cleaned_data['email']
email2 = self.cleaned_data['email2']
diff --git a/pgcommitfest/userprofile/models.py b/pgcommitfest/userprofile/models.py
index 367e0bd..759df48 100644
--- a/pgcommitfest/userprofile/models.py
+++ b/pgcommitfest/userprofile/models.py
@@ -1,6 +1,7 @@
from django.db import models
from django.contrib.auth.models import User
+
class UserExtraEmail(models.Model):
user = models.ForeignKey(User, null=False, blank=False, db_index=True)
email = models.EmailField(max_length=100, null=False, blank=False, unique=True)
diff --git a/pgcommitfest/userprofile/util.py b/pgcommitfest/userprofile/util.py
index bd2bcc8..a72bd09 100644
--- a/pgcommitfest/userprofile/util.py
+++ b/pgcommitfest/userprofile/util.py
@@ -5,6 +5,7 @@ from email.header import Header
from models import UserProfile
+
def generate_random_token():
"""
Generate a random token of 64 characters. This token will be
diff --git a/pgcommitfest/userprofile/views.py b/pgcommitfest/userprofile/views.py
index 62e09ea..49ffe08 100644
--- a/pgcommitfest/userprofile/views.py
+++ b/pgcommitfest/userprofile/views.py
@@ -14,6 +14,7 @@ from models import UserProfile, UserExtraEmail
from forms import UserProfileForm, MailForm
from util import generate_random_token
+
@login_required
@transaction.atomic
def userprofile(request):
@@ -59,7 +60,8 @@ def userprofile(request):
'form': form,
'extramails': extramails,
'mailform': mailform,
- })
+ })
+
@login_required
@transaction.atomic
@@ -80,6 +82,7 @@ def deletemail(request):
e.delete()
return HttpResponseRedirect('../')
+
@login_required
@transaction.atomic
def confirmemail(request, tokenhash):
diff --git a/tools/commitfest/check_patches_in_archives.py b/tools/commitfest/check_patches_in_archives.py
index b8b2953..f3c8a90 100755
--- a/tools/commitfest/check_patches_in_archives.py
+++ b/tools/commitfest/check_patches_in_archives.py
@@ -26,62 +26,62 @@ from django.conf import settings
from pgcommitfest.commitfest.models import MailThreadAttachment
if __name__ == "__main__":
- debug = "--debug" in sys.argv
+ debug = "--debug" in sys.argv
- # Logging always done to stdout, but we can turn on/off how much
- logging.basicConfig(format='%(asctime)s %(levelname)s: %(msg)s',
- level=debug and logging.DEBUG or logging.INFO,
- stream=sys.stdout)
+ # Logging always done to stdout, but we can turn on/off how much
+ logging.basicConfig(format='%(asctime)s %(levelname)s: %(msg)s',
+ level=debug and logging.DEBUG or logging.INFO,
+ stream=sys.stdout)
- socket.setdefaulttimeout(settings.ARCHIVES_TIMEOUT)
- mag = magic.open(magic.MIME)
- mag.load()
+ socket.setdefaulttimeout(settings.ARCHIVES_TIMEOUT)
+ mag = magic.open(magic.MIME)
+ mag.load()
- logging.debug("Updating attachment metadata from archives")
+ logging.debug("Updating attachment metadata from archives")
- # Try to fetch/scan all attachments that haven't already been scanned.
- # If they have already been scanned, we don't bother.
- # We will hit the archives without delay when doing this, but that
- # should generally not be a problem because it's not going to be
- # downloading a lot...
- for a in MailThreadAttachment.objects.filter(ispatch=None):
- url = "/message-id/attachment/%s/attach" % a.attachmentid
- logging.debug("Checking attachment %s" % a.attachmentid)
+ # Try to fetch/scan all attachments that haven't already been scanned.
+ # If they have already been scanned, we don't bother.
+ # We will hit the archives without delay when doing this, but that
+ # should generally not be a problem because it's not going to be
+ # downloading a lot...
+ for a in MailThreadAttachment.objects.filter(ispatch=None):
+ url = "/message-id/attachment/%s/attach" % a.attachmentid
+ logging.debug("Checking attachment %s" % a.attachmentid)
- if settings.ARCHIVES_PORT != 443:
- h = httplib.HTTPConnection(host=settings.ARCHIVES_SERVER,
- port=settings.ARCHIVES_PORT,
- strict=True,
- timeout=settings.ARCHIVES_TIMEOUT)
- else:
- h = httplib.HTTPSConnection(host=settings.ARCHIVES_SERVER,
- port=settings.ARCHIVES_PORT,
- strict=True,
- timeout=settings.ARCHIVES_TIMEOUT)
- h.request('GET', url, headers={
- 'Host': settings.ARCHIVES_HOST,
- })
- resp = h.getresponse()
- if resp.status != 200:
- logging.error("Failed to get %s: %s" % (url, resp.status))
- continue
+ if settings.ARCHIVES_PORT != 443:
+ h = httplib.HTTPConnection(host=settings.ARCHIVES_SERVER,
+ port=settings.ARCHIVES_PORT,
+ strict=True,
+ timeout=settings.ARCHIVES_TIMEOUT)
+ else:
+ h = httplib.HTTPSConnection(host=settings.ARCHIVES_SERVER,
+ port=settings.ARCHIVES_PORT,
+ strict=True,
+ timeout=settings.ARCHIVES_TIMEOUT)
+ h.request('GET', url, headers={
+ 'Host': settings.ARCHIVES_HOST,
+ })
+ resp = h.getresponse()
+ if resp.status != 200:
+ logging.error("Failed to get %s: %s" % (url, resp.status))
+ continue
- contents = resp.read()
- resp.close()
- h.close()
+ contents = resp.read()
+ resp.close()
+ h.close()
- # Attempt to identify the file using magic information
- mtype = mag.buffer(contents)
- logging.debug("Detected MIME type is %s" % mtype)
+ # Attempt to identify the file using magic information
+ mtype = mag.buffer(contents)
+ logging.debug("Detected MIME type is %s" % mtype)
- # We don't support gzipped or tar:ed patches or anything like
- # that at this point - just plain patches.
- if mtype.startswith('text/x-diff'):
- a.ispatch = True
- else:
- a.ispatch = False
- logging.info("Attachment %s is patch: %s" % (a.id, a.ispatch))
- a.save()
+ # We don't support gzipped or tar:ed patches or anything like
+ # that at this point - just plain patches.
+ if mtype.startswith('text/x-diff'):
+ a.ispatch = True
+ else:
+ a.ispatch = False
+ logging.info("Attachment %s is patch: %s" % (a.id, a.ispatch))
+ a.save()
- connection.close()
- logging.debug("Done.")
+ connection.close()
+ logging.debug("Done.")
diff --git a/tools/commitfest/oneoff/update_attachment_filenames.py b/tools/commitfest/oneoff/update_attachment_filenames.py
index 3ee675c..9bc1dbe 100755
--- a/tools/commitfest/oneoff/update_attachment_filenames.py
+++ b/tools/commitfest/oneoff/update_attachment_filenames.py
@@ -27,53 +27,53 @@ from django.db import connection
from commitfest.models import MailThreadAttachment
if __name__ == "__main__":
- debug = "--debug" in sys.argv
-
- # Logging always done to stdout, but we can turn on/off how much
- logging.basicConfig(format='%(asctime)s %(levelname)s: %(msg)s',
- level=debug and logging.DEBUG or logging.INFO,
- stream=sys.stdout)
-
- socket.setdefaulttimeout(settings.ARCHIVES_TIMEOUT)
- mag = magic.open(magic.MIME)
- mag.load()
-
- logging.info("Fetching attachment filenames from archives")
-
- for a in MailThreadAttachment.objects.filter(filename=""):
- url = "/message-id.json/%s" % a.messageid
- logging.debug("Checking attachment %s" % a.attachmentid)
-
- h = httplib.HTTPConnection(settings.ARCHIVES_SERVER,
- settings.ARCHIVES_PORT,
- True,
- settings.ARCHIVES_TIMEOUT)
- h.request('GET', url, headers={
- 'Host': settings.ARCHIVES_HOST,
- })
- resp = h.getresponse()
- if resp.status != 200:
- logging.error("Failed to get %s: %s" % (url, resp.status))
- continue
-
- contents = resp.read()
- resp.close()
- h.close()
-
- obj = simplejson.loads(contents)
-
- try:
- for msg in obj:
- for att in msg['atts']:
- if att['id'] == a.attachmentid:
- print "id %s, att id %s, filename %s" % (a.id, a.attachmentid, att['name'])
- a.filename = att['name']
- a.save()
- raise StopIteration
- logging.error("No match found for attachmentid %s" % a.attachmentid)
- except StopIteration:
- # Success
- pass
-
- connection.close()
- logging.debug("Done.")
+ debug = "--debug" in sys.argv
+
+ # Logging always done to stdout, but we can turn on/off how much
+ logging.basicConfig(format='%(asctime)s %(levelname)s: %(msg)s',
+ level=debug and logging.DEBUG or logging.INFO,
+ stream=sys.stdout)
+
+ socket.setdefaulttimeout(settings.ARCHIVES_TIMEOUT)
+ mag = magic.open(magic.MIME)
+ mag.load()
+
+ logging.info("Fetching attachment filenames from archives")
+
+ for a in MailThreadAttachment.objects.filter(filename=""):
+ url = "/message-id.json/%s" % a.messageid
+ logging.debug("Checking attachment %s" % a.attachmentid)
+
+ h = httplib.HTTPConnection(settings.ARCHIVES_SERVER,
+ settings.ARCHIVES_PORT,
+ True,
+ settings.ARCHIVES_TIMEOUT)
+ h.request('GET', url, headers={
+ 'Host': settings.ARCHIVES_HOST,
+ })
+ resp = h.getresponse()
+ if resp.status != 200:
+ logging.error("Failed to get %s: %s" % (url, resp.status))
+ continue
+
+ contents = resp.read()
+ resp.close()
+ h.close()
+
+ obj = simplejson.loads(contents)
+
+ try:
+ for msg in obj:
+ for att in msg['atts']:
+ if att['id'] == a.attachmentid:
+ print "id %s, att id %s, filename %s" % (a.id, a.attachmentid, att['name'])
+ a.filename = att['name']
+ a.save()
+ raise StopIteration
+ logging.error("No match found for attachmentid %s" % a.attachmentid)
+ except StopIteration:
+ # Success
+ pass
+
+ connection.close()
+ logging.debug("Done.")
diff --git a/tools/commitfest/update_archive_threads.py b/tools/commitfest/update_archive_threads.py
index 19dd221..59064f6 100755
--- a/tools/commitfest/update_archive_threads.py
+++ b/tools/commitfest/update_archive_threads.py
@@ -22,17 +22,17 @@ from pgcommitfest.commitfest.models import MailThread
from pgcommitfest.commitfest.ajax import refresh_single_thread
if __name__ == "__main__":
- debug = "--debug" in sys.argv
+ debug = "--debug" in sys.argv
- # Logging always done to stdout, but we can turn on/off how much
- logging.basicConfig(format='%(asctime)s %(levelname)s: %(msg)s',
- level=debug and logging.DEBUG or logging.INFO,
- stream=sys.stdout)
+ # Logging always done to stdout, but we can turn on/off how much
+ logging.basicConfig(format='%(asctime)s %(levelname)s: %(msg)s',
+ level=debug and logging.DEBUG or logging.INFO,
+ stream=sys.stdout)
- logging.debug("Checking for updated mail threads in the archives")
- for thread in MailThread.objects.filter(patches__commitfests__status__in=(1,2,3)).distinct():
- logging.debug("Checking %s in the archives" % thread.messageid)
- refresh_single_thread(thread)
+ logging.debug("Checking for updated mail threads in the archives")
+ for thread in MailThread.objects.filter(patches__commitfests__status__in=(1, 2, 3)).distinct():
+ logging.debug("Checking %s in the archives" % thread.messageid)
+ refresh_single_thread(thread)
- connection.close()
- logging.debug("Done.")
+ connection.close()
+ logging.debug("Done.")
diff --git a/tools/mail/send_queued_mail.py b/tools/mail/send_queued_mail.py
index 84f240d..54848c9 100755
--- a/tools/mail/send_queued_mail.py
+++ b/tools/mail/send_queued_mail.py
@@ -23,23 +23,23 @@ from django.db import connection, transaction
from pgcommitfest.mailqueue.models import QueuedMail
if __name__ == "__main__":
- # Grab advisory lock, if available. Lock id is just a random number
- # since we only need to interlock against ourselves. The lock is
- # automatically released when we're done.
- curs = connection.cursor()
- curs.execute("SELECT pg_try_advisory_lock(72181379)")
- if not curs.fetchall()[0][0]:
- print "Failed to get advisory lock, existing send_queued_mail process stuck?"
- connection.close()
- sys.exit(1)
+ # Grab advisory lock, if available. Lock id is just a random number
+ # since we only need to interlock against ourselves. The lock is
+ # automatically released when we're done.
+ curs = connection.cursor()
+ curs.execute("SELECT pg_try_advisory_lock(72181379)")
+ if not curs.fetchall()[0][0]:
+ print "Failed to get advisory lock, existing send_queued_mail process stuck?"
+ connection.close()
+ sys.exit(1)
- for m in QueuedMail.objects.all():
- # Yes, we do a new connection for each run. Just because we can.
- # If it fails we'll throw an exception and just come back on the
- # next cron job. And local delivery should never fail...
- smtp = smtplib.SMTP("localhost")
- smtp.sendmail(m.sender, m.receiver, m.fullmsg.encode('utf-8'))
- smtp.close()
- m.delete()
- transaction.commit()
- connection.close()
+ for m in QueuedMail.objects.all():
+ # Yes, we do a new connection for each run. Just because we can.
+ # If it fails we'll throw an exception and just come back on the
+ # next cron job. And local delivery should never fail...
+ smtp = smtplib.SMTP("localhost")
+ smtp.sendmail(m.sender, m.receiver, m.fullmsg.encode('utf-8'))
+ smtp.close()
+ m.delete()
+ transaction.commit()
+ connection.close()