Merge lp:~elachuni/rnr-server/filter-reviews into lp:rnr-server

Proposed by Anthony Lenton
Status: Merged
Approved by: Łukasz Czyżykowski
Approved revision: 106
Merged at revision: 105
Proposed branch: lp:~elachuni/rnr-server/filter-reviews
Merge into: lp:rnr-server
Diff against target: 437 lines (+157/-65)
6 files modified
src/reviewsapp/api/handlers.py (+13/-5)
src/reviewsapp/api/urls.py (+8/-7)
src/reviewsapp/tests/test_handlers.py (+116/-45)
src/reviewsapp/tests/test_rnrclient.py (+2/-0)
src/reviewsapp/tests/test_utilities.py (+8/-6)
src/reviewsapp/utilities.py (+10/-2)
To merge this branch: bzr merge lp:~elachuni/rnr-server/filter-reviews
Reviewer Review Type Date Requested Status
Ratings and Reviews Developers Pending
Review via email: mp+46815@code.launchpad.net

Description of the change

Overview
========
This branch implements the agreed solution from bug #688112 providing an optional 'version' argument when fetching reviews, and making all arguments to the reviews getter optional.

Details
=======
For fetching reviews you now have an additional 'version' component in the url that allows you to filter by version. Additionally, if the language, origin, distroseries or version are specified as "any", reviews for any value of that parameter will be retrieved.

See the comments in the bug for a full discussion.

This branch needs lp:~elachuni/rnr-server/rnrclient-filter-reviews to work correctly.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/reviewsapp/api/handlers.py'
2--- src/reviewsapp/api/handlers.py 2011-01-10 19:15:32 +0000
3+++ src/reviewsapp/api/handlers.py 2011-01-19 19:59:08 +0000
4@@ -87,8 +87,8 @@
5 )
6 allowed_methods = ('GET',)
7
8- def read(self, request, language, origin, distroseries, package_name,
9- page='1'):
10+ def read(self, request, language, origin, distroseries, version,
11+ package_name, page='1'):
12 # The %2F used for slashes is itself being quoted before reaching
13 # the handler.
14 software_item = urllib.unquote_plus(urllib.unquote_plus(package_name))
15@@ -96,10 +96,18 @@
16 batch_size = settings.API_REVIEWS_PAGINATION
17 batch_start = batch_size * (int(page) - 1)
18 batch_end = batch_start + batch_size
19+ kwargs = {
20+ 'language': language,
21+ 'repository__distroseries': distroseries,
22+ 'repository__origin': origin,
23+ 'version': version,
24+ }
25+ kwargs = dict(item for item in kwargs.items() if item[1] != 'any')
26 return Review.objects.filter(
27- repository__origin=origin, repository__distroseries=distroseries,
28- softwareitem__package_name=package_name, softwareitem__app_name=appname,
29- hide=False, language=language).order_by(
30+ softwareitem__package_name=package_name,
31+ softwareitem__app_name=appname,
32+ hide=False,
33+ **kwargs).order_by(
34 '-usefulness_percentage')[batch_start:batch_end]
35
36
37
38=== modified file 'src/reviewsapp/api/urls.py'
39--- src/reviewsapp/api/urls.py 2011-01-04 16:45:55 +0000
40+++ src/reviewsapp/api/urls.py 2011-01-19 19:59:08 +0000
41@@ -83,13 +83,14 @@
42 submit_usefulness_resource, name='rnr-api-recommendations'),
43
44 # gets the reviews (and ratings) for a given pkg/app
45- # GET /1.0/en/ubuntu/+binary/lucid/gnome-games;sane/page/1/
46- # GET /1.0/en/ubuntu/+binary/lucid/2vcard/
47- url(r'^1.0/(?P<language>\w+)/(?P<origin>\w+)/(?P<distroseries>\w+)/'
48- r'(?P<package_name>[\w%+.;-]+)/$', show_reviews_resource,
49- name='rnr-api-reviews-for-package'),
50- url(r'^1.0/(?P<language>\w+)/(?P<origin>\w+)/(?P<distroseries>\w+)/'
51- r'(?P<package_name>[\w%+.;-]+)/page/(?P<page>\d+)/$',
52+ # GET /1.0/en/ubuntu/+binary/lucid/1:2.32.0-0ubuntu1/gnome-games;sane/page/1/
53+ # GET /1.0/en/ubuntu/+binary/lucid/1:2.32.0-0ubuntu1/2vcard/
54+ url(r'^1.0/(?P<language>\w+)/(?P<origin>\w+)/(?P<distroseries>\w+)/'
55+ r'(?P<version>[-\w+.:~]+)/(?P<package_name>[\w%+.;-]+)/$',
56+ show_reviews_resource, name='rnr-api-reviews-for-package'),
57+ url(r'^1.0/(?P<language>\w+)/(?P<origin>\w+)/(?P<distroseries>\w+)/'
58+ r'(?P<version>[-\w+.:~]+)/(?P<package_name>[\w%+.;-]+)/'
59+ r'page/(?P<page>\d+)/$',
60 show_reviews_resource, name='rnr-api-reviews-for-package'),
61
62 # submits a new review for a given pkg/app
63
64=== modified file 'src/reviewsapp/tests/test_handlers.py'
65--- src/reviewsapp/tests/test_handlers.py 2011-01-04 16:42:36 +0000
66+++ src/reviewsapp/tests/test_handlers.py 2011-01-19 19:59:08 +0000
67@@ -148,12 +148,11 @@
68 class ShowReviewsHandlerTestCase(TestCaseWithFactory):
69 def test_review_for_package(self):
70 review = self.factory.makeReview(
71- software_item=self.factory.makeSoftwareItem('package_foo'),
72- repository=self.factory.makeRepository('ubuntu', 'hardy'),
73- language='de')
74+ software_item=self.factory.makeSoftwareItem('package_foo'))
75 handler = ShowReviewsHandler()
76
77- reviews = handler.read(None, 'de', 'ubuntu', 'hardy', 'package_foo')
78+ reviews = handler.read(None, 'any', 'any', 'any', 'any',
79+ 'package_foo')
80
81 self.assertEqual(1, len(reviews))
82 self.assertEqual(review, reviews[0])
83@@ -161,12 +160,10 @@
84 def test_review_for_app(self):
85 review = self.factory.makeReview(
86 software_item=self.factory.makeSoftwareItem('package_foo',
87- app_name='app_foo'),
88- repository=self.factory.makeRepository('ubuntu', 'hardy'),
89- language='en')
90+ app_name='app_foo'))
91 handler = ShowReviewsHandler()
92
93- reviews = handler.read(None, 'en', 'ubuntu', 'hardy',
94+ reviews = handler.read(None, 'any', 'any', 'any', 'any',
95 'package_foo;app_foo')
96
97 self.assertEqual(1, len(reviews))
98@@ -174,60 +171,134 @@
99
100 def test_review_for_language(self):
101 package = self.factory.makeSoftwareItem('package_foo')
102- repo = self.factory.makeRepository('ubuntu', 'hardy')
103 review1 = self.factory.makeReview(software_item=package,
104- repository=repo, language='en')
105+ language='en')
106 review2 = self.factory.makeReview(software_item=package,
107- repository=repo, language='de')
108+ language='de')
109 handler = ShowReviewsHandler()
110
111- reviews = handler.read(None, 'en', 'ubuntu', 'hardy', 'package_foo')
112+ reviews = handler.read(None, 'en', 'any', 'any', 'any',
113+ 'package_foo')
114
115 self.assertEqual(1, len(reviews))
116 self.assertIn(review1, reviews)
117 self.assertNotIn(review2, reviews)
118
119+ def test_review_for_any_language(self):
120+ package = self.factory.makeSoftwareItem('package_foo')
121+ repository = self.factory.makeRepository('ubuntu', 'hardy')
122+ review1 = self.factory.makeReview(software_item=package,
123+ language='en', repository=repository, version='1.0')
124+ review2 = self.factory.makeReview(software_item=package,
125+ language='de', repository=repository, version='1.0')
126+ handler = ShowReviewsHandler()
127+
128+ reviews = handler.read(None, 'any', 'ubuntu', 'hardy', '1.0',
129+ 'package_foo')
130+
131+ self.assertEqual(2, len(reviews))
132+ self.assertIn(review1, reviews)
133+ self.assertIn(review2, reviews)
134+
135 def test_review_from_distroseries(self):
136 package = self.factory.makeSoftwareItem('package_foo')
137 review1 = self.factory.makeReview(software_item=package,
138+ repository=self.factory.makeRepository('ubuntu', 'hardy'))
139+ review2 = self.factory.makeReview(software_item=package,
140+ repository=self.factory.makeRepository('ubuntu', 'lucid'))
141+ handler = ShowReviewsHandler()
142+
143+ reviews = handler.read(None, 'any', 'any', 'hardy', 'any',
144+ 'package_foo')
145+
146+ self.assertEqual(1, len(reviews))
147+ self.assertIn(review1, reviews)
148+ self.assertNotIn(review2, reviews)
149+
150+ def test_review_from_any_distroseries(self):
151+ package = self.factory.makeSoftwareItem('package_foo')
152+ review1 = self.factory.makeReview(software_item=package,
153 repository=self.factory.makeRepository('ubuntu', 'hardy'),
154- language='en')
155+ language='en', version='+-1')
156 review2 = self.factory.makeReview(software_item=package,
157 repository=self.factory.makeRepository('ubuntu', 'lucid'),
158- language='en')
159+ language='en', version='+-1')
160 handler = ShowReviewsHandler()
161
162- reviews = handler.read(None, 'en', 'ubuntu', 'hardy', 'package_foo')
163+ reviews = handler.read(None, 'en', 'ubuntu', 'any', '+-1',
164+ 'package_foo')
165
166- self.assertEqual(1, len(reviews))
167+ self.assertEqual(2, len(reviews))
168 self.assertIn(review1, reviews)
169- self.assertNotIn(review2, reviews)
170+ self.assertIn(review2, reviews)
171
172 def test_review_from_origin(self):
173 package = self.factory.makeSoftwareItem('package_foo')
174 review1 = self.factory.makeReview(software_item=package,
175+ repository=self.factory.makeRepository('ubuntu', 'hardy'))
176+ review2 = self.factory.makeReview(software_item=package,
177+ repository=self.factory.makeRepository('debian', 'lenny'))
178+ handler = ShowReviewsHandler()
179+
180+ reviews = handler.read(None, 'any', 'ubuntu', 'any', 'any',
181+ 'package_foo')
182+
183+ self.assertEqual(1, len(reviews))
184+ self.assertIn(review1, reviews)
185+ self.assertNotIn(review2, reviews)
186+
187+ def test_review_from_any_origin(self):
188+ package = self.factory.makeSoftwareItem('package_foo')
189+ review1 = self.factory.makeReview(software_item=package,
190 repository=self.factory.makeRepository('ubuntu', 'hardy'),
191- language='en')
192- review2 = self.factory.makeReview(software_item=package,
193- repository=self.factory.makeRepository('debian', 'lenny'),
194- language='en')
195- handler = ShowReviewsHandler()
196-
197- reviews = handler.read(None, 'en', 'ubuntu', 'hardy', 'package_foo')
198+ language='en', version='vanilla')
199+ review2 = self.factory.makeReview(software_item=package,
200+ repository=self.factory.makeRepository('debian', 'hardy'),
201+ language='en', version='vanilla')
202+ handler = ShowReviewsHandler()
203+
204+ reviews = handler.read(None, 'en', 'any', 'hardy', 'vanilla',
205+ 'package_foo')
206+
207+ self.assertEqual(2, len(reviews))
208+ self.assertIn(review1, reviews)
209+ self.assertIn(review2, reviews)
210+
211+ def test_review_for_version(self):
212+ package = self.factory.makeSoftwareItem('package_foo')
213+ review1 = self.factory.makeReview(software_item=package,
214+ version='0.2')
215+ review2 = self.factory.makeReview(software_item=package,
216+ version='0.3')
217+ handler = ShowReviewsHandler()
218+
219+ reviews = handler.read(None, 'any', 'any', 'any', '0.2',
220+ 'package_foo')
221
222 self.assertEqual(1, len(reviews))
223 self.assertIn(review1, reviews)
224 self.assertNotIn(review2, reviews)
225
226+ def test_review_for_any_version(self):
227+ package = self.factory.makeSoftwareItem('package_foo')
228+ repository = self.factory.makeRepository('ubuntu', 'hardy')
229+ review1 = self.factory.makeReview(software_item=package,
230+ language='en', repository=repository, version='1.0')
231+ review2 = self.factory.makeReview(software_item=package,
232+ language='en', repository=repository, version='2.0')
233+ handler = ShowReviewsHandler()
234+
235+ reviews = handler.read(None, 'en', 'ubuntu', 'hardy', 'any',
236+ 'package_foo')
237+
238+ self.assertEqual(2, len(reviews))
239+ self.assertIn(review1, reviews)
240+ self.assertIn(review2, reviews)
241+
242 def test_review_sorting(self):
243 package = self.factory.makeSoftwareItem('pkg_foo')
244- repository = self.factory.makeRepository('ubuntu', 'hardy')
245- review1 = self.factory.makeReview(software_item=package,
246- repository=repository,
247- language='en')
248- review2 = self.factory.makeReview(software_item=package,
249- repository=repository,
250- language='en')
251+ review1 = self.factory.makeReview(software_item=package)
252+ review2 = self.factory.makeReview(software_item=package)
253 showHandler = ShowReviewsHandler()
254 usefulnessHandler = SubmitUsefulnessHandler()
255
256@@ -235,7 +306,8 @@
257 request = Mock()
258 request.user = self.factory.makeUser()
259 usefulnessHandler.create(request, review2.id)
260- reviews = showHandler.read(None, 'en', 'ubuntu', 'hardy', 'pkg_foo')
261+ reviews = showHandler.read(None, 'any', 'any', 'any', 'any',
262+ 'pkg_foo')
263
264 self.assertEqual(2, len(reviews))
265 # review2 is sorted first
266@@ -246,31 +318,28 @@
267 request.user = self.factory.makeUser()
268 usefulnessHandler.create(request, review1.id)
269
270- reviews = showHandler.read(None, 'en', 'ubuntu', 'hardy', 'pkg_foo')
271+ reviews = showHandler.read(None, 'any', 'any', 'any', 'any',
272+ 'pkg_foo')
273
274 self.assertEqual(2, len(reviews))
275 # review1 is sorted first
276 self.assertEquals(review1, reviews[0])
277
278- def _make_5_reviews_for_package(self, package_name, origin='ubuntu',
279- distro_series='lucid', language='en'):
280+ def _make_5_reviews_for_package(self, package_name):
281 package = self.factory.makeSoftwareItem(package_name)
282- repository = self.factory.makeRepository(
283- origin=origin, distro_series=distro_series)
284- foo_reviews = []
285 for count in range(5):
286- foo_reviews.append(self.factory.makeReview(
287- software_item=package, language=language,
288- repository=repository))
289+ self.factory.makeReview(software_item=package)
290
291- def _reviews_url_for_package(self, package_name, origin='ubuntu',
292- distro_series='lucid', language='en',
293+ def _reviews_url_for_package(self, package_name, origin='any',
294+ distro_series='any', language='any',
295+ version='any',
296 page=None):
297 kwargs = {
298 'language': language,
299 'origin': origin,
300 'distroseries': distro_series,
301 'package_name': package_name,
302+ 'version': version,
303 }
304 if page is not None:
305 kwargs['page'] = page
306@@ -423,7 +492,8 @@
307 software_item = self.factory.makeSoftwareItem(
308 package_name=self.required_data['package_name'],
309 ratings_total=0, ratings_average=0)
310- url_keys = ('language', 'origin', 'distroseries', 'package_name')
311+ url_keys = ('language', 'origin', 'distroseries', 'version',
312+ 'package_name')
313 url_kwargs = dict((key, self.required_data[key]) for key in url_keys)
314 url = reverse('rnr-api-reviews-for-package', kwargs=url_kwargs)
315 self.client.get(url)
316@@ -484,7 +554,8 @@
317 url_kwargs = dict(language=review.language,
318 origin=review.repository.origin,
319 distroseries=review.repository.distroseries,
320- package_name=review.softwareitem.package_name)
321+ package_name=review.softwareitem.package_name,
322+ version=review.version)
323 url = reverse('rnr-api-reviews-for-package', kwargs=url_kwargs)
324 self.client.get(url)
325 key = cache_key_for_url(url)
326
327=== modified file 'src/reviewsapp/tests/test_rnrclient.py'
328--- src/reviewsapp/tests/test_rnrclient.py 2011-01-10 19:15:32 +0000
329+++ src/reviewsapp/tests/test_rnrclient.py 2011-01-19 19:59:08 +0000
330@@ -148,12 +148,14 @@
331 distroseries=review.repository.distroseries,
332 packagename=review.package_name(),
333 appname=review.app_name(),
334+ version = review.version
335 )
336
337 self.assertEqual(1, len(reviews))
338 self.assertEqual(review.package_name(), reviews[0].package_name)
339 self.assertEqual(review.app_name(), reviews[0].app_name)
340 self.assertEqual(review.summary, reviews[0].summary)
341+ self.assertEqual(review.version, reviews[0].version)
342
343 def test_get_reviews_page_2(self):
344 # The rnr_client can get multiple pages of results.
345
346=== modified file 'src/reviewsapp/tests/test_utilities.py'
347--- src/reviewsapp/tests/test_utilities.py 2011-01-10 20:26:56 +0000
348+++ src/reviewsapp/tests/test_utilities.py 2011-01-19 19:59:08 +0000
349@@ -167,11 +167,12 @@
350
351 class InvalidatePaginatedReviewsTestCase(TestCaseWithFactory):
352 def _url_for_package(self, package_name, origin='ubuntu',
353- distro_series='lucid', language='en', page=None):
354+ distro_series='lucid', language='en', version='1.0', page=None):
355 kwargs = {
356 'language': language,
357 'origin': origin,
358 'distroseries': distro_series,
359+ 'version': version,
360 'package_name': urllib.quote_plus(package_name),
361 }
362 if page is not None:
363@@ -180,10 +181,10 @@
364 return reverse('rnr-api-reviews-for-package', kwargs=kwargs)
365
366 def _request_reviews_for_package(self, package_name, origin='ubuntu',
367- distro_series='lucid', language='en', page=None):
368+ distro_series='lucid', language='en', version='1.0', page=None):
369
370 url = self._url_for_package(package_name, origin, distro_series,
371- language, page)
372+ language, version, page)
373
374 with patch_settings(API_REVIEWS_PAGINATION=2):
375 response = self.client.get(url)
376@@ -191,7 +192,7 @@
377 return response
378
379 def _populate_reviews_and_cache(self, package_name, origin='ubuntu',
380- distro_series='lucid', language='en', pages=1):
381+ distro_series='lucid', language='en', version='1.0', pages=1):
382 package = self.factory.makeSoftwareItem(package_name)
383 repository = self.factory.makeRepository(
384 origin=origin, distro_series=distro_series)
385@@ -201,8 +202,9 @@
386 reviews = []
387 for review_num in range(pages * 2):
388 reviews.append(
389- self.factory.makeReview(software_item=package, language=language,
390- repository=repository))
391+ self.factory.makeReview(software_item=package,
392+ language=language, repository=repository,
393+ version=version))
394
395 # Now ensure the cache is populated by requesting each url.
396 self._request_reviews_for_package(package_name)
397
398=== modified file 'src/reviewsapp/utilities.py'
399--- src/reviewsapp/utilities.py 2011-01-12 18:50:58 +0000
400+++ src/reviewsapp/utilities.py 2011-01-19 19:59:08 +0000
401@@ -166,11 +166,18 @@
402
403
404 def invalidate_paginated_reviews_for(review):
405+ # XXX achuni 2011-01-19: Here we're invalidating pages only for the exact
406+ # version, language, distroseries and origin of the review. We'd also
407+ # need to invalidate partial matches, up to including all reviews
408+ # for the package (/reviews/any/any/any/any/packagename/). This is
409+ # a lot of work. Is it worth it?
410 language = review.language
411 origin = review.repository.origin
412 distroseries = review.repository.distroseries
413 package_name = review.softwareitem.package_name
414 app_name = review.softwareitem.app_name
415+ version = review.version
416+
417 if app_name:
418 package_app_name = "{0};{1}".format(package_name, app_name)
419 else:
420@@ -180,7 +187,8 @@
421 repository__origin=origin, repository__distroseries=distroseries,
422 softwareitem__package_name=package_name,
423 softwareitem__app_name=app_name, hide=False,
424- language=language).count()
425+ language=language,
426+ version=version).count()
427
428 # Ensure we've got a list of all the possible page numbers,
429 # including None (ie. first page is displayed if there is no page
430@@ -190,7 +198,7 @@
431 for page in pages:
432 url_kwargs = dict(
433 language=language, origin=origin, distroseries=distroseries,
434- package_name=urllib.quote_plus(package_app_name))
435+ version=version, package_name=urllib.quote_plus(package_app_name))
436 if page:
437 url_kwargs['page'] = page
438

Subscribers

People subscribed via source and target branches