Merge lp:~danilo/launchpad/bug-720826-links into lp:launchpad/db-devel

Proposed by Данило Шеган
Status: Merged
Approved by: Данило Шеган
Approved revision: no longer in the source branch.
Merged at revision: 10265
Proposed branch: lp:~danilo/launchpad/bug-720826-links
Merge into: lp:launchpad/db-devel
Prerequisite: lp:~danilo/launchpad/bug-720826-emails
Diff against target: 153 lines (+39/-6)
5 files modified
lib/lp/bugs/configure.zcml (+4/-0)
lib/lp/bugs/doc/bugnotification-sending.txt (+9/-3)
lib/lp/bugs/mail/bugnotificationrecipients.py (+11/-0)
lib/lp/bugs/model/bugnotification.py (+11/-0)
lib/lp/bugs/model/structuralsubscription.py (+4/-3)
To merge this branch: bzr merge lp:~danilo/launchpad/bug-720826-links
Reviewer Review Type Date Requested Status
Gary Poster (community) Approve
Review via email: mp+52226@code.launchpad.net

Commit message

[r=gary][bug=720826] Populate BugNotificationFilter table with links between BugNotifications and BugSubscriptionFilters to finally close off 720826.

Description of the change

= Bug 720826 =

This finally ties everything up together: we start adding links to
subscription filters that have caused a certain BugNotification to
go off.

Previously, framework for this was provided, and if these links were
there, appropriate email headers and content was added to outgoing
emails.

== Proposed fix ==

 * Extend BugNotificationRecipients to allow holding relevant filters
   along with recipients and reasons they are getting emails
 * Find out what those filters are and add them to the `recipients`
   in structuralsubscription._get_structural_subscribers
 * In BugNotificationSet.addNotification(), we insert appropriate
   linking rows for all the filters present in `recipients`.

== Implementation details ==

BugNotificationRecipients is a structure that is passed around. IMHO, it is somewhat nasty that `recipients` is passed around and updated as a side-effect in a few methods which are called get*, but because it already is, I am abusing it to pass the subscription filters list as well (especially since I can easily calculate them at the same time all the other recipients stuff is calculated).

I am only providing the integration test in bugnotification-sending.txt.

== Tests ==

bin/test -cvvt bugnotification-sending.txt

== Demo and Q/A ==

Add a few subscription filters, and run "cronscripts/send-bug-notifications.py -vvv" and watch for the X-Launchpad-Subscription-Filter and "Matching filters" line.

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/bugs/model/bugnotification.py
  lib/lp/bugs/mail/bugnotificationrecipients.py
  lib/lp/bugs/model/tests/test_bugtask.py
  lib/lp/bugs/doc/bugnotification-sending.txt
  lib/lp/bugs/model/bug.py
  lib/lp/bugs/tests/test_structuralsubscriptiontarget.py
  lib/lp/bugs/model/structuralsubscription.py
  lib/lp/bugs/model/bugtask.py

./lib/lp/bugs/model/bugnotification.py
     132: E202 whitespace before ']'
./lib/lp/bugs/doc/bugnotification-sending.txt
     433: want has trailing whitespace.
     451: want has trailing whitespace.

To post a comment you must log in.
Revision history for this message
Gary Poster (gary) wrote :

Let's remove the distinct=True in the structural subscription code, as we discussed on IRC. It might have made some sense when we were not getting a result per filter, but does not now.

I asked for a test showing multiple filters and you said they existed in unit tests. I'm mostly OK with that as being sufficient here. :-)

Yay, thank you!

review: Approve
Revision history for this message
Данило Шеган (danilo) wrote :

Yep, unit tests are available in "bin/test -cvvt test_header_multiple -t test_body_multiple".

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/bugs/configure.zcml'
--- lib/lp/bugs/configure.zcml 2011-03-02 23:08:54 +0000
+++ lib/lp/bugs/configure.zcml 2011-03-05 17:49:56 +0000
@@ -1056,6 +1056,10 @@
1056 class="lp.bugs.mail.bugnotificationrecipients.BugNotificationRecipients">1056 class="lp.bugs.mail.bugnotificationrecipients.BugNotificationRecipients">
1057 <allow1057 <allow
1058 interface="canonical.launchpad.interfaces.launchpad.INotificationRecipientSet"/>1058 interface="canonical.launchpad.interfaces.launchpad.INotificationRecipientSet"/>
1059 <!-- BugNotificationRecipients provides the following
1060 attributes/methods in addition. -->
1061 <allow
1062 attributes="subscription_filters addFilter"/>
1059 </class>1063 </class>
1060 <securedutility1064 <securedutility
1061 provides="lp.bugs.interfaces.bugnotification.IBugNotificationSet"1065 provides="lp.bugs.interfaces.bugnotification.IBugNotificationSet"
10621066
=== modified file 'lib/lp/bugs/doc/bugnotification-sending.txt'
--- lib/lp/bugs/doc/bugnotification-sending.txt 2011-02-22 10:44:48 +0000
+++ lib/lp/bugs/doc/bugnotification-sending.txt 2011-03-05 17:49:56 +0000
@@ -21,8 +21,10 @@
2121
22 >>> def print_notification_headers(email_notification):22 >>> def print_notification_headers(email_notification):
23 ... for header in ['To', 'From', 'Subject',23 ... for header in ['To', 'From', 'Subject',
24 ... 'X-Launchpad-Message-Rationale']:24 ... 'X-Launchpad-Message-Rationale',
25 ... print "%s: %s" % (header, email_notification[header])25 ... 'X-Launchpad-Subscription-Filter']:
26 ... if email_notification[header]:
27 ... print "%s: %s" % (header, email_notification[header])
2628
27 >>> def print_notification(email_notification):29 >>> def print_notification(email_notification):
28 ... print_notification_headers(email_notification)30 ... print_notification_headers(email_notification)
@@ -676,7 +678,6 @@
676been set properly.678been set properly.
677679
678 >>> from lp.bugs.model.bugnotification import BugNotification680 >>> from lp.bugs.model.bugnotification import BugNotification
679 >>> from lp.bugs.enum import BugNotificationStatus
680 >>> for notification in BugNotification.select(orderBy='id')[-8:]:681 >>> for notification in BugNotification.select(orderBy='id')[-8:]:
681 ... if notification.is_comment:682 ... if notification.is_comment:
682 ... identifier = 'comment'683 ... identifier = 'comment'
@@ -1247,6 +1248,7 @@
1247 >>> with lp_dbuser():1248 >>> with lp_dbuser():
1248 ... filter = subscription_no_priv.newBugFilter()1249 ... filter = subscription_no_priv.newBugFilter()
1249 ... filter.bug_notification_level = BugNotificationLevel.COMMENTS1250 ... filter.bug_notification_level = BugNotificationLevel.COMMENTS
1251 ... filter.description = u"Allow-comments filter"
12501252
1251 >>> comment = getUtility(IMessageSet).fromText(1253 >>> comment = getUtility(IMessageSet).fromText(
1252 ... 'subject', 'another comment.', sample_person,1254 ... 'subject', 'another comment.', sample_person,
@@ -1279,12 +1281,14 @@
1279 From: Sample Person <...@bugs.launchpad.net>1281 From: Sample Person <...@bugs.launchpad.net>
1280 Subject: [Bug 1] subject1282 Subject: [Bug 1] subject
1281 X-Launchpad-Message-Rationale: Subscriber (Mozilla Firefox)1283 X-Launchpad-Message-Rationale: Subscriber (Mozilla Firefox)
1284 X-Launchpad-Subscription-Filter: Allow-comments filter
1282 <BLANKLINE>1285 <BLANKLINE>
1283 another comment.1286 another comment.
1284 <BLANKLINE>1287 <BLANKLINE>
1285 --1288 --
1286 You received this bug notification because you are subscribed to Mozilla1289 You received this bug notification because you are subscribed to Mozilla
1287 Firefox.1290 Firefox.
1291 Matching filters: Allow-comments filter
1288 ...1292 ...
1289 ----------------------------------------------------------------------1293 ----------------------------------------------------------------------
1290 To: support@ubuntu.com1294 To: support@ubuntu.com
@@ -1390,6 +1394,7 @@
1390 From: Sample Person <...@bugs.launchpad.net>1394 From: Sample Person <...@bugs.launchpad.net>
1391 Subject: [Bug 1] subject1395 Subject: [Bug 1] subject
1392 X-Launchpad-Message-Rationale: Subscriber (Mozilla Firefox)1396 X-Launchpad-Message-Rationale: Subscriber (Mozilla Firefox)
1397 X-Launchpad-Subscription-Filter: Allow-comments filter
1393 <BLANKLINE>1398 <BLANKLINE>
1394 no comment for no-priv.1399 no comment for no-priv.
1395 <BLANKLINE>1400 <BLANKLINE>
@@ -1400,6 +1405,7 @@
1400 --1405 --
1401 You received this bug notification because you are subscribed to Mozilla1406 You received this bug notification because you are subscribed to Mozilla
1402 Firefox.1407 Firefox.
1408 Matching filters: Allow-comments filter
1403 ...1409 ...
1404 ----------------------------------------------------------------------1410 ----------------------------------------------------------------------
1405 To: support@ubuntu.com1411 To: support@ubuntu.com
14061412
=== modified file 'lib/lp/bugs/mail/bugnotificationrecipients.py'
--- lib/lp/bugs/mail/bugnotificationrecipients.py 2011-03-02 14:07:23 +0000
+++ lib/lp/bugs/mail/bugnotificationrecipients.py 2011-03-05 17:49:56 +0000
@@ -58,6 +58,7 @@
58 """58 """
59 NotificationRecipientSet.__init__(self)59 NotificationRecipientSet.__init__(self)
60 self.duplicateof = duplicateof60 self.duplicateof = duplicateof
61 self.subscription_filters = set()
6162
62 def _addReason(self, person, reason, header):63 def _addReason(self, person, reason, header):
63 """Adds a reason (text and header) for a person.64 """Adds a reason (text and header) for a person.
@@ -127,3 +128,13 @@
127 else:128 else:
128 text = "are the registrant for %s" % upstream.displayname129 text = "are the registrant for %s" % upstream.displayname
129 self._addReason(person, text, reason)130 self._addReason(person, text, reason)
131
132 def update(self, recipient_set):
133 """See `INotificationRecipientSet`."""
134 super(BugNotificationRecipients, self).update(recipient_set)
135 self.subscription_filters.update(
136 recipient_set.subscription_filters)
137
138 def addFilter(self, subscription_filter):
139 if subscription_filter is not None:
140 self.subscription_filters.add(subscription_filter)
130141
=== modified file 'lib/lp/bugs/model/bugnotification.py'
--- lib/lp/bugs/model/bugnotification.py 2011-02-25 16:19:58 +0000
+++ lib/lp/bugs/model/bugnotification.py 2011-03-05 17:49:56 +0000
@@ -150,12 +150,23 @@
150 reason_body, reason_header = recipients.getReason(recipient)150 reason_body, reason_header = recipients.getReason(recipient)
151 sql_values.append('(%s, %s, %s, %s)' % sqlvalues(151 sql_values.append('(%s, %s, %s, %s)' % sqlvalues(
152 bug_notification, recipient, reason_header, reason_body))152 bug_notification, recipient, reason_header, reason_body))
153
153 # We add all the recipients in a single SQL statement to make154 # We add all the recipients in a single SQL statement to make
154 # this a bit more efficient for bugs with many subscribers.155 # this a bit more efficient for bugs with many subscribers.
155 store.execute("""156 store.execute("""
156 INSERT INTO BugNotificationRecipient157 INSERT INTO BugNotificationRecipient
157 (bug_notification, person, reason_header, reason_body)158 (bug_notification, person, reason_header, reason_body)
158 VALUES %s;""" % ', '.join(sql_values))159 VALUES %s;""" % ', '.join(sql_values))
160
161 if len(recipients.subscription_filters) > 0:
162 filter_link_sql = [
163 "(%s, %s)" % sqlvalues(bug_notification, filter.id)
164 for filter in recipients.subscription_filters]
165 store.execute("""
166 INSERT INTO BugNotificationFilter
167 (bug_notification, bug_subscription_filter)
168 VALUES %s;""" % ", ".join(filter_link_sql))
169
159 return bug_notification170 return bug_notification
160171
161172
162173
=== modified file 'lib/lp/bugs/model/structuralsubscription.py'
--- lib/lp/bugs/model/structuralsubscription.py 2011-03-04 02:29:09 +0000
+++ lib/lp/bugs/model/structuralsubscription.py 2011-03-05 17:49:56 +0000
@@ -585,14 +585,15 @@
585 else:585 else:
586 subscribers = []586 subscribers = []
587 query_results = source.find(587 query_results = source.find(
588 (Person, StructuralSubscription),588 (Person, StructuralSubscription, BugSubscriptionFilter),
589 *constraints).config(distinct=True)589 *constraints)
590 for person, subscription in query_results:590 for person, subscription, filter in query_results:
591 # Set up results.591 # Set up results.
592 if person not in recipients:592 if person not in recipients:
593 subscribers.append(person)593 subscribers.append(person)
594 recipients.addStructuralSubscriber(594 recipients.addStructuralSubscriber(
595 person, subscription.target)595 person, subscription.target)
596 recipients.addFilter(filter)
596 return subscribers597 return subscribers
597598
598599

Subscribers

People subscribed via source and target branches

to status/vote changes: