← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~danilo/launchpad/bug-772763-remove-nothing into lp:launchpad/db-devel

 

Данило Шеган has proposed merging lp:~danilo/launchpad/bug-772763-remove-nothing into lp:launchpad/db-devel with lp:~danilo/launchpad/proper-bug-muting as a prerequisite.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers): code
  Stuart Bishop (stub): db

For more details, see:
https://code.launchpad.net/~danilo/launchpad/bug-772763-remove-nothing/+merge/61251

= Bug 772763: Remove BugNotificationLevel.NOTHING =

Remove BugNotificationLevel.NOTHING value from the enum and adapt the code to not depend on it.  Previous (prerequisite) branch has already changed bug muting to not use this level, so now it's mostly about removing it from the tests and bits of UI code, and as the default level for a bunch of methods.

In a few tests, I had to replace the old call (used to be compatible with bug.mute()) bug.subscribe(..., level=NOTHING) with the appropriate bug.mute(...) call.

Most of the code is simplified with this removal.

I didn't fix lint issues in xx-bug.txt because it simply has too many of them.

== Tests ==

bin/test -cvvm lp.bugs

== Demo and Q/A ==

Go to a bug page and play with muting/unmuting a bug.
You'll need to turn the malone.advanced-subscriptions.enabled feature flag to on.

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/bugs/model/tests/test_bugsubscriptioninfo.py
  lib/lp/bugs/model/bugnotification.py
  lib/lp/bugs/browser/tests/test_bugsubscriptionfilter.py
  database/schema/patch-2208-70-0.sql
  lib/lp/bugs/configure.zcml
  lib/lp/bugs/tests/test_structuralsubscription.py
  lib/lp/bugs/model/tests/test_bug.py
  lib/lp/bugs/enum.py
  database/schema/comments.sql
  lib/lp/bugs/tests/test_bugnotification.py
  database/schema/security.cfg
  lib/lp/bugs/stories/webservice/xx-bug.txt
  lib/lp/bugs/model/bugsubscriptionfilter.py
  lib/lp/bugs/scripts/tests/test_bugnotification.py
  lib/lp/bugs/browser/bugsubscriptionfilter.py
  lib/lp/bugs/model/bug.py
  lib/lp/bugs/browser/tests/test_bugsubscription_views.py
  lib/lp/bugs/browser/bugsubscription.py
  lib/lp/bugs/tests/test_bugchanges.py
  lib/lp/bugs/model/personsubscriptioninfo.py
  lib/lp/bugs/scripts/bugnotification.py
  lib/lp/bugs/model/tests/test_personsubscriptioninfo.py
  lib/lp/bugs/tests/test_bug.py
  lib/lp/registry/model/person.py
  lib/lp/bugs/browser/tests/test_bug_context_menu.py
  lib/lp/bugs/interfaces/bugnotification.py
  lib/lp/bugs/interfaces/bug.py

./lib/lp/bugs/stories/webservice/xx-bug.txt
      13: source has bad indentation.
      53: want exceeds 78 characters.
      61: source has bad indentation.
      67: source has bad indentation.
      74: source has bad indentation.
     165: source has bad indentation.
     170: source exceeds 78 characters.
     176: source exceeds 78 characters.
     182: source has bad indentation.
     194: source has bad indentation.
     205: source has bad indentation.
     211: source has bad indentation.
     221: source has bad indentation.
     232: source has bad indentation.
     250: source has bad indentation.
     253: source has bad indentation.
     260: source has bad indentation.
     265: source exceeds 78 characters.
     265: source has bad indentation.
     271: source has bad indentation.
     281: source has bad indentation.
     292: source has bad indentation.
     301: source has bad indentation.
     316: source has bad indentation.
     322: source has bad indentation.
     349: want exceeds 78 characters.
     354: source has bad indentation.
     359: source has bad indentation.
     364: source has bad indentation.
     370: source has bad indentation.
     374: source has bad indentation.
     378: source has bad indentation.
     385: source has bad indentation.
     389: source has bad indentation.
     395: source has bad indentation.
     398: source has bad indentation.
     402: source has bad indentation.
     408: source has bad indentation.
     414: source has bad indentation.
     418: source has bad indentation.
     426: source has bad indentation.
     429: source has bad indentation.
     434: source has bad indentation.
     440: source has bad indentation.
     446: source has bad indentation.
     452: source has bad indentation.
     460: source has bad indentation.
     473: source has bad indentation.
     482: source has bad indentation.
     492: source has bad indentation.
     502: source has bad indentation.
     512: source has bad indentation.
     523: source has bad indentation.
     549: source has bad indentation.
     559: source has bad indentation.
     568: source has bad indentation.
     578: source has bad indentation.
     827: source has bad indentation.
     851: source has bad indentation.
     863: source exceeds 78 characters.
     863: source has bad indentation.
    1057: source has bad indentation.
    1062: source has bad indentation.
    1066: source has bad indentation.
    1085: source has bad indentation.
    1091: source has bad indentation.
    1096: source has bad indentation.
    1099: source has bad indentation.
    1103: source has bad indentation.
    1109: source has bad indentation.
    1122: source has bad indentation.
    1136: source has bad indentation.
    1160: source has bad indentation.
    1162: source has bad indentation.
    1175: want exceeds 78 characters.
    1180: source has bad indentation.
    1201: source has bad indentation.
    1212: source has bad indentation.
    1217: want exceeds 78 characters.
    1253: source has bad indentation.
    1263: source has bad indentation.
    1276: source has bad indentation.
    1295: source has bad indentation.
    1309: source has bad indentation.
    1317: source has bad indentation.
    1319: source has bad indentation.
    1326: source has bad indentation.
    1329: source has bad indentation.
    1332: source has bad indentation.
    1338: source has bad indentation.
    1340: want exceeds 78 characters.
    1353: source has bad indentation.
    1364: source has bad indentation.
    1370: source has bad indentation.
    1382: source has bad indentation.
    1388: source has bad indentation.
    1391: want exceeds 78 characters.
    1646: source exceeds 78 characters.
    2019: source exceeds 78 characters.
    2079: narrative exceeds 78 characters.
    2124: source has bad indentation.
    2135: source has bad indentation.
./lib/lp/registry/model/person.py
    3849: local variable 'karma_total' is assigned to but never used
-- 
https://code.launchpad.net/~danilo/launchpad/bug-772763-remove-nothing/+merge/61251
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~danilo/launchpad/bug-772763-remove-nothing into lp:launchpad/db-devel.
=== modified file 'lib/lp/bugs/browser/bugsubscription.py'
--- lib/lp/bugs/browser/bugsubscription.py	2011-05-17 13:35:56 +0000
+++ lib/lp/bugs/browser/bugsubscription.py	2011-05-17 13:36:01 +0000
@@ -43,7 +43,7 @@
 from lp.bugs.browser.structuralsubscription import (
     expose_structural_subscription_data_to_js,
     )
-from lp.bugs.enum import BugNotificationLevel, HIDDEN_BUG_NOTIFICATION_LEVELS
+from lp.bugs.enum import BugNotificationLevel
 from lp.bugs.interfaces.bugsubscription import IBugSubscription
 from lp.bugs.model.personsubscriptioninfo import PersonSubscriptions
 from lp.bugs.model.structuralsubscription import (
@@ -121,17 +121,12 @@
             SimpleTerm(
                 level, level.title,
                 self._bug_notification_level_descriptions[level])
-            # We reorder the items so that COMMENTS comes first. We also
-            # drop the NOTHING option since it just makes the UI
-            # confusing.
-            for level in sorted(BugNotificationLevel.items, reverse=True)
-                if level not in HIDDEN_BUG_NOTIFICATION_LEVELS]
+            # We reorder the items so that COMMENTS comes first.
+            for level in sorted(BugNotificationLevel.items, reverse=True)]
         bug_notification_vocabulary = SimpleVocabulary(
             bug_notification_level_terms)
 
-        if (self.current_user_subscription is not None and
-            self.current_user_subscription.bug_notification_level not in
-                HIDDEN_BUG_NOTIFICATION_LEVELS):
+        if self.current_user_subscription is not None:
             default_value = (
                 self.current_user_subscription.bug_notification_level)
         else:
@@ -556,9 +551,6 @@
         for subscription in direct_subscriptions:
             if not check_permission('launchpad.View', subscription.person):
                 continue
-            if (subscription.bug_notification_level ==
-                BugNotificationLevel.NOTHING):
-                continue
             if subscription.person == self.user:
                 can_unsubscribe = [subscription] + can_unsubscribe
             elif subscription.canBeUnsubscribedByUser(self.user):

=== modified file 'lib/lp/bugs/browser/bugsubscriptionfilter.py'
--- lib/lp/bugs/browser/bugsubscriptionfilter.py	2011-02-08 16:21:39 +0000
+++ lib/lp/bugs/browser/bugsubscriptionfilter.py	2011-05-17 13:36:01 +0000
@@ -65,16 +65,10 @@
         description = self.context.description
         return u"" if description is None else description.strip()
 
-    @property
-    def filters_everything(self):
-        """Return a boolean as to whether the filter masks everything.
-
-        Right now the only thing we check is the bug_notification_level.  We
-        could check more later--in particular, if no importances are checked,
-        or no statuses.
-        """
-        return (self.context.bug_notification_level ==
-                BugNotificationLevel.NOTHING)
+    # At the moment, we never filter everything.
+    # We could turn it into a property and check more later--
+    # in particular, if no importances are checked, or no statuses.
+    filters_everything = False
 
     @property
     def conditions(self):
@@ -82,15 +76,10 @@
         conditions = []
         bug_notification_level = self.context.bug_notification_level
         if bug_notification_level < BugNotificationLevel.COMMENTS:
-            if bug_notification_level == BugNotificationLevel.NOTHING:
-                return conditions # The template should use
-                # filters_everything to determine whether the conditions
-                # should be rendered.
-            else:
-                mapping = bug_notification_level_description_mapping(
-                    'the bug')
-                conditions.append(
-                    mapping[bug_notification_level].lower()[:-1])
+            mapping = bug_notification_level_description_mapping(
+                'the bug')
+            conditions.append(
+                mapping[bug_notification_level].lower()[:-1])
         statuses = self.context.statuses
         if len(statuses) > 0:
             conditions.append(

=== modified file 'lib/lp/bugs/browser/tests/test_bug_context_menu.py'
--- lib/lp/bugs/browser/tests/test_bug_context_menu.py	2011-05-17 13:35:56 +0000
+++ lib/lp/bugs/browser/tests/test_bug_context_menu.py	2011-05-17 13:36:01 +0000
@@ -74,7 +74,8 @@
         with feature_flags():
             with person_logged_in(person):
                 self.bug.subscribe(
-                    person, person, level=BugNotificationLevel.NOTHING)
+                    person, person, level=BugNotificationLevel.METADATA)
+                self.bug.mute(person, person)
                 request = LaunchpadTestRequest()
                 request.features = get_relevant_feature_controller()
                 view = create_initialized_view(

=== modified file 'lib/lp/bugs/browser/tests/test_bugsubscription_views.py'
--- lib/lp/bugs/browser/tests/test_bugsubscription_views.py	2011-05-17 13:35:56 +0000
+++ lib/lp/bugs/browser/tests/test_bugsubscription_views.py	2011-05-17 13:36:01 +0000
@@ -49,12 +49,9 @@
         with person_logged_in(bug.owner):
             bug.unsubscribe(bug.owner, bug.owner)
 
-        # We don't display BugNotificationLevel.NOTHING as an option.
-        # This is tested below.
         with FeatureFixture({self.feature_flag: ON}):
             displayed_levels = [
-                level for level in BugNotificationLevel.items
-                if level != BugNotificationLevel.NOTHING]
+                level for level in BugNotificationLevel.items]
             for level in displayed_levels:
                 person = self.factory.makePerson()
                 with person_logged_in(person):
@@ -74,28 +71,6 @@
                         level.title,
                         subscription.bug_notification_level.title))
 
-    def test_nothing_is_not_a_valid_level(self):
-        # BugNotificationLevel.NOTHING isn't considered valid when
-        # someone is trying to subscribe.
-        bug = self.factory.makeBug()
-        person = self.factory.makePerson()
-        with FeatureFixture({self.feature_flag: ON}):
-            with person_logged_in(person):
-                level = BugNotificationLevel.NOTHING
-                harness = LaunchpadFormHarness(
-                    bug.default_bugtask, BugSubscriptionSubscribeSelfView)
-                form_data = {
-                    'field.subscription': person.name,
-                    'field.bug_notification_level': level.title,
-                    }
-                harness.submit('continue', form_data)
-                self.assertTrue(harness.hasErrors())
-                self.assertEqual(
-                    'Invalid value',
-                    harness.getFieldError('bug_notification_level'),
-                    "The view should treat BugNotificationLevel.NOTHING "
-                    "as an invalid value.")
-
     def test_user_can_update_subscription(self):
         # A user can update their bug subscription using the
         # BugSubscriptionSubscribeSelfView.
@@ -255,31 +230,6 @@
                 self.assertFalse(
                     harness.view.widgets['bug_notification_level'].visible)
 
-    def test_bug_721400(self):
-        # If a subscription exists with a BugNotificationLevel of
-        # NOTHING the view will still render correctly, even though
-        # NOTHING is not accepted as a valid value for the
-        # bug_notification_level field.
-        # This is a regression test for bug 721400.
-        bug = self.factory.makeBug()
-        person = self.factory.makePerson()
-        with person_logged_in(person):
-            bug.subscribe(
-                person, person, level=BugNotificationLevel.NOTHING)
-
-        with FeatureFixture({self.feature_flag: ON}):
-            with person_logged_in(person):
-                subscribe_view = create_initialized_view(
-                    bug.default_bugtask, name='+subscribe')
-                self.assertEqual(0, len(subscribe_view.errors))
-                bug_notification_level_widget = (
-                    subscribe_view.widgets['bug_notification_level'])
-                default_notification_level_value = (
-                    bug_notification_level_widget._getDefault())
-                self.assertEqual(
-                    BugNotificationLevel.COMMENTS,
-                    default_notification_level_value)
-
     def test_muted_subs_have_unmute_option(self):
         # If a user has a muted subscription, the
         # BugSubscriptionSubscribeSelfView's subscription field will
@@ -449,34 +399,6 @@
             harness.view.initialize()
 
 
-class BugPortletSubscribersContentsTestCase(TestCaseWithFactory):
-    """Tests for the BugPortletSubscribersContents view."""
-
-    layer = LaunchpadFunctionalLayer
-
-    def setUp(self):
-        super(BugPortletSubscribersContentsTestCase, self).setUp()
-        self.bug = self.factory.makeBug()
-        self.subscriber = self.factory.makePerson()
-
-    def test_sorted_direct_subscriptions_doesnt_show_mutes(self):
-        # BugPortletSubscribersContents.sorted_direct_subscriptions does
-        # not return muted subscriptions.
-        with person_logged_in(self.subscriber):
-            subscription = self.bug.subscribe(
-                self.subscriber, self.subscriber,
-                level=BugNotificationLevel.NOTHING)
-            view = create_initialized_view(
-                self.bug, name="+bug-portlet-subscribers-content")
-            # Loop over the results of sorted_direct_subscriptions to
-            # extract the subscriptions from their
-            # SubscriptionAttrDecorator intances.
-            sorted_subscriptions = [
-                decorator.subscription for decorator in
-                view.sorted_direct_subscriptions]
-            self.assertFalse(subscription in sorted_subscriptions)
-
-
 class BugMuteSelfViewTestCase(TestCaseWithFactory):
     """Tests for the BugMuteSelfView."""
 

=== modified file 'lib/lp/bugs/browser/tests/test_bugsubscriptionfilter.py'
--- lib/lp/bugs/browser/tests/test_bugsubscriptionfilter.py	2011-03-30 15:20:46 +0000
+++ lib/lp/bugs/browser/tests/test_bugsubscriptionfilter.py	2011-05-17 13:36:01 +0000
@@ -251,18 +251,6 @@
         # If nothing is set the conditions list is empty.
         self.assertEqual([], self.view.conditions)
 
-    def test_conditions_with_no_events_subscribed(self):
-        with person_logged_in(self.owner):
-            self.subscription_filter.bug_notification_level = (
-                BugNotificationLevel.NOTHING)
-        self.assertEqual([], self.view.conditions)
-
-    def test_filters_everything_with_no_events_subscribed(self):
-        with person_logged_in(self.owner):
-            self.subscription_filter.bug_notification_level = (
-                BugNotificationLevel.NOTHING)
-        self.failUnless(self.view.filters_everything)
-
     def test_not_filters_everything_normally(self):
         self.failIf(self.view.filters_everything)
 
@@ -384,9 +372,7 @@
             u"There are no filter conditions!")
 
     def test_render_with_no_events_allowed(self):
-        with person_logged_in(self.owner):
-            self.subscription_filter.bug_notification_level = (
-                BugNotificationLevel.NOTHING)
+        self.view.filters_everything = True
         self.assertRender(
             u"This filter allows no mail through.",
             u"")
@@ -507,10 +493,8 @@
         # When advanced features are turned on for subscriptions a user
         # can specify a bug_notification_level on the +filter form.
         with feature_flags():
-            # We don't display BugNotificationLevel.NOTHING as an option.
             displayed_levels = [
-                level for level in BugNotificationLevel.items
-                if level != BugNotificationLevel.NOTHING]
+                level for level in BugNotificationLevel.items]
             for level in displayed_levels:
                 person = self.factory.makePerson()
                 with person_logged_in(person):
@@ -526,7 +510,7 @@
                         'field.bug_notification_level': level.title,
                         "field.actions.create": "Create",
                         }
-                    view = create_initialized_view(
+                    create_initialized_view(
                         subscription, name="+new-filter", form=form)
 
                 filters = subscription.bug_filters
@@ -539,26 +523,6 @@
                     "is actually %s." % (
                         level.name, new_filter.bug_notification_level.name))
 
-    def test_nothing_is_not_a_valid_level(self):
-        # BugNotificationLevel.NOTHING isn't considered valid when a
-        # user is subscribing via the web UI.
-        person = self.factory.makePerson()
-        with person_logged_in(person):
-            subscription = self.target.addBugSubscription(person, person)
-            form = {
-                "field.description": "New description",
-                "field.statuses": ["NEW", "INCOMPLETE"],
-                "field.importances": ["LOW", "MEDIUM"],
-                "field.tags": u"foo bar",
-                "field.find_all_tags": "on",
-                'field.bug_notification_level': BugNotificationLevel.NOTHING,
-                "field.actions.create": "Create",
-                }
-            with feature_flags():
-                view = create_initialized_view(
-                    subscription, name="+new-filter", form=form)
-                self.assertTrue(view.errors)
-
     def test_extra_features_hidden_without_feature_flag(self):
         # If the malone.advanced-subscriptions.enabled flag is turned
         # off, the bug_notification_level field doesn't appear on the

=== modified file 'lib/lp/bugs/enum.py'
--- lib/lp/bugs/enum.py	2011-03-05 03:28:12 +0000
+++ lib/lp/bugs/enum.py	2011-05-17 13:36:01 +0000
@@ -7,7 +7,6 @@
 __all__ = [
     'BugNotificationLevel',
     'BugNotificationStatus',
-    'HIDDEN_BUG_NOTIFICATION_LEVELS',
     ]
 
 from lazr.enum import (
@@ -22,12 +21,6 @@
     The type and volume of bug notification email sent to subscribers.
     """
 
-    NOTHING = DBItem(10, """
-        Nothing
-
-        Don't send any notifications about bugs.
-        """)
-
     LIFECYCLE = DBItem(20, """
         Lifecycle
 
@@ -51,10 +44,6 @@
         """)
 
 
-# The set of bug notification levels that won't be displayed in the UI.
-HIDDEN_BUG_NOTIFICATION_LEVELS = [BugNotificationLevel.NOTHING]
-
-
 class BugNotificationStatus(DBEnumeratedType):
     """The status of a bug notification.
 

=== modified file 'lib/lp/bugs/interfaces/bug.py'
--- lib/lp/bugs/interfaces/bug.py	2011-05-17 13:35:56 +0000
+++ lib/lp/bugs/interfaces/bug.py	2011-05-17 13:36:01 +0000
@@ -492,8 +492,7 @@
     def isMuted(person):
         """Does person have a muted subscription on this bug?
 
-        :returns: True if the user has a direct subscription to this bug
-            with a BugNotificationLevel of NOTHING.
+        :returns: True if the user has muted all email from this bug.
         """
 
     @operation_parameters(

=== modified file 'lib/lp/bugs/model/bug.py'
--- lib/lp/bugs/model/bug.py	2011-05-17 13:35:56 +0000
+++ lib/lp/bugs/model/bug.py	2011-05-17 13:36:01 +0000
@@ -902,7 +902,7 @@
             BugSubscription.bug_id == self.id).order_by(BugSubscription.id)
         return DecoratedResultSet(results, operator.itemgetter(1))
 
-    def getSubscriptionInfo(self, level=BugNotificationLevel.NOTHING):
+    def getSubscriptionInfo(self, level=BugNotificationLevel.LIFECYCLE):
         """See `IBug`."""
         return BugSubscriptionInfo(self, level)
 
@@ -919,7 +919,7 @@
         it.
         """
         if level is None:
-            level = BugNotificationLevel.NOTHING
+            level = BugNotificationLevel.LIFECYCLE
         subscriptions = self.getSubscriptionInfo(level).direct_subscriptions
         if recipients is not None:
             for subscriber in subscriptions.subscribers:
@@ -977,7 +977,7 @@
             return []
 
         if level is None:
-            level = BugNotificationLevel.NOTHING
+            level = BugNotificationLevel.LIFECYCLE
         info = self.getSubscriptionInfo(level)
 
         if recipients is not None:

=== modified file 'lib/lp/bugs/model/personsubscriptioninfo.py'
--- lib/lp/bugs/model/personsubscriptioninfo.py	2011-04-15 10:24:58 +0000
+++ lib/lp/bugs/model/personsubscriptioninfo.py	2011-05-17 13:36:01 +0000
@@ -11,9 +11,8 @@
 from zope.interface import implements
 from zope.proxy import sameProxiedObjects
 
-from lp.bugs.enum import BugNotificationLevel
 from lp.bugs.model.bugsubscription import BugSubscription
-from lp.bugs.model.bug import Bug
+from lp.bugs.model.bug import Bug, BugMute
 from lp.bugs.interfaces.personsubscriptioninfo import (
     IAbstractSubscriptionInfoCollection,
     IRealSubscriptionInfoCollection,
@@ -219,6 +218,18 @@
                     pillar.security_contact, pillar.bug_supervisor)
         return (direct, duplicates)
 
+    def _isMuted(self, person, bug):
+        store = Store.of(person)
+        mutes = store.find(
+            BugMute,
+            BugMute.bug == bug,
+            BugMute.person == person)
+        is_muted = mutes.one()
+        if is_muted is None:
+            return False
+        else:
+            return True
+
     def loadSubscriptionsFor(self, person, bug):
         self.person = person
         self.administrated_teams = person.getAdministratedTeams()
@@ -228,6 +239,9 @@
         direct, from_duplicate = (
             self._getDirectAndDuplicateSubscriptions(person, bug))
 
+        # Then get the 'muted' flag.
+        self.muted = self._isMuted(person, bug)
+
         # Then get owner and assignee virtual subscriptions.
         as_owner = VirtualSubscriptionInfoCollection(
             self.person, self.administrated_teams)
@@ -241,10 +255,6 @@
             assignee = bugtask.assignee
             if person.inTeam(assignee):
                 as_assignee.add(assignee, bug, pillar, bugtask)
-        self.muted = bool(
-            direct.personal and
-            direct.personal[0].subscription.bug_notification_level
-                == BugNotificationLevel.NOTHING)
         self.count = 0
         for name, collection in (
             ('direct', direct), ('from_duplicate', from_duplicate),

=== modified file 'lib/lp/bugs/model/tests/test_bug.py'
--- lib/lp/bugs/model/tests/test_bug.py	2011-04-20 14:58:11 +0000
+++ lib/lp/bugs/model/tests/test_bug.py	2011-05-17 13:36:01 +0000
@@ -181,7 +181,7 @@
 
     def test_get_direct_subscribers_default_level(self):
         # If no `level` parameter is passed to getDirectSubscribers(),
-        # the assumed `level` is BugNotification.NOTHING.
+        # the assumed `level` is BugNotification.LIFECYCLE.
         bug = self.factory.makeBug()
         # We unsubscribe the bug's owner because if we don't there will
         # be two COMMENTS-level subscribers.
@@ -196,7 +196,7 @@
 
         # All the subscribers should be returned by
         # getDirectSubscribers() because it defaults to returning
-        # subscribers at level NOTHING, which everything is higher than.
+        # subscribers at level LIFECYCLE, which everything is higher than.
         direct_subscribers = bug.getDirectSubscribers()
         self.assertEqual(
             set(subscribers), set(direct_subscribers),
@@ -241,7 +241,7 @@
         subscriber = self.factory.makePerson()
         with person_logged_in(subscriber):
             bug.subscribe(
-                subscriber, subscriber, level=BugNotificationLevel.NOTHING)
+                subscriber, subscriber, level=BugNotificationLevel.LIFECYCLE)
             duplicate_bug.subscribe(
                 subscriber, subscriber, level=BugNotificationLevel.METADATA)
         duplicate_subscribers = bug.getSubscribersFromDuplicates()
@@ -256,7 +256,7 @@
             info = bug.getSubscriptionInfo()
         self.assertIsInstance(info, BugSubscriptionInfo)
         self.assertEqual(bug, info.bug)
-        self.assertEqual(BugNotificationLevel.NOTHING, info.level)
+        self.assertEqual(BugNotificationLevel.LIFECYCLE, info.level)
         # A level can also be specified.
         with person_logged_in(bug.owner):
             info = bug.getSubscriptionInfo(BugNotificationLevel.METADATA)

=== modified file 'lib/lp/bugs/model/tests/test_bugsubscriptioninfo.py'
--- lib/lp/bugs/model/tests/test_bugsubscriptioninfo.py	2011-04-27 16:01:06 +0000
+++ lib/lp/bugs/model/tests/test_bugsubscriptioninfo.py	2011-05-17 13:36:01 +0000
@@ -130,7 +130,7 @@
 
     def getInfo(self):
         return BugSubscriptionInfo(
-            self.bug, BugNotificationLevel.NOTHING)
+            self.bug, BugNotificationLevel.LIFECYCLE)
 
     def test_direct(self):
         # The set of direct subscribers.
@@ -370,7 +370,7 @@
         self.target = self.factory.makeProduct()
         self.bug = self.factory.makeBug(product=self.target)
         self.info = BugSubscriptionInfo(
-            self.bug, BugNotificationLevel.NOTHING)
+            self.bug, BugNotificationLevel.LIFECYCLE)
         # Get the Storm cache into a known state.
         self.store = Store.of(self.bug)
         self.store.invalidate()

=== modified file 'lib/lp/bugs/model/tests/test_personsubscriptioninfo.py'
--- lib/lp/bugs/model/tests/test_personsubscriptioninfo.py	2011-04-15 10:24:58 +0000
+++ lib/lp/bugs/model/tests/test_personsubscriptioninfo.py	2011-05-17 13:36:01 +0000
@@ -8,7 +8,6 @@
 from zope.security.proxy import removeSecurityProxy
 
 from canonical.testing import DatabaseFunctionalLayer
-from lp.bugs.enum import BugNotificationLevel
 from lp.bugs.interfaces.personsubscriptioninfo import (
     IRealSubscriptionInfo,
     IRealSubscriptionInfoCollection,
@@ -482,8 +481,7 @@
     def test_is_muted(self):
         # Subscribed directly to the bug, muted.
         with person_logged_in(self.subscriber):
-            self.bug.subscribe(self.subscriber, self.subscriber,
-                               level=BugNotificationLevel.NOTHING)
+            self.bug.mute(self.subscriber, self.subscriber)
 
         # Load a `PersonSubscriptionInfo`s for subscriber and a bug.
         self.subscriptions.reload()

=== modified file 'lib/lp/bugs/stories/webservice/xx-bug.txt'
--- lib/lp/bugs/stories/webservice/xx-bug.txt	2011-04-12 11:36:11 +0000
+++ lib/lp/bugs/stories/webservice/xx-bug.txt	2011-05-17 13:36:01 +0000
@@ -902,13 +902,13 @@
 
 They can also update the subscription's bug_notification_level directly.
 
-    >>> patch = {u'bug_notification_level': u'Nothing'}
+    >>> patch = {u'bug_notification_level': u'Lifecycle'}
     >>> pprint_entry(
     ...     webservice.patch(
     ...         new_subscription['self_link'], 'application/json',
     ...         dumps(patch), api_version="devel").jsonBody())
     bug_link: u'.../bugs/1'
-    bug_notification_level: u'Nothing'...
+    bug_notification_level: u'Lifecycle'...
 
 If one person tries to unsubscribe another individual, the web
 service will return an unauthorized error.

=== modified file 'lib/lp/bugs/tests/test_bug.py'
--- lib/lp/bugs/tests/test_bug.py	2011-05-17 13:35:56 +0000
+++ lib/lp/bugs/tests/test_bug.py	2011-05-17 13:36:01 +0000
@@ -46,8 +46,8 @@
             self.assertEqual(True, self.bug.isMuted(self.person))
 
     def test_is_muted_returns_false_for_direct_subscribers(self):
-        # Bug.isMuted() will return False if the user has a subscription
-        # with BugNotificationLevel that's not NOTHING.
+        # Bug.isMuted() will return False if the user has a
+        # regular subscription.
         with person_logged_in(self.person):
             self.bug.subscribe(
                 self.person, self.person, level=BugNotificationLevel.METADATA)

=== modified file 'lib/lp/bugs/tests/test_structuralsubscription.py'
--- lib/lp/bugs/tests/test_structuralsubscription.py	2011-04-03 00:53:10 +0000
+++ lib/lp/bugs/tests/test_structuralsubscription.py	2011-05-17 13:36:01 +0000
@@ -154,7 +154,7 @@
         self.initial_filter = self.subscription.bug_filters[0]
 
     def assertSubscribers(
-        self, expected_subscribers, level=BugNotificationLevel.NOTHING):
+        self, expected_subscribers, level=BugNotificationLevel.LIFECYCLE):
         observed_subscribers = list(
             get_structural_subscribers(self.bugtask, None, level))
         self.assertEqual(expected_subscribers, observed_subscribers)
@@ -208,9 +208,9 @@
         self.initial_filter.bug_notification_level = (
             BugNotificationLevel.METADATA)
 
-        # The subscription is found when looking for NOTHING or above.
+        # The subscription is found when looking for LIFECYCLE or above.
         self.assertSubscribers(
-            [self.ordinary_subscriber], BugNotificationLevel.NOTHING)
+            [self.ordinary_subscriber], BugNotificationLevel.LIFECYCLE)
         # The subscription is found when looking for METADATA or above.
         self.assertSubscribers(
             [self.ordinary_subscriber], BugNotificationLevel.METADATA)


Follow ups