Merge lp:~michael.nelson/rnr-server/731736-other-origins into lp:rnr-server

Proposed by Michael Nelson
Status: Merged
Approved by: Michael Nelson
Approved revision: 154
Merged at revision: 151
Proposed branch: lp:~michael.nelson/rnr-server/731736-other-origins
Merge into: lp:rnr-server
Diff against target: 571 lines (+277/-103)
9 files modified
django_project/config_dev/config/main.cfg (+8/-0)
django_project/config_dev/schema.py (+1/-0)
src/reviewsapp/api/handlers.py (+3/-1)
src/reviewsapp/forms.py (+45/-38)
src/reviewsapp/models/reviews.py (+6/-0)
src/reviewsapp/tests/test_handlers.py (+42/-3)
src/reviewsapp/tests/test_rnrclient.py (+8/-3)
src/reviewsapp/tests/test_utilities.py (+120/-43)
src/reviewsapp/utilities.py (+44/-15)
To merge this branch: bzr merge lp:~michael.nelson/rnr-server/731736-other-origins
Reviewer Review Type Date Requested Status
Danny Tamez (community) Approve
Review via email: mp+53007@code.launchpad.net

Commit message

[r=zematynnad][bug=731376] Enable reviews of packages in partner and extras.

Description of the change

Overview
========

This branch is fixing bug 731376 by enabling reviews for origins other than 'ubuntu'.

To test: follow the README and then `make test`

This branch will not land until the next one, dealing with the issue identified below, is ready.

Details for the next branch
===========================
The main issue is verifying the origin for a new review when we don't yet have a record of that origin.

For 'ubuntu' and 'canonical' it is simple enough - we can use the LP API to verify that a binary with the given package name is published in the repository for the distroseries and arch. For extras it's also possible to verify (differently) using the API.

But we cannot generalise the origin for public PPAs currently, as the published origin is ambiguous (I created bug 733170). So I've just left that for the moment.

For the commercial PPAs, we cannot verify that the specified origin is correct, as LP doesn't let us query private PPAs for binaries :). So currently (in this branch) submitting a review for 'linux' in the fluendo-dvd origin would work, as would submitting a review for 'vendetta-online' in the fluendo-dvd origin, as would 'fluendo-dvd' in the correct origin, but with 'hoary' as the distroseries etc.

Sooo, we need a solution. The solutions I can think of are:
 1) Pull and cache the staging/production sca available apps to get the data (currently this will also pull the icons, but we could later add a separate url on sca for just the data we need, if necessary)
 2) (Temporary solution): Encode the binary publishings (ie. ppa-name, arch, distroseries) for each of the commercial apps in the settings (and update settings each time a new app is added).
...
So I'll probably go ahead with 1 (Update: checked with achuni and he agrees).

To post a comment you must log in.
Revision history for this message
Danny Tamez (zematynnad) wrote :

Michael - great works as always. Approved but what would you think of adding a test that is the negative test for "test_create_repository_and_software_item"? As it would be good to also test that when lp returns False that the item and repo are not created.

review: Approve
Revision history for this message
Michael Nelson (michael.nelson) wrote :

On Mon, Mar 14, 2011 at 6:46 PM, Danny Tamez <email address hidden>wrote:

> Review: Approve
> Michael - great works as always. Approved but what would you think of
> adding a test that is the negative test for
> "test_create_repository_and_software_item"? As it would be good to also
> test that when lp returns False that the item and repo are not created.
>

Yeah - good find... I'll add the test.

Thanks again!
M

154. By Michael Nelson

Added test ensuring new repositories are not created when lp_verify returns false.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'django_project/config_dev/config/main.cfg'
2--- django_project/config_dev/config/main.cfg 2011-03-11 21:09:10 +0000
3+++ django_project/config_dev/config/main.cfg 2011-03-15 09:36:33 +0000
4@@ -98,6 +98,14 @@
5 cache_review_stats_seconds = 14400
6 token_cache_expiry_hours = 4
7 reviewsapp_media_root = src/reviewsapp/media
8+commercial_origins = lp-ppa-commercial-ppa-uploaders-fluendo-dvd
9+ lp-ppa-commercial-ppa-uploaders-fluendo-plugins
10+ lp-ppa-commercial-ppa-uploaders-fluendo-wmv-plugins
11+ lp-ppa-commercial-ppa-uploaders-brukkon
12+ lp-ppa-commercial-ppa-uploaders-vendetta-online
13+ lp-ppa-commercial-ppa-uploaders-world-of-goo
14+ lp-ppa-commercial-ppa-uploaders-illumination
15+
16
17 [sso_api]
18 sso_api_service_root = https://login.staging.ubuntu.com/api/1.0
19
20=== modified file 'django_project/config_dev/schema.py'
21--- django_project/config_dev/schema.py 2011-03-10 22:56:54 +0000
22+++ django_project/config_dev/schema.py 2011-03-15 09:36:33 +0000
23@@ -56,6 +56,7 @@
24 rnr.token_cache_expiry_hours = IntConfigOption(default=4)
25 rnr.reviewsapp_media_root = StringConfigOption()
26 rnr.allow_multiple_reviews_for_testing = BoolConfigOption(default=False)
27+ rnr.commercial_origins = LinesConfigOption(item=StringConfigOption())
28
29 # Launchpad
30 launchpad = ConfigSection()
31
32=== modified file 'src/reviewsapp/api/handlers.py'
33--- src/reviewsapp/api/handlers.py 2011-03-01 12:24:51 +0000
34+++ src/reviewsapp/api/handlers.py 2011-03-15 09:36:33 +0000
35@@ -80,7 +80,7 @@
36
37 class RetrieveReviewHandler(BaseHandler):
38 allowed_methods = ('GET',)
39-
40+
41 def read(self, request, review_id):
42 try:
43 review = Review.objects.get(id=review_id)
44@@ -95,6 +95,8 @@
45 'id',
46 'package_name',
47 'app_name',
48+ 'origin',
49+ 'distroseries',
50 'language',
51 'date_created',
52 'rating',
53
54=== modified file 'src/reviewsapp/forms.py'
55--- src/reviewsapp/forms.py 2011-03-09 11:45:47 +0000
56+++ src/reviewsapp/forms.py 2011-03-15 09:36:33 +0000
57@@ -88,8 +88,7 @@
58 if not self.is_valid():
59 return self.cleaned_data
60
61- self._validate_and_populate_software_item()
62- self._validate_and_populate_repository()
63+ self._validate_software_item_and_repository()
64
65 if not settings.ALLOW_MULTIPLE_REVIEWS_FOR_TESTING:
66 # Ensure a user cannot submit a second review for the same app
67@@ -117,52 +116,60 @@
68 self.cleaned_data['architecture'] = architecture
69 return arch_tag
70
71- def _validate_and_populate_software_item(self):
72- """Add the software item to the cleaned data, creating if necessary.
73+ def _validate_software_item_and_repository(self):
74+ """Add the software item and repository to the cleaned data.
75+
76+ If they do not exist in the db, we check the validity and
77+ create them if they are valid.
78 """
79 package_name = self.cleaned_data['package_name']
80 app_name = self.cleaned_data['app_name']
81+ origin = self.cleaned_data['origin']
82 distroseries = self.cleaned_data['distroseries']
83 arch_tag=self.cleaned_data['arch_tag']
84- review_count = Review.objects.filter(
85- softwareitem__package_name=package_name,
86- softwareitem__app_name=app_name,
87- repository__distroseries=distroseries,
88- architecture__tag=arch_tag).count()
89- if review_count == 0:
90- # This is the first review for this software_item and distroseries
91- if not WebServices().lp_verify_packagename_in_distro(
92- package_name, distroseries, arch_tag=arch_tag):
93+
94+ require_lp_check = False
95+ repository = None
96+ # First we grab the repository - if it exists.
97+ try:
98+ repository = Repository.objects.get(
99+ origin=origin, distroseries=distroseries)
100+ except Repository.DoesNotExist:
101+ require_lp_check = True
102+
103+ if repository is not None:
104+ # Check whether there are any existing reviews for this
105+ # software in the repository with the given arch.
106+ review_count = Review.objects.filter(
107+ softwareitem__package_name=package_name,
108+ softwareitem__app_name=app_name,
109+ repository=repository,
110+ architecture__tag=arch_tag).count()
111+ if review_count == 0:
112+ # This is the first review for this software_item in the
113+ # repository with the given arch.
114+ require_lp_check = True
115+
116+ if require_lp_check:
117+ valid_in_lp = WebServices().lp_verify_packagename_in_repository(
118+ package_name, origin, distroseries, arch_tag=arch_tag)
119+
120+ if not valid_in_lp:
121 raise forms.ValidationError(
122- ': package {0} not in {1} for {2}'.format(
123- package_name, distroseries, arch_tag))
124+ ': package {0} not in {1} {2} for {2}'.format(
125+ package_name, origin, distroseries, arch_tag))
126+
127+ # Now we know the given data corresponds to a published binary
128+ # on launchpad, so we can populate the cleaned data, creating
129+ # the repository and software_item records if necessary.
130+ repository = repository or Repository.objects.create(
131+ origin=origin, distroseries=distroseries)
132+ self.cleaned_data['repository'] = repository
133+
134 software_item, created = SoftwareItem.objects.get_or_create(
135 package_name=package_name, app_name=app_name)
136-
137 self.cleaned_data['software_item'] = software_item
138
139- def _validate_and_populate_repository(self):
140- """Add the repository to the cleaned data, creating if necessary."""
141- # Find the origin/distroseries for the software item.
142- origin = self.cleaned_data['origin']
143- distroseries = self.cleaned_data['distroseries']
144- try:
145- repository = Repository.objects.get(
146- origin=origin,
147- distroseries=distroseries)
148- except Repository.DoesNotExist:
149- # The software repository does not yet exist, probably because
150- # this is the first review for this origin/distroseries. That's
151- # okay, create a record for it in our database.
152- #
153- # XXX 2010-03-03 bug=688043 Verify with Launchpad first.
154- repository = Repository(
155- origin=origin,
156- distroseries=distroseries)
157- repository.save()
158-
159- self.cleaned_data['repository'] = repository
160-
161
162 class ReviewModerationFilterForm(forms.Form):
163 """Filtering options for review moderation list."""
164
165=== modified file 'src/reviewsapp/models/reviews.py'
166--- src/reviewsapp/models/reviews.py 2011-03-09 08:27:34 +0000
167+++ src/reviewsapp/models/reviews.py 2011-03-15 09:36:33 +0000
168@@ -270,6 +270,12 @@
169 def app_name(self):
170 return self.softwareitem.app_name
171
172+ def origin(self):
173+ return self.repository.origin
174+
175+ def distroseries(self):
176+ return self.repository.distroseries
177+
178 def package_app_name(self):
179 app_name = self.app_name()
180 if app_name:
181
182=== modified file 'src/reviewsapp/tests/test_handlers.py'
183--- src/reviewsapp/tests/test_handlers.py 2011-03-09 11:49:10 +0000
184+++ src/reviewsapp/tests/test_handlers.py 2011-03-15 09:36:33 +0000
185@@ -51,6 +51,7 @@
186 SubmitUsefulnessHandler,
187 )
188 from reviewsapp.models import (
189+ Repository,
190 Review,
191 ReviewModerationFlag,
192 SoftwareItem,
193@@ -475,7 +476,7 @@
194 }
195 super(SubmitReviewHandlerTestCase, self).setUp()
196
197- def _post_new_review(self, data, user=None):
198+ def _post_new_review(self, data, user=None, lp_verify_result=True):
199 # Post a review as an authenticated user.
200 url = reverse('rnr-api-reviews')
201
202@@ -485,11 +486,11 @@
203
204 is_authed_fn = 'reviewsapp.auth.SSOOAuthAuthentication.is_authenticated'
205 lp_verify_fn = ('reviewsapp.utilities.WebServices.'
206- 'lp_verify_packagename_in_distro')
207+ 'lp_verify_packagename_in_repository')
208 with patch(is_authed_fn) as mock_is_authenticated:
209 mock_is_authenticated.return_value = True
210 with patch(lp_verify_fn) as mock_lp_verify_method:
211- mock_lp_verify_method.return_value = True
212+ mock_lp_verify_method.return_value = lp_verify_result
213 response = self.client.post(
214 url, data=data, content_type='application/json')
215 return response
216@@ -520,6 +521,44 @@
217 response_dict = simplejson.loads(response.content)
218 self.assertEqual('inkscape', response_dict['package_name'])
219
220+ def test_creates_repository_and_software_item(self):
221+ # Submitting a review for a software item or repository of which
222+ # we don't yet have a record will create those records (after
223+ # validating that the corresponding binary exists on Launchpad).
224+ required_data = self.required_data
225+ required_data['distroseries'] = 'doesntexist'
226+ self.assertEqual(0, Repository.objects.filter(
227+ origin='ubuntu', distroseries='doesntexist').count())
228+ self.assertEqual(0, SoftwareItem.objects.filter(
229+ package_name='inkscape').count())
230+
231+ response = self._post_new_review(simplejson.dumps(self.required_data))
232+
233+ self.assertEqual(1, Repository.objects.filter(
234+ origin='ubuntu', distroseries='doesntexist').count())
235+ self.assertEqual(1, SoftwareItem.objects.filter(
236+ package_name='inkscape').count())
237+
238+ def test_bad_repository(self):
239+ # If lp_verify returns false a bad request status is returned,
240+ # and no new repositories are created.
241+ required_data = self.required_data
242+ required_data['distroseries'] = 'doesntexist'
243+ self.assertEqual(0, Repository.objects.filter(
244+ origin='ubuntu', distroseries='doesntexist').count())
245+ self.assertEqual(0, SoftwareItem.objects.filter(
246+ package_name='inkscape').count())
247+
248+ response = self._post_new_review(
249+ simplejson.dumps(self.required_data), lp_verify_result=False)
250+
251+ self.assertEqual(httplib.BAD_REQUEST, response.status_code)
252+ self.assertEqual(0, Repository.objects.filter(
253+ origin='ubuntu', distroseries='doesntexist').count())
254+ self.assertEqual(0, SoftwareItem.objects.filter(
255+ package_name='inkscape').count())
256+
257+
258 def test_max_length_summary(self):
259 # Posting with a summary > 80 chars results in a bad request.
260 data = self.required_data
261
262=== modified file 'src/reviewsapp/tests/test_rnrclient.py'
263--- src/reviewsapp/tests/test_rnrclient.py 2011-03-09 08:27:34 +0000
264+++ src/reviewsapp/tests/test_rnrclient.py 2011-03-15 09:36:33 +0000
265@@ -154,6 +154,8 @@
266 reviews[0].reviewer_username)
267 self.assertEqual(review.reviewer_displayname(),
268 reviews[0].reviewer_displayname)
269+ self.assertEqual(review.origin(), reviews[0].origin)
270+ self.assertEqual(review.distroseries(), reviews[0].distroseries)
271
272 def test_get_reviews_for_app(self):
273 software_item = self.factory.makeSoftwareItem(app_name='something')
274@@ -202,9 +204,11 @@
275 review = self.factory.makeReview()
276
277 api = RatingsAndReviewsAPI()
278- review_request = api.get_review(review_id=review.id)
279+ review_detail = api.get_review(review_id=review.id)
280
281- self.assertEqual(review_request.id, review.id)
282+ self.assertEqual(review_detail.id, review.id)
283+ self.assertEqual(review_detail.origin, review.origin())
284+ self.assertEqual(review_detail.distroseries, review.distroseries())
285 invalidate_paginated_reviews_for(review)
286
287
288@@ -222,7 +226,8 @@
289 auth = OAuthAuthorizer(token.token, token.token_secret, consumer.key,
290 consumer.secret)
291 lp_verify_packagename_method = (
292- 'reviewsapp.utilities.WebServices.lp_verify_packagename_in_distro')
293+ 'reviewsapp.utilities.WebServices.'
294+ 'lp_verify_packagename_in_repository')
295
296 if mock_verify_package is None:
297 mock_verify_package = Mock()
298
299=== modified file 'src/reviewsapp/tests/test_utilities.py'
300--- src/reviewsapp/tests/test_utilities.py 2011-03-10 22:56:54 +0000
301+++ src/reviewsapp/tests/test_utilities.py 2011-03-15 09:36:33 +0000
302@@ -100,58 +100,135 @@
303 class LaunchpadTestCase(TestCaseWithFactory):
304 def setUp(self):
305 super(LaunchpadTestCase, self).setUp()
306- self._request = HttpRequest()
307- self._request.user = self.factory.makeUser()
308- self.binary = Mock()
309- self.mock_lp = Mock()
310- archive = self.mock_lp.load.return_value
311- archive.getPublishedBinaries.return_value = [self.binary]
312- self.client.login(username=self._request.user.username, password='test')
313 # Force web_services to recreate the the Launchpad service root
314 WebServices._launchpad_service = None
315
316- @patch('reviewsapp.utilities.Launchpad')
317- def test_valid_package(self, mock_launchpad):
318- # A valid package in a distroseries can be found.
319- mock_launchpad.login_anonymously.return_value = self.mock_lp
320- self.binary.binary_package_name = 'apt'
321- ws = WebServices()
322-
323- self.assertTrue(ws.lp_verify_packagename_in_distro("apt", "lucid",
324- 'i386'))
325-
326- @patch('reviewsapp.utilities.Launchpad')
327- def test_invalid_distro(self, mock_launchpad):
328- # Invalid distroseries (assuming we never call a release 'xxx') cannot
329- # be found.
330- mock_launchpad.login_anonymously.return_value = self.mock_lp
331+ def _make_mock_launchpad(self, binary_name='mypkg'):
332+ mock_ubuntu = Mock()
333+ mock_ubuntu.self_link = 'http://lpapi/ubuntu'
334+
335+ mock_launchpad = Mock()
336+ mock_launchpad.distributions = dict(ubuntu=mock_ubuntu)
337+ app_review_board = Mock()
338+ mock_launchpad.people = {'app-review-board': app_review_board}
339+
340+ mock_archive = Mock()
341+ mock_ubuntu.getArchive.return_value = mock_archive
342+ app_review_board.getPPAByName.return_value = mock_archive
343+
344+ mock_binary = Mock()
345+ mock_binary.binary_package_name = binary_name
346+ mock_archive.getPublishedBinaries.return_value = [mock_binary]
347+ return (mock_launchpad, mock_ubuntu, mock_archive)
348+
349+ def _verify_package(self, mock_lp_api, package_name,
350+ distro, series, arch_tag):
351+ with patch('reviewsapp.utilities.Launchpad') as mock_launchpad:
352+ mock_launchpad.login_anonymously.return_value = mock_lp_api
353+ return WebServices().lp_verify_packagename_in_repository(
354+ package_name, distro, series, arch_tag)
355+
356+ def test_package_in_ubuntu(self):
357+ lp_api, ubuntu, archive = self._make_mock_launchpad()
358+
359+ result = self._verify_package(lp_api, 'mypkg', 'ubuntu', 'lucid',
360+ 'i386')
361+
362+ ubuntu.getArchive.assert_called_with(name='primary')
363+ archive.getPublishedBinaries.assert_called_with(
364+ binary_name='mypkg',
365+ distro_arch_series='http://lpapi/ubuntu/lucid/i386',
366+ status='Published', exact_match=True)
367+ self.assertTrue(result)
368+
369+ def test_package_not_in_ubuntu(self):
370+ lp_api, ubuntu, archive = self._make_mock_launchpad(
371+ binary_name='other_pkg')
372+
373+ result = self._verify_package(lp_api, 'mypkg', 'ubuntu', 'lucid',
374+ 'i386')
375+
376+ ubuntu.getArchive.assert_called_with(name='primary')
377+ archive.getPublishedBinaries.assert_called_with(
378+ binary_name='mypkg',
379+ distro_arch_series='http://lpapi/ubuntu/lucid/i386',
380+ status='Published', exact_match=True)
381+ self.assertFalse(result)
382+
383+ def test_package_in_partner(self):
384+ lp_api, ubuntu, archive = self._make_mock_launchpad()
385+
386+ result = self._verify_package(lp_api, 'mypkg', 'canonical', 'lucid',
387+ 'i386')
388+
389+ ubuntu.getArchive.assert_called_with(name='partner')
390+ archive.getPublishedBinaries.assert_called_with(
391+ binary_name='mypkg',
392+ distro_arch_series='http://lpapi/ubuntu/lucid/i386',
393+ status='Published', exact_match=True)
394+ self.assertTrue(result)
395+
396+ def test_package_in_extras(self):
397+ lp_api, ubuntu, archive = self._make_mock_launchpad()
398+
399+ result = self._verify_package(lp_api, 'mypkg',
400+ 'lp-ppa-app-review-board', 'lucid', 'i386')
401+
402+ app_review_board = lp_api.people['app-review-board']
403+ app_review_board.getPPAByName.assert_called_with(name='ppa')
404+ archive.getPublishedBinaries.assert_called_with(
405+ binary_name='mypkg',
406+ distro_arch_series='http://lpapi/ubuntu/lucid/i386',
407+ status='Published', exact_match=True)
408+ self.assertTrue(result)
409+
410+ def test_commercial_package(self):
411+ lp_api, ubuntu, archive = self._make_mock_launchpad()
412+
413+ with patch_settings(COMMERCIAL_ORIGINS=['lp-ppa-commercial-one']):
414+ result = self._verify_package(lp_api, 'anything',
415+ 'lp-ppa-commercial-one', 'anything', 'anything')
416+
417+ # XXX The result should not always be true... we need a way to
418+ # know the content of commercial ppas.
419+ self.assertTrue(result)
420+
421+ def test_unknown_origin(self):
422+ lp_api, ubuntu, archive = self._make_mock_launchpad()
423+
424+ result = self._verify_package(lp_api, 'mypkg',
425+ 'lp-ppa-unknown', 'lucid', 'i386')
426+
427+ # Currently we only support primary, partner, extras and the
428+ # specified commercial origins.
429+ self.assertEqual(0, archive.getPublishedBinaries.call_count)
430+ self.assertFalse(result)
431+
432+ def test_invalid_series_or_arch(self):
433+ # An invalid series or arch raises a 400 Bad Request.
434+ lp_api, ubuntu, archive = self._make_mock_launchpad()
435 response = Mock()
436- response.status = 404
437- mock_launchpad.load.side_effect = HTTPError(response, 'content')
438- ws = WebServices()
439-
440- self.assertFalse(ws.lp_verify_packagename_in_distro("apt", "xxx",
441- 'i386'))
442-
443- @patch('reviewsapp.utilities.Launchpad')
444- def test_invalid_package(self, mock_launchpad):
445- # Invalid package (assuming no one creates such a package) in a valid
446- # distroseries cannot be found.
447- mock_launchpad.login_anonymously.return_value = self.mock_lp
448- ws = WebServices()
449-
450- self.assertFalse(ws.lp_verify_packagename_in_distro(
451- "***xxx***", "lucid", 'i386'))
452+ response.status = 400
453+ archive.getPublishedBinaries.side_effect = HTTPError(
454+ response, 'content')
455+
456+ result = self._verify_package(lp_api, 'mypkg', 'ubuntu', 'lucid',
457+ 'i386')
458+
459+ self.assertFalse(result)
460
461 @patch('reviewsapp.utilities.Launchpad')
462 def test_doesnt_sign_in_each_time(self, mock_launchpad):
463- mock_launchpad.login_anonymously.return_value = self.mock_lp
464+ lp_api, ubuntu, archive = self._make_mock_launchpad()
465+ mock_launchpad.login_anonymously.return_value = lp_api
466 ws = WebServices()
467- ws.lp_verify_packagename_in_distro("foobar", "lucid", 'i386')
468+ ws.lp_verify_packagename_in_repository("foobar", 'ubuntu',
469+ "lucid", 'i386')
470 self.assertTrue(mock_launchpad.login_anonymously.called)
471 mock_launchpad.login_anonymously.reset_mock()
472
473- ws.lp_verify_packagename_in_distro("foobar", "lucid", 'i386')
474+ ws.lp_verify_packagename_in_repository("foobar", 'ubuntu',
475+ "lucid", 'i386')
476
477 self.assertFalse(mock_launchpad.login_anonymously.called)
478
479@@ -163,8 +240,8 @@
480 del os.environ['HOME']
481 ws = WebServices()
482 # SyntaxError is raised when we fail to parse our dummy wadl
483- self.assertRaises(SyntaxError, ws.lp_verify_packagename_in_distro,
484- "foobar", "lucid", 'i386')
485+ self.assertRaises(SyntaxError, ws.lp_verify_packagename_in_repository,
486+ "foobar", "ubuntu", "lucid", 'i386')
487
488
489 class InvalidatePaginatedReviewsTestCase(TestCaseWithFactory):
490
491=== modified file 'src/reviewsapp/utilities.py'
492--- src/reviewsapp/utilities.py 2011-03-10 11:02:01 +0000
493+++ src/reviewsapp/utilities.py 2011-03-15 09:36:33 +0000
494@@ -157,33 +157,62 @@
495 result.update(api.accounts.me())
496 return result
497
498- def lp_verify_packagename_in_distro(self, pkgname, distroseries,
499- arch_tag):
500+ def lp_verify_packagename_in_repository(self, pkgname, origin, distroseries,
501+ arch_tag):
502 """Verify that a given package exists in a distroseries.
503
504 :param pkgname: The name of the package to check.
505+ :param origin: The repository origin identifier.
506 :param distroseries: The name of distribution series.
507 :param arch_tag: The machine architecture (i386, amd64...)
508 :return: Whether the package was found or not.
509 :rtype: bool
510 """
511- # FIXME: is there a better way to get the root_uri from LP?
512- ubuntu_uri = str(self.launchpad_service._root_uri) + "ubuntu/"
513+ ubuntu = self.launchpad_service.distributions['ubuntu']
514+ if origin == 'ubuntu':
515+ archive = ubuntu.getArchive(name='primary')
516+ elif origin == 'canonical':
517+ archive = ubuntu.getArchive(name='partner')
518+ elif origin =='lp-ppa-app-review-board':
519+ app_review_board = self.launchpad_service.people[
520+ 'app-review-board']
521+ archive = app_review_board.getPPAByName(name='ppa')
522+ elif origin in settings.COMMERCIAL_ORIGINS:
523+ # XXX 2011-03-11 michaeln bug=733170 PPA origins are
524+ # currently ambiguous.
525+ # We should check this in a way that doesn't require
526+ # settings, either pulling the data from SCA, or request
527+ # that LP updates IArchive to allow public access to
528+ # getPublishedBinaries() for commercial PPAs (but not
529+ # private-only).
530+ # XXX - chat with achuni about options - dict in settings?
531+ # Perhaps for now just a non-configglue setting with a
532+ # complex dict:
533+ # 'lp-ppa-commercial-ppa-uploaders-fluendo-dvd': {
534+ # 'package_name': 'fluendo-dvd',
535+ # 'releases': {
536+ # 'natty': ['i386', 'amd64'],
537+ # ...
538+ # And then we can make this available on SCA as json/api.
539+ return True
540+ else:
541+ return False
542+
543+ # We now have the archive, check for the distroseries and the
544+ # package.
545+ distro_arch_series = ubuntu.self_link + '/{0}/{1}'.format(
546+ distroseries, arch_tag)
547 try:
548- release = self.launchpad_service.load(ubuntu_uri + distroseries)
549- distro_arch = self.launchpad_service.load(
550- ubuntu_uri + '{0}/{1}'.format(distroseries, arch_tag))
551+ binaries = archive.getPublishedBinaries(
552+ binary_name=pkgname, distro_arch_series=distro_arch_series,
553+ status='Published', exact_match=True)
554 except HTTPError as error:
555- if error.response.status == 404:
556- # Either the release or distro_arch does not exist.
557- # Obviously, this does not verify! Any other status is
558- # unexpected.
559+ if error.response.status == 400:
560+ # A bad request is raised if the distro arch series we
561+ # indicate does not exist. Obviously, this does not
562+ # verify! Any other status is unexpected.
563 return False
564 raise
565- archive = self.launchpad_service.load(ubuntu_uri + '+archive/primary')
566- binaries = archive.getPublishedBinaries(
567- binary_name=pkgname, distro_arch_series=distro_arch,
568- exact_match=True)
569 for binary in binaries:
570 if binary.binary_package_name == pkgname:
571 return True

Subscribers

People subscribed via source and target branches