← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~allenap/launchpad/structural-subscriptions-with-filters-2 into lp:launchpad

 

Gavin Panella has proposed merging lp:~allenap/launchpad/structural-subscriptions-with-filters-2 into lp:launchpad with lp:~allenap/launchpad/structural-subscriptions-with-filters as a prerequisite.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers): code
Related bugs:
  #650991 Add getSubscriptionsForBug to IStructuralSubscriptionTarget
  https://bugs.launchpad.net/bugs/650991


Adds filtering by importance to StructuralSubscriptionTargetMixin.getSubscriptionsForBug().

The tests are getting heavy on set-up, so my next branch is going to be to create some simple helper methods to do that lifting instead.

This is an intermediate branch and probably won't be landed as-is.

-- 
https://code.launchpad.net/~allenap/launchpad/structural-subscriptions-with-filters-2/+merge/37051
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~allenap/launchpad/structural-subscriptions-with-filters-2 into lp:launchpad.
=== modified file 'lib/lp/bugs/stories/structural-subscriptions/xx-bug-subscriptions.txt'
--- lib/lp/bugs/stories/structural-subscriptions/xx-bug-subscriptions.txt	2010-09-14 19:16:47 +0000
+++ lib/lp/bugs/stories/structural-subscriptions/xx-bug-subscriptions.txt	2010-09-29 19:53:06 +0000
@@ -1,4 +1,5 @@
-= Subscriptions to bug notifications =
+Subscriptions to bug notifications
+----------------------------------
 
 Any logged in user can subscribe themselves to bug notifications for any
 Launchpad structure, as well as subscribe any of the teams to which
@@ -64,7 +65,8 @@
         Landscape Developers
 
 
-== Additional options for distribution drivers ==
+Additional options for distribution drivers
+===========================================
 
 When editing the subscriptions for a package, a distribution driver
 can subscribe any Launchpad user.
@@ -97,7 +99,8 @@
 
     >>> for message in find_tags_by_class(browser.contents, 'message'):
     ...     print message.renderContents()
-    No Privileges Person will now receive an e-mail each time someone reports or changes a public bug in "mozilla-firefox in ubuntu".
+    No Privileges Person will now receive an e-mail each time someone reports
+    or changes a public bug in "mozilla-firefox in ubuntu".
 
     >>> print extract_text(find_portlet(browser.contents, 'Bug subscriptions'))
     Bug subscriptions
@@ -117,7 +120,8 @@
     >>> browser.getControl('Save these changes').click()
     >>> print find_tags_by_class(
     ...    browser.contents, 'informational message')[0].contents[0]
-    No Privileges Person will no longer automatically receive e-mail about public bugs in "mozilla-firefox in ubuntu".
+    No Privileges Person will no longer automatically receive e-mail about
+    public bugs in "mozilla-firefox in ubuntu".
     >>> print extract_text(find_portlet(browser.contents, 'Bug subscriptions'))
     Bug subscriptions
       For...mozilla-firefox...package in Ubuntu:
@@ -179,7 +183,8 @@
     LookupError: label '\xa0Foo Bar'
 
 
-== Bug #462742 ==
+Bug #462742
+===========
 
 Loading pages with the subscription menu works fine for anonymous users, even
 when there are existing subscriptions.
@@ -195,7 +200,8 @@
     >>> print anon_browser.title
     Bazaar Version Control System in Launchpad
 
-== Distribution with a bug supervisor ==
+Distribution with a bug supervisor
+==================================
 
 If a distribution has a bug supervisor only that team or members of it can
 subscribe to all of the distribution's bugs.

=== modified file 'lib/lp/registry/doc/structural-subscriptions.txt'
--- lib/lp/registry/doc/structural-subscriptions.txt	2010-08-16 13:50:28 +0000
+++ lib/lp/registry/doc/structural-subscriptions.txt	2010-09-29 19:53:06 +0000
@@ -1,4 +1,5 @@
-= Structural Subscriptions =
+Structural Subscriptions
+------------------------
 
 Structural subscriptions allow a user to subscribe to a launchpad
 structure like a product, project, productseries, distribution,
@@ -44,7 +45,8 @@
     3
 
 
-== Parent subscription targets ==
+Parent subscription targets
+===========================
 
 Some subscription targets relate to other targets hierarchically. An
 IDistribution, for example, can be said to be a parent of all
@@ -68,17 +70,17 @@
     >>> print ff_milestone.parent_subscription_target.displayname
     Mozilla Firefox
 
-   >>> ff_trunk = firefox.getSeries('trunk')
-   >>> ff_trunk.parent_subscription_target == firefox
-   True
-   >>> print ff_trunk.parent_subscription_target.displayname
-   Mozilla Firefox
+    >>> ff_trunk = firefox.getSeries('trunk')
+    >>> ff_trunk.parent_subscription_target == firefox
+    True
+    >>> print ff_trunk.parent_subscription_target.displayname
+    Mozilla Firefox
 
-   >>> warty = ubuntu.getSeries('warty')
-   >>> warty.parent_subscription_target == ubuntu
-   True
-   >>> print warty.parent_subscription_target.displayname
-   Ubuntu
+    >>> warty = ubuntu.getSeries('warty')
+    >>> warty.parent_subscription_target == ubuntu
+    True
+    >>> print warty.parent_subscription_target.displayname
+    Ubuntu
 
 When notifying subscribers of bug activity, both subscribers to the
 target and to the target's parent are notified.
@@ -128,8 +130,6 @@
     >>> print_bug_recipients(recipients)
     name12 "Subscriber (evolution in ubuntu)"
 
-
-
 Foo Bar subscribes to Ubuntu.
 
     >>> login('foo.bar@xxxxxxxxxxxxx')
@@ -198,7 +198,8 @@
     name16
 
 
-== Retrieving structural subscribers of targets ==
+Retrieving structural subscribers of targets
+============================================
 
 Subscribers of one or more targets are retrieved by
 PersonSet.getSubscribersForTargets.
@@ -252,7 +253,8 @@
     name16
 
 
-== Target type display ==
+Target type display
+===================
 
 Structural subscription targets have a `target_type_display` attribute, which
 can be used to refer to them in display.
@@ -263,4 +265,3 @@
     package
     >>> print ff_milestone.target_type_display
     milestone
-    

=== modified file 'lib/lp/registry/model/structuralsubscription.py'
--- lib/lp/registry/model/structuralsubscription.py	2010-09-29 19:53:01 +0000
+++ lib/lp/registry/model/structuralsubscription.py	2010-09-29 19:53:06 +0000
@@ -27,6 +27,9 @@
     )
 from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
 from lp.bugs.model.bugsubscriptionfilter import BugSubscriptionFilter
+from lp.bugs.model.bugsubscriptionfilterimportance import (
+    BugSubscriptionFilterImportance,
+    )
 from lp.bugs.model.bugsubscriptionfilterstatus import (
     BugSubscriptionFilterStatus,
     )
@@ -490,12 +493,27 @@
                 BugSubscriptionFilterStatus,
                 BugSubscriptionFilterStatus.filter_id == (
                     BugSubscriptionFilter.id)),
+            LeftJoin(
+                BugSubscriptionFilterImportance,
+                BugSubscriptionFilterImportance.filter_id == (
+                    BugSubscriptionFilter.id)),
             ]
 
         conditions = [
+            # There's no filter or ...
             Or(BugSubscriptionFilter.id == None,
-               BugSubscriptionFilterStatus.status.is_in(
-                    bugtask.status for bugtask in bugtasks)),
+               # there is a filter ...
+               And(
+                    # there's no status filter, or there is a status filter
+                    # and and it matches.
+                    Or(BugSubscriptionFilterStatus.id == None,
+                       BugSubscriptionFilterStatus.status.is_in(
+                            bugtask.status for bugtask in bugtasks)),
+                    # there's no importance filter, or there is an importance
+                    # filter and it matches.
+                    Or(BugSubscriptionFilterImportance.id == None,
+                       BugSubscriptionFilterImportance.importance.is_in(
+                            bugtask.importance for bugtask in bugtasks)))),
             ]
 
         return Store.of(self.__helper.pillar).using(*origin).find(

=== modified file 'lib/lp/registry/tests/structural-subscription-target.txt'
--- lib/lp/registry/tests/structural-subscription-target.txt	2010-08-18 15:52:41 +0000
+++ lib/lp/registry/tests/structural-subscription-target.txt	2010-09-29 19:53:06 +0000
@@ -1,5 +1,5 @@
-= IStructuralSubscriptionTarget =
-
+IStructuralSubscriptionTarget
+-----------------------------
 
 Let's subscribe ubuntu-team.
 
@@ -61,7 +61,8 @@
     ubuntu-team COMMENTS NOTHING
 
 
-=== Structural subscriptions and indirect bug subscriptions ===
+Structural subscriptions and indirect bug subscriptions
+=======================================================
 
     >>> bug = filebug(target, 'test bug one')
     >>> indirect_subscribers = set(

=== modified file 'lib/lp/registry/tests/test_structuralsubscriptiontarget.py'
--- lib/lp/registry/tests/test_structuralsubscriptiontarget.py	2010-09-29 19:53:01 +0000
+++ lib/lp/registry/tests/test_structuralsubscriptiontarget.py	2010-09-29 19:53:06 +0000
@@ -28,8 +28,14 @@
     LaunchpadZopelessLayer,
     )
 from lp.bugs.interfaces.bug import CreateBugParams
-from lp.bugs.interfaces.bugtask import BugTaskStatus
+from lp.bugs.interfaces.bugtask import (
+    BugTaskImportance,
+    BugTaskStatus,
+    )
 from lp.bugs.model.bugsubscriptionfilter import BugSubscriptionFilter
+from lp.bugs.model.bugsubscriptionfilterimportance import (
+    BugSubscriptionFilterImportance,
+    )
 from lp.bugs.model.bugsubscriptionfilterstatus import (
     BugSubscriptionFilterStatus,
     )
@@ -215,6 +221,80 @@
             bugtask.bug, BugNotificationLevel.NOTHING)
         self.assertEqual([subscription], list(subscriptions_for_bug))
 
+    def test_getSubscriptionsForBug_with_filter_on_importance(self):
+        # If an importance filter exists for a subscription, the result of
+        # getSubscriptionsForBug() may be a subset of getSubscriptions().
+        bugtask = self.makeBugTask()
+
+        # Create a new subscription on self.target.
+        login_person(self.ordinary_subscriber)
+        subscription = self.target.addSubscription(
+            self.ordinary_subscriber, self.ordinary_subscriber)
+        subscription.bug_notification_level = BugNotificationLevel.COMMENTS
+
+        # Without any filters the subscription is found.
+        subscriptions_for_bug = self.target.getSubscriptionsForBug(
+            bugtask.bug, BugNotificationLevel.NOTHING)
+        self.assertEqual([subscription], list(subscriptions_for_bug))
+
+        # Filter the subscription to bugs in the CRITICAL state.
+        subscription_filter = BugSubscriptionFilter()
+        subscription_filter.structural_subscription = subscription
+        subscription_filter_importance = BugSubscriptionFilterImportance()
+        subscription_filter_importance.filter = subscription_filter
+        subscription_filter_importance.importance = BugTaskImportance.CRITICAL
+
+        # With the filter the subscription is not found.
+        subscriptions_for_bug = self.target.getSubscriptionsForBug(
+            bugtask.bug, BugNotificationLevel.NOTHING)
+        self.assertEqual([], list(subscriptions_for_bug))
+
+        # If the filter is adjusted, the subscription is found again.
+        subscription_filter_importance.importance = bugtask.importance
+        subscriptions_for_bug = self.target.getSubscriptionsForBug(
+            bugtask.bug, BugNotificationLevel.NOTHING)
+        self.assertEqual([subscription], list(subscriptions_for_bug))
+
+    def test_getSubscriptionsForBug_with_multiple_filters(self):
+        # If multiple filters exist for a subscription, all filters must
+        # match.
+        bugtask = self.makeBugTask()
+
+        # Create a new subscription on self.target.
+        login_person(self.ordinary_subscriber)
+        subscription = self.target.addSubscription(
+            self.ordinary_subscriber, self.ordinary_subscriber)
+        subscription.bug_notification_level = BugNotificationLevel.COMMENTS
+
+        # Filter the subscription to bugs in the CRITICAL state.
+        subscription_filter = BugSubscriptionFilter()
+        subscription_filter.structural_subscription = subscription
+        subscription_filter_status = BugSubscriptionFilterStatus()
+        subscription_filter_status.filter = subscription_filter
+        subscription_filter_status.status = BugTaskStatus.CONFIRMED
+        subscription_filter_importance = BugSubscriptionFilterImportance()
+        subscription_filter_importance.filter = subscription_filter
+        subscription_filter_importance.importance = BugTaskImportance.CRITICAL
+
+        # With the filter the subscription is not found.
+        subscriptions_for_bug = self.target.getSubscriptionsForBug(
+            bugtask.bug, BugNotificationLevel.NOTHING)
+        self.assertEqual([], list(subscriptions_for_bug))
+
+        # If the filter is adjusted to match status but not importance, the
+        # subscription is still not found.
+        subscription_filter_status.status = bugtask.status
+        subscriptions_for_bug = self.target.getSubscriptionsForBug(
+            bugtask.bug, BugNotificationLevel.NOTHING)
+        self.assertEqual([], list(subscriptions_for_bug))
+
+        # If the filter is adjusted to also match importance, the subscription
+        # is found again.
+        subscription_filter_importance.importance = bugtask.importance
+        subscriptions_for_bug = self.target.getSubscriptionsForBug(
+            bugtask.bug, BugNotificationLevel.NOTHING)
+        self.assertEqual([subscription], list(subscriptions_for_bug))
+
 
 class TestStructuralSubscriptionForDistro(
     FilteredStructuralSubscriptionTestBase, TestCaseWithFactory):


Follow ups