# 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 = []
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
reversed = True
if str not in self.order_map.keys():
- (self.order, self.reversed) = self.default_order
return
self.order = str
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
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
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
'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
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)
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: