[PATCH 2/2] utils: Rename to 'notifications'
Stephen Finucane
stephenfinucane at hotmail.com
Fri Sep 2 07:38:54 AEST 2016
Every function in this file is related to notifications. Rename the
file and functions therein to something more meaningful.
Signed-off-by: Stephen Finucane <stephenfinucane at hotmail.com>
---
patchwork/management/commands/cron.py | 5 +-
patchwork/notifications.py | 116 ++++++++++++++++++++++++++++++++++
patchwork/tests/test_expiry.py | 10 +--
patchwork/tests/test_notifications.py | 2 +-
patchwork/utils.py | 113 ---------------------------------
5 files changed, 125 insertions(+), 121 deletions(-)
create mode 100644 patchwork/notifications.py
delete mode 100644 patchwork/utils.py
diff --git a/patchwork/management/commands/cron.py b/patchwork/management/commands/cron.py
index 4272177..e3e906a 100644
--- a/patchwork/management/commands/cron.py
+++ b/patchwork/management/commands/cron.py
@@ -19,7 +19,8 @@
from django.core.management.base import BaseCommand
-from patchwork.utils import send_notifications, do_expiry
+from patchwork.notifications import expire_notifications
+from patchwork.notifications import send_notifications
class Command(BaseCommand):
@@ -32,4 +33,4 @@ class Command(BaseCommand):
self.stderr.write("Failed sending to %s: %s" %
(recipient.email, error))
- do_expiry()
+ expire_notifications()
diff --git a/patchwork/notifications.py b/patchwork/notifications.py
new file mode 100644
index 0000000..5420401
--- /dev/null
+++ b/patchwork/notifications.py
@@ -0,0 +1,116 @@
+# Patchwork - automated patch tracking system
+# Copyright (C) 2008 Jeremy Kerr <jk at ozlabs.org>
+#
+# This file is part of the Patchwork package.
+#
+# Patchwork is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Patchwork is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Patchwork; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import datetime
+import itertools
+
+from django.conf import settings
+from django.contrib.auth.models import User
+from django.contrib.sites.models import Site
+from django.core.mail import EmailMessage
+from django.db.models import Count, Q, F
+
+from patchwork.compat import render_to_string
+from patchwork.models import EmailConfirmation
+from patchwork.models import EmailOptout
+from patchwork.models import PatchChangeNotification
+
+
+def send_notifications():
+ date_limit = datetime.datetime.now() - datetime.timedelta(
+ minutes=settings.NOTIFICATION_DELAY_MINUTES)
+
+ # We delay sending notifications to a user if they have other
+ # notifications that are still in the "pending" state. To do this,
+ # we compare the total number of patch change notifications queued
+ # for each user against the number of "ready" notifications.
+ qs = PatchChangeNotification.objects.all()
+ qs2 = PatchChangeNotification.objects\
+ .filter(last_modified__lt=date_limit)\
+ .values('patch__submitter')\
+ .annotate(count=Count('patch__submitter'))
+ qs2 = {elem['patch__submitter']: elem['count'] for elem in qs2}
+
+ groups = itertools.groupby(qs.order_by('patch__submitter'),
+ lambda n: n.patch.submitter)
+
+ errors = []
+
+ for (recipient, notifications) in groups:
+ notifications = list(notifications)
+
+ if recipient.id not in qs2 or qs2[recipient.id] < len(notifications):
+ continue
+
+ projects = set([n.patch.project.linkname for n in notifications])
+
+ def delete_notifications():
+ pks = [n.pk for n in notifications]
+ PatchChangeNotification.objects.filter(pk__in=pks).delete()
+
+ if EmailOptout.is_optout(recipient.email):
+ delete_notifications()
+ continue
+
+ context = {
+ 'site': Site.objects.get_current(),
+ 'notifications': notifications,
+ 'projects': projects,
+ }
+
+ subject = render_to_string(
+ 'patchwork/patch-change-notification-subject.text',
+ context).strip()
+ content = render_to_string('patchwork/patch-change-notification.mail',
+ context)
+
+ message = EmailMessage(subject=subject, body=content,
+ from_email=settings.NOTIFICATION_FROM_EMAIL,
+ to=[recipient.email],
+ headers={'Precedence': 'bulk'})
+
+ try:
+ message.send()
+ except Exception as ex:
+ errors.append((recipient, ex))
+ continue
+
+ delete_notifications()
+
+ return errors
+
+
+def expire_notifications():
+ """Expire any pending confirmations.
+
+ Users whose registration confirmation has expired are removed.
+ """
+ # expire any invalid confirmations
+ q = (Q(date__lt=datetime.datetime.now() - EmailConfirmation.validity) |
+ Q(active=False))
+ EmailConfirmation.objects.filter(q).delete()
+
+ # remove inactive users with no pending confirmation
+ pending_confs = EmailConfirmation.objects.values('user')
+ users = User.objects.filter(is_active=False,
+ last_login=F('date_joined')).exclude(
+ id__in=pending_confs)
+
+ # delete users
+ users.delete()
diff --git a/patchwork/tests/test_expiry.py b/patchwork/tests/test_expiry.py
index 7622464..054d156 100644
--- a/patchwork/tests/test_expiry.py
+++ b/patchwork/tests/test_expiry.py
@@ -25,9 +25,9 @@ from django.test import TestCase
from patchwork.models import EmailConfirmation
from patchwork.models import Patch
from patchwork.models import Person
+from patchwork.notifications import expire_notifications
from patchwork.tests.utils import create_patch
from patchwork.tests.utils import create_user
-from patchwork.utils import do_expiry
class TestRegistrationExpiry(TestCase):
@@ -50,7 +50,7 @@ class TestRegistrationExpiry(TestCase):
datetime.timedelta(hours=1))
user, conf = self.register(date)
- do_expiry()
+ expire_notifications()
self.assertFalse(User.objects.filter(pk=user.pk).exists())
self.assertFalse(
@@ -61,7 +61,7 @@ class TestRegistrationExpiry(TestCase):
datetime.timedelta(hours=1))
user, conf = self.register(date)
- do_expiry()
+ expire_notifications()
self.assertTrue(User.objects.filter(pk=user.pk).exists())
self.assertTrue(
@@ -75,7 +75,7 @@ class TestRegistrationExpiry(TestCase):
conf.user.save()
conf.deactivate()
- do_expiry()
+ expire_notifications()
self.assertTrue(User.objects.filter(pk=user.pk).exists())
self.assertFalse(
@@ -100,7 +100,7 @@ class TestRegistrationExpiry(TestCase):
conf.save()
# ... which expires
- do_expiry()
+ expire_notifications()
# we should see no matching user
self.assertFalse(User.objects.filter(email=patch.submitter.email)
diff --git a/patchwork/tests/test_notifications.py b/patchwork/tests/test_notifications.py
index 5c426fc..6cd3200 100644
--- a/patchwork/tests/test_notifications.py
+++ b/patchwork/tests/test_notifications.py
@@ -25,11 +25,11 @@ from django.test import TestCase
from patchwork.models import EmailOptout
from patchwork.models import PatchChangeNotification
+from patchwork.notifications import send_notifications
from patchwork.tests.utils import create_patch
from patchwork.tests.utils import create_patches
from patchwork.tests.utils import create_project
from patchwork.tests.utils import create_state
-from patchwork.utils import send_notifications
class PatchNotificationModelTest(TestCase):
diff --git a/patchwork/utils.py b/patchwork/utils.py
deleted file mode 100644
index b496af4..0000000
--- a/patchwork/utils.py
+++ /dev/null
@@ -1,113 +0,0 @@
-# Patchwork - automated patch tracking system
-# Copyright (C) 2008 Jeremy Kerr <jk at ozlabs.org>
-#
-# This file is part of the Patchwork package.
-#
-# Patchwork is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# Patchwork is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Patchwork; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-from __future__ import absolute_import
-
-import datetime
-import itertools
-
-from django.conf import settings
-from django.contrib.auth.models import User
-from django.contrib.sites.models import Site
-from django.core.mail import EmailMessage
-from django.db.models import Count, Q, F
-
-from patchwork.compat import render_to_string
-from patchwork.models import (PatchChangeNotification, EmailOptout,
- EmailConfirmation)
-
-
-def send_notifications():
- date_limit = datetime.datetime.now() - datetime.timedelta(
- minutes=settings.NOTIFICATION_DELAY_MINUTES)
-
- # We delay sending notifications to a user if they have other
- # notifications that are still in the "pending" state. To do this,
- # we compare the total number of patch change notifications queued
- # for each user against the number of "ready" notifications.
- qs = PatchChangeNotification.objects.all()
- qs2 = PatchChangeNotification.objects\
- .filter(last_modified__lt=date_limit)\
- .values('patch__submitter')\
- .annotate(count=Count('patch__submitter'))
- qs2 = {elem['patch__submitter']: elem['count'] for elem in qs2}
-
- groups = itertools.groupby(qs.order_by('patch__submitter'),
- lambda n: n.patch.submitter)
-
- errors = []
-
- for (recipient, notifications) in groups:
- notifications = list(notifications)
-
- if recipient.id not in qs2 or qs2[recipient.id] < len(notifications):
- continue
-
- projects = set([n.patch.project.linkname for n in notifications])
-
- def delete_notifications():
- pks = [n.pk for n in notifications]
- PatchChangeNotification.objects.filter(pk__in=pks).delete()
-
- if EmailOptout.is_optout(recipient.email):
- delete_notifications()
- continue
-
- context = {
- 'site': Site.objects.get_current(),
- 'notifications': notifications,
- 'projects': projects,
- }
-
- subject = render_to_string(
- 'patchwork/patch-change-notification-subject.text',
- context).strip()
- content = render_to_string('patchwork/patch-change-notification.mail',
- context)
-
- message = EmailMessage(subject=subject, body=content,
- from_email=settings.NOTIFICATION_FROM_EMAIL,
- to=[recipient.email],
- headers={'Precedence': 'bulk'})
-
- try:
- message.send()
- except Exception as ex:
- errors.append((recipient, ex))
- continue
-
- delete_notifications()
-
- return errors
-
-
-def do_expiry():
- # expire any pending confirmations
- q = (Q(date__lt=datetime.datetime.now() - EmailConfirmation.validity) |
- Q(active=False))
- EmailConfirmation.objects.filter(q).delete()
-
- # expire inactive users with no pending confirmation
- pending_confs = EmailConfirmation.objects.values('user')
- users = User.objects.filter(is_active=False,
- last_login=F('date_joined')).exclude(
- id__in=pending_confs)
-
- # delete users
- users.delete()
--
2.7.4
More information about the Patchwork
mailing list