]> git.ozlabs.org Git - patchwork/commitdiff
Merge branch 'notifications'
authorJeremy Kerr <jk@ozlabs.org>
Mon, 19 Sep 2011 01:42:44 +0000 (09:42 +0800)
committerJeremy Kerr <jk@ozlabs.org>
Mon, 19 Sep 2011 01:42:44 +0000 (09:42 +0800)
1  2 
apps/patchwork/utils.py
apps/settings.py
docs/INSTALL

diff --combined apps/patchwork/utils.py
index 5a8e4c0a4746f700bd201f316db32b0e7519d371,5cb45e8eeaa41191955ead4a9fea3ca434dbb81d..e7619c319091ce2dd9e78396f24ffbe8dac1f6db
  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  
  
- from patchwork.models import Bundle, Project, BundlePatch
+ import itertools
+ import datetime
  from django.shortcuts import get_object_or_404
+ from django.template.loader import render_to_string
+ from django.contrib.sites.models import Site
+ from django.conf import settings
+ from django.core.mail import EmailMessage
+ from django.db.models import Max
+ from patchwork.forms import MultiplePatchForm
+ from patchwork.models import Bundle, Project, BundlePatch, UserProfile, \
+         PatchChangeNotification, EmailOptout
  
  def get_patch_ids(d, prefix = 'patch_id'):
      ids = []
@@@ -49,12 -58,12 +58,12 @@@ class Order(object)
      def __init__(self, str = None, editable = False):
          self.reversed = False
          self.editable = editable
 +        (self.order, self.reversed) = self.default_order
  
          if self.editable:
              return
  
          if str is None or str == '':
 -            (self.order, self.reversed) = self.default_order
              return
  
          reversed = False
@@@ -63,6 -72,7 +72,6 @@@
              reversed = True
  
          if str not in self.order_map.keys():
 -            (self.order, self.reversed) = self.default_order
              return
  
          self.order = str
@@@ -136,3 -146,60 +145,60 @@@ def set_bundle(user, project, action, d
      bundle.save()
  
      return []
+ def send_notifications():
+     date_limit = datetime.datetime.now() - \
+                      datetime.timedelta(minutes =
+                                 settings.NOTIFICATION_DELAY_MINUTES)
+     # This gets funky: we want to filter out any notifications that should
+     # be grouped with other notifications that aren't ready to go out yet. To
+     # do that, we join back onto PatchChangeNotification (PCN -> Patch ->
+     # Person -> Patch -> max(PCN.last_modified)), filtering out any maxima
+     # that are with the date_limit.
+     qs = PatchChangeNotification.objects \
+             .annotate(m = Max('patch__submitter__patch__patchchangenotification'
+                         '__last_modified')) \
+                 .filter(m__lt = date_limit)
+     groups = itertools.groupby(qs.order_by('patch__submitter'),
+                                lambda n: n.patch.submitter)
+     errors = []
+     for (recipient, notifications) in groups:
+         notifications = list(notifications)
+         def delete_notifications():
+             PatchChangeNotification.objects.filter(
+                                 pk__in = notifications).delete()
+         if EmailOptout.is_optout(recipient.email):
+             delete_notifications()
+             continue
+         context = {
+             'site': Site.objects.get_current(),
+             'person': recipient,
+             'notifications': notifications,
+         }
+         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 ex:
+             errors.append((recipient, ex))
+             continue
+         delete_notifications()
+     return errors
diff --combined apps/settings.py
index 24d376259dff926ecab7ee9ebfca3ef670b7a19b,4432f3f04d7cbdf953e21d70bc87ba5b78d3cfa4..7523099374cc09922008bc3cb3ddc3f81b101842
@@@ -10,12 -10,12 +10,12 @@@ ADMINS = 
  
  MANAGERS = ADMINS
  
 -DATABASE_ENGINE = 'postgresql_psycopg2'           # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'.
 -DATABASE_NAME = 'patchwork'             # Or path to database file if using sqlite3.
 -DATABASE_USER = ''             # Not used with sqlite3.
 -DATABASE_PASSWORD = ''         # Not used with sqlite3.
 -DATABASE_HOST = ''             # Set to empty string for localhost. Not used with sqlite3.
 -DATABASE_PORT = ''             # Set to empty string for default. Not used with sqlite3.
 +DATABASES = {
 +    'default': {
 +        'ENGINE': 'django.db.backends.postgresql_psycopg2',
 +        'NAME': 'patchwork',
 +    },
 +}
  
  # Local time zone for this installation. Choices can be found here:
  # http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE
@@@ -64,7 -64,7 +64,7 @@@ MIDDLEWARE_CLASSES = 
  
  ROOT_URLCONF = 'apps.urls'
  
- LOGIN_URL = '/accounts/login'
+ LOGIN_URL = '/user/login/'
  LOGIN_REDIRECT_URL = '/user/'
  
  # If you change the ROOT_DIR setting in your local_settings.py, you'll need to
@@@ -96,13 -96,15 +96,15 @@@ INSTALLED_APPS = 
      'django.contrib.sites',
      'django.contrib.admin',
      'patchwork',
-     'registration',
  )
  
  DEFAULT_PATCHES_PER_PAGE = 100
  DEFAULT_FROM_EMAIL = 'Patchwork <patchwork@patchwork.example.com>'
  
- ACCOUNT_ACTIVATION_DAYS = 7
+ CONFIRMATION_VALIDITY_DAYS = 7
+ NOTIFICATION_DELAY_MINUTES = 10
+ NOTIFICATION_FROM_EMAIL = DEFAULT_FROM_EMAIL
  
  # Set to True to enable the Patchwork XML-RPC interface
  ENABLE_XMLRPC = False
diff --combined docs/INSTALL
index ee87e4d5d58837c87a525f6b1e922ce77a361996,050fc9f10a4cefcef22454967d2d234ee3326d30..c63d6f707e08690c38539a15247bd5a09ebb1df0
@@@ -3,13 -3,13 +3,13 @@@ Deploying Patchwor
  Patchwork uses the django framework - there is some background on deploying
  django applications here:
  
 - http://www.djangobook.com/en/1.0/chapter20/
 + http://www.djangobook.com/en/2.0/chapter12/
  
  You'll need the following (applications used for patchwork development are
  in brackets):
  
    * A python interpreter
 -  * django
 +  * django >= 1.2
    * A webserver (apache)
    * mod_python or flup
    * A database server (postgresql)
@@@ -73,7 -73,7 +73,7 @@@
          lib/packages is for stuff we'll download, lib/python is to add
          to our python path. We'll symlink python modules into lib/python.
  
 -        At the time of release, patchwork depends on django version 1.0 or
 +        At the time of release, patchwork depends on django version 1.2 or
          later. Your distro probably provides this. If not, do a:
  
           cd lib/packages
           cd ../python
           ln -s ../packages/django/django ./django
  
-         We also use the django-registration infrastructure from
-         http://bitbucket.org/ubernostrum/django-registration/. Your distro
-         may provide the django-registration python module (in Ubuntu/Debian it's
-         called 'python-django-registration'). If not, download the module
-         and symlink it to lib/python/ :
-          cd lib/packages/
-          hg clone http://bitbucket.org/ubernostrum/django-registration/
-          cd ../python
-          ln -s ../packages/django-registration/registration ./registration
          We also use some Javascript libraries:
  
           cd lib/packages
            ADMINS
            TIME_ZONE
            LANGUAGE_CODE
+           DEFAULT_FROM_EMAIL
+           NOTIFICATION_FROM_EMAIL
  
          You can generate the SECRET_KEY with the following python code: