diff options
author | Magnus Hagander | 2019-02-05 22:55:23 +0000 |
---|---|---|
committer | Magnus Hagander | 2019-02-06 09:29:00 +0000 |
commit | 463b3c1fe2e5bea061269ed9eea4b876a9eab213 (patch) | |
tree | c7f6f057b238434b4865129e2a4f61312be4d274 | |
parent | a32f4007670330d05a834db1b67687ab8b8c3b34 (diff) |
Fixes for pep8 compatibility
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() |