launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #01045
[Merge] lp:~allenap/launchpad/sub-search-queries into lp:launchpad
Gavin Panella has proposed merging lp:~allenap/launchpad/sub-search-queries into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
- Add Storm model classes for BugSubscriptionFilter* tables (which
already exist),
- Add database permissions for the aforementioned tables,
- Clean up some of the code in StructuralSubscriptionTargetMixin.
--
https://code.launchpad.net/~allenap/launchpad/sub-search-queries/+merge/35546
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~allenap/launchpad/sub-search-queries into lp:launchpad.
=== modified file 'database/schema/security.cfg'
--- database/schema/security.cfg 2010-09-10 12:59:49 +0000
+++ database/schema/security.cfg 2010-09-15 15:32:53 +0000
@@ -539,6 +539,10 @@
public.bugnotification = SELECT, INSERT
public.bugnotificationrecipient = SELECT, INSERT
public.bugsubscription = SELECT
+public.bugsubscriptionfilter = SELECT
+public.bugsubscriptionfilterstatus = SELECT
+public.bugsubscriptionfilterimportance = SELECT
+public.bugsubscriptionfiltertag = SELECT
public.bugtask = SELECT, INSERT, UPDATE
public.bugtracker = SELECT, INSERT
public.bugtrackeralias = SELECT
@@ -618,6 +622,10 @@
public.bugactivity = SELECT, INSERT
public.bugaffectsperson = SELECT, INSERT, UPDATE, DELETE
public.bugsubscription = SELECT
+public.bugsubscriptionfilter = SELECT
+public.bugsubscriptionfilterstatus = SELECT
+public.bugsubscriptionfilterimportance = SELECT
+public.bugsubscriptionfiltertag = SELECT
public.bugnotification = SELECT, INSERT
public.bugnotificationrecipient = SELECT, INSERT
public.structuralsubscription = SELECT
@@ -804,6 +812,10 @@
public.bugactivity = SELECT, INSERT
public.bugaffectsperson = SELECT, INSERT, UPDATE, DELETE
public.bugsubscription = SELECT
+public.bugsubscriptionfilter = SELECT
+public.bugsubscriptionfilterstatus = SELECT
+public.bugsubscriptionfilterimportance = SELECT
+public.bugsubscriptionfiltertag = SELECT
public.bugnotification = SELECT, INSERT
public.bugnotificationrecipient = SELECT, INSERT
public.bugnomination = SELECT
@@ -928,6 +940,10 @@
public.bugpackageinfestation = SELECT, INSERT, UPDATE
public.bugproductinfestation = SELECT, INSERT, UPDATE
public.bugsubscription = SELECT, INSERT, UPDATE, DELETE
+public.bugsubscriptionfilter = SELECT, INSERT, UPDATE, DELETE
+public.bugsubscriptionfilterstatus = SELECT, INSERT, UPDATE, DELETE
+public.bugsubscriptionfilterimportance = SELECT, INSERT, UPDATE, DELETE
+public.bugsubscriptionfiltertag = SELECT, INSERT, UPDATE, DELETE
public.bugtask = SELECT, INSERT, UPDATE, DELETE
public.bugtracker = SELECT, INSERT, UPDATE, DELETE
public.bugtrackeralias = SELECT, INSERT, UPDATE, DELETE
@@ -1154,6 +1170,10 @@
public.bugaffectsperson = SELECT, INSERT, UPDATE, DELETE
public.bugjob = SELECT, INSERT
public.bugsubscription = SELECT
+public.bugsubscriptionfilter = SELECT
+public.bugsubscriptionfilterstatus = SELECT
+public.bugsubscriptionfilterimportance = SELECT
+public.bugsubscriptionfiltertag = SELECT
public.bugnotification = SELECT, INSERT
public.bugnotificationrecipient = SELECT, INSERT
public.bugnomination = SELECT
@@ -1256,6 +1276,10 @@
public.bugaffectsperson = SELECT, INSERT, UPDATE, DELETE
public.bugjob = SELECT, INSERT
public.bugsubscription = SELECT
+public.bugsubscriptionfilter = SELECT
+public.bugsubscriptionfilterstatus = SELECT
+public.bugsubscriptionfilterimportance = SELECT
+public.bugsubscriptionfiltertag = SELECT
public.bugnotification = SELECT, INSERT
public.bugnotificationrecipient = SELECT, INSERT
public.bugnomination = SELECT
@@ -1323,6 +1347,10 @@
public.bugnotification = SELECT, INSERT, UPDATE
public.bugnotificationrecipient = SELECT, INSERT, UPDATE
public.bugsubscription = SELECT, INSERT
+public.bugsubscriptionfilter = SELECT, INSERT
+public.bugsubscriptionfilterstatus = SELECT, INSERT
+public.bugsubscriptionfilterimportance = SELECT, INSERT
+public.bugsubscriptionfiltertag = SELECT, INSERT
public.bugnomination = SELECT
public.bug = SELECT, INSERT, UPDATE
public.bugactivity = SELECT, INSERT
@@ -1542,6 +1570,10 @@
public.bugaffectsperson = SELECT, INSERT, UPDATE, DELETE
public.bugjob = SELECT, INSERT
public.bugsubscription = SELECT, INSERT
+public.bugsubscriptionfilter = SELECT, INSERT
+public.bugsubscriptionfilterstatus = SELECT, INSERT
+public.bugsubscriptionfilterimportance = SELECT, INSERT
+public.bugsubscriptionfiltertag = SELECT, INSERT
public.bugnotification = SELECT, INSERT
public.bugnotificationattachment = SELECT
public.bugnotificationrecipient = SELECT, INSERT
@@ -1550,6 +1582,10 @@
public.bugtask = SELECT, INSERT, UPDATE
public.bugmessage = SELECT, INSERT
public.bugsubscription = SELECT, INSERT, UPDATE, DELETE
+public.bugsubscriptionfilter = SELECT, INSERT, UPDATE, DELETE
+public.bugsubscriptionfilterstatus = SELECT, INSERT, UPDATE, DELETE
+public.bugsubscriptionfilterimportance = SELECT, INSERT, UPDATE, DELETE
+public.bugsubscriptionfiltertag = SELECT, INSERT, UPDATE, DELETE
public.bugtracker = SELECT, INSERT
public.bugtrackeralias = SELECT, INSERT
public.bugwatch = SELECT, INSERT
@@ -1809,6 +1845,10 @@
public.message = SELECT, INSERT
public.messagechunk = SELECT, INSERT
public.bugsubscription = SELECT, INSERT
+public.bugsubscriptionfilter = SELECT, INSERT
+public.bugsubscriptionfilterstatus = SELECT, INSERT
+public.bugsubscriptionfilterimportance = SELECT, INSERT
+public.bugsubscriptionfiltertag = SELECT, INSERT
public.bugmessage = SELECT, INSERT
public.sourcepackagename = SELECT
public.job = SELECT, INSERT, UPDATE
@@ -1836,6 +1876,10 @@
public.bug = SELECT, UPDATE
public.bugattachment = SELECT, DELETE
public.bugsubscription = SELECT
+public.bugsubscriptionfilter = SELECT
+public.bugsubscriptionfilterstatus = SELECT
+public.bugsubscriptionfilterimportance = SELECT
+public.bugsubscriptionfiltertag = SELECT
public.bugaffectsperson = SELECT
public.bugnotification = SELECT, DELETE
public.bugnotificationrecipientarchive = SELECT
=== modified file 'lib/lp/bugs/model/bugsubscription.py'
--- lib/lp/bugs/model/bugsubscription.py 2010-09-09 21:00:54 +0000
+++ lib/lp/bugs/model/bugsubscription.py 2010-09-15 15:32:53 +0000
@@ -7,13 +7,27 @@
__all__ = ['BugSubscription']
from sqlobject import ForeignKey
+from storm.base import Storm
+from storm.locals import (
+ Bool,
+ Int,
+ Reference,
+ Unicode,
+ )
from zope.interface import implements
from canonical.database.constants import UTC_NOW
from canonical.database.datetimecol import UtcDateTimeCol
-from canonical.database.enumcol import EnumCol
+from canonical.database.enumcol import (
+ DBEnum,
+ EnumCol,
+ )
from canonical.database.sqlbase import SQLBase
from lp.bugs.interfaces.bugsubscription import IBugSubscription
+from lp.bugs.interfaces.bugtask import (
+ BugTaskImportance,
+ BugTaskStatus,
+ )
from lp.registry.enum import BugNotificationLevel
from lp.registry.interfaces.person import validate_person
@@ -66,3 +80,63 @@
if self.person.is_team:
return user.inTeam(self.person)
return user == self.person
+
+
+class BugSubscriptionFilter(Storm):
+ """A filter to specialize a *structural* subscription."""
+
+ __storm_table__ = "BugSubscriptionFilter"
+
+ id = Int(primary=True)
+
+ structural_subscription_id = Int("structuralsubscription", allow_none=False)
+ structural_subscription = Reference(
+ structural_subscription_id, "StructuralSubscription.id")
+
+ find_all_tags = Bool(allow_none=False, default=False)
+ include_any_tags = Bool(allow_none=False, default=False)
+ exclude_any_tags = Bool(allow_none=False, default=False)
+
+ other_parameters = Unicode()
+
+ description = Unicode()
+
+
+class BugSubscriptionFilterStatus(Storm):
+ """Statuses to filter."""
+
+ __storm_table__ = "BugSubscriptionFilterStatus"
+
+ id = Int(primary=True)
+
+ filter_id = Int("filter", allow_none=False)
+ filter = Reference(filter_id, "BugSubscriptionFilter.id")
+
+ status = DBEnum(enum=BugTaskStatus, allow_none=False)
+
+
+class BugSubscriptionFilterImportance(Storm):
+ """Importances to filter."""
+
+ __storm_table__ = "BugSubscriptionFilterImportance"
+
+ id = Int(primary=True)
+
+ filter_id = Int("filter", allow_none=False)
+ filter = Reference(filter_id, "BugSubscriptionFilter.id")
+
+ importance = DBEnum(enum=BugTaskImportance, allow_none=False)
+
+
+class BugSubscriptionFilterTag(Storm):
+ """Tags to filter."""
+
+ __storm_table__ = "BugSubscriptionFilterTag"
+
+ id = Int(primary=True)
+
+ filter_id = Int("filter", allow_none=False)
+ filter = Reference(filter_id, "BugSubscriptionFilter.id")
+
+ include = Bool(allow_none=False)
+ tag = Unicode(allow_none=False)
=== added directory 'lib/lp/bugs/model/tests'
=== added file 'lib/lp/bugs/model/tests/__init__.py'
=== added file 'lib/lp/bugs/model/tests/test_bugsubscription.py'
--- lib/lp/bugs/model/tests/test_bugsubscription.py 1970-01-01 00:00:00 +0000
+++ lib/lp/bugs/model/tests/test_bugsubscription.py 2010-09-15 15:32:53 +0000
@@ -0,0 +1,182 @@
+# Copyright 2010 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Tests for the bugsubscription module."""
+
+__metaclass__ = type
+
+from canonical.launchpad.interfaces.lpstorm import IStore
+from canonical.testing import DatabaseFunctionalLayer
+from lp.bugs.interfaces.bugtask import (
+ BugTaskImportance,
+ BugTaskStatus,
+ )
+from lp.bugs.model.bugsubscription import (
+ BugSubscriptionFilter,
+ BugSubscriptionFilterImportance,
+ BugSubscriptionFilterStatus,
+ BugSubscriptionFilterTag,
+ )
+from lp.testing import (
+ login_person,
+ TestCaseWithFactory,
+ )
+
+
+class TestBugSubscriptionFilter(TestCaseWithFactory):
+
+ layer = DatabaseFunctionalLayer
+
+ def setUp(self):
+ super(TestBugSubscriptionFilter, self).setUp()
+ self.target = self.factory.makeProduct()
+ self.subscriber = self.target.owner
+ login_person(self.subscriber)
+ self.subscription = self.target.addBugSubscription(
+ self.subscriber, self.subscriber)
+
+ def test_basics(self):
+ """Test the basic operation of `BugSubscriptionFilter` objects."""
+ # Create.
+ bug_subscription_filter = BugSubscriptionFilter()
+ bug_subscription_filter.structural_subscription = self.subscription
+ bug_subscription_filter.find_all_tags = True
+ bug_subscription_filter.include_any_tags = True
+ bug_subscription_filter.exclude_any_tags = True
+ bug_subscription_filter.other_parameters = u"foo"
+ bug_subscription_filter.description = u"bar"
+ # Flush and reload.
+ IStore(bug_subscription_filter).flush()
+ IStore(bug_subscription_filter).reload(bug_subscription_filter)
+ # Check.
+ self.assertIsNot(None, bug_subscription_filter.id)
+ self.assertEqual(
+ self.subscription.id,
+ bug_subscription_filter.structural_subscription_id)
+ self.assertEqual(
+ self.subscription,
+ bug_subscription_filter.structural_subscription)
+ self.assertIs(True, bug_subscription_filter.find_all_tags)
+ self.assertIs(True, bug_subscription_filter.include_any_tags)
+ self.assertIs(True, bug_subscription_filter.exclude_any_tags)
+ self.assertEqual(u"foo", bug_subscription_filter.other_parameters)
+ self.assertEqual(u"bar", bug_subscription_filter.description)
+
+ def test_defaults(self):
+ """Test the default values of `BugSubscriptionFilter` objects."""
+ # Create.
+ bug_subscription_filter = BugSubscriptionFilter()
+ bug_subscription_filter.structural_subscription = self.subscription
+ # Check.
+ self.assertIs(False, bug_subscription_filter.find_all_tags)
+ self.assertIs(False, bug_subscription_filter.find_all_tags)
+ self.assertIs(False, bug_subscription_filter.include_any_tags)
+ self.assertIs(False, bug_subscription_filter.exclude_any_tags)
+ self.assertIs(None, bug_subscription_filter.other_parameters)
+ self.assertIs(None, bug_subscription_filter.description)
+
+
+class TestBugSubscriptionFilterStatus(TestCaseWithFactory):
+
+ layer = DatabaseFunctionalLayer
+
+ def setUp(self):
+ super(TestBugSubscriptionFilterStatus, self).setUp()
+ self.target = self.factory.makeProduct()
+ self.subscriber = self.target.owner
+ login_person(self.subscriber)
+ self.subscription = self.target.addBugSubscription(
+ self.subscriber, self.subscriber)
+ self.subscription_filter = BugSubscriptionFilter()
+ self.subscription_filter.structural_subscription = self.subscription
+
+ def test_basics(self):
+ """Test the basics of `BugSubscriptionFilterStatus` objects."""
+ # Create.
+ bug_sub_filter_status = BugSubscriptionFilterStatus()
+ bug_sub_filter_status.filter = self.subscription_filter
+ bug_sub_filter_status.status = BugTaskStatus.NEW
+ # Flush and reload.
+ IStore(bug_sub_filter_status).flush()
+ IStore(bug_sub_filter_status).reload(bug_sub_filter_status)
+ # Check.
+ self.assertIsNot(None, bug_sub_filter_status.id)
+ self.assertEqual(
+ self.subscription_filter.id,
+ bug_sub_filter_status.filter_id)
+ self.assertEqual(
+ self.subscription_filter,
+ bug_sub_filter_status.filter)
+ self.assertEqual(BugTaskStatus.NEW, bug_sub_filter_status.status)
+
+
+class TestBugSubscriptionFilterImportance(TestCaseWithFactory):
+
+ layer = DatabaseFunctionalLayer
+
+ def setUp(self):
+ super(TestBugSubscriptionFilterImportance, self).setUp()
+ self.target = self.factory.makeProduct()
+ self.subscriber = self.target.owner
+ login_person(self.subscriber)
+ self.subscription = self.target.addBugSubscription(
+ self.subscriber, self.subscriber)
+ self.subscription_filter = BugSubscriptionFilter()
+ self.subscription_filter.structural_subscription = self.subscription
+
+ def test_basics(self):
+ """Test the basics of `BugSubscriptionFilterImportance` objects."""
+ # Create.
+ bug_sub_filter_importance = BugSubscriptionFilterImportance()
+ bug_sub_filter_importance.filter = self.subscription_filter
+ bug_sub_filter_importance.importance = BugTaskImportance.HIGH
+ # Flush and reload.
+ IStore(bug_sub_filter_importance).flush()
+ IStore(bug_sub_filter_importance).reload(bug_sub_filter_importance)
+ # Check.
+ self.assertIsNot(None, bug_sub_filter_importance.id)
+ self.assertEqual(
+ self.subscription_filter.id,
+ bug_sub_filter_importance.filter_id)
+ self.assertEqual(
+ self.subscription_filter,
+ bug_sub_filter_importance.filter)
+ self.assertEqual(
+ BugTaskImportance.HIGH,
+ bug_sub_filter_importance.importance)
+
+
+class TestBugSubscriptionFilterTag(TestCaseWithFactory):
+
+ layer = DatabaseFunctionalLayer
+
+ def setUp(self):
+ super(TestBugSubscriptionFilterTag, self).setUp()
+ self.target = self.factory.makeProduct()
+ self.subscriber = self.target.owner
+ login_person(self.subscriber)
+ self.subscription = self.target.addBugSubscription(
+ self.subscriber, self.subscriber)
+ self.subscription_filter = BugSubscriptionFilter()
+ self.subscription_filter.structural_subscription = self.subscription
+
+ def test_basics(self):
+ """Test the basics of `BugSubscriptionFilterTag` objects."""
+ # Create.
+ bug_sub_filter_tag = BugSubscriptionFilterTag()
+ bug_sub_filter_tag.filter = self.subscription_filter
+ bug_sub_filter_tag.include = True
+ bug_sub_filter_tag.tag = u"foo"
+ # Flush and reload.
+ IStore(bug_sub_filter_tag).flush()
+ IStore(bug_sub_filter_tag).reload(bug_sub_filter_tag)
+ # Check.
+ self.assertIsNot(None, bug_sub_filter_tag.id)
+ self.assertEqual(
+ self.subscription_filter.id,
+ bug_sub_filter_tag.filter_id)
+ self.assertEqual(
+ self.subscription_filter,
+ bug_sub_filter_tag.filter)
+ self.assertIs(True, bug_sub_filter_tag.include)
+ self.assertEqual(u"foo", bug_sub_filter_tag.tag)
=== modified file 'lib/lp/registry/model/structuralsubscription.py'
--- lib/lp/registry/model/structuralsubscription.py 2010-08-20 20:31:18 +0000
+++ lib/lp/registry/model/structuralsubscription.py 2010-09-15 15:32:53 +0000
@@ -266,47 +266,36 @@
min_blueprint_notification_level=
BlueprintNotificationLevel.NOTHING):
"""See `IStructuralSubscriptionTarget`."""
- target_clause_parts = []
- for key, value in self._target_args.items():
+ clauses = [
+ "StructuralSubscription.subscriber = Person.id",
+ "StructuralSubscription.bug_notification_level "
+ ">= %s" % quote(min_bug_notification_level),
+ "StructuralSubscription.blueprint_notification_level "
+ ">= %s" % quote(min_blueprint_notification_level),
+ ]
+ for key, value in self._target_args.iteritems():
if value is None:
- target_clause_parts.append(
- "StructuralSubscription.%s IS NULL " % (key, ))
+ clauses.append(
+ "StructuralSubscription.%s IS NULL" % (key,))
else:
- target_clause_parts.append(
- "StructuralSubscription.%s = %s " % (key, quote(value)))
- target_clause = " AND ".join(target_clause_parts)
- query = target_clause + """
- AND StructuralSubscription.subscriber = Person.id
- """
- all_subscriptions = StructuralSubscription.select(
- query,
- orderBy='Person.displayname',
- clauseTables=['Person'])
- subscriptions = [sub for sub
- in all_subscriptions
- if ((sub.bug_notification_level >=
- min_bug_notification_level) and
- (sub.blueprint_notification_level >=
- min_blueprint_notification_level))]
- return subscriptions
+ clauses.append(
+ "StructuralSubscription.%s = %s" % (key, quote(value)))
+ query = " AND ".join(clauses)
+ return StructuralSubscription.select(
+ query, orderBy='Person.displayname', clauseTables=['Person'])
def getBugNotificationsRecipients(self, recipients=None, level=None):
"""See `IStructuralSubscriptionTarget`."""
- subscribers = set()
if level is None:
subscriptions = self.bug_subscriptions
else:
subscriptions = self.getSubscriptions(
min_bug_notification_level=level)
- for subscription in subscriptions:
- if (level is not None and
- subscription.bug_notification_level < level):
- continue
- subscriber = subscription.subscriber
- subscribers.add(subscriber)
- if recipients is not None:
- recipients.addStructuralSubscriber(
- subscriber, self)
+ subscribers = set(
+ subscription.subscriber for subscription in subscriptions)
+ if recipients is not None:
+ for subscriber in subscribers:
+ recipients.addStructuralSubscriber(subscriber, self)
parent = self.parent_subscription_target
if parent is not None:
subscribers.update(