← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~abentley/launchpad/no-proprietary-linked-products into lp:launchpad

 

Aaron Bentley has proposed merging lp:~abentley/launchpad/no-proprietary-linked-products into lp:launchpad.

Commit message:
No packaging links for Proprietary products.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1063297 in Launchpad itself: "Linking a private project to an ubuntu source package breaks Ubuntu"
  https://bugs.launchpad.net/launchpad/+bug/1063297

For more details, see:
https://code.launchpad.net/~abentley/launchpad/no-proprietary-linked-products/+merge/129507

= Summary =
Fix bug #1063297: Linking a private project to an ubuntu source package breaks Ubuntu
== Proposed fix ==
Prevent creating packaging links for private products, prevent making packaged products proprietary

== Pre-implementation notes ==
None

== LOC Rationale ==
Part of Private Projects

== Implementation details ==
The restrictions are implemented on the model level, and the errors it emits are handled as user errors in the UI.

ProductSeries.setPackaging and SourcePackage.setPackaging are updated to use PackagingUtil.createPackaging instead of using the constructor directly.

PackagingUtil.createPackaging is updated to raise
CannotPackageProprietaryProduct if the productseries is private.

PackagingUtil.createPackaging is changed to a class method, and packagingEntryExists to a staticmethod to permit direct use.

ProductEditView is updated to handle CannotChangeInformationType, and to stay on the current page if there are errors.

ProductSeries is updated to add an error to the main page if CannotPackageProprietaryProduct is raised.

The validator for SourcePackageChangeUpstreamStepOne is updated to check whether the product is private.  This affects both steps (i.e. SourcePackageChangeUpstreamStepOne.validateStep is run for StepTwo).

The packaging portal is hidden for private product series.  (They should not have packagings, and should not be able to set them.)



== Tests ==
bin/test -t test_no_proprietary_if_packaging -t test_createPackaging_refuses_ -t test_error_on_proprietary_product -t test_proprietary_hides_packaging -t test_package_proprietary_error

== Demo and Q/A ==
Create a product series with a public project.  Click on "trunk".  Click on "Link to Ubuntu package".  In another browser window, edit the project and set it to Proprietary.  Enter a source package name and series.  Click "Update".  It should say "Only Public project series can be packaged, not Proprietary."

Go to a source package.  Click "Choose another upstream project".  Click "Link to Upstream Project".  Enter the name of a proprietary product.  It should say "Only Public project series can be packaged, not Proprietary."

Disable JavaScript.  Create a public product and link its trunk to a source package.  Click "Change details."  Select "Proprietary".  Click "change".  It should say "Some series are packaged."


= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/registry/tests/test_productseries.py
  lib/lp/registry/errors.py
  lib/lp/registry/model/productseries.py
  lib/lp/registry/browser/sourcepackage.py
  lib/lp/registry/model/packaging.py
  lib/lp/registry/browser/product.py
  lib/lp/registry/tests/test_sourcepackage.py
  lib/lp/registry/tests/test_packaging.py
  lib/lp/registry/browser/productseries.py
  lib/lp/registry/browser/tests/test_product.py
  lib/lp/registry/browser/tests/test_sourcepackage_views.py
  lib/lp/registry/model/sourcepackage.py
  lib/lp/registry/model/product.py
  lib/lp/registry/templates/productseries-index.pt
  lib/lp/registry/tests/test_product.py
  lib/lp/registry/browser/tests/test_productseries_views.py
-- 
https://code.launchpad.net/~abentley/launchpad/no-proprietary-linked-products/+merge/129507
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~abentley/launchpad/no-proprietary-linked-products into lp:launchpad.
=== modified file 'lib/lp/registry/browser/product.py'
--- lib/lp/registry/browser/product.py	2012-10-11 12:41:43 +0000
+++ lib/lp/registry/browser/product.py	2012-10-12 20:13:24 +0000
@@ -156,6 +156,7 @@
     PillarViewMixin,
     )
 from lp.registry.browser.productseries import get_series_branch_error
+from lp.registry.errors import CannotChangeInformationType
 from lp.registry.interfaces.pillar import IPillarNameSet
 from lp.registry.interfaces.product import (
     IProduct,
@@ -1397,6 +1398,8 @@
     def next_url(self):
         """See `LaunchpadFormView`."""
         if self.context.active:
+            if len(self.errors) > 0:
+                return None
             return canonical_url(self.context)
         else:
             return canonical_url(getUtility(IProductSet))
@@ -1438,7 +1441,10 @@
 
     @action("Change", name='change')
     def change_action(self, action, data):
-        self.updateContextFromData(data)
+        try:
+            self.updateContextFromData(data)
+        except CannotChangeInformationType as e:
+            self.setFieldError('information_type', str(e))
 
 
 class ProductValidationMixin:

=== modified file 'lib/lp/registry/browser/productseries.py'
--- lib/lp/registry/browser/productseries.py	2012-10-10 20:23:48 +0000
+++ lib/lp/registry/browser/productseries.py	2012-10-12 20:13:24 +0000
@@ -111,6 +111,7 @@
     InvolvedMenu,
     PillarInvolvementView,
     )
+from lp.registry.errors import CannotPackageProprietaryProduct
 from lp.registry.interfaces.packaging import (
     IPackaging,
     IPackagingUtil,
@@ -636,8 +637,11 @@
             sourcepackagename, distroseries, productseries=self.context):
             # There is no change.
             return
-        self.context.setPackaging(
-            distroseries, sourcepackagename, self.user)
+        try:
+            self.context.setPackaging(
+                distroseries, sourcepackagename, self.user)
+        except CannotPackageProprietaryProduct, e:
+            self.request.response.addErrorNotification(str(e))
 
 
 class ProductSeriesEditView(LaunchpadEditFormView):

=== modified file 'lib/lp/registry/browser/sourcepackage.py'
--- lib/lp/registry/browser/sourcepackage.py	2012-01-03 05:05:39 +0000
+++ lib/lp/registry/browser/sourcepackage.py	2012-10-12 20:13:24 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2012 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Browser views for sourcepackages."""
@@ -302,6 +302,16 @@
         self.next_step = SourcePackageChangeUpstreamStepTwo
         self.request.form['product'] = data['product']
 
+    def validateStep(self, data):
+        super(SourcePackageChangeUpstreamStepOne, self).validateStep(data)
+        product = data.get('product')
+        if product is None:
+            return
+        if product.private:
+            self.setFieldError('product',
+                'Only Public projects can be packaged, not %s.' %
+                data['product'].information_type.title)
+
     @property
     def register_upstream_url(self):
         return get_register_upstream_url(self.context)

=== modified file 'lib/lp/registry/browser/tests/test_product.py'
--- lib/lp/registry/browser/tests/test_product.py	2012-10-10 13:56:03 +0000
+++ lib/lp/registry/browser/tests/test_product.py	2012-10-12 20:13:24 +0000
@@ -432,7 +432,7 @@
             cache.objects['team_membership_policy_data'])
 
 
-class TestProductEditView(TestCaseWithFactory):
+class TestProductEditView(BrowserTestCase):
     """Tests for the ProductEditView"""
 
     layer = DatabaseFunctionalLayer
@@ -481,6 +481,22 @@
             # the product when the information type is changed.
             self.assertIsNotNone(updated_product.commercial_subscription)
 
+    def test_change_information_type_proprietary_packaged(self):
+        self.useFixture(FeatureFixture(
+            {u'disclosure.private_projects.enabled': u'on'}))
+        product = self.factory.makeProduct()
+        sourcepackage = self.factory.makeSourcePackage()
+        sourcepackage.setPackaging(product.development_focus, product.owner)
+        browser = self.getViewBrowser(product, '+edit', user=product.owner)
+        info_type = browser.getControl(name='field.information_type')
+        info_type.value = ['PROPRIETARY']
+        old_url = browser.url
+        browser.getControl('Change').click()
+        self.assertEqual(old_url, browser.url)
+        tag = Tag('error', 'div', text='Some series are packaged.',
+                  attrs={'class': 'message'})
+        self.assertThat(browser.contents, HTMLContains(tag))
+
     def test_change_information_type_public(self):
         owner = self.factory.makePerson(name='pting')
         product = self.factory.makeProduct(

=== modified file 'lib/lp/registry/browser/tests/test_productseries_views.py'
--- lib/lp/registry/browser/tests/test_productseries_views.py	2012-06-19 18:27:50 +0000
+++ lib/lp/registry/browser/tests/test_productseries_views.py	2012-10-12 20:13:24 +0000
@@ -1,4 +1,4 @@
-# Copyright 2011 Canonical Ltd.  This software is licensed under the
+# Copyright 2011-2012 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """View tests for ProductSeries pages."""
@@ -7,7 +7,9 @@
 
 
 import soupmatchers
+from testtools.matchers import Not
 
+from lp.app.enums import InformationType
 from lp.bugs.interfaces.bugtask import (
     BugTaskStatus,
     BugTaskStatusSearch,
@@ -58,6 +60,35 @@
         browser = self.getViewBrowser(series)
         self.assertThat(browser.contents, soupmatchers.HTMLContains(tag))
 
+    def test_package_proprietary_error(self):
+        """Packaging a proprietary product produces an error."""
+        product = self.factory.makeProduct(
+            information_type=InformationType.PROPRIETARY)
+        productseries = self.factory.makeProductSeries(product=product)
+        ubuntu_series = self.factory.makeUbuntuDistroSeries()
+        sp = self.factory.makeSourcePackage(distroseries=ubuntu_series,
+                                            publish=True)
+        browser = self.getViewBrowser(productseries, '+ubuntupkg')
+        browser.getControl('Source Package Name').value = (
+            sp.sourcepackagename.name)
+        browser.getControl(ubuntu_series.displayname).selected = True
+        browser.getControl('Update').click()
+        tag = soupmatchers.Tag(
+            'error-div', 'div', attrs={'class': 'error message'},
+             text='Only Public project series can be packaged, not'
+             ' Proprietary.')
+        self.assertThat(browser.contents, soupmatchers.HTMLContains(tag))
+
+    def test_proprietary_hides_packaging(self):
+        """Proprietary, Embargoed lack "Distribution packaging" sections."""
+        product = self.factory.makeProduct(
+            information_type=InformationType.PROPRIETARY)
+        series = self.factory.makeProductSeries(product=product)
+        browser = self.getViewBrowser(series)
+        tag = soupmatchers.Tag(
+            'portlet-packages', True, attrs={'id': 'portlet-packages'})
+        self.assertThat(browser.contents, Not(soupmatchers.HTMLContains(tag)))
+
 
 class TestProductSeriesStatus(TestCaseWithFactory):
     """Tests for ProductSeries:+status."""

=== modified file 'lib/lp/registry/browser/tests/test_sourcepackage_views.py'
--- lib/lp/registry/browser/tests/test_sourcepackage_views.py	2012-09-18 20:38:09 +0000
+++ lib/lp/registry/browser/tests/test_sourcepackage_views.py	2012-10-12 20:13:24 +0000
@@ -1,4 +1,4 @@
-# Copyright 2010-2011 Canonical Ltd.  This software is licensed under the
+# Copyright 2010-2012 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Tests for SourcePackage view code."""
@@ -12,6 +12,7 @@
 from zope.interface import implements
 from zope.security.proxy import removeSecurityProxy
 
+from lp.app.enums import InformationType
 from lp.registry.browser.sourcepackage import (
     get_register_upstream_url,
     PackageUpstreamTracking,
@@ -25,6 +26,7 @@
 from lp.registry.interfaces.sourcepackage import ISourcePackage
 from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
 from lp.testing import (
+    BrowserTestCase,
     person_logged_in,
     TestCaseWithFactory,
     )
@@ -287,3 +289,38 @@
         menu, user = self.makeSourcePackageOverviewMenu(True, None)
         with person_logged_in(user):
             self.assertFalse(menu.remove_packaging().enabled)
+
+
+class TestSourcePackageChangeUpstreamView(BrowserTestCase):
+
+    layer = DatabaseFunctionalLayer
+
+    def test_error_on_proprietary_product(self):
+        """Packaging cannot be created for PROPRIETARY products"""
+        product = self.factory.makeProduct(
+            information_type=InformationType.PROPRIETARY)
+        ubuntu_series = self.factory.makeUbuntuDistroSeries()
+        sp = self.factory.makeSourcePackage(distroseries=ubuntu_series)
+        browser = self.getViewBrowser(sp, '+edit-packaging')
+        browser.getControl('Project').value = product.name
+        browser.getControl('Continue').click()
+        self.assertIn(
+            'Only Public projects can be packaged, not Proprietary.',
+            browser.contents)
+
+    def test_error_on_proprietary_productseries(self):
+        """Packaging cannot be created for PROPRIETARY productseries"""
+        product = self.factory.makeProduct()
+        series = self.factory.makeProductSeries(product=product)
+        ubuntu_series = self.factory.makeUbuntuDistroSeries()
+        sp = self.factory.makeSourcePackage(distroseries=ubuntu_series)
+        browser = self.getViewBrowser(sp, '+edit-packaging')
+        browser.getControl('Project').value = product.name
+        browser.getControl('Continue').click()
+        with person_logged_in(product.owner):
+            product.information_type = InformationType.PROPRIETARY
+        browser.getControl(series.displayname).selected = True
+        browser.getControl('Change').click()
+        self.assertIn(
+            'Only Public projects can be packaged, not Proprietary.',
+            browser.contents)

=== modified file 'lib/lp/registry/errors.py'
--- lib/lp/registry/errors.py	2012-09-04 04:27:53 +0000
+++ lib/lp/registry/errors.py	2012-10-12 20:13:24 +0000
@@ -9,6 +9,7 @@
     'CannotDeleteCommercialSubscription',
     'CannotTransitionToCountryMirror',
     'CommercialSubscribersOnly',
+    'CannotPackageProprietaryProduct',
     'CountryMirrorAlreadySet',
     'DeleteSubscriptionError',
     'InvalidFilename',
@@ -202,3 +203,7 @@
 @error_status(httplib.BAD_REQUEST)
 class CannotChangeInformationType(Exception):
     """The information type cannot be changed."""
+
+
+class CannotPackageProprietaryProduct(Exception):
+    """Raised when a non-PUBLIC product's series is linked to a package."""

=== modified file 'lib/lp/registry/model/packaging.py'
--- lib/lp/registry/model/packaging.py	2012-09-19 14:23:35 +0000
+++ lib/lp/registry/model/packaging.py	2012-10-12 20:13:24 +0000
@@ -16,7 +16,9 @@
 from zope.interface import implements
 from zope.security.interfaces import Unauthorized
 
+from lp.app.enums import InformationType
 from lp.app.interfaces.launchpad import ILaunchpadCelebrities
+from lp.registry.errors import CannotPackageProprietaryProduct
 from lp.registry.interfaces.packaging import (
     IPackaging,
     IPackagingUtil,
@@ -95,17 +97,26 @@
     """Utilities for Packaging."""
     implements(IPackagingUtil)
 
-    def createPackaging(self, productseries, sourcepackagename,
+    @classmethod
+    def createPackaging(cls, productseries, sourcepackagename,
                         distroseries, packaging, owner):
         """See `IPackaging`.
 
         Raises an assertion error if there is already packaging for
         the sourcepackagename in the distroseries.
         """
-        if self.packagingEntryExists(sourcepackagename, distroseries):
+        if cls.packagingEntryExists(sourcepackagename, distroseries):
             raise AssertionError(
                 "A packaging entry for %s in %s already exists." %
                 (sourcepackagename.name, distroseries.name))
+        # XXX: AaronBentley: 2012-08-12 bug=1066063 Cannot adapt ProductSeries
+        # to IInformationType.
+        # info_type = IInformationType(productseries).information_type
+        info_type = productseries.product.information_type
+        if info_type != InformationType.PUBLIC:
+            raise CannotPackageProprietaryProduct(
+                "Only Public project series can be packaged, not %s."
+                % info_type.title)
         return Packaging(productseries=productseries,
                          sourcepackagename=sourcepackagename,
                          distroseries=distroseries,
@@ -126,7 +137,8 @@
                distroseries.parent.name, distroseries.name))
         packaging.destroySelf()
 
-    def packagingEntryExists(self, sourcepackagename, distroseries,
+    @staticmethod
+    def packagingEntryExists(sourcepackagename, distroseries,
                              productseries=None):
         """See `IPackaging`."""
         criteria = dict(

=== modified file 'lib/lp/registry/model/product.py'
--- lib/lp/registry/model/product.py	2012-10-11 07:35:25 +0000
+++ lib/lp/registry/model/product.py	2012-10-12 20:13:24 +0000
@@ -438,6 +438,8 @@
         # If you have a commercial subscription, but it's not current, you
         # cannot set the information type to a PROPRIETARY type.
         if not self._SO_creating and value in PROPRIETARY_INFORMATION_TYPES:
+            if not self.packagings.is_empty():
+                raise CannotChangeInformationType('Some series are packaged.')
             # Create the complimentary commercial subscription for the product.
             self._ensure_complimentary_subscription()
 

=== modified file 'lib/lp/registry/model/productseries.py'
--- lib/lp/registry/model/productseries.py	2012-10-06 23:40:20 +0000
+++ lib/lp/registry/model/productseries.py	2012-10-12 20:13:24 +0000
@@ -71,7 +71,7 @@
     HasMilestonesMixin,
     Milestone,
     )
-from lp.registry.model.packaging import Packaging
+from lp.registry.model.packaging import PackagingUtil
 from lp.registry.model.productrelease import ProductRelease
 from lp.registry.model.series import SeriesMixin
 from lp.services.database.constants import UTC_NOW
@@ -504,7 +504,7 @@
 
         # ok, we didn't find a packaging record that matches, let's go ahead
         # and create one
-        pkg = Packaging(
+        pkg = PackagingUtil.createPackaging(
             distroseries=distroseries,
             sourcepackagename=sourcepackagename,
             productseries=self,

=== modified file 'lib/lp/registry/model/sourcepackage.py'
--- lib/lp/registry/model/sourcepackage.py	2012-09-26 05:21:07 +0000
+++ lib/lp/registry/model/sourcepackage.py	2012-10-12 20:13:24 +0000
@@ -54,7 +54,7 @@
     ISourcePackageFactory,
     )
 from lp.registry.model.hasdrivers import HasDriversMixin
-from lp.registry.model.packaging import Packaging
+from lp.registry.model.packaging import Packaging, PackagingUtil
 from lp.registry.model.suitesourcepackage import SuiteSourcePackage
 from lp.services.database.lpstorm import IStore
 from lp.services.database.sqlbase import (
@@ -523,7 +523,7 @@
             # Delete the current packaging and create a new one so
             # that the translation sharing jobs are started.
             self.direct_packaging.destroySelf()
-        Packaging(
+        PackagingUtil.createPackaging(
             distroseries=self.distroseries,
             sourcepackagename=self.sourcepackagename,
             productseries=productseries, owner=owner,

=== modified file 'lib/lp/registry/templates/productseries-index.pt'
--- lib/lp/registry/templates/productseries-index.pt	2012-02-01 15:31:32 +0000
+++ lib/lp/registry/templates/productseries-index.pt	2012-10-12 20:13:24 +0000
@@ -154,7 +154,8 @@
             tal:content="structure context/@@+portlet-latestbugs"
             tal:condition="context/@@+get-involved/official_malone" />
 
-          <div tal:content="structure context/@@+portlet-packages" />
+          <div tal:content="structure context/@@+portlet-packages"
+               tal:condition="not: context/product/private" />
         </div>
 
         <div class="yui-u">

=== modified file 'lib/lp/registry/tests/test_packaging.py'
--- lib/lp/registry/tests/test_packaging.py	2012-09-19 16:56:38 +0000
+++ lib/lp/registry/tests/test_packaging.py	2012-10-12 20:13:24 +0000
@@ -11,10 +11,13 @@
     ObjectCreatedEvent,
     ObjectDeletedEvent,
     )
+from testtools.testcase import ExpectedException
 from zope.component import getUtility
 from zope.security.interfaces import Unauthorized
 from zope.security.proxy import removeSecurityProxy
 
+from lp.app.enums import InformationType
+from lp.registry.errors import CannotPackageProprietaryProduct
 from lp.registry.interfaces.distribution import IDistributionSet
 from lp.registry.interfaces.packaging import (
     IPackagingUtil,
@@ -169,6 +172,28 @@
             self.productseries, self.sourcepackagename, self.distroseries,
             PackagingType.PRIME, self.owner)
 
+    def test_createPackaging_refuses_PROPRIETARY(self):
+        """Packaging cannot be created for PROPRIETARY productseries"""
+        product = self.factory.makeProduct(
+            information_type=InformationType.PROPRIETARY)
+        series = self.factory.makeProductSeries(product=product)
+        with ExpectedException(CannotPackageProprietaryProduct,
+            'Only Public project series can be packaged, not Proprietary.'):
+            self.packaging_util.createPackaging(
+                series, self.sourcepackagename, self.distroseries,
+                PackagingType.PRIME, owner=self.owner)
+
+    def test_createPackaging_refuses_EMBARGOED(self):
+        """Packaging cannot be created for EMBARGOED productseries"""
+        product = self.factory.makeProduct(
+            information_type=InformationType.EMBARGOED)
+        series = self.factory.makeProductSeries(product=product)
+        with ExpectedException(CannotPackageProprietaryProduct,
+            'Only Public project series can be packaged, not Embargoed.'):
+            self.packaging_util.createPackaging(
+                series, self.sourcepackagename, self.distroseries,
+                PackagingType.PRIME, owner=self.owner)
+
 
 class TestPackagingEntryExists(PackagingUtilMixin, TestCaseWithFactory):
     """Test PackagingUtil.packagingEntryExists."""

=== modified file 'lib/lp/registry/tests/test_product.py'
--- lib/lp/registry/tests/test_product.py	2012-10-11 04:21:07 +0000
+++ lib/lp/registry/tests/test_product.py	2012-10-12 20:13:24 +0000
@@ -513,6 +513,18 @@
                 CannotChangeInformationType, 'Answers is enabled.'):
                 product.information_type = InformationType.PROPRIETARY
 
+    def test_no_proprietary_if_packaging(self):
+        # information_type cannot be set to proprietary while any
+        # productseries are packaged.
+        product = self.factory.makeProduct(
+            licenses=[License.OTHER_PROPRIETARY])
+        series = self.factory.makeProductSeries(product=product)
+        self.factory.makePackagingLink(productseries=series)
+        with person_logged_in(product.owner):
+            with ExpectedException(
+                CannotChangeInformationType, 'Some series are packaged.'):
+                product.information_type = InformationType.PROPRIETARY
+
 
 class TestProductBugInformationTypes(TestCaseWithFactory):
 

=== modified file 'lib/lp/registry/tests/test_productseries.py'
--- lib/lp/registry/tests/test_productseries.py	2012-01-01 02:58:52 +0000
+++ lib/lp/registry/tests/test_productseries.py	2012-10-12 20:13:24 +0000
@@ -1,14 +1,17 @@
-# Copyright 2010-2011 Canonical Ltd.  This software is licensed under the
+# Copyright 2010-2012 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Tests for ProductSeries and ProductSeriesSet."""
 
 __metaclass__ = type
 
+from testtools.testcase import ExpectedException
 import transaction
 from zope.component import getUtility
 from zope.security.proxy import removeSecurityProxy
 
+from lp.app.enums import InformationType
+from lp.registry.errors import CannotPackageProprietaryProduct
 from lp.registry.interfaces.distribution import IDistributionSet
 from lp.registry.interfaces.distroseries import IDistroSeriesSet
 from lp.registry.interfaces.productseries import (
@@ -138,6 +141,28 @@
             distroseries=self.ubuntu_series)
         return sourcepackage
 
+    def test_refuses_PROPRIETARY(self):
+        """Packaging cannot be created for PROPRIETARY productseries"""
+        product = self.factory.makeProduct(
+            information_type=InformationType.PROPRIETARY)
+        series = self.factory.makeProductSeries(product=product)
+        sp = self.makeSourcePackage()
+        with ExpectedException(CannotPackageProprietaryProduct,
+            'Only Public project series can be packaged, not Proprietary.'):
+            series.setPackaging(
+                sp.distroseries, sp.sourcepackagename, series.owner)
+
+    def test_refuses_EMBARGOED(self):
+        """Packaging cannot be created for EMBARGOED productseries"""
+        product = self.factory.makeProduct(
+            information_type=InformationType.EMBARGOED)
+        sp = self.makeSourcePackage()
+        series = self.factory.makeProductSeries(product=product)
+        with ExpectedException(CannotPackageProprietaryProduct,
+            'Only Public project series can be packaged, not Embargoed.'):
+            series.setPackaging(
+                sp.distroseries, sp.sourcepackagename, series.owner)
+
     def test_setPackaging_two_packagings(self):
         # More than one sourcepackage from the same distroseries
         # can be linked to a productseries.

=== modified file 'lib/lp/registry/tests/test_sourcepackage.py'
--- lib/lp/registry/tests/test_sourcepackage.py	2012-09-19 14:23:35 +0000
+++ lib/lp/registry/tests/test_sourcepackage.py	2012-10-12 20:13:24 +0000
@@ -11,16 +11,19 @@
     )
 from storm.locals import Store
 import transaction
+from testtools.testcase import ExpectedException
 from zope.component import getUtility
 from zope.interface.verify import verifyObject
 from zope.security.checker import canAccess
 from zope.security.management import checkPermission
 from zope.security.proxy import removeSecurityProxy
 
+from lp.app.enums import InformationType
 from lp.app.interfaces.launchpad import ILaunchpadCelebrities
 from lp.code.model.seriessourcepackagebranch import (
     SeriesSourcePackageBranchSet,
     )
+from lp.registry.errors import CannotPackageProprietaryProduct
 from lp.registry.interfaces.distribution import NoPartnerArchive
 from lp.registry.interfaces.pocket import PackagePublishingPocket
 from lp.registry.interfaces.series import SeriesStatus
@@ -322,6 +325,17 @@
         self.assertIsInstance(event2, ObjectDeletedEvent)
         self.assertIsInstance(event3, ObjectCreatedEvent)
 
+    def test_refuses_PROPRIETARY(self):
+        """Packaging cannot be created for PROPRIETARY productseries"""
+        product = self.factory.makeProduct(
+            information_type=InformationType.PROPRIETARY)
+        series = self.factory.makeProductSeries(product=product)
+        ubuntu_series = self.factory.makeUbuntuDistroSeries()
+        sp = self.factory.makeSourcePackage(distroseries=ubuntu_series)
+        with ExpectedException(CannotPackageProprietaryProduct,
+            'Only Public project series can be packaged, not Proprietary.'):
+            sp.setPackaging(series, series.owner)
+
     def test_setPackagingReturnSharingDetailPermissions__ordinary_user(self):
         """An ordinary user can create a packaging link but he cannot
         set the series' branch or translation syncronisation settings,


Follow ups