Merge lp:~michael.nelson/launchpad/bug-235279-old-series-in-sources-list into lp:launchpad

Proposed by Michael Nelson
Status: Merged
Approved by: Deryck Hodge
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~michael.nelson/launchpad/bug-235279-old-series-in-sources-list
Merge into: lp:launchpad
Diff against target: None lines
To merge this branch: bzr merge lp:~michael.nelson/launchpad/bug-235279-old-series-in-sources-list
Reviewer Review Type Date Requested Status
Deryck Hodge (community) Approve
Review via email: mp+9327@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Michael Nelson (michael.nelson) wrote :

= Summary =

Currently the distroseries selector, used on the PPA index page,
presents as an option a distroseries for which all packages have been
deleted in that PPA.

See https://bugs.edge.launchpad.net/soyuz/+bug/235279
for further explanation and an example.

== Proposed fix ==

It turned out that the underlying Archive.series_with_sources method was
not checking the status of the published sources.

This fix ensures that non-active publications (ie. deleted or superseded
publications) are ignored when determining an archive's series with sources.

== Pre-implementation notes ==

None.

== Implementation details ==

I took the chance to convert the query to Storm, and reduced it to one
single query rather than two separate ones.

I know we have a policy against lambda functions, but I just used the
same sorting that is already present on Distribution.serieses. I'll be
happy to convert it to a normal function if that's preferable.

== Tests ==

bin/test -vvt TestSeriesWithSources

== Demo and Q/A ==

There is an example linked from the bug that can be used for QA.

= Launchpad lint =

Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.

Linting changed files:
  lib/lp/soyuz/tests/test_archive.py
  lib/lp/soyuz/model/archive.py

--
Michael

Revision history for this message
Deryck Hodge (deryck) wrote :

Hi, Michael.

This looks good to me. I'll defer to your own judgment about the lambda. I'm not personally bothered by it, especially since this is like another section of the code.

Otherwise, the changes and the test look good.

Cheers,
deryck

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/soyuz/model/archive.py'
2--- lib/lp/soyuz/model/archive.py 2009-07-18 21:19:37 +0000
3+++ lib/lp/soyuz/model/archive.py 2009-07-27 14:45:01 +0000
4@@ -23,6 +23,7 @@
5 from zope.interface import alsoProvides, implements
6 from zope.security.interfaces import Unauthorized
7
8+from lp.archivepublisher.debversion import Version
9 from lp.archiveuploader.utils import re_issource, re_isadeb
10 from canonical.config import config
11 from canonical.database.constants import UTC_NOW
12@@ -80,7 +81,8 @@
13 from lp.soyuz.interfaces.packagecopyrequest import (
14 IPackageCopyRequestSet)
15 from lp.soyuz.interfaces.publishing import (
16- PackagePublishingPocket, PackagePublishingStatus, IPublishingSet)
17+ active_publishing_status, PackagePublishingPocket,
18+ PackagePublishingStatus, IPublishingSet)
19 from lp.registry.interfaces.sourcepackagename import (
20 ISourcePackageNameSet)
21 from lp.soyuz.scripts.packagecopier import (
22@@ -211,14 +213,25 @@
23 @property
24 def series_with_sources(self):
25 """See `IArchive`."""
26- cur = cursor()
27- query = """SELECT DISTINCT distroseries FROM
28- SourcePackagePublishingHistory WHERE
29- SourcePackagePublishingHistory.archive = %s"""
30- cur.execute(query % self.id)
31- published_series_ids = [int(row[0]) for row in cur.fetchall()]
32- return [s for s in self.distribution.serieses if s.id in
33- published_series_ids]
34+ store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
35+
36+ # Import DistroSeries here to avoid circular imports.
37+ from lp.registry.model.distroseries import DistroSeries
38+
39+ distro_serieses = store.find(
40+ DistroSeries,
41+ DistroSeries.distribution == self.distribution,
42+ SourcePackagePublishingHistory.distroseries == DistroSeries.id,
43+ SourcePackagePublishingHistory.archive == self,
44+ SourcePackagePublishingHistory.status.is_in(
45+ active_publishing_status))
46+
47+ distro_serieses.config(distinct=True)
48+
49+ # Ensure the ordering is the same as presented by
50+ # Distribution.serieses
51+ return sorted(
52+ distro_serieses, key=lambda a: Version(a.version), reverse=True)
53
54 @property
55 def dependencies(self):
56
57=== modified file 'lib/lp/soyuz/tests/test_archive.py'
58--- lib/lp/soyuz/tests/test_archive.py 2009-07-17 18:46:25 +0000
59+++ lib/lp/soyuz/tests/test_archive.py 2009-07-27 14:45:01 +0000
60@@ -1,7 +1,7 @@
61 # Copyright 2009 Canonical Ltd. This software is licensed under the
62 # GNU Affero General Public License version 3 (see the file LICENSE).
63
64-"""Test Build features."""
65+"""Test Archive features."""
66
67 from datetime import datetime
68 import pytz
69@@ -168,5 +168,80 @@
70 self.publisher.ubuntutest.main_archive.binaries_size)
71
72
73+class TestSeriesWithSources(TestCaseWithFactory):
74+ """Create some sources in different series."""
75+
76+ layer = LaunchpadZopelessLayer
77+
78+ def setUp(self):
79+ super(TestSeriesWithSources, self).setUp()
80+ self.publisher = SoyuzTestPublisher()
81+ self.publisher.prepareBreezyAutotest()
82+
83+ # Create three sources for the two different distroseries.
84+ breezy_autotest = self.publisher.distroseries
85+ ubuntu_test = breezy_autotest.distribution
86+ self.serieses = [breezy_autotest]
87+ self.serieses.append(self.factory.makeDistroRelease(
88+ distribution=ubuntu_test, name="foo-series"))
89+
90+ self.sources = []
91+ gedit_src_hist = self.publisher.getPubSource(
92+ sourcename="gedit", status=PackagePublishingStatus.PUBLISHED)
93+ self.sources.append(gedit_src_hist)
94+
95+ firefox_src_hist = self.publisher.getPubSource(
96+ sourcename="firefox", status=PackagePublishingStatus.PUBLISHED,
97+ distroseries=self.serieses[1])
98+ self.sources.append(firefox_src_hist)
99+
100+ gtg_src_hist = self.publisher.getPubSource(
101+ sourcename="getting-things-gnome",
102+ status=PackagePublishingStatus.PUBLISHED,
103+ distroseries=self.serieses[1])
104+ self.sources.append(gtg_src_hist)
105+
106+ # Shortcuts for test readability.
107+ self.archive = self.serieses[0].main_archive
108+
109+ def test_series_with_sources_returns_all_series(self):
110+ # Calling series_with_sources returns all series with publishings.
111+ serieses = self.archive.series_with_sources
112+ serieses_names = [series.displayname for series in serieses]
113+
114+ self.assertContentEqual(
115+ [u'Breezy Badger Autotest', u'Foo-series'],
116+ serieses_names)
117+
118+ def test_series_with_sources_ignore_non_published_records(self):
119+ # If all publishings in a series are deleted or superseded
120+ # the series will not be returned.
121+ self.sources[0].secure_record.status = (
122+ PackagePublishingStatus.DELETED)
123+
124+ serieses = self.archive.series_with_sources
125+ serieses_names = [series.displayname for series in serieses]
126+
127+ self.assertContentEqual([u'Foo-series'], serieses_names)
128+
129+ def test_series_with_sources_ordered_by_version(self):
130+ # The returned series are ordered by the distroseries version.
131+ serieses = self.archive.series_with_sources
132+ versions = [series.version for series in serieses]
133+
134+ # Latest version should be first
135+ self.assertEqual(
136+ [u'6.6.6', u'1.0'], versions,
137+ "The latest version was not first.")
138+
139+ # Update the version of breezyautotest and ensure that the
140+ # latest version is still first.
141+ self.serieses[0].version = u'0.5'
142+ serieses = self.archive.series_with_sources
143+ versions = [series.version for series in serieses]
144+ self.assertEqual(
145+ [u'1.0', u'0.5'], versions,
146+ "The latest version was not first.")
147+
148 def test_suite():
149 return unittest.TestLoader().loadTestsFromName(__name__)