← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wgrant/launchpad/bug-informationtype-refactor into lp:launchpad

 

William Grant has proposed merging lp:~wgrant/launchpad/bug-informationtype-refactor into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~wgrant/launchpad/bug-informationtype-refactor/+merge/117002

This branch pushes bug information type restrictions down from a Registry vocab into the Bugs model, where they belong.

The bug target pillars (Product and Distribution) grow a getAllowedBugInformationTypes() method equivalent to BranchNamespace.getAllowedInformationTypes(). Bug.getAllowedInformationTypes() uses these methods to only allow types that are mutually acceptable to the bug's pillars. All the views that used InformationTypeVocabulary now give it the allowed information types. As a consequence of the present lack of model support for Proprietary, tests that asserted its presence have been removed. It'll be reintroduced shortly when the model is taught to use Product.bug_sharing_policy.

Some of the views needed some minor refactoring to cope with the fact that they're called on all manner of objects, only some of which have the necessary methods. The particularly messy one was ProjectGroup:+filebug, which really should be split into a separate class from the rest of +filebug as it functions quite differently.

Due to test fallout, the +filebug split and various other cleanups (including making transitionToInformationType respect getAllowedInformationTypes) are planned for a subsequent cleanup branch. This one's big and messy enough.
-- 
https://code.launchpad.net/~wgrant/launchpad/bug-informationtype-refactor/+merge/117002
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/bug-informationtype-refactor into lp:launchpad.
=== modified file 'lib/lp/app/browser/informationtype.py'
--- lib/lp/app/browser/informationtype.py	2012-07-24 06:39:54 +0000
+++ lib/lp/app/browser/informationtype.py	2012-07-27 04:55:23 +0000
@@ -9,7 +9,6 @@
 from lazr.restful.interfaces import IJSONRequestCache
 
 from lp.registry.enums import PRIVATE_INFORMATION_TYPES
-from lp.registry.vocabularies import InformationTypeVocabulary
 
 
 class InformationTypePortletMixin:
@@ -20,7 +19,7 @@
             {'value': term.name, 'description': term.description,
             'name': term.title,
             'description_css_class': 'choice-description'}
-            for term in InformationTypeVocabulary(self.context)]
+            for term in self.context.getAllowedInformationTypes(self.user)]
         cache.objects['private_types'] = [
             type.name for type in PRIVATE_INFORMATION_TYPES]
 

=== modified file 'lib/lp/app/widgets/tests/test_itemswidgets.py'
--- lib/lp/app/widgets/tests/test_itemswidgets.py	2012-07-17 03:51:38 +0000
+++ lib/lp/app/widgets/tests/test_itemswidgets.py	2012-07-27 04:55:23 +0000
@@ -29,7 +29,6 @@
     LaunchpadRadioWidgetWithDescription,
     PlainMultiCheckBoxWidget,
     )
-from lp.registry.vocabularies import InformationTypeVocabulary
 from lp.services.features.testing import FeatureFixture
 from lp.services.webapp.menu import structured
 from lp.services.webapp.servers import LaunchpadTestRequest
@@ -222,16 +221,6 @@
         hint_html = self.widget.renderExtraHint()
         self.assertEqual(expected, hint_html)
 
-    def test_renderDescription(self):
-        # If the vocabulary provides a description property, it is used over
-        # the one provided by the enum.
-        vocab = InformationTypeVocabulary()
-        widget = LaunchpadRadioWidgetWithDescription(
-            self.field, vocab, self.request)
-        self.assertRenderItem(
-            "...permitted to see private...", widget.renderItem,
-            vocab.getTermByToken('USERDATA'))
-
 
 class TestVocabularyToChoiceEditItems(TestCase):
     """Tests for vocabulary_to_choice_edit_items.

=== modified file 'lib/lp/bugs/browser/bug.py'
--- lib/lp/bugs/browser/bug.py	2012-07-09 04:14:09 +0000
+++ lib/lp/bugs/browser/bug.py	2012-07-27 04:55:23 +0000
@@ -10,6 +10,7 @@
     'BugContextMenu',
     'BugEditView',
     'BugFacets',
+    'BugInformationTypePortletView',
     'BugMarkAsAffectingUserView',
     'BugMarkAsDuplicateView',
     'BugNavigation',
@@ -514,7 +515,12 @@
         return getUtility(ILaunchBag).bugtask
 
 
-class BugView(InformationTypePortletMixin, LaunchpadView, BugViewMixin):
+class BugInformationTypePortletView(InformationTypePortletMixin,
+                                    LaunchpadView):
+    """View class for the information type portlet."""
+
+
+class BugView(LaunchpadView, BugViewMixin):
     """View class for presenting information about an `IBug`.
 
     Since all bug pages are registered on IBugTask, the context will be
@@ -823,10 +829,12 @@
     @property
     def schema(self):
         """Schema for editing the information type of a `IBug`."""
+        info_types = self.context.bug.getAllowedInformationTypes(self.user)
+
         class information_type_schema(Interface):
             information_type_field = copy_field(
                 IBug['information_type'], readonly=False,
-                vocabulary=InformationTypeVocabulary(self.context))
+                vocabulary=InformationTypeVocabulary(types=info_types))
         return information_type_schema
 
     @property

=== modified file 'lib/lp/bugs/browser/bugtarget.py'
--- lib/lp/bugs/browser/bugtarget.py	2012-07-17 06:34:59 +0000
+++ lib/lp/bugs/browser/bugtarget.py	2012-07-27 04:55:23 +0000
@@ -272,11 +272,15 @@
             type.name for type in PRIVATE_INFORMATION_TYPES]
         cache.objects['bug_private_by_default'] = (
             IProduct.providedBy(self.context) and self.context.private_bugs)
-        cache.objects['information_type_data'] = [
-            {'value': term.name, 'description': term.description,
-            'name': term.title,
-            'description_css_class': 'choice-description'}
-            for term in InformationTypeVocabulary(self.context)]
+        # Project groups are special. The Next button sends you to
+        # Product:+filebug, so we need none of the usual stuff.
+        if not IProjectGroup.providedBy(self.context):
+            cache.objects['information_type_data'] = [
+                {'value': term.name, 'description': term.description,
+                'name': term.title,
+                'description_css_class': 'choice-description'}
+                for term in
+                self.context.pillar.getAllowedBugInformationTypes()]
         bugtask_status_data = vocabulary_to_choice_edit_items(
             BugTaskStatus, include_description=True, css_class_prefix='status',
             excluded_items=[
@@ -297,10 +301,17 @@
         """Set up the form fields. See `LaunchpadFormView`."""
         super(FileBugReportingGuidelines, self).setUpFields()
 
+        # Project groups are special. The Next button sends you to
+        # Product:+filebug, so we need none of the usual stuff.
+        if IProjectGroup.providedBy(self.context):
+            return
+
         if self.is_bug_supervisor:
+            info_type_vocab = InformationTypeVocabulary(
+                types=self.context.pillar.getAllowedBugInformationTypes())
             information_type_field = copy_field(
                 IBug['information_type'], readonly=False,
-                vocabulary=InformationTypeVocabulary(self.context))
+                vocabulary=info_type_vocab)
             self.form_fields = self.form_fields.omit('information_type')
             self.form_fields += Fields(information_type_field)
         else:

=== modified file 'lib/lp/bugs/browser/bugtask.py'
--- lib/lp/bugs/browser/bugtask.py	2012-07-24 15:37:08 +0000
+++ lib/lp/bugs/browser/bugtask.py	2012-07-27 04:55:23 +0000
@@ -3105,8 +3105,13 @@
 
     def getInformationTypeWidgetValues(self):
         """Return data used to render the Information Type checkboxes."""
-        return self.getWidgetValues(
-            vocabulary=InformationTypeVocabulary(self.context))
+        if (IProduct.providedBy(self.context)
+            or IDistribution.providedBy(self.context)):
+            vocab = InformationTypeVocabulary(
+                types=self.context.getAllowedBugInformationTypes())
+        else:
+            vocab = InformationType
+        return self.getWidgetValues(vocabulary=vocab)
 
     def getMilestoneWidgetValues(self):
         """Return data used to render the milestone checkboxes."""

=== modified file 'lib/lp/bugs/browser/configure.zcml'
--- lib/lp/bugs/browser/configure.zcml	2012-05-25 18:39:46 +0000
+++ lib/lp/bugs/browser/configure.zcml	2012-07-27 04:55:23 +0000
@@ -525,7 +525,7 @@
             for="lp.bugs.interfaces.bugtask.IBugTask"
             name="+bugtask-macros-listing"
             template="../templates/bugtask-macros-listing.pt"
-            permission="zope.Public"/>
+            permission="launchpad.View"/>
         <browser:page
             name="+edit"
             for="lp.bugs.interfaces.bugtask.IBugTask"
@@ -554,7 +554,7 @@
             for="lp.bugs.interfaces.bugtask.IBugTask"
             name="+text"
             class="lp.bugs.browser.bugtask.BugTaskTextView"
-            permission="zope.Public"
+            permission="launchpad.View"
             attribute="__call__"/>
         <browser:page
             name="+affectsmetoo"
@@ -954,7 +954,7 @@
             for="lp.bugs.interfaces.bug.IBug"
             name="+index"
             class="lp.bugs.browser.bug.BugWithoutContextView"
-            permission="zope.Public"
+            permission="launchpad.View"
             attribute="__call__"/>
         <browser:page
             for="lp.bugs.interfaces.bug.IBug"
@@ -972,20 +972,23 @@
             for="lp.bugs.interfaces.bug.IBug"
             name="+text"
             class="lp.bugs.browser.bug.BugTextView"
-            permission="zope.Public"
+            permission="launchpad.View"
             attribute="__call__"/>
         <browser:page
             for="lp.bugs.interfaces.bug.IBug"
             name="+listing-detailed"
             template="../templates/bug-listing-detailed.pt"
-            permission="zope.Public"/>
+            permission="launchpad.View"/>
+        <browser:page
+            for="lp.bugs.interfaces.bug.IBug"
+            name="+portlet-privacy"
+            class="lp.bugs.browser.bug.BugInformationTypePortletView"
+            template="../templates/bug-portlet-privacy.pt"
+            permission="launchpad.View"/>
         <browser:pages
             for="lp.bugs.interfaces.bug.IBug"
             class="lp.bugs.browser.bug.BugView"
-            permission="zope.Public">
-            <browser:page
-                name="+portlet-privacy"
-                template="../templates/bug-portlet-privacy.pt"/>
+            permission="launchpad.View">
             <browser:page
                 name="+portlet-watch"
                 template="../templates/bug-portlet-watch.pt"/>
@@ -1013,13 +1016,13 @@
             name="+bug-portlet-subscribers-details"
             class="
               lp.bugs.browser.bugsubscription.BugPortletSubscribersWithDetails"
-            permission="zope.Public"/>
+            permission="launchpad.View"/>
         <browser:page
             for="lp.bugs.interfaces.bugtask.IBugTask"
             name="+bug-portlet-subscribers-details"
             class="
               lp.bugs.browser.bugsubscription.BugPortletSubscribersWithDetails"
-            permission="zope.Public"/>
+            permission="launchpad.View"/>
         <browser:navigation
             module="lp.bugs.browser.bug"
             classes="

=== modified file 'lib/lp/bugs/browser/tests/test_bug_views.py'
--- lib/lp/bugs/browser/tests/test_bug_views.py	2012-07-17 14:10:53 +0000
+++ lib/lp/bugs/browser/tests/test_bug_views.py	2012-07-27 04:55:23 +0000
@@ -409,20 +409,6 @@
         self.assertEqual(
             u'Private', soup.find('label', text="Private"))
 
-    def test_information_type_vocabulary_commercial_project(self):
-        # Test that the view creates the vocabulary correctly for commercial
-        # projects.
-        product = self.factory.makeProduct()
-        self.factory.makeCommercialSubscription(product)
-        bug = self.factory.makeBug(product=product)
-        with person_logged_in(bug.owner):
-            view = create_initialized_view(
-                bug.default_bugtask, name='+secrecy',
-                principal=bug.owner)
-            html = view.render()
-            soup = BeautifulSoup(html)
-        self.assertIsNot(None, soup.find('label', text="Proprietary"))
-
 
 class TestBugTextViewPrivateTeams(TestCaseWithFactory):
     """ Test for rendering BugTextView with private team artifacts.

=== modified file 'lib/lp/bugs/browser/tests/test_bugtarget_filebug.py'
--- lib/lp/bugs/browser/tests/test_bugtarget_filebug.py	2012-07-17 06:34:59 +0000
+++ lib/lp/bugs/browser/tests/test_bugtarget_filebug.py	2012-07-27 04:55:23 +0000
@@ -27,9 +27,8 @@
 from lp.registry.enums import (
     InformationType,
     PRIVATE_INFORMATION_TYPES,
-    PUBLIC_INFORMATION_TYPES,
     )
-from lp.registry.vocabularies import InformationTypeVocabulary
+from lp.registry.interfaces.projectgroup import IProjectGroup
 from lp.services.features.testing import FeatureFixture
 from lp.services.webapp.servers import LaunchpadTestRequest
 from lp.testing import (
@@ -393,18 +392,6 @@
         bug = self.filebug_via_view(private_bugs=True)
         self.assertEqual(InformationType.USERDATA, bug.information_type)
 
-    def test_filebug_information_type_commercial_projects(self):
-        # The vocabulary for information_type when filing a bug is created
-        # correctly for proprietary projects.
-        product = self.factory.makeProduct(official_malone=True)
-        self.factory.makeCommercialSubscription(product)
-        with person_logged_in(product.owner):
-            view = create_initialized_view(
-                product, '+filebug', principal=product.owner)
-            html = view.render()
-            soup = BeautifulSoup(html)
-        self.assertIsNotNone(soup.find('label', text="Proprietary"))
-
     def test_filebug_information_type_normal_projects(self):
         # The vocabulary for information_type when filing a bug is created
         # correctly for non commercial projects.
@@ -425,7 +412,7 @@
                 product, '+filebug', principal=product.owner)
             html = view.render()
             soup = BeautifulSoup(html)
-        for info_type in InformationTypeVocabulary(product):
+        for info_type in product.getAllowedBugInformationTypes():
             self.assertIsNotNone(soup.find('label', text=info_type.title))
 
     def test_filebug_view_renders_info_type_widget(self):
@@ -441,21 +428,6 @@
         self.assertIsNotNone(
             soup.find('input', attrs={'name': 'field.information_type'}))
 
-    def test_filebug_information_type_vocabulary_private_projects(self):
-        # The vocabulary for information_type when filing a bug only has
-        # private info types for private bug projects.
-        product = self.factory.makeProduct(
-            official_malone=True, private_bugs=True)
-        with person_logged_in(product.owner):
-            view = create_initialized_view(
-                product, '+filebug', principal=product.owner)
-            html = view.render()
-            soup = BeautifulSoup(html)
-        for info_type in InformationTypeVocabulary(private_only=True):
-            self.assertIsNotNone(soup.find('label', text=info_type.title))
-        for info_type in PUBLIC_INFORMATION_TYPES:
-            self.assertIsNone(soup.find('label', text=info_type.title))
-
 
 class TestFileBugForNonBugSupervisors(TestCaseWithFactory):
 
@@ -657,13 +629,14 @@
         self.assertEqual(
             bugtask_importance_data, cache['bugtask_importance_data'])
         bugtask_info_type_data = []
-        for item in InformationTypeVocabulary(private_only=private_only):
-            new_item = {'name': item.title, 'value': item.name,
-                        'description': item.description,
-                        'description_css_class': 'choice-description'}
-            bugtask_info_type_data.append(new_item)
-        self.assertContentEqual(
-            bugtask_info_type_data, cache['information_type_data'])
+        if not IProjectGroup.providedBy(view.context):
+            for item in view.context.getAllowedBugInformationTypes():
+                new_item = {'name': item.title, 'value': item.name,
+                            'description': item.description,
+                            'description_css_class': 'choice-description'}
+                bugtask_info_type_data.append(new_item)
+            self.assertContentEqual(
+                bugtask_info_type_data, cache['information_type_data'])
 
     def test_product(self):
         project = self.factory.makeProduct(official_malone=True)

=== modified file 'lib/lp/bugs/browser/tests/test_bugview.py'
--- lib/lp/bugs/browser/tests/test_bugview.py	2012-07-17 06:34:59 +0000
+++ lib/lp/bugs/browser/tests/test_bugview.py	2012-07-27 04:55:23 +0000
@@ -76,8 +76,7 @@
 
     def test_proprietary_excluded_for_normal_projects(self):
         # The Proprietary information type isn't in the JSON request cache for
-        # projects without commercial subscriptions.
-        # projects with commercial subscriptions.
+        # normal projects without proprietary bugs configured.
         product = self.factory.makeProduct(official_malone=True)
         bug = self.factory.makeBug(product=product)
         view = BugView(bug, LaunchpadTestRequest())
@@ -91,22 +90,3 @@
         self.assertContentEqual(expected, [
             type['value']
             for type in cache.objects['information_type_data']])
-
-    def test_proprietary_included_for_commercial_projects(self):
-        # The Proprietary information type is in the JSON request cache for
-        # projects with commercial subscriptions.
-        product = self.factory.makeProduct(official_malone=True)
-        self.factory.makeCommercialSubscription(product)
-        bug = self.factory.makeBug(product=product)
-        view = BugView(bug, LaunchpadTestRequest())
-        view.initialize()
-        cache = IJSONRequestCache(view.request)
-        expected = [
-            InformationType.PUBLIC.name,
-            InformationType.PUBLICSECURITY.name,
-            InformationType.PRIVATESECURITY.name,
-            InformationType.USERDATA.name,
-            InformationType.PROPRIETARY.name]
-        self.assertContentEqual(expected, [
-            type['value']
-            for type in cache.objects['information_type_data']])

=== modified file 'lib/lp/bugs/interfaces/bug.py'
--- lib/lp/bugs/interfaces/bug.py	2012-07-25 04:52:04 +0000
+++ lib/lp/bugs/interfaces/bug.py	2012-07-27 04:55:23 +0000
@@ -713,6 +713,12 @@
         Otherwise, return False.
         """
 
+    def getAllowedInformationTypes(user):
+        """Get a list of acceptable `InformationType`s for this bug.
+
+        The intersection of the affected pillars' allowed types is permitted.
+        """
+
 
 class IBugEdit(Interface):
     """IBug attributes that require launchpad.Edit permission."""

=== modified file 'lib/lp/bugs/model/bug.py'
--- lib/lp/bugs/model/bug.py	2012-07-25 22:25:27 +0000
+++ lib/lp/bugs/model/bug.py	2012-07-27 04:55:23 +0000
@@ -1733,6 +1733,14 @@
         return self.transitionToInformationType(
             convert_to_information_type(self.private, security_related), who)
 
+    def getAllowedInformationTypes(self, who):
+        """See `IBug`."""
+        types = set(InformationType.items)
+        for pillar in self.affected_pillars:
+            types.intersection_update(
+                set(pillar.getAllowedBugInformationTypes()))
+        return types
+
     def transitionToInformationType(self, information_type, who,
                                     from_api=False):
         """See `IBug`."""

=== modified file 'lib/lp/bugs/model/tests/test_bug.py'
--- lib/lp/bugs/model/tests/test_bug.py	2012-07-19 04:40:03 +0000
+++ lib/lp/bugs/model/tests/test_bug.py	2012-07-27 04:55:23 +0000
@@ -937,6 +937,15 @@
                 (pillar, InformationType.USERDATA) for pillar in pillars),
             get_policies_for_artifact(bug))
 
+    def test_getAllowedInformationTypes(self):
+        # A bug's information type must be in the intersection of its
+        # pillars' permitted information types. Currently that means
+        # it's just one of the usual four.
+        self.assertContentEqual(
+            [InformationType.PUBLIC, InformationType.PUBLICSECURITY,
+             InformationType.PRIVATESECURITY, InformationType.USERDATA],
+            self.factory.makeBug().getAllowedInformationTypes(None))
+
 
 class TestBugPrivateAndSecurityRelatedUpdatesPrivateProject(
         TestBugPrivateAndSecurityRelatedUpdatesMixin, TestCaseWithFactory):

=== modified file 'lib/lp/registry/interfaces/distribution.py'
--- lib/lp/registry/interfaces/distribution.py	2012-05-25 18:31:09 +0000
+++ lib/lp/registry/interfaces/distribution.py	2012-07-27 04:55:23 +0000
@@ -619,6 +619,12 @@
               bug watches or to products that use_malone.
         """
 
+    def getAllowedBugInformationTypes():
+        """Get the information types that a bug in this distribution can have.
+
+        :return: A sequence of `InformationType`s.
+        """
+
     def userCanEdit(user):
         """Can the user edit this distribution?"""
 

=== modified file 'lib/lp/registry/interfaces/product.py'
--- lib/lp/registry/interfaces/product.py	2012-07-13 08:29:56 +0000
+++ lib/lp/registry/interfaces/product.py	2012-07-27 04:55:23 +0000
@@ -793,6 +793,12 @@
     def setPrivateBugs(private_bugs, user):
         """Mutator for private_bugs that checks entitlement."""
 
+    def getAllowedBugInformationTypes():
+        """Get the information types that a bug in this distribution can have.
+
+        :return: A sequence of `InformationType`s.
+        """
+
     def getVersionSortedSeries(statuses=None, filter_statuses=None):
         """Return all the series sorted by the name field as a version.
 

=== modified file 'lib/lp/registry/model/distribution.py'
--- lib/lp/registry/model/distribution.py	2012-07-17 06:34:59 +0000
+++ lib/lp/registry/model/distribution.py	2012-07-27 04:55:23 +0000
@@ -192,7 +192,6 @@
     get_current_source_releases,
     SourcePackagePublishingHistory,
     )
-from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease
 from lp.translations.enums import TranslationPermission
 from lp.translations.model.hastranslationimports import (
     HasTranslationImportsMixin,
@@ -1597,6 +1596,12 @@
         if bug_supervisor is not None:
             self.addBugSubscription(bug_supervisor, user)
 
+    def getAllowedBugInformationTypes(self):
+        """See `IDistribution.`"""
+        types = set(InformationType.items)
+        types.discard(InformationType.PROPRIETARY)
+        return types
+
     def userCanEdit(self, user):
         """See `IDistribution`."""
         if user is None:

=== modified file 'lib/lp/registry/model/product.py'
--- lib/lp/registry/model/product.py	2012-07-24 06:39:54 +0000
+++ lib/lp/registry/model/product.py	2012-07-27 04:55:23 +0000
@@ -565,6 +565,12 @@
         self.checkPrivateBugsTransitionAllowed(private_bugs, user)
         self.private_bugs = private_bugs
 
+    def getAllowedBugInformationTypes(self):
+        """See `IProduct.`"""
+        types = set(InformationType.items)
+        types.discard(InformationType.PROPRIETARY)
+        return types
+
     def _ensurePolicies(self, information_types):
         # Ensure that the product has access policies for the specified
         # information types.

=== modified file 'lib/lp/registry/tests/test_distribution.py'
--- lib/lp/registry/tests/test_distribution.py	2012-07-17 06:34:59 +0000
+++ lib/lp/registry/tests/test_distribution.py	2012-07-27 04:55:23 +0000
@@ -276,6 +276,14 @@
             InformationType.USERDATA, InformationType.PRIVATESECURITY]
         self.assertContentEqual(expected, [policy.type for policy in ap])
 
+    def test_getAllowedBugInformationTypes(self):
+        # All distros currently support just the non-proprietary
+        # information types.
+        self.assertContentEqual(
+            [InformationType.PUBLIC, InformationType.PUBLICSECURITY,
+             InformationType.PRIVATESECURITY, InformationType.USERDATA],
+            self.factory.makeProduct().getAllowedBugInformationTypes())
+
 
 class TestDistributionCurrentSourceReleases(
     CurrentSourceReleasesMixin, TestCase):

=== modified file 'lib/lp/registry/tests/test_information_type_vocabulary.py'
--- lib/lp/registry/tests/test_information_type_vocabulary.py	2012-07-26 06:14:26 +0000
+++ lib/lp/registry/tests/test_information_type_vocabulary.py	2012-07-27 04:55:23 +0000
@@ -1,65 +1,29 @@
 # Copyright 2012 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
-"""Test the Distribution Source Package vocabulary."""
+"""Test the information type vocabulary."""
 
 __metaclass__ = type
 
-
 from testtools.matchers import MatchesStructure
 
-from lp.registry.enums import (
-    InformationType,
-    PRIVATE_INFORMATION_TYPES,
-    PUBLIC_INFORMATION_TYPES,
-    )
+from lp.registry.enums import InformationType
 from lp.registry.vocabularies import InformationTypeVocabulary
-from lp.services.features.testing import FeatureFixture
-from lp.testing import (
-    person_logged_in,
-    TestCaseWithFactory,
-    )
-from lp.testing.layers import DatabaseFunctionalLayer
-
-
-class TestInformationTypeVocabulary(TestCaseWithFactory):
-
-    layer = DatabaseFunctionalLayer
-
-    def test_vocabulary_items(self):
-        product = self.factory.makeProduct()
-        self.factory.makeCommercialSubscription(product)
-        vocab = InformationTypeVocabulary(product)
-        for info_type in InformationType:
-            self.assertIn(info_type.value, vocab)
-
-    def test_vocabulary_items_project(self):
-        # The vocab has all info types for a project without private_bugs set.
-        product = self.factory.makeProduct()
-        self.factory.makeCommercialSubscription(product)
-        vocab = InformationTypeVocabulary(product)
-        for info_type in InformationType:
-            self.assertIn(info_type.value, vocab)
-
-    def test_vocabulary_items_private_bugs_project(self):
-        # The vocab has private info types for a project with private_bugs set.
-        product = self.factory.makeProduct(private_bugs=True)
-        self.factory.makeCommercialSubscription(product)
-        vocab = InformationTypeVocabulary(product)
-        for info_type in PRIVATE_INFORMATION_TYPES:
-            self.assertIn(info_type, vocab)
-        for info_type in PUBLIC_INFORMATION_TYPES:
-            self.assertNotIn(info_type, vocab)
+from lp.testing import TestCase
+
+
+class TestInformationTypeVocabulary(TestCase):
 
     def test_vocabulary_items_custom(self):
-        # The vocab can be given a custom set of types to include.
+        # The vocab is given a custom set of types to include.
         vocab = InformationTypeVocabulary(
-            types=[InformationType.PUBLICSECURITY, InformationType.USERDATA])
+            [InformationType.PUBLICSECURITY, InformationType.USERDATA])
         self.assertIn(InformationType.USERDATA, vocab)
+        self.assertIn(InformationType.PUBLICSECURITY, vocab)
         self.assertNotIn(InformationType.PUBLIC, vocab)
 
     def test_getTermByToken(self):
-        vocab = InformationTypeVocabulary()
+        vocab = InformationTypeVocabulary([InformationType.PUBLIC])
         self.assertThat(
             vocab.getTermByToken('PUBLIC'),
             MatchesStructure.byEquality(
@@ -67,58 +31,3 @@
                 token='PUBLIC',
                 title='Public',
                 description=InformationType.PUBLIC.description))
-
-    def test_proprietary_disabled(self):
-        # The feature flag disables proprietary even if it would otherwise be
-        # included.
-        feature_flag = {
-            'disclosure.proprietary_information_type.disabled': 'on'}
-        with FeatureFixture(feature_flag):
-            product = self.factory.makeProduct()
-            vocab = InformationTypeVocabulary(product)
-            self.assertRaises(
-                LookupError, vocab.getTermByToken, 'PROPRIETARY')
-
-    def test_proprietary_disabled_for_non_commercial_projects(self):
-        # Only projects with commercial subscriptions have PROPRIETARY.
-        product = self.factory.makeProduct()
-        vocab = InformationTypeVocabulary(product)
-        self.assertRaises(
-            LookupError, vocab.getTermByToken, 'PROPRIETARY')
-
-    def test_proprietary_enabled_for_commercial_projects(self):
-        # Only projects with commercial subscriptions have PROPRIETARY.
-        product = self.factory.makeProduct()
-        self.factory.makeCommercialSubscription(product)
-        vocab = InformationTypeVocabulary(product)
-        term = vocab.getTermByToken('PROPRIETARY')
-        self.assertEqual('Proprietary', term.title)
-
-    def test_proprietary_enabled_for_contexts_already_proprietary(self):
-        # The vocabulary has PROPRIETARY for contexts which are already
-        # proprietary.
-        owner = self.factory.makePerson()
-        bug = self.factory.makeBug(
-            owner=owner, information_type=InformationType.PROPRIETARY)
-        with person_logged_in(owner):
-            vocab = InformationTypeVocabulary(bug)
-        term = vocab.getTermByToken('PROPRIETARY')
-        self.assertEqual('Proprietary', term.title)
-
-    def test_multi_pillar_bugs(self):
-        # Multi-pillar bugs are forbidden from being PROPRIETARY, no matter
-        # the setting of proprietary_information_type.disabled.
-        bug = self.factory.makeBug()
-        self.factory.makeBugTask(bug=bug, target=self.factory.makeProduct())
-        vocab = InformationTypeVocabulary(bug)
-        self.assertRaises(LookupError, vocab.getTermByToken, 'PROPRIETARY')
-
-    def test_multi_task_bugs(self):
-        # Multi-task bugs are allowed to be PROPRIETARY.
-        product = self.factory.makeProduct()
-        self.factory.makeCommercialSubscription(product)
-        bug = self.factory.makeBug(product=product)
-        self.factory.makeBugTask(bug=bug) # Uses the same pillar.
-        vocab = InformationTypeVocabulary(bug)
-        term = vocab.getTermByToken('PROPRIETARY')
-        self.assertEqual('Proprietary', term.title)

=== modified file 'lib/lp/registry/tests/test_product.py'
--- lib/lp/registry/tests/test_product.py	2012-07-24 06:39:54 +0000
+++ lib/lp/registry/tests/test_product.py	2012-07-27 04:55:23 +0000
@@ -401,6 +401,14 @@
         grantees = set([grant.grantee for grant in grants])
         self.assertEqual(expected_grantess, grantees)
 
+    def test_getAllowedBugInformationTypes(self):
+        # All projects currently support just the non-proprietary
+        # information types.
+        self.assertContentEqual(
+            [InformationType.PUBLIC, InformationType.PUBLICSECURITY,
+             InformationType.PRIVATESECURITY, InformationType.USERDATA],
+            self.factory.makeProduct().getAllowedBugInformationTypes())
+
 
 class TestProductFiles(TestCase):
     """Tests for downloadable product files."""

=== modified file 'lib/lp/registry/vocabularies.py'
--- lib/lp/registry/vocabularies.py	2012-07-27 03:57:33 +0000
+++ lib/lp/registry/vocabularies.py	2012-07-27 04:55:23 +0000
@@ -103,10 +103,7 @@
 
 from lp.app.interfaces.launchpad import ILaunchpadCelebrities
 from lp.blueprints.interfaces.specification import ISpecification
-from lp.bugs.interfaces.bug import IBug
 from lp.bugs.interfaces.bugtask import IBugTask
-from lp.code.interfaces.branch import IBranch
-from lp.registry.enums import InformationType
 from lp.registry.interfaces.accesspolicy import IAccessPolicySource
 from lp.registry.interfaces.distribution import (
     IDistribution,
@@ -177,7 +174,6 @@
     SQLBase,
     sqlvalues,
     )
-from lp.services.features import getFeatureFlag
 from lp.services.helpers import (
     ensure_unicode,
     shortlist,
@@ -2244,53 +2240,7 @@
 
     implements(IEnumeratedType)
 
-    def _calculateTypes(self, context, public_only, private_only):
-        types = []
-        if not public_only:
-            types = [
-                InformationType.PRIVATESECURITY,
-                InformationType.USERDATA]
-            # So long as not disabled by the feature flag, Proprietary is
-            # allowed for:
-            # - single pillar bugs where the target has a current commercial
-            #   subscription
-            # - branches for a project with a current commercial subscription
-            # - projects with current commercial subscriptions
-            # - contexts which already have an information type set to
-            #   proprietary
-            proprietary_disabled = bool(getFeatureFlag(
-                'disclosure.proprietary_information_type.disabled'))
-            if not proprietary_disabled:
-                subscription_context = context
-                if (IBug.providedBy(context)
-                    and len(context.affected_pillars) == 1):
-                    subscription_context = context.affected_pillars[0]
-                elif (IBugTask.providedBy(context)
-                    and len(context.bug.affected_pillars) == 1):
-                    subscription_context = context.pillar
-                elif IBranch.providedBy(context):
-                    subscription_context = context.target.context
-                has_commercial_subscription = (
-                    IProduct.providedBy(subscription_context) and
-                    subscription_context.has_current_commercial_subscription)
-                already_proprietary = (
-                    safe_hasattr(context, 'information_type') and
-                    context.information_type == InformationType.PROPRIETARY)
-                if has_commercial_subscription or already_proprietary:
-                    types.append(InformationType.PROPRIETARY)
-        # Disallow public items for projects with private bugs.
-        if (not private_only and (context is None or
-            not IProduct.providedBy(context) or
-            not context.private_bugs)):
-            types = [InformationType.PUBLIC,
-                     InformationType.PUBLICSECURITY] + types
-        return types
-
-    def __init__(self, context=None, public_only=False, private_only=False,
-                 types=None):
-        if types is None:
-            types = self._calculateTypes(context, public_only, private_only)
-
+    def __init__(self, types):
         terms = []
         for type in types:
             term = SimpleTerm(type, type.name, type.title)


Follow ups