← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wgrant/launchpad/packageset-distroseries-mandatory into lp:launchpad

 

William Grant has proposed merging lp:~wgrant/launchpad/packageset-distroseries-mandatory into lp:launchpad.

Commit message:
Fix packagesets for derived distros. Methods no longer default to ubuntu.currentseries, and packageset URLs include the distribution, not just the distroseries.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~wgrant/launchpad/packageset-distroseries-mandatory/+merge/225659

Fix packagesets for derived distros. Methods no longer default to ubuntu.currentseries, and packageset URLs include the distribution, not just the distroseries.
-- 
https://code.launchpad.net/~wgrant/launchpad/packageset-distroseries-mandatory/+merge/225659
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/packageset-distroseries-mandatory into lp:launchpad.
=== modified file 'lib/lp/archiveuploader/tests/nascentupload-packageset.txt'
--- lib/lp/archiveuploader/tests/nascentupload-packageset.txt	2012-01-20 15:42:44 +0000
+++ lib/lp/archiveuploader/tests/nascentupload-packageset.txt	2014-07-04 13:05:35 +0000
@@ -92,7 +92,8 @@
 
     >>> ps_set = getUtility(IPackagesetSet)
     >>> empty_ps = ps_set.new(
-    ...     u'empty-pkg-set', u'Empty package set.', name16)
+    ...     u'empty-pkg-set', u'Empty package set.', name16,
+    ...     ubuntu.currentseries)
     >>> transaction.commit()
 
 And here's name16's upload permission for it.
@@ -127,7 +128,8 @@
 for the former.
 
     >>> foo_ps = ps_set.new(
-    ...     u'foo-pkg-set', u'Packages that require special care.', name16)
+    ...     u'foo-pkg-set', u'Packages that require special care.', name16,
+    ...     ubuntu.currentseries)
     >>> transaction.commit()
 
 Add 'bar' to the 'foo' package set.

=== modified file 'lib/lp/registry/model/distroseriesdifference.py'
--- lib/lp/registry/model/distroseriesdifference.py	2013-06-20 05:50:00 +0000
+++ lib/lp/registry/model/distroseriesdifference.py	2014-07-04 13:05:35 +0000
@@ -1,4 +1,4 @@
-# Copyright 2010-2012 Canonical Ltd.  This software is licensed under the
+# Copyright 2010-2014 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Database classes for a difference between two distribution series."""
@@ -465,7 +465,7 @@
             name_matches = [SPN.name == name_filter]
             try:
                 packageset = getUtility(IPackagesetSet).getByName(
-                    name_filter, distroseries=distro_series)
+                    distro_series, name_filter)
             except NoSuchPackageSet:
                 packageset = None
             if packageset is not None:

=== modified file 'lib/lp/soyuz/adapters/packagelocation.py'
--- lib/lp/soyuz/adapters/packagelocation.py	2012-06-29 08:40:05 +0000
+++ lib/lp/soyuz/adapters/packagelocation.py	2014-07-04 13:05:35 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2014 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Logic for bulk copying of source/binary publishing history data."""
@@ -160,7 +160,7 @@
         for packageset_name in packageset_names:
             try:
                 packageset = packageset_set.getByName(
-                    packageset_name, distroseries=distroseries)
+                    distroseries, packageset_name)
             except NotFoundError as err:
                 raise PackageLocationError(
                     "Could not find packageset %s" % err)

=== modified file 'lib/lp/soyuz/browser/archive.py'
--- lib/lp/soyuz/browser/archive.py	2014-06-30 13:51:15 +0000
+++ lib/lp/soyuz/browser/archive.py	2014-07-04 13:05:35 +0000
@@ -398,8 +398,7 @@
                 except NotFoundError:
                     series = None
             if series is not None:
-                the_item = getUtility(IPackagesetSet).getByName(
-                    item, distroseries=series)
+                the_item = getUtility(IPackagesetSet).getByName(series, item)
         elif item_type == 'pocket':
             # See if "item" is a pocket name.
             try:

=== modified file 'lib/lp/soyuz/browser/configure.zcml'
--- lib/lp/soyuz/browser/configure.zcml	2014-06-17 15:16:18 +0000
+++ lib/lp/soyuz/browser/configure.zcml	2014-07-04 13:05:35 +0000
@@ -697,7 +697,7 @@
         />
     <browser:url
         for="lp.soyuz.interfaces.packageset.IPackageset"
-        path_expression="string:${distroseries/name}/${name}"
+        path_expression="string:${distroseries/distribution/name}/${distroseries/name}/${name}"
         parent_utility="lp.soyuz.interfaces.packageset.IPackagesetSet"
         />
     <browser:url

=== modified file 'lib/lp/soyuz/browser/packageset.py'
--- lib/lp/soyuz/browser/packageset.py	2011-12-24 17:49:30 +0000
+++ lib/lp/soyuz/browser/packageset.py	2014-07-04 13:05:35 +0000
@@ -9,7 +9,9 @@
     'PackagesetSetNavigation',
     ]
 
+from zope.component import getUtility
 
+from lp.registry.interfaces.distribution import IDistributionSet
 from lp.services.webapp import GetitemNavigation
 from lp.soyuz.interfaces.packageset import IPackagesetSet
 
@@ -18,21 +20,24 @@
     """Navigation methods for PackagesetSet."""
     usedfor = IPackagesetSet
 
-    def traverse(self, distroseries):
+    def traverse(self, distribution_name):
         """Traverse package sets in distro series context.
 
         The URI fragment of interest is:
 
-            /package-sets/lucid/mozilla
+            /package-sets/ubuntu/lucid/mozilla
 
-        where 'lucid' is the distro series and 'mozilla' is the package set
-        *name* respectively.
+        where 'ubuntu' is the distro, 'lucid' is the distro series and
+        'mozilla' is the package set.
         """
+        distro = getUtility(IDistributionSet).getByName(distribution_name)
+        if distro is None:
+            return None
+        if self.request.stepstogo:
+            distroseries_name = self.request.stepstogo.consume()
+            distroseries = distro[distroseries_name]
         if self.request.stepstogo:
             # The package set name follows after the distro series.
             ps_name = self.request.stepstogo.consume()
-            return self.context.getByName(ps_name, distroseries=distroseries)
-
-        # Otherwise return None (to trigger a NotFound error).
+            return self.context.getByName(distroseries, ps_name)
         return None
-        

=== modified file 'lib/lp/soyuz/interfaces/packageset.py'
--- lib/lp/soyuz/interfaces/packageset.py	2013-01-07 02:40:55 +0000
+++ lib/lp/soyuz/interfaces/packageset.py	2014-07-04 13:05:35 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2012 Canonical Ltd.  This software is licensed under the
+# 2009-2012 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Packageset interfaces."""
@@ -377,7 +377,7 @@
             IPerson, title=_("Person"), required=True, readonly=True,
             description=_("The person who owns this package set.")),
         distroseries=Reference(
-            IDistroSeries, title=_("Distroseries"), required=False,
+            IDistroSeries, title=_("Distroseries"), required=True,
             readonly=True, description=_(
                 "The distribution series to which the packageset "
                 "is related.")),
@@ -387,14 +387,14 @@
                 "The new package set will share the package set group "
                 "with this one.")))
     @export_factory_operation(IPackageset, [])
-    def new(name, description, owner, distroseries=None, related_set=None):
+    def new(name, description, owner, distroseries, related_set=None):
         """Create a new package set.
 
         :param name: the name of the package set to be created.
         :param description: the description for the package set to be created.
         :param owner: the owner of the package set to be created.
         :param distroseries: the distroseries to which the new packageset
-            is related. Defaults to the current Ubuntu series.
+            is related.
         :param related_set: the newly created package set is to be related to
             `related_set` (by being placed in the same package group).
 
@@ -409,20 +409,16 @@
     export_as_webservice_collection(IPackageset)
 
     @operation_parameters(
-        name=TextLine(title=_('Package set name'), required=True),
-        distroseries=Reference(
-            IDistroSeries, title=_("Distroseries"), required=False,
-            readonly=True, description=_(
-                "The distribution series to which the packageset "
-                "is related.")))
+        name=copy_field(IPackageset['name']),
+        distroseries=copy_field(IPackageset['distroseries']))
     @operation_returns_entry(IPackageset)
     @export_read_operation()
-    def getByName(name, distroseries=None):
+    def getByName(distroseries, name):
         """Return the single package set with the given name (if any).
 
+        :param distroseries: the distroseries to which the new packageset
+            is related.
         :param name: the name of the package set sought.
-        :param distroseries: the distroseries to which the new packageset
-            is related. Defaults to the current Ubuntu series.
 
         :return: An `IPackageset` instance.
         :raise NoSuchPackageSet: if no package set is found.
@@ -497,6 +493,3 @@
             name cannot be found.
         :return: A (potentially empty) sequence of `IPackageset` instances.
         """
-
-    def __getitem__(name):
-        """Retrieve a package set by name."""

=== modified file 'lib/lp/soyuz/model/packageset.py'
--- lib/lp/soyuz/model/packageset.py	2013-06-20 05:50:00 +0000
+++ lib/lp/soyuz/model/packageset.py	2014-07-04 13:05:35 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2012 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2014 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 __metaclass__ = type
@@ -17,8 +17,6 @@
 from zope.component import getUtility
 from zope.interface import implements
 
-from lp.app.errors import NotFoundError
-from lp.registry.interfaces.distribution import IDistributionSet
 from lp.registry.interfaces.sourcepackagename import (
     ISourcePackageName,
     ISourcePackageNameSet,
@@ -344,8 +342,7 @@
     """See `IPackagesetSet`."""
     implements(IPackagesetSet)
 
-    def new(
-        self, name, description, owner, distroseries=None, related_set=None):
+    def new(self, name, description, owner, distroseries, related_set=None):
         """See `IPackagesetSet`."""
         store = IMasterStore(Packageset)
 
@@ -361,10 +358,6 @@
             packagesetgroup.owner = owner
             store.add(packagesetgroup)
 
-        if distroseries is None:
-            ubuntu = getUtility(IDistributionSet).getByName('ubuntu')
-            distroseries = ubuntu.currentseries
-
         packageset = Packageset()
         packageset.packagesetgroup = packagesetgroup
         packageset.name = name
@@ -384,35 +377,16 @@
 
         return packageset
 
-    def __getitem__(self, name):
-        """See `IPackagesetSet`."""
-        return self.getByName(name)
-
-    def getByName(self, name, distroseries=None):
+    def getByName(self, distroseries, name):
         """See `IPackagesetSet`."""
         store = IStore(Packageset)
         if not isinstance(name, unicode):
             name = unicode(name, 'utf-8')
-
-        ubuntu = getUtility(IDistributionSet).getByName(u'ubuntu')
-        extra_args = []
-        if distroseries is not None:
-            # If the user just passed a distro series name, look it up.
-            if isinstance(distroseries, basestring):
-                try:
-                    distroseries = ubuntu[distroseries]
-                except NotFoundError:
-                    raise NoSuchPackageSet(distroseries)
-            extra_args.append(Packageset.distroseries == distroseries)
-        else:
-            extra_args.append(Packageset.distroseries == ubuntu.currentseries)
-
         package_set = store.find(
-            Packageset, Packageset.name == name, *extra_args).one()
-
+            Packageset, Packageset.name == name,
+            Packageset.distroseries == distroseries).one()
         if package_set is None:
             raise NoSuchPackageSet(name)
-
         return package_set
 
     def getByOwner(self, owner):

=== modified file 'lib/lp/soyuz/scripts/initialize_distroseries.py'
--- lib/lp/soyuz/scripts/initialize_distroseries.py	2013-11-14 07:56:46 +0000
+++ lib/lp/soyuz/scripts/initialize_distroseries.py	2014-07-04 13:05:35 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2012 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2014 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Initialize a distroseries from its parent distroseries."""
@@ -670,7 +670,7 @@
             # First, try to fetch an existing packageset with this name.
             try:
                 child_ps = packageset_set.getByName(
-                    parent_ps.name, self.distroseries)
+                    self.distroseries, parent_ps.name)
             except NoSuchPackageSet:
                 if self.distroseries.distribution.id in parent_distro_ids:
                     new_owner = parent_ps.owner

=== modified file 'lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py'
--- lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py	2013-09-18 06:34:44 +0000
+++ lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py	2014-07-04 13:05:35 +0000
@@ -1,4 +1,4 @@
-# Copyright 2010-2013 Canonical Ltd.  This software is licensed under the
+# Copyright 2010-2014 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Test the initialize_distroseries script machinery."""
@@ -150,7 +150,7 @@
             pocket=PackagePublishingPocket.RELEASE)
         try:
             packageset = getUtility(IPackagesetSet).getByName(
-                packageset_name, distroseries=distroseries)
+                distroseries, packageset_name)
         except NoSuchPackageSet:
             packageset = getUtility(IPackagesetSet).new(
                 packageset_name, packageset_name, distroseries.owner,
@@ -628,12 +628,9 @@
             self.parent.main_archive, uploader, test1)
         child = self._fullInitialize([self.parent])
         # We can fetch the copied sets from the child.
-        child_test1 = getUtility(IPackagesetSet).getByName(
-            u'test1', distroseries=child)
-        child_test2 = getUtility(IPackagesetSet).getByName(
-            u'test2', distroseries=child)
-        child_test3 = getUtility(IPackagesetSet).getByName(
-            u'test3', distroseries=child)
+        child_test1 = getUtility(IPackagesetSet).getByName(child, u'test1')
+        child_test2 = getUtility(IPackagesetSet).getByName(child, u'test2')
+        child_test3 = getUtility(IPackagesetSet).getByName(child, u'test3')
         # And we can see they are exact copies, with the related_set for the
         # copies pointing to the packageset in the parent.
         self.assertEqual(test1.description, child_test1.description)
@@ -710,7 +707,7 @@
             [previous_parent], previous_series=child,
             distribution=parent.distribution)
         grandchild_packageset = getUtility(IPackagesetSet).getByName(
-            parent_packageset.name, distroseries=grandchild)
+            grandchild, parent_packageset.name)
         # The copied grandchild set has sources matching the child.
         self.assertContentEqual(
             child_packageset.getSourcesIncluded(),
@@ -808,8 +805,7 @@
             u'ps', u'packageset', ps_owner, distroseries=self.parent)
         child = self._fullInitialize(
             [self.parent], distribution=self.parent.distribution)
-        child_ps = getUtility(IPackagesetSet).getByName(
-            u'ps', distroseries=child)
+        child_ps = getUtility(IPackagesetSet).getByName(child, u'ps')
         self.assertEqual(ps_owner, child_ps.owner)
 
     def test_packageset_owner_not_preserved_cross_distro(self):
@@ -820,8 +816,7 @@
             u'ps', u'packageset', self.factory.makePerson(),
             distroseries=self.parent)
         child = self._fullInitialize([self.parent])
-        child_ps = getUtility(IPackagesetSet).getByName(
-            u'ps', distroseries=child)
+        child_ps = getUtility(IPackagesetSet).getByName(child, u'ps')
         self.assertEqual(child.owner, child_ps.owner)
 
     def test_copy_limit_packagesets(self):
@@ -838,15 +833,14 @@
         for pkg in packages:
             test1.addSources(pkg)
         packageset1 = getUtility(IPackagesetSet).getByName(
-            u'test1', distroseries=self.parent)
+            self.parent, u'test1')
         child = self._fullInitialize(
             [self.parent], packagesets=(str(packageset1.id),))
-        child_test1 = getUtility(IPackagesetSet).getByName(
-            u'test1', distroseries=child)
+        child_test1 = getUtility(IPackagesetSet).getByName(child, u'test1')
         self.assertEqual(test1.description, child_test1.description)
         self.assertRaises(
             NoSuchPackageSet, getUtility(IPackagesetSet).getByName,
-                u'test2', distroseries=child)
+            child, u'test2')
         parent_srcs = test1.getSourcesIncluded(direct_inclusion=True)
         child_srcs = child_test1.getSourcesIncluded(
             direct_inclusion=True)
@@ -1027,8 +1021,7 @@
         child = self._fullInitialize([self.parent1, self.parent2])
 
         # In the child, the identical packagesets are merged into one.
-        child_test1 = getUtility(IPackagesetSet).getByName(
-            u'test1', distroseries=child)
+        child_test1 = getUtility(IPackagesetSet).getByName(child, u'test1')
         child_srcs = child_test1.getSourcesIncluded(
             direct_inclusion=True)
         parent1_srcs = test1_parent1.getSourcesIncluded(direct_inclusion=True)

=== modified file 'lib/lp/soyuz/stories/webservice/xx-archive.txt'
--- lib/lp/soyuz/stories/webservice/xx-archive.txt	2013-09-16 04:17:25 +0000
+++ lib/lp/soyuz/stories/webservice/xx-archive.txt	2014-07-04 13:05:35 +0000
@@ -342,7 +342,8 @@
     HTTP/1.1 201 Created
     ...
 
-    >>> packageset = webservice.get("/package-sets/hoary/umbrella").jsonBody()
+    >>> packageset = webservice.get(
+    ...     "/package-sets/ubuntu/hoary/umbrella").jsonBody()
 
 
 To be able to amend any permissions on a distribution archive,

=== modified file 'lib/lp/soyuz/stories/webservice/xx-packageset.txt'
--- lib/lp/soyuz/stories/webservice/xx-packageset.txt	2013-06-20 05:50:00 +0000
+++ lib/lp/soyuz/stories/webservice/xx-packageset.txt	2014-07-04 13:05:35 +0000
@@ -30,7 +30,7 @@
 
     >>> name12 = webservice.get("/~name12").jsonBody()
     >>> response = webservice.named_post(
-    ...     '/package-sets', 'new', {},
+    ...     '/package-sets', 'new', {}, distroseries='/ubuntu/hoary',
     ...     name=u'umbrella', description=u'Contains all source packages',
     ...     owner=name12['self_link'])
     >>> print response
@@ -47,30 +47,36 @@
     ...     for datum in sort_by_id(iterable):
     ...          print('%3d -> %s' % (datum.id, datum.name))
 
+    >>> from lp.registry.interfaces.distribution import IDistributionSet
     >>> from lp.soyuz.interfaces.packageset import (
     ...     IPackagesetSet)
+    >>> ubuntu = getUtility(IDistributionSet).getByName('ubuntu')
     >>> ps_factory = getUtility(IPackagesetSet)
-    >>> print_data((ps_factory[u'umbrella'], ))
+    >>> print_data(
+    ...     (ps_factory.getByName(ubuntu.currentseries, u'umbrella'), ))
     1 -> umbrella
 
 Can we access it via the webservice API as well?
 
     >>> logout()
-    >>> umbrella = webservice.get("/package-sets/hoary/umbrella").jsonBody()
+    >>> umbrella = webservice.get(
+    ...     "/package-sets/ubuntu/hoary/umbrella").jsonBody()
     >>> print umbrella['self_link']
-    http://api.launchpad.dev/beta/package-sets/hoary/umbrella
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/umbrella
 
 `PackageSet`s can be looked up by name.
 
     >>> response = webservice.named_get(
-    ...     '/package-sets', 'getByName', {}, name=u'umbrella')
+    ...     '/package-sets', 'getByName', {}, distroseries='/ubuntu/hoary',
+    ...     name=u'umbrella')
     >>> print response.jsonBody()['self_link']
-    http://api.launchpad.dev/beta/package-sets/hoary/umbrella
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/umbrella
 
 When a `PackageSet` cannot be found, an error is returned.
 
     >>> response = webservice.named_get(
-    ...     '/package-sets', 'getByName', {}, name=u'not-found')
+    ...     '/package-sets', 'getByName', {}, distroseries='/ubuntu/hoary',
+    ...     name=u'not-found')
     >>> print response
     HTTP/1.1 404 Not Found
     ...
@@ -78,7 +84,8 @@
 
 Here's an example with a funny URL concoted by a "smart" user.
 
-    >>> response = webservice.get("/package-sets/lucid-plus-1/umbrella/+pwn")
+    >>> response = webservice.get(
+    ...     "/package-sets/ubuntu/lucid-plus-1/umbrella/+pwn")
     >>> print response
     HTTP/1.1 404 Not Found
     ...
@@ -86,7 +93,7 @@
 Let's create another set.
 
     >>> response = webservice.named_post(
-    ...     '/package-sets', 'new', {},
+    ...     '/package-sets', 'new', {}, distroseries='/ubuntu/hoary',
     ...     name=u'shortlived', description=u'An ephemeral packageset',
     ...     owner=name12['self_link'])
     >>> print response
@@ -101,7 +108,8 @@
     ...          u'description': u'Repurposed packageset',
     ...          u'owner_link': name16['self_link']}
     >>> response = webservice.patch(
-    ...     '/package-sets/hoary/shortlived', 'application/json', dumps(patch))
+    ...     '/package-sets/ubuntu/hoary/shortlived', 'application/json',
+    ...     dumps(patch))
     >>> print response
     HTTP/1.1 301 Moved Permanently
     ...
@@ -109,7 +117,7 @@
 And then delete it.
 
     >>> response = webservice.delete(
-    ...     '/package-sets/hoary/renamed', {}, api_version='devel')
+    ...     '/package-sets/ubuntu/hoary/renamed', {}, api_version='devel')
     >>> print response
     HTTP/1.1 200 Ok
     ...
@@ -120,7 +128,7 @@
     >>> from lp.registry.model.sourcepackagename import SourcePackageName
     >>> all_spns = IStore(SourcePackageName).find(SourcePackageName)
     >>> response = webservice.named_post(
-    ...     '/package-sets/hoary/umbrella', 'addSources', {},
+    ...     '/package-sets/ubuntu/hoary/umbrella', 'addSources', {},
     ...     names=[spn.name for spn in all_spns])
     >>> print response
     HTTP/1.1 200 Ok
@@ -130,7 +138,7 @@
 exist will not fail. Non-existing source package names are *ignored*.
 
     >>> response = webservice.named_post(
-    ...     '/package-sets/hoary/umbrella', 'addSources', {},
+    ...     '/package-sets/ubuntu/hoary/umbrella', 'addSources', {},
     ...     names=[u'does-not-exist'])
     >>> print response
     HTTP/1.1 200 Ok
@@ -138,7 +146,7 @@
     null
 
     >>> response = webservice.named_post(
-    ...     '/package-sets/hoary/umbrella', 'removeSources', {},
+    ...     '/package-sets/ubuntu/hoary/umbrella', 'removeSources', {},
     ...     names=[u'does-not-exist'])
     >>> print response
     HTTP/1.1 200 Ok
@@ -148,7 +156,7 @@
 Let's see what we got.
 
     >>> response = webservice.named_get(
-    ...     '/package-sets/hoary/umbrella', 'getSourcesIncluded', {})
+    ...     '/package-sets/ubuntu/hoary/umbrella', 'getSourcesIncluded', {})
     >>> print response
     HTTP/1.1 200 Ok
     ...
@@ -175,7 +183,7 @@
 from the 'umbrella' package set.
 
     >>> response = webservice.named_post(
-    ...     '/package-sets/hoary/umbrella', 'removeSources', {},
+    ...     '/package-sets/ubuntu/hoary/umbrella', 'removeSources', {},
     ...     names=["foobar", "iceweasel"])
     >>> print response
     HTTP/1.1 200 Ok
@@ -185,7 +193,7 @@
 from the list below.
 
     >>> response = webservice.named_get(
-    ...     '/package-sets/hoary/umbrella', 'getSourcesIncluded', {})
+    ...     '/package-sets/ubuntu/hoary/umbrella', 'getSourcesIncluded', {})
     >>> print response
     HTTP/1.1 200 Ok
     ...
@@ -215,13 +223,13 @@
 
     >>> response = anon_webservice.get("/package-sets/")
     >>> print_payload(response)
-    http://api.launchpad.dev/beta/package-sets/hoary/umbrella
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/umbrella
 
 Package sets may include other package sets (as subsets). At this point,
 however, we only have the 'umbrella' package set. It hence has no subsets.
 
     >>> response = webservice.named_get(
-    ...     '/package-sets/hoary/umbrella', 'setsIncluded', {})
+    ...     '/package-sets/ubuntu/hoary/umbrella', 'setsIncluded', {})
     >>> print response
     HTTP/1.1 200 Ok
     ...
@@ -230,7 +238,7 @@
 Let's create a few more package sets and set up a package set hierarchy.
 
     >>> response = webservice.named_post(
-    ...     '/package-sets', 'new', {},
+    ...     '/package-sets', 'new', {}, distroseries='/ubuntu/hoary',
     ...     name=u'gnome', description=u'Contains all gnome packages',
     ...     owner=name12['self_link'])
     >>> print response
@@ -238,7 +246,7 @@
     ...
 
     >>> response = webservice.named_post(
-    ...     '/package-sets', 'new', {},
+    ...     '/package-sets', 'new', {}, distroseries='/ubuntu/hoary',
     ...     name=u'mozilla', description=u'Contains all mozilla packages',
     ...     owner=name12['self_link'])
     >>> print response
@@ -253,12 +261,13 @@
 
     >>> from lazr.restful.testing.webservice import pprint_entry
     >>> mozilla = webservice.named_get(
-    ...     '/package-sets', 'getByName', {}, name=u'mozilla').jsonBody()
+    ...     '/package-sets', 'getByName', {}, distroseries='/ubuntu/hoary',
+    ...     name=u'mozilla').jsonBody()
     >>> print mozilla['distroseries_link']
     http://api.launchpad.dev/beta/ubuntu/hoary
 
     >>> print mozilla['self_link']
-    http://api.launchpad.dev/beta/package-sets/hoary/mozilla
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/mozilla
 
 A collection of package sets belonging to a given distro series can be
 obtained via the `getBySeries` call.
@@ -287,10 +296,9 @@
 it is related to 'mozilla' in 'hoary'.
 
     >>> response = webservice.named_post(
-    ...     '/package-sets', 'new', {},
-    ...     name=u'mozilla',
+    ...     '/package-sets', 'new', {}, distroseries=grumpy['self_link'],
+    ...     name=u'mozilla', owner=name12['self_link'],
     ...     description=u'Contains all mozilla packages in grumpy',
-    ...     owner=name12['self_link'], distroseries=grumpy['self_link'],
     ...     related_set=mozilla['self_link'])
     >>> print response
     HTTP/1.1 201 Created
@@ -303,12 +311,12 @@
     http://api.launchpad.dev/beta/ubuntu/grumpy
 
     >>> print grumpy_mozilla['self_link']
-    http://api.launchpad.dev/beta/package-sets/grumpy/mozilla
+    http://api.launchpad.dev/beta/package-sets/ubuntu/grumpy/mozilla
 
     >>> response = webservice.named_get(
     ...     mozilla['self_link'], 'relatedSets', {})
     >>> print_payload(response)
-    http://api.launchpad.dev/beta/package-sets/grumpy/mozilla
+    http://api.launchpad.dev/beta/package-sets/ubuntu/grumpy/mozilla
 
 
 Package set hierarchy
@@ -317,7 +325,7 @@
 More package sets are needed to set up the hierarchy described below.
 
     >>> response = webservice.named_post(
-    ...     '/package-sets', 'new', {},
+    ...     '/package-sets', 'new', {}, distroseries='/ubuntu/hoary',
     ...     name=u'firefox', description=u'Contains all firefox packages',
     ...     owner=name12['self_link'])
     >>> print response
@@ -325,19 +333,17 @@
     ...
 
     >>> response = webservice.named_post(
-    ...     '/package-sets', 'new', {},
-    ...     name=u'thunderbird',
-    ...     description=u'Contains all thunderbird packages',
-    ...     owner=name12['self_link'])
+    ...     '/package-sets', 'new', {}, distroseries='/ubuntu/hoary',
+    ...     name=u'thunderbird', owner=name12['self_link'],
+    ...     description=u'Contains all thunderbird packages')
     >>> print response
     HTTP/1.1 201 Created
     ...
 
     >>> response = webservice.named_post(
-    ...     '/package-sets', 'new', {},
-    ...     name=u'languagepack',
-    ...     description=u'Contains all languagepack packages',
-    ...     owner=name12['self_link'])
+    ...     '/package-sets', 'new', {}, distroseries='/ubuntu/hoary',
+    ...     name=u'languagepack', owner=name12['self_link'],
+    ...     description=u'Contains all languagepack packages')
     >>> print response
     HTTP/1.1 201 Created
     ...
@@ -346,10 +352,9 @@
 set with the same name in 'grumpy' to make sure that the right one is found.
 
     >>> response = webservice.named_post(
-    ...     '/package-sets', 'new', {},
-    ...     name=u'languagepack',
-    ...     description=u'Contains all languagepack packages',
-    ...     owner=name12['self_link'], distroseries=grumpy['self_link'])
+    ...     '/package-sets', 'new', {}, distroseries=grumpy['self_link'],
+    ...     name=u'languagepack', owner=name12['self_link'],
+    ...     description=u'Contains all languagepack packages')
     >>> print response
     HTTP/1.1 201 Created
     ...
@@ -367,28 +372,28 @@
           * languagepack
 
     >>> response = webservice.named_post(
-    ...     '/package-sets/hoary/umbrella', 'addSubsets', {},
+    ...     '/package-sets/ubuntu/hoary/umbrella', 'addSubsets', {},
     ...     names=[u'gnome', u'mozilla'])
     >>> print response
     HTTP/1.1 200 Ok
     ...
 
     >>> response = webservice.named_post(
-    ...     '/package-sets/hoary/gnome', 'addSubsets', {},
-    ...     names=[u'languagepack'])
-    >>> print response
-    HTTP/1.1 200 Ok
-    ...
-
-    >>> response = webservice.named_post(
-    ...     '/package-sets/hoary/thunderbird', 'addSubsets', {},
-    ...     names=[u'languagepack'])
-    >>> print response
-    HTTP/1.1 200 Ok
-    ...
-
-    >>> response = webservice.named_post(
-    ...     '/package-sets/hoary/mozilla', 'addSubsets', {},
+    ...     '/package-sets/ubuntu/hoary/gnome', 'addSubsets', {},
+    ...     names=[u'languagepack'])
+    >>> print response
+    HTTP/1.1 200 Ok
+    ...
+
+    >>> response = webservice.named_post(
+    ...     '/package-sets/ubuntu/hoary/thunderbird', 'addSubsets', {},
+    ...     names=[u'languagepack'])
+    >>> print response
+    HTTP/1.1 200 Ok
+    ...
+
+    >>> response = webservice.named_post(
+    ...     '/package-sets/ubuntu/hoary/mozilla', 'addSubsets', {},
     ...     names=[u'firefox', u'thunderbird'])
     >>> print response
     HTTP/1.1 200 Ok
@@ -398,7 +403,7 @@
 non-existing package sets will not fail.
 
     >>> response = webservice.named_post(
-    ...     '/package-sets/hoary/thunderbird', 'addSubsets', {},
+    ...     '/package-sets/ubuntu/hoary/thunderbird', 'addSubsets', {},
     ...     names=[u'does-not-exist'])
     >>> print response
     HTTP/1.1 200 Ok
@@ -406,7 +411,7 @@
     null
 
     >>> response = webservice.named_post(
-    ...     '/package-sets/hoary/thunderbird', 'removeSubsets', {},
+    ...     '/package-sets/ubuntu/hoary/thunderbird', 'removeSubsets', {},
     ...     names=[u'does-not-exist'])
     >>> print response
     HTTP/1.1 200 Ok
@@ -416,49 +421,49 @@
 The 'umbrella' package set should have plenty of subsets now.
 
     >>> response = webservice.named_get(
-    ...     '/package-sets/hoary/umbrella', 'setsIncluded', {})
+    ...     '/package-sets/ubuntu/hoary/umbrella', 'setsIncluded', {})
     >>> print_payload(response)
-    http://api.launchpad.dev/beta/package-sets/hoary/firefox
-    http://api.launchpad.dev/beta/package-sets/hoary/gnome
-    http://api.launchpad.dev/beta/package-sets/hoary/languagepack
-    http://api.launchpad.dev/beta/package-sets/hoary/mozilla
-    http://api.launchpad.dev/beta/package-sets/hoary/thunderbird
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/firefox
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/gnome
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/languagepack
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/mozilla
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/thunderbird
 
 However only two of the above are direct subsets.
 
     >>> response = webservice.named_get(
-    ...     '/package-sets/hoary/umbrella', 'setsIncluded', {},
+    ...     '/package-sets/ubuntu/hoary/umbrella', 'setsIncluded', {},
     ...     direct_inclusion=True)
     >>> print_payload(response)
-    http://api.launchpad.dev/beta/package-sets/hoary/gnome
-    http://api.launchpad.dev/beta/package-sets/hoary/mozilla
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/gnome
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/mozilla
 
 Let's ask the question the other way around what package sets are including
 a particular subset?
 
     >>> response = webservice.named_get(
-    ...     '/package-sets/hoary/languagepack', 'setsIncludedBy', {})
+    ...     '/package-sets/ubuntu/hoary/languagepack', 'setsIncludedBy', {})
     >>> print_payload(response)
-    http://api.launchpad.dev/beta/package-sets/hoary/gnome
-    http://api.launchpad.dev/beta/package-sets/hoary/mozilla
-    http://api.launchpad.dev/beta/package-sets/hoary/thunderbird
-    http://api.launchpad.dev/beta/package-sets/hoary/umbrella
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/gnome
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/mozilla
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/thunderbird
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/umbrella
 
 The list of package sets that *directly* include 'languagepack' will be
 shorter because the transitive closure is ignored.
 
     >>> response = webservice.named_get(
-    ...     '/package-sets/hoary/languagepack', 'setsIncludedBy', {},
+    ...     '/package-sets/ubuntu/hoary/languagepack', 'setsIncludedBy', {},
     ...     direct_inclusion=True)
     >>> print_payload(response)
-    http://api.launchpad.dev/beta/package-sets/hoary/gnome
-    http://api.launchpad.dev/beta/package-sets/hoary/thunderbird
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/gnome
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/thunderbird
 
 We can remove subsets as well. In the example below 'thunderbird' will
 stop including 'languagepack'.
 
     >>> response = webservice.named_post(
-    ...     '/package-sets/hoary/thunderbird', 'removeSubsets', {},
+    ...     '/package-sets/ubuntu/hoary/thunderbird', 'removeSubsets', {},
     ...     names=[u'languagepack'])
     >>> print response
     HTTP/1.1 200 Ok
@@ -467,37 +472,38 @@
 And, here we go, now 'languagepack' has only one direct predecessor: 'gnome'.
 
     >>> response = webservice.named_get(
-    ...     '/package-sets/hoary/languagepack', 'setsIncludedBy', {},
+    ...     '/package-sets/ubuntu/hoary/languagepack', 'setsIncludedBy', {},
     ...     direct_inclusion=True)
     >>> print_payload(response)
-    http://api.launchpad.dev/beta/package-sets/hoary/gnome
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/gnome
 
 Let's add a few source packages to the 'firefox' and the 'thunderbird'
 package sets.
 
     >>> response = webservice.named_post(
-    ...     '/package-sets/hoary/firefox', 'addSources', {},
+    ...     '/package-sets/ubuntu/hoary/firefox', 'addSources', {},
     ...     names=['at', 'mozilla-firefox', 'language-pack-de'])
     >>> print response
     HTTP/1.1 200 Ok
     ...
 
     >>> response = webservice.named_get(
-    ...     '/package-sets/hoary/firefox', 'getSourcesIncluded', {})
+    ...     '/package-sets/ubuntu/hoary/firefox', 'getSourcesIncluded', {})
     >>> print response
     HTTP/1.1 200 Ok
     ...
     ["at", "language-pack-de", "mozilla-firefox"]
 
     >>> response = webservice.named_post(
-    ...     '/package-sets/hoary/thunderbird', 'addSources', {},
+    ...     '/package-sets/ubuntu/hoary/thunderbird', 'addSources', {},
     ...     names=['at', 'cnews', 'thunderbird', 'language-pack-de'])
     >>> print response
     HTTP/1.1 200 Ok
     ...
 
     >>> response = webservice.named_get(
-    ...     '/package-sets/hoary/thunderbird', 'getSourcesIncluded', {})
+    ...     '/package-sets/ubuntu/hoary/thunderbird', 'getSourcesIncluded',
+    ...     {})
     >>> print response
     HTTP/1.1 200 Ok
     ...
@@ -509,9 +515,9 @@
     ...     '/package-sets/', 'setsIncludingSource', {},
     ...     sourcepackagename=u'mozilla-firefox')
     >>> print_payload(response)
-    http://api.launchpad.dev/beta/package-sets/hoary/firefox
-    http://api.launchpad.dev/beta/package-sets/hoary/mozilla
-    http://api.launchpad.dev/beta/package-sets/hoary/umbrella
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/firefox
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/mozilla
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/umbrella
 
 Which package sets include the 'mozilla-firefox' source package *directly*?
 
@@ -520,8 +526,8 @@
     ...     sourcepackagename=u'mozilla-firefox',
     ...     direct_inclusion=True)
     >>> print_payload(response)
-    http://api.launchpad.dev/beta/package-sets/hoary/firefox
-    http://api.launchpad.dev/beta/package-sets/hoary/umbrella
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/firefox
+    http://api.launchpad.dev/beta/package-sets/ubuntu/hoary/umbrella
 
 If a non-existing source package name is passed it returns an error.
 
@@ -537,9 +543,9 @@
 package sets?
 
     >>> thunderbird = webservice.get(
-    ...     "/package-sets/hoary/thunderbird").jsonBody()
+    ...     "/package-sets/ubuntu/hoary/thunderbird").jsonBody()
     >>> response = webservice.named_get(
-    ...     '/package-sets/hoary/firefox', 'getSourcesSharedBy', {},
+    ...     '/package-sets/ubuntu/hoary/firefox', 'getSourcesSharedBy', {},
     ...     other_package_set=thunderbird['self_link'])
     >>> print response
     HTTP/1.1 200 Ok
@@ -549,17 +555,18 @@
 How about the complement set i.e. the packages not shared?
 
     >>> response = webservice.named_get(
-    ...     '/package-sets/hoary/firefox', 'getSourcesNotSharedBy', {},
+    ...     '/package-sets/ubuntu/hoary/firefox', 'getSourcesNotSharedBy', {},
     ...     other_package_set=thunderbird['self_link'])
     >>> print response
     HTTP/1.1 200 Ok
     ...
     ["mozilla-firefox"]
 
-    >>> firefox = webservice.get("/package-sets/hoary/firefox").jsonBody()
+    >>> firefox = webservice.get(
+    ...     "/package-sets/ubuntu/hoary/firefox").jsonBody()
     >>> response = webservice.named_get(
-    ...     '/package-sets/hoary/thunderbird', 'getSourcesNotSharedBy', {},
-    ...     other_package_set=firefox['self_link'])
+    ...     '/package-sets/ubuntu/hoary/thunderbird', 'getSourcesNotSharedBy',
+    ...     {}, other_package_set=firefox['self_link'])
     >>> print response
     HTTP/1.1 200 Ok
     ...
@@ -784,11 +791,10 @@
 Create a new package set ('thunderbird') in 'grumpy'.
 
     >>> response = webservice.named_post(
-    ...     '/package-sets', 'new', {},
+    ...     '/package-sets', 'new', {}, distroseries=grumpy['self_link'],
     ...     name=u'thunderbird',
     ...     description=u'Contains all thunderbird packages in grumpy',
-    ...     owner=name12['self_link'], distroseries=grumpy['self_link'],
-    ...     related_set=thunderbird['self_link'])
+    ...     owner=name12['self_link'], related_set=thunderbird['self_link'])
     >>> print response
     HTTP/1.1 201 Created
     ...
@@ -796,12 +802,12 @@
     >>> response = webservice.named_get(
     ...     thunderbird['self_link'], 'relatedSets', {})
     >>> print_payload(response)
-    http://api.launchpad.dev/beta/package-sets/grumpy/thunderbird
+    http://api.launchpad.dev/beta/package-sets/ubuntu/grumpy/thunderbird
 
 Associate 'thunderbird' with the appropriate source packages.
 
     >>> response = webservice.named_post(
-    ...     '/package-sets/grumpy/thunderbird', 'addSources', {},
+    ...     '/package-sets/ubuntu/grumpy/thunderbird', 'addSources', {},
     ...     names=['thunderbird', 'language-pack-de'])
     >>> print response
     HTTP/1.1 200 Ok
@@ -810,7 +816,7 @@
 Grant 'name12' upload permissions to 'thunderbird' in 'grumpy'.
 
     >>> grouchy_bird = webservice.get(
-    ...     "/package-sets/grumpy/thunderbird").jsonBody()
+    ...     "/package-sets/ubuntu/grumpy/thunderbird").jsonBody()
 
     >>> response = webservice.named_post(
     ...     ubuntu['main_archive_link'], 'newPackagesetUploader', {},

=== modified file 'lib/lp/soyuz/tests/test_packageset.py'
--- lib/lp/soyuz/tests/test_packageset.py	2013-06-20 05:50:00 +0000
+++ lib/lp/soyuz/tests/test_packageset.py	2014-07-04 13:05:35 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2014 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Test Packageset features."""
@@ -49,17 +49,7 @@
             distribution=self.getUbuntu(), name="experimental",
             status=SeriesStatus.EXPERIMENTAL)
 
-    def test_new_defaults_to_current_distroseries(self):
-        # If the distroseries is not provided, the current development
-        # distroseries will be assumed.
-        packageset = self.ps_set.new(
-            self.factory.getUniqueUnicode(), self.factory.getUniqueUnicode(),
-            self.factory.makePerson())
-        self.failUnlessEqual(
-            self.getUbuntu().currentseries, packageset.distroseries)
-
-    def test_new_with_specified_distroseries(self):
-        # A distroseries can be provided when creating a package set.
+    def test_new(self):
         experimental_series = self.makeExperimentalSeries()
         packageset = self.ps_set.new(
             self.factory.getUniqueUnicode(), self.factory.getUniqueUnicode(),
@@ -108,18 +98,7 @@
             related_set=pset1)
         self.assertEqual(pset1.packagesetgroup, pset2.packagesetgroup)
 
-    def test_get_by_name_in_current_distroseries(self):
-        # IPackagesetSet.getByName() will return the package set in the
-        # current distroseries if the optional `distroseries` parameter is
-        # omitted.
-        name = self.factory.getUniqueUnicode()
-        pset1 = self.factory.makePackageset(name)
-        self.factory.makePackageset(
-            name, distroseries=self.makeExperimentalSeries(),
-            related_set=pset1)
-        self.assertEqual(pset1, self.ps_set.getByName(name))
-
-    def test_get_by_name_in_specified_distroseries(self):
+    def test_get_by_name(self):
         # IPackagesetSet.getByName() will return the package set in the
         # specified distroseries.
         name = self.factory.getUniqueUnicode()
@@ -127,8 +106,7 @@
         pset1 = self.factory.makePackageset(name)
         pset2 = self.factory.makePackageset(
             name, distroseries=experimental_series, related_set=pset1)
-        pset_found = self.ps_set.getByName(
-            name, distroseries=experimental_series)
+        pset_found = self.ps_set.getByName(experimental_series, name)
         self.assertEqual(pset2, pset_found)
 
     def test_get_by_distroseries(self):
@@ -182,11 +160,6 @@
         self.factory.makePackageset(owner=person)
         self.assertEqual(self.ps_set.getByOwner(person).count(), 1)
 
-    def test_dict_access(self):
-        # The packagesetset acts as a dictionary
-        packageset = self.factory.makePackageset()
-        self.assertEqual(self.ps_set[packageset.name], packageset)
-
     def test_list(self):
         # get returns the first N (N=50 by default) package sets sorted by name
         # for iterating packagesets over the web services API
@@ -259,21 +232,23 @@
         with person_logged_in(self.factory.makePerson()):
             self.assertRaises(Unauthorized, getattr, self.ps_set, 'new')
 
-    def test_create_packagset_as_techboard(self):
+    def test_create_packageset_as_techboard(self):
         # Ubuntu techboard members can create packagesets
         with celebrity_logged_in('ubuntu_techboard'):
             self.ps_set.new(
                 self.factory.getUniqueUnicode(),
                 self.factory.getUniqueUnicode(),
-                self.factory.makePerson())
+                self.factory.makePerson(),
+                self.factory.makeDistroSeries())
 
-    def test_create_packagset_as_admin(self):
+    def test_create_packageset_as_admin(self):
         # Admins can create packagesets
         with admin_logged_in():
             self.ps_set.new(
                 self.factory.getUniqueUnicode(),
                 self.factory.getUniqueUnicode(),
-                self.factory.makePerson())
+                self.factory.makePerson(),
+                self.factory.makeDistroSeries())
 
 
 class TestPackageset(TestCaseWithFactory):
@@ -302,7 +277,8 @@
         # If the package set is the only one in the group the result set
         # returned by relatedSets() is empty.
         packageset = self.packageset_set.new(
-            u'kernel', u'Contains all OS kernel packages', self.person1)
+            u'kernel', u'Contains all OS kernel packages', self.person1,
+            self.distroseries_current)
 
         self.failUnlessEqual(packageset.relatedSets().count(), 0)
 
@@ -313,7 +289,8 @@
 
         # The original package set.
         pset1 = self.packageset_set.new(
-            u'kernel', u'Contains all OS kernel packages', self.person1)
+            u'kernel', u'Contains all OS kernel packages', self.person1,
+            distroseries=self.distroseries_current)
 
         # A related package set.
         pset2 = self.packageset_set.new(
@@ -342,11 +319,14 @@
         self.failUnlessEqual(pset3.relatedSets().count(), 0)
 
     def test_destroy(self):
+        series = self.factory.makeDistroSeries()
         pset = self.packageset_set.new(
-            u'kernel', u'Contains all OS kernel packages', self.person1)
+            u'kernel', u'Contains all OS kernel packages', self.person1,
+            series)
         pset.destroySelf()
-        self.assertRaises(NoSuchPackageSet, self.packageset_set.getByName,
-                          u'kernel')
+        self.assertRaises(
+            NoSuchPackageSet, self.packageset_set.getByName, series,
+            u'kernel')
 
         # Did we clean up the single packagesetgroup?
         store = IStore(PackagesetGroup)
@@ -355,61 +335,74 @@
 
     def test_destroy_with_ancestor(self):
         ancestor = self.packageset_set.new(
-            u'kernel', u'Contains all OS kernel packages', self.person1)
+            u'kernel', u'Contains all OS kernel packages', self.person1,
+            distroseries=self.distroseries_current)
         pset = self.packageset_set.new(
             u'kernel', u'Contains all OS kernel packages', self.person1,
             distroseries=self.distroseries_experimental, related_set=ancestor)
         pset.destroySelf()
         self.assertRaises(
             NoSuchPackageSet, self.packageset_set.getByName,
-            u'kernel', distroseries=self.distroseries_experimental)
+            self.distroseries_experimental, u'kernel')
 
     def test_destroy_with_packages(self):
+        series = self.factory.makeDistroSeries()
         pset = self.packageset_set.new(
-            u'kernel', u'Contains all OS kernel packages', self.person1)
+            u'kernel', u'Contains all OS kernel packages', self.person1,
+            series)
         package = self.factory.makeSourcePackageName()
         pset.addSources([package.name])
 
         pset.destroySelf()
-        self.assertRaises(NoSuchPackageSet, self.packageset_set.getByName,
-                          u'kernel')
+        self.assertRaises(
+            NoSuchPackageSet, self.packageset_set.getByName, series,
+            u'kernel')
 
     def test_destroy_child(self):
+        series = self.factory.makeDistroSeries()
         parent = self.packageset_set.new(
-            u'core', u'Contains all the important packages', self.person1)
+            u'core', u'Contains all the important packages', self.person1,
+            series)
         child = self.packageset_set.new(
-            u'kernel', u'Contains all OS kernel packages', self.person1)
+            u'kernel', u'Contains all OS kernel packages', self.person1,
+            series)
         parent.add((child,))
 
         child.destroySelf()
-        self.assertRaises(NoSuchPackageSet, self.packageset_set.getByName,
-                          u'kernel')
+        self.assertRaises(
+            NoSuchPackageSet, self.packageset_set.getByName, series,
+            u'kernel')
         self.assertTrue(parent.setsIncluded(direct_inclusion=True).is_empty())
 
     def test_destroy_parent(self):
+        series = self.factory.makeDistroSeries()
         parent = self.packageset_set.new(
-            u'core', u'Contains all the important packages', self.person1)
+            u'core', u'Contains all the important packages', self.person1,
+            series)
         child = self.packageset_set.new(
-            u'kernel', u'Contains all OS kernel packages', self.person1)
+            u'kernel', u'Contains all OS kernel packages', self.person1,
+            series)
         parent.add((child,))
 
         parent.destroySelf()
-        self.assertRaises(NoSuchPackageSet, self.packageset_set.getByName,
-                          u'core')
+        self.assertRaises(
+            NoSuchPackageSet, self.packageset_set.getByName, series, u'core')
         self.assertTrue(child.setsIncludedBy(direct_inclusion=True).is_empty())
 
     def test_destroy_intermidate(self):
         # Destroying an intermediate packageset severs the indirect inclusion
-        parent = self.factory.makePackageset()
-        child = self.factory.makePackageset()
-        grandchild = self.factory.makePackageset()
+        series = self.factory.makeDistroSeries()
+        parent = self.factory.makePackageset(distroseries=series)
+        child = self.factory.makePackageset(distroseries=series)
+        grandchild = self.factory.makePackageset(distroseries=series)
         parent.add((child,))
         child.add((grandchild,))
         self.assertEqual(parent.setsIncluded().count(), 2)
 
         child.destroySelf()
-        self.assertRaises(NoSuchPackageSet, self.packageset_set.getByName,
-                          child.name)
+        self.assertRaises(
+            NoSuchPackageSet, self.packageset_set.getByName, series,
+            child.name)
         self.assertTrue(parent.setsIncluded().is_empty())
 
     def buildSet(self, size=5):

=== modified file 'lib/lp/testing/factory.py'
--- lib/lp/testing/factory.py	2014-06-20 10:53:51 +0000
+++ lib/lp/testing/factory.py	2014-07-04 13:05:35 +0000
@@ -3934,6 +3934,9 @@
         if owner is None:
             person = self.getUniqueString(u'package-set-owner')
             owner = self.makePerson(name=person)
+        if distroseries is None:
+            distroseries = getUtility(IDistributionSet)[
+                'ubuntu'].currentseries
         techboard = getUtility(ILaunchpadCelebrities).ubuntu_techboard
         ps_set = getUtility(IPackagesetSet)
         package_set = run_with_login(


Follow ups