Merge lp:~zematynnad/rnr-server/api_check_856808 into lp:rnr-server

Proposed by Danny Tamez
Status: Merged
Approved by: Anthony Lenton
Approved revision: 220
Merged at revision: 218
Proposed branch: lp:~zematynnad/rnr-server/api_check_856808
Merge into: lp:rnr-server
Diff against target: 203 lines (+57/-61)
4 files modified
.bzrignore (+2/-1)
fabtasks/bootstrap.py (+8/-1)
src/reviewsapp/tests/test_utilities.py (+32/-24)
src/reviewsapp/utilities.py (+15/-35)
To merge this branch: bzr merge lp:~zematynnad/rnr-server/api_check_856808
Reviewer Review Type Date Requested Status
Michael Nelson (community) Approve
Review via email: mp+100028@code.launchpad.net

Commit message

Now calling sca's piston API for published apps.

Description of the change

Overview
=========
This branch switches to using SCA's piston api for retrieving applications.

Details
========
Now that SCA has this API available there is no need to call the view we were calling before. get_sca_publishings_for now calls api/2.0/applications/en/ubuntu/<distro>/<arch>/

To Test
========
$fab bootstrap test

To post a comment you must log in.
Revision history for this message
Michael Nelson (michael.nelson) wrote :

Looks fine Danny. I'm assuming you looked at whether it was worth using the actual piston mini-client and decided against it for this one call?

Sheesh - I just checked the scaclient, and it's also using the old view-based available apps:

http://bazaar.launchpad.net/~canonical-ca-hackers/software-center/scaclient/view/head:/scaclient.py

for all api calls :/

In which case, it might be best to (1) update the scaclient to use the 2.0 api for all calls (it's tested in test_scaclient.py in sca), and then (2) update rnr to use the sca client? I think (1) is necessary, (2) is just a matter of us dogfooding our own tools - feel free to ignore (2) and land this branch as is, but given that scaclient is what where giving others to use (such as USC) I think we should update it asap. What do you think?

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

Hi Danny!

Thanks for updating to use the sca client. I'm not sure how I missed above that the scaclient *is* using the /2.0/ api already - I must have missed the 'default_service_root' property.

Two things that might be worth considering with this branch - see what you think.

1) In utilities.py, you don't need to go through the whole _sca_service, _set_sca_service() before providing your sca property. It's used for lazr.restful clients which actually ping for wadl when they're instantiated. But in the case of the sca client, it's cheap to instantiate, so you can just have the sca property doing it directly without any cached service.

2) You wouldn't need your DictToObj conversion if you instead patched SoftwareCenterAgentAPI._get (or whatever it's underlying code is calling) with self.factory.get_test_file('software_center_apps.json') and let the piston-mini-client do the conversion for you.

See what you think. Happy to +1 the MP if you've got reasons against the above 2 points.

Revision history for this message
Danny Tamez (zematynnad) wrote :

As per our conversation on mumble - 1) no need to cache the service just use it directly as it's cheap. 2) instead of patching available_apps, patch httplib2.Http.request with a return value of ({'status': '200', <value of serialized json from file>) instead.

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

Thanks Danny - looks great. I can see why we'd no longer need the test_retrieved_url (as we'd be testing the sca client implementation), but I'm not sure why we'd remove test_get_sca_publishings_cached. If we did want to keep it, we could switch the @patch('httplib2.Http.request') into the setUp(), with:

{{{
def setUp(self):
   self.patcher = patch('httplib2.Http.request')
   self.mock_http_request = self.patcher.start()
   self.addCleanup(self.patcher.stop)
}}}

that way we could keep test_get_sca_publishings_cached, asserting that self.mock_http_request.call_count == 0... if we wanted to, but maybe there's a reason for removing the test. Anyway, I'm adding a +1 and you can see what you think.

review: Approve
Revision history for this message
Danny Tamez (zematynnad) wrote :

Combined the branch and the dependent branch into this one as there was much overlap in the comments on the two.

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

Two small things - see if you think they're worth changes, but +1 :)

1:

16:04 <noodles> Hey there! Should the assertion on line 121 alse be on line 117 (it looks like the
                previous code had a typo, which you've fixed, but we're only checking after the
                second call)
16:04 * zematynnad takes a look

2: I don't *think* you should need to make assumptions about the caching backend being used to mock it, we've got similar tests elsewhere that patch out the cache.get, but no biggie.

review: Approve
Revision history for this message
ISD Branch Mangler (isd-branches-mangler) wrote :

There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2011-10-06 13:08:27 +0000
3+++ .bzrignore 2012-04-11 16:37:30 +0000
4@@ -18,4 +18,5 @@
5 .virtualenvs
6 branches/*
7 virtualenv/*
8-sourcecode/*
9\ No newline at end of file
10+sourcecode/*
11+django_project/scaclient.py
12
13=== modified file 'fabtasks/bootstrap.py'
14--- fabtasks/bootstrap.py 2012-01-27 12:39:58 +0000
15+++ fabtasks/bootstrap.py 2012-04-11 16:37:30 +0000
16@@ -17,7 +17,7 @@
17 import os
18 import os.path
19
20-from fabric.api import local, cd
21+from fabric.api import local
22
23
24 def _get_or_pull_bzr_branch(repo, name):
25@@ -67,6 +67,13 @@
26 "branches/wsgi-oops/canonical",
27 "django_project/canonical")
28
29+ _get_or_pull_bzr_branch(
30+ "lp:~canonical-ca-hackers/software-center/scaclient",
31+ "scaclient")
32+ _symlink(
33+ "branches/scaclient/scaclient.py",
34+ "django_project/scaclient.py")
35+
36
37 def download_multi_mechanize():
38 multi_mechanize = "multi-mechanize_1.010.zip"
39
40=== modified file 'src/reviewsapp/tests/test_utilities.py'
41--- src/reviewsapp/tests/test_utilities.py 2012-01-25 16:18:35 +0000
42+++ src/reviewsapp/tests/test_utilities.py 2012-04-11 16:37:30 +0000
43@@ -45,8 +45,8 @@
44 from reviewsapp.utilities import (
45 cache_key_for_url,
46 invalidate_paginated_reviews_for,
47+ WebServices,
48 WebServiceError,
49- WebServices,
50 full_claimed_id,
51 )
52
53@@ -238,24 +238,28 @@
54
55 class SCATestCase(TestCaseWithFactory):
56
57+ @patch('httplib2.Http.request')
58 def _request_sca_pubs_for(self, distroseries, arch_tag,
59- disable_cache=True):
60- with patch('urllib.urlretrieve') as mock_urlretrieve:
61- mock_urlretrieve.return_value = (
62- self.factory.get_test_file('software_center_apps.json'), None)
63- if disable_cache:
64- with patch('django.core.cache') as mock_cache:
65- mock_cache.get.return_value = False
66- published_apps = WebServices().get_sca_publishings_for(
67- distroseries, arch_tag)
68- else:
69+ disable_cache, mock_request):
70+ data_file = self.factory.get_test_file('software_center_apps.json')
71+ with open(data_file) as test_data:
72+ data = test_data.read()
73+ mock_request.return_value = ({'status': '200'}, data)
74+
75+ if disable_cache:
76+ func = 'django.core.cache.cache.get'
77+ with patch(func) as mock_get:
78+ mock_get.return_value = False
79 published_apps = WebServices().get_sca_publishings_for(
80 distroseries, arch_tag)
81- return published_apps, mock_urlretrieve
82+ else:
83+ published_apps = WebServices().get_sca_publishings_for(
84+ distroseries, arch_tag)
85+ return published_apps, mock_request
86
87 def test_get_sca_publishings(self):
88- published_apps, ignored = self._request_sca_pubs_for(
89- 'maverick', 'i386')
90+ published_apps, _ = self._request_sca_pubs_for(
91+ 'maverick', 'i386', True)
92
93 self.assertEqual({
94 'lp-ppa-commercial-ppa-uploaders-brukkon': 'brukkon',
95@@ -272,19 +276,23 @@
96
97 def test_retrieved_url(self):
98 with patch_settings(SCA_HOST_URL='http://example.com/'):
99- ignored, mock_urlretrieve = self._request_sca_pubs_for(
100- 'natty', 'amd64')
101+ ignored, mock_request = self._request_sca_pubs_for(
102+ 'natty', 'amd64', True)
103
104- mock_urlretrieve.assert_called_with(
105- 'http://example.com/apps/en/ubuntu/natty/amd64/')
106+ mock_request.assert_called_with(
107+ 'http://example.com/api/2.0/applications/any/ubuntu/any/any/',
108+ body='', headers={}, method='GET')
109
110 def test_get_sca_publishings_cached(self):
111- published_apps, mock_url_retrieve = self._request_sca_pubs_for(
112- 'maverick', 'i386', disable_cache=False)
113- published_apps, mock_urlretrieve = self._request_sca_pubs_for(
114- 'maverick', 'i386', disable_cache=False)
115-
116- self.assertEqual(0, mock_urlretrieve.call_count)
117+ cache.clear()
118+ published_apps, mock_request = self._request_sca_pubs_for(
119+ 'maverick', 'i386', False)
120+ self.assertEqual(1, mock_request.call_count)
121+
122+ published_apps, mock_request = self._request_sca_pubs_for(
123+ 'natty', 'i386', False)
124+
125+ self.assertEqual(0, mock_request.call_count)
126
127 def _request_sca_verify(self, pkgname, origin, distroseries, arch_tag):
128 with patch('urllib.urlretrieve') as mock_urlretrieve:
129
130=== modified file 'src/reviewsapp/utilities.py'
131--- src/reviewsapp/utilities.py 2012-01-27 12:50:26 +0000
132+++ src/reviewsapp/utilities.py 2012-04-11 16:37:30 +0000
133@@ -37,7 +37,6 @@
134 from django.http import HttpRequest
135 from django.utils.cache import get_cache_key
136 from django.utils.http import urlquote_plus
137-from django.utils import simplejson
138
139 from launchpadlib.launchpad import Launchpad
140 from launchpadlib.uris import lookup_service_root
141@@ -46,6 +45,7 @@
142 from lazr.restfulclient.errors import HTTPError
143 from lazr.restfulclient.resource import ServiceRoot
144 from oauth.oauth import OAuthToken
145+from scaclient import SoftwareCenterAgentAPI
146
147
148 class WebServiceError(Exception):
149@@ -222,40 +222,20 @@
150 return False
151
152 def get_sca_publishings_for(self, distroseries, arch_tag):
153- """A helper that builds a dict of publishings for sca-sold apps.
154-
155- XXX michaeln 2011-03-14 bug=734747 Optional parms for available_apps.
156- It would be great if we could just pull /apps/en/ubuntu/ and use
157- each items 'series' dict to populate this, rather than pulling each
158- distroserie/arch separately. If we can assume that an app sold via
159- softwarecenter will always be available for maverick i386, then we
160- could do just the one call too.
161- """
162- cache_key = 'sca_{0}_{1}'.format(distroseries, arch_tag)
163- result = cache.get(cache_key)
164- if result is not None:
165- return result
166-
167- # XXX michaeln 2011-03-14 Update to use sca piston client.
168- # Once production SCA includes the piston client version we can
169- # use that instead. At time of writing the following url works
170- # on staging but not production sca:
171- # api/2.0/applications/en/ubuntu/maverick/i386/
172- filename, headers = urllib.urlretrieve(
173- settings.SCA_HOST_URL +
174- 'apps/en/ubuntu/{0}/{1}/'.format(distroseries, arch_tag))
175-
176- with open(filename, 'r') as sca_apps_file:
177- sca_apps = simplejson.load(sca_apps_file)
178-
179- # We ensure the keys match Launchpad's current (ambiguous)
180- # origin identifiers - Launchpad bug 733170.
181- app_names = dict([(
182- 'lp-ppa-' + app['archive_id'].replace('/', '-'),
183- app['package_name'],
184- ) for app in sca_apps])
185- cache.set(cache_key, app_names, settings.SCA_APPS_CACHE_TIMEOUT)
186- return app_names
187+ cache_key = 'sca_all_available'
188+ apps = cache.get(cache_key)
189+
190+ if not apps:
191+ api = SoftwareCenterAgentAPI(service_root="{0}api/2.0/"
192+ .format(settings.SCA_HOST_URL))
193+ apps = api.available_apps(lang='any', series='any', arch='any')
194+ cache.set(cache_key, apps, settings.SCA_APPS_CACHE_TIMEOUT)
195+
196+ return dict([(
197+ 'lp-ppa-' + app.archive_id.replace('/', '-'),
198+ app.package_name,
199+ ) for app in apps if distroseries in app.series and
200+ arch_tag in app.series[distroseries]])
201
202
203 def cache_key_for_url(url):

Subscribers

People subscribed via source and target branches