~launchpad-pqm/launchpad/devel

10322.3.2 by Curtis Hovey
Added a unit test for personnotifications.
1
# Copyright 2010 Canonical Ltd.  This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
3
4
"""Person notification script utilities."""
5
6
__all__ = [
7
    'PersonNotificationManager',
8
    ]
9
10
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
11
from datetime import (
12
    datetime,
13
    timedelta,
14
    )
15
10322.3.2 by Curtis Hovey
Added a unit test for personnotifications.
16
import pytz
17
from zope.component import getUtility
18
14605.1.1 by Curtis Hovey
Moved canonical.config to lp.services.
19
from lp.services.config import config
10322.3.2 by Curtis Hovey
Added a unit test for personnotifications.
20
from lp.registry.interfaces.personnotification import IPersonNotificationSet
21
22
23
class PersonNotificationManager:
24
25
    def __init__(self, txn, logger):
26
        """Initialize the manager with a transaction manager and logger."""
27
        self.txn = txn
28
        self.logger = logger
29
30
    def sendNotifications(self):
31
        """Send notifications to users."""
32
        notifications_sent = False
10322.3.6 by Curtis Hovey
Updated names and doc.
33
        unsent_notifications = []
10322.3.2 by Curtis Hovey
Added a unit test for personnotifications.
34
        notification_set = getUtility(IPersonNotificationSet)
35
        pending_notifications = notification_set.getNotificationsToSend()
36
        self.logger.info(
37
            '%d notification(s) to send.' % pending_notifications.count())
38
        for notification in pending_notifications:
39
            person = notification.person
12589.6.10 by Curtis Hovey
Added to_addresses and can_send to IPersonNotification.
40
            if not notification.can_send:
10322.3.6 by Curtis Hovey
Updated names and doc.
41
                unsent_notifications.append(notification)
10322.3.2 by Curtis Hovey
Added a unit test for personnotifications.
42
                self.logger.info(
43
                    "%s has no email address." % person.name)
44
                continue
13082.1.3 by William Grant
Log the email addresses inside PN.send.
45
            self.logger.info("Notifying %s." % person.name)
46
            notification.send(logger=self.logger)
10322.3.2 by Curtis Hovey
Added a unit test for personnotifications.
47
            notifications_sent = True
48
            # Commit after each email sent, so that we won't re-mail the
49
            # notifications in case of something going wrong in the middle.
50
            self.txn.commit()
51
        if not notifications_sent:
52
            self.logger.debug("No notifications were sent.")
10322.3.6 by Curtis Hovey
Updated names and doc.
53
        if len(unsent_notifications) == 0:
54
            unsent_notifications = None
55
        return unsent_notifications
10322.3.2 by Curtis Hovey
Added a unit test for personnotifications.
56
57
    def purgeNotifications(self, extra_notifications=None):
58
        """Delete PersonNotifications that are older than the retention limit.
59
10322.3.6 by Curtis Hovey
Updated names and doc.
60
        The limit is set in the configuration:
61
        person_notification.retained_days
10322.3.2 by Curtis Hovey
Added a unit test for personnotifications.
62
63
        :param extra_messages: a list of additional notifications to
64
            purge. These may be messages to users without email addresses.
65
        """
66
        retained_days = timedelta(
67
            days=int(config.person_notification.retained_days))
68
        time_limit = (datetime.now(pytz.timezone('UTC')) - retained_days)
69
        notification_set = getUtility(IPersonNotificationSet)
70
        to_delete = notification_set.getNotificationsOlderThan(time_limit)
71
        if to_delete.count():
72
            self.logger.info(
73
                "Notification retention limit is %s." % retained_days)
74
            self.logger.info(
75
                "Deleting %d old notification(s)." % to_delete.count())
76
            for notification in to_delete:
77
                notification.destroySelf()
78
            self.txn.commit()
79
        if extra_notifications is not None:
80
            for notification in extra_notifications:
81
                notification.destroySelf()
82
                self.txn.commit()