Merge lp:~wgrant/launchpad/get-bpr-by-filename into lp:launchpad

Proposed by William Grant on 2010-03-12
Status: Merged
Merged at revision: not available
Proposed branch: lp:~wgrant/launchpad/get-bpr-by-filename
Merge into: lp:launchpad
Diff against target: 181 lines (+121/-3)
4 files modified
lib/lp/soyuz/interfaces/archive.py (+8/-0)
lib/lp/soyuz/model/archive.py (+16/-0)
lib/lp/soyuz/tests/test_archive.py (+84/-0)
lib/lp/soyuz/tests/test_publishing.py (+13/-3)
To merge this branch: bzr merge lp:~wgrant/launchpad/get-bpr-by-filename
Reviewer Review Type Date Requested Status
Abel Deuring (community) code 2010-03-12 Approve on 2010-03-12
Review via email: mp+21211@code.launchpad.net

Commit Message

Add Archive.getBinaryPackageReleaseByFileName.

Description of the Change

This branch adds Archive.getBinaryPackageReleaseByFileName, which I need for my PPA download stats branch series. The method itself is pretty obvious, except that it will return None in the (illegal and very unlikely, but occurring occasionally due to various bugs) case of multiple matching BPRs in the archive.

I also adjusted SoyuzTestPublisher.getPubBinaries to allow me to specify a version and arch-indepness without first creating a custom source. This was needed in the gBPRBFN test.

To post a comment you must log in.
Abel Deuring (adeuring) wrote :

Hi William,

a very nice branch! Just one suggestion: You mention on in the MP and in the comment in test_returns_none_for_duplicate_file() bugs that make it possible to have more than one matching BPR. If we have related bugs filed in Launchpad, could you metion their numbers in the comment?

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/soyuz/interfaces/archive.py'
2--- lib/lp/soyuz/interfaces/archive.py 2010-03-10 10:05:40 +0000
3+++ lib/lp/soyuz/interfaces/archive.py 2010-03-12 06:49:19 +0000
4@@ -418,6 +418,14 @@
5 :return the corresponding `ILibraryFileAlias` is the file was found.
6 """
7
8+ def getBinaryPackageReleaseByFileName(filename):
9+ """Return the corresponding `IBinaryPackageRelease` in this context.
10+
11+ :param filename: The filename to look up.
12+ :return: The `IBinaryPackageRelease` with the specified filename,
13+ or None if it was not found.
14+ """
15+
16 def requestPackageCopy(target_location, requestor, suite=None,
17 copy_binaries=False, reason=None):
18 """Return a new `PackageCopyRequest` for this archive.
19
20=== modified file 'lib/lp/soyuz/model/archive.py'
21--- lib/lp/soyuz/model/archive.py 2010-03-10 12:50:18 +0000
22+++ lib/lp/soyuz/model/archive.py 2010-03-12 06:49:19 +0000
23@@ -82,6 +82,7 @@
24 from lp.soyuz.interfaces.processor import IProcessorFamilySet
25 from lp.soyuz.interfaces.publishing import (
26 active_publishing_status, PackagePublishingStatus, IPublishingSet)
27+from lp.soyuz.model.binarypackagerelease import BinaryPackageRelease
28 from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet
29 from lp.soyuz.scripts.packagecopier import do_copy
30 from canonical.launchpad.webapp.interfaces import (
31@@ -1127,6 +1128,21 @@
32
33 return archive_file
34
35+ def getBinaryPackageReleaseByFileName(self, filename):
36+ store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
37+ results = store.find(
38+ BinaryPackageRelease,
39+ BinaryPackageFile.binarypackagereleaseID ==
40+ BinaryPackageRelease.id,
41+ BinaryPackageFile.libraryfileID == LibraryFileAlias.id,
42+ LibraryFileAlias.filename == filename,
43+ BinaryPackagePublishingHistory.archive == self,
44+ BinaryPackagePublishingHistory.binarypackagereleaseID ==
45+ BinaryPackageRelease.id).config(distinct=True)
46+ if results.count() > 1:
47+ return None
48+ return results.one()
49+
50 def requestPackageCopy(self, target_location, requestor, suite=None,
51 copy_binaries=False, reason=None):
52 """See `IArchive`."""
53
54=== modified file 'lib/lp/soyuz/tests/test_archive.py'
55--- lib/lp/soyuz/tests/test_archive.py 2010-03-06 04:57:40 +0000
56+++ lib/lp/soyuz/tests/test_archive.py 2010-03-12 06:49:19 +0000
57@@ -658,5 +658,89 @@
58 CannotSwitchPrivacy, self.make_ppa_public, self.private_ppa)
59
60
61+class TestGetBinaryPackageReleaseByFileName(TestCaseWithFactory):
62+ """Ensure that getBinaryPackageReleaseByFileName works as expected."""
63+
64+ layer = LaunchpadZopelessLayer
65+
66+ def setUp(self):
67+ """Setup an archive with relevant publications."""
68+ super(TestGetBinaryPackageReleaseByFileName, self).setUp()
69+ self.publisher = SoyuzTestPublisher()
70+ self.publisher.prepareBreezyAutotest()
71+
72+ self.archive = self.factory.makeArchive()
73+ self.archive.require_virtualized = False
74+
75+ self.i386_pub, self.hppa_pub = self.publisher.getPubBinaries(
76+ version="1.2.3-4", archive=self.archive, binaryname="foo-bin",
77+ status=PackagePublishingStatus.PUBLISHED,
78+ architecturespecific=True)
79+
80+ self.i386_indep_pub, self.hppa_indep_pub = (
81+ self.publisher.getPubBinaries(
82+ version="1.2.3-4", archive=self.archive, binaryname="bar-bin",
83+ status=PackagePublishingStatus.PUBLISHED))
84+
85+ def test_returns_matching_binarypackagerelease(self):
86+ # The BPR with a file by the given name should be returned.
87+ self.assertEqual(
88+ self.i386_pub.binarypackagerelease,
89+ self.archive.getBinaryPackageReleaseByFileName(
90+ "foo-bin_1.2.3-4_i386.deb"))
91+
92+ def test_returns_correct_architecture(self):
93+ # The architecture is taken into account correctly.
94+ self.assertEqual(
95+ self.hppa_pub.binarypackagerelease,
96+ self.archive.getBinaryPackageReleaseByFileName(
97+ "foo-bin_1.2.3-4_hppa.deb"))
98+
99+ def test_works_with_architecture_independent_binaries(self):
100+ # Architecture independent binaries with multiple publishings
101+ # are found properly.
102+ self.assertEqual(
103+ self.i386_indep_pub.binarypackagerelease,
104+ self.archive.getBinaryPackageReleaseByFileName(
105+ "bar-bin_1.2.3-4_all.deb"))
106+
107+ def test_returns_none_for_source_file(self):
108+ # None is returned if the file is a source component instead.
109+ self.assertIs(
110+ None,
111+ self.archive.getBinaryPackageReleaseByFileName(
112+ "foo_1.2.3-4.dsc"))
113+
114+ def test_returns_none_for_nonexistent_file(self):
115+ # Non-existent files return None.
116+ self.assertIs(
117+ None,
118+ self.archive.getBinaryPackageReleaseByFileName(
119+ "this-is-not-real_1.2.3-4_all.deb"))
120+
121+ def test_returns_none_for_duplicate_file(self):
122+ # In the unlikely case of multiple BPRs in this archive with the same
123+ # name (hopefully impossible, but it still happens occasionally due
124+ # to bugs), None is returned.
125+
126+ # Publish the same binaries again. Evil.
127+ self.publisher.getPubBinaries(
128+ version="1.2.3-4", archive=self.archive, binaryname="foo-bin",
129+ status=PackagePublishingStatus.PUBLISHED,
130+ architecturespecific=True)
131+
132+ self.assertIs(
133+ None,
134+ self.archive.getBinaryPackageReleaseByFileName(
135+ "foo-bin_1.2.3-4_i386.deb"))
136+
137+ def test_returns_none_from_another_archive(self):
138+ # Cross-archive searches are not performed.
139+ self.assertIs(
140+ None,
141+ self.factory.makeArchive().getBinaryPackageReleaseByFileName(
142+ "foo-bin_1.2.3-4_i386.deb"))
143+
144+
145 def test_suite():
146 return unittest.TestLoader().loadTestsFromName(__name__)
147
148=== modified file 'lib/lp/soyuz/tests/test_publishing.py'
149--- lib/lp/soyuz/tests/test_publishing.py 2010-03-10 12:50:18 +0000
150+++ lib/lp/soyuz/tests/test_publishing.py 2010-03-12 06:49:19 +0000
151@@ -259,8 +259,12 @@
152 pocket=PackagePublishingPocket.RELEASE,
153 format=BinaryPackageFormat.DEB,
154 scheduleddeletiondate=None, dateremoved=None,
155- distroseries=None, archive=None,
156- pub_source=None, builder=None):
157+ distroseries=None,
158+ archive=None,
159+ pub_source=None,
160+ version='666',
161+ architecturespecific=False,
162+ builder=None):
163 """Return a list of binary publishing records."""
164 if distroseries is None:
165 distroseries = self.distroseries
166@@ -270,9 +274,15 @@
167
168 if pub_source is None:
169 sourcename = "%s" % binaryname.split('-')[0]
170+ if architecturespecific:
171+ architecturehintlist = 'any'
172+ else:
173+ architecturehintlist = 'all'
174+
175 pub_source = self.getPubSource(
176 sourcename=sourcename, status=status, pocket=pocket,
177- archive=archive, distroseries=distroseries)
178+ archive=archive, distroseries=distroseries,
179+ version=version, architecturehintlist=architecturehintlist)
180 else:
181 archive = pub_source.archive
182