Merge lp:~elopio/cloudspacesclient/cloudspacer into lp:cloudspacesclient
- cloudspacer
- Merge into trunk
Proposed by
Leo Arias
Status: | Merged |
---|---|
Merged at revision: | 30 |
Proposed branch: | lp:~elopio/cloudspacesclient/cloudspacer |
Merge into: | lp:cloudspacesclient |
Prerequisite: | lp:~elopio/cloudspacesclient/expected_state_verification |
Diff against target: |
622 lines (+81/-297) 7 files modified
src/cloudspacesclient/__init__.py (+0/-7) src/cloudspacesclient/client.py (+0/-104) src/cloudspacesclient/tests/conformance/test_cloudspaces_api.py (+18/-17) src/cloudspacesclient/tests/unit/test_client.py (+0/-124) src/cloudspacesclient/tests/unit/test_schemas.py (+20/-4) src/cloudspacesclient/tests/unit/test_ubuntuone.py (+31/-27) src/cloudspacesclient/ubuntuone.py (+12/-14) |
To merge this branch: | bzr merge lp:~elopio/cloudspacesclient/cloudspacer |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Richard Huddie (community) | Approve | ||
Review via email:
|
This proposal supersedes a proposal from 2013-11-29.
Commit message
Use cloudspacer as the client.
Description of the change
This branch ports the code to python3-only.
It requires a small fix in ssoclient to work with python3, so please don't merge it yet.
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/cloudspacesclient/__init__.py' |
2 | --- src/cloudspacesclient/__init__.py 2013-11-20 05:06:14 +0000 |
3 | +++ src/cloudspacesclient/__init__.py 2013-12-03 14:19:38 +0000 |
4 | @@ -14,10 +14,3 @@ |
5 | # |
6 | # You should have received a copy of the GNU General Public License |
7 | # along with cloudspacesclient. If not, see <http://www.gnu.org/licenses/>. |
8 | - |
9 | -__all__ = [ |
10 | - 'APIException', |
11 | - 'CloudspacesAPIClient' |
12 | -] |
13 | - |
14 | -from client import APIException, CloudspacesAPIClient |
15 | |
16 | === removed file 'src/cloudspacesclient/client.py' |
17 | --- src/cloudspacesclient/client.py 2013-11-28 11:37:30 +0000 |
18 | +++ src/cloudspacesclient/client.py 1970-01-01 00:00:00 +0000 |
19 | @@ -1,104 +0,0 @@ |
20 | -# Copyright (C) 2013 Canonical Ltd. |
21 | -# |
22 | -# This file is part of cloudspacesclient. |
23 | -# |
24 | -# cloudspacesclient is free software: you can redistribute it and/or modify |
25 | -# it under the terms of the GNU General Public License as published by |
26 | -# the Free Software Foundation, either version 3 of the License, or |
27 | -# (at your option) any later version. |
28 | -# |
29 | -# cloudspacesclient is distributed in the hope that it will be useful, |
30 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
31 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
32 | -# GNU General Public License for more details. |
33 | -# |
34 | -# You should have received a copy of the GNU General Public License |
35 | -# along with cloudspacesclient. If not, see <http://www.gnu.org/licenses/>. |
36 | - |
37 | -"""Cloudspaces API client library.""" |
38 | - |
39 | -import json |
40 | -import urlparse |
41 | -import requests |
42 | -import json |
43 | - |
44 | -JSON_MIME_TYPE = 'application/json' |
45 | - |
46 | - |
47 | -class APIException(Exception): |
48 | - """Exception raised when there is an error calling the Cloudspaces API.""" |
49 | - |
50 | - |
51 | -class CloudspacesAPIClient(object): |
52 | - |
53 | - content_type = JSON_MIME_TYPE |
54 | - |
55 | - def __init__(self, service_root_url, auth): |
56 | - super(CloudspacesAPIClient, self).__init__() |
57 | - self.service_root_url = service_root_url |
58 | - self.auth = auth |
59 | - |
60 | - def get_user_representation(self): |
61 | - """Return the representation of the currently authorized user.""" |
62 | - response = requests.get( |
63 | - self.service_root_url, auth=self.auth, headers=self._get_headers()) |
64 | - if not response.ok: |
65 | - raise APIException( |
66 | - "{0}: {1}".format(response.status_code, response.reason)) |
67 | - return response.json() |
68 | - |
69 | - def _get_headers(self): |
70 | - return { |
71 | - 'Content-Type': self.content_type, |
72 | - 'Accept': self.content_type |
73 | - } |
74 | - |
75 | - def create_folder(self, folder_name, parent_node_id=""): |
76 | - """Create a folder with the name folder_name |
77 | - :parameter folder_name: the name of the folder to create |
78 | - :parameter parent_node_id: the id of the parent folder |
79 | - """ |
80 | - params = {'folder_name': folder_name, 'parent_node_id': parent_node_id} |
81 | - # convert parameters to json string |
82 | - json_params = json.dumps(params) |
83 | - url = urlparse.urljoin(self.service_root_url, 'metadata/') |
84 | - # send the post request |
85 | - response = requests.post( |
86 | - url, data=json_params, auth=self.auth, headers=self._get_headers()) |
87 | - if not response.ok: |
88 | - raise APIException( |
89 | - "{0}: {1}".format(response.status_code, response.reason)) |
90 | - return response.json() |
91 | - |
92 | - def get_metadata(self, node_id): |
93 | - """Return the metadata for a file or folder. |
94 | - |
95 | - :parameter node_id: the id of a file or folder. |
96 | - |
97 | - """ |
98 | - url = urlparse.urljoin( |
99 | - self.service_root_url, 'metadata/{}'.format(node_id)) |
100 | - response = requests.get( |
101 | - url, auth=self.auth, headers=self._get_headers()) |
102 | - if not response.ok: |
103 | - raise APIException( |
104 | - "{0}: {1}".format(response.status_code, response.reason)) |
105 | - return response.json() |
106 | - |
107 | - def create_file(self, file_name, folder_node_id=''): |
108 | - """Create a new file. |
109 | - |
110 | - :parameter file_name: the name of the file to create. |
111 | - :parameter folder_node_id: the id of the folder where the file will be |
112 | - created. The default value creates the file on the root node. |
113 | - |
114 | - """ |
115 | - url = urlparse.urljoin( |
116 | - self.service_root_url, 'content/{}'.format(folder_node_id)) |
117 | - response = requests.post( |
118 | - url, auth=self.auth, headers=self._get_headers(), |
119 | - data=json.dumps({'file_name': file_name})) |
120 | - if not response.ok: |
121 | - raise APIException( |
122 | - "{0}: {1}".format(response.status_code, response.reason)) |
123 | - return response.json() |
124 | |
125 | === modified file 'src/cloudspacesclient/tests/conformance/test_cloudspaces_api.py' |
126 | --- src/cloudspacesclient/tests/conformance/test_cloudspaces_api.py 2013-11-29 09:37:48 +0000 |
127 | +++ src/cloudspacesclient/tests/conformance/test_cloudspaces_api.py 2013-12-03 14:19:38 +0000 |
128 | @@ -19,13 +19,14 @@ |
129 | |
130 | import os |
131 | import unittest |
132 | -import urlparse |
133 | +import urllib.parse |
134 | from datetime import datetime |
135 | |
136 | import validictory |
137 | +import cloudspacer.cooked |
138 | from dateutil import parser, tz |
139 | |
140 | -from cloudspacesclient import client, config, schemas, ubuntuone |
141 | +from cloudspacesclient import config, schemas, ubuntuone |
142 | |
143 | |
144 | class CloudspacesAPITestCase(unittest.TestCase): |
145 | @@ -42,13 +43,13 @@ |
146 | self.test_user = self.test_server.create_test_user() |
147 | self.addCleanup(self.test_server.delete_test_user, self.test_user) |
148 | |
149 | - auth = self.test_server.get_auth_credentials(self.test_user) |
150 | - self.service_root = urlparse.urljoin( |
151 | + auth_session = self.test_server.get_auth_session(self.test_user) |
152 | + self.service_root = urllib.parse.urljoin( |
153 | self.cloudspaces_server_url, 'api/cloudspaces/') |
154 | # TODO the client class should be defined in a config file, to make |
155 | # it easy to test different Cloudspaces clients. |
156 | - self.cloudspaces_api_client = client.CloudspacesAPIClient( |
157 | - self.service_root, auth) |
158 | + self.cloudspaces_api_client = cloudspacer.cooked.CloudSpacer( |
159 | + self.service_root, auth_session) |
160 | |
161 | def _get_now_datetime(self): |
162 | now = datetime.now(tz.tzutc()) |
163 | @@ -92,7 +93,7 @@ |
164 | self._assert_resource_path(node_id, resource_path) |
165 | |
166 | def _assert_resource_path(self, node_id, resource_path): |
167 | - path = urlparse.urlparse(self.service_root).path |
168 | + path = urllib.parse.urlparse(self.service_root).path |
169 | self.assertEqual( |
170 | resource_path, '{0}metadata/{1}'.format(path, node_id)) |
171 | |
172 | @@ -160,7 +161,7 @@ |
173 | "The root folder shouldn't include the {} key".format(key)) |
174 | |
175 | def _assert_content_path(self, node_id, content_path): |
176 | - path = urlparse.urlparse(self.service_root).path |
177 | + path = urllib.parse.urlparse(self.service_root).path |
178 | self.assertEqual( |
179 | content_path, '{0}content/{1}'.format(path, node_id)) |
180 | |
181 | @@ -170,8 +171,8 @@ |
182 | # create the folder |
183 | folder_name = 'root_folder_1' |
184 | |
185 | - metadata = self.cloudspaces_api_client.create_folder( |
186 | - folder_name, root_node_id) |
187 | + metadata = self.cloudspaces_api_client.make_folder( |
188 | + root_node_id, folder_name) |
189 | # validate the folder properties from response |
190 | validictory.validate( |
191 | metadata, schemas.GET_FOLDER_METADATA_RESPONSE_SCHEMA) |
192 | @@ -188,7 +189,7 @@ |
193 | # this should add folder to root level by default |
194 | folder_name = 'folder_no_parent_id' |
195 | |
196 | - metadata = self.cloudspaces_api_client.create_folder(folder_name) |
197 | + metadata = self.cloudspaces_api_client.make_folder("", folder_name) |
198 | # validate the folder properties from response |
199 | validictory.validate( |
200 | metadata, schemas.GET_FOLDER_METADATA_RESPONSE_SCHEMA) |
201 | @@ -203,15 +204,15 @@ |
202 | root_node_id, root_name = self._get_root_info() |
203 | parent_folder_name = 'parent_folder_1' |
204 | # create the parent folder |
205 | - parent_metadata = self.cloudspaces_api_client.create_folder( |
206 | - parent_folder_name, root_node_id) |
207 | + parent_metadata = self.cloudspaces_api_client.make_folder( |
208 | + root_node_id, parent_folder_name) |
209 | # Now create a sub folder under the parent folder |
210 | child_folder_name = 'child_folder_1' |
211 | parent_node_id = parent_metadata.get('node_id') |
212 | child_folder_path = '{0}/{1}'.format(root_name, parent_folder_name) |
213 | |
214 | - metadata = self.cloudspaces_api_client.create_folder( |
215 | - child_folder_name, parent_node_id) |
216 | + metadata = self.cloudspaces_api_client.make_folder( |
217 | + parent_node_id, child_folder_name) |
218 | # validate the sub-folder properties from response |
219 | validictory.validate( |
220 | metadata, schemas.GET_FOLDER_METADATA_RESPONSE_SCHEMA) |
221 | @@ -226,8 +227,8 @@ |
222 | test_file_name = 'test.txt' |
223 | test_file_mimetype = 'text/plain' |
224 | |
225 | - metadata = self.cloudspaces_api_client.create_file( |
226 | - test_file_name, root_node_id) |
227 | + metadata = self.cloudspaces_api_client.make_file( |
228 | + root_node_id, test_file_name) |
229 | |
230 | validictory.validate( |
231 | metadata, schemas.GET_FILE_METADATA_RESPONSE_SCHEMA) |
232 | |
233 | === removed file 'src/cloudspacesclient/tests/unit/test_client.py' |
234 | --- src/cloudspacesclient/tests/unit/test_client.py 2013-11-27 06:14:16 +0000 |
235 | +++ src/cloudspacesclient/tests/unit/test_client.py 1970-01-01 00:00:00 +0000 |
236 | @@ -1,124 +0,0 @@ |
237 | -# Copyright (C) 2013 Canonical Ltd. |
238 | -# |
239 | -# This file is part of cloudspacesclient. |
240 | -# |
241 | -# cloudspacesclient is free software: you can redistribute it and/or modify |
242 | -# it under the terms of the GNU General Public License as published by |
243 | -# the Free Software Foundation, either version 3 of the License, or |
244 | -# (at your option) any later version. |
245 | -# |
246 | -# cloudspacesclient is distributed in the hope that it will be useful, |
247 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
248 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
249 | -# GNU General Public License for more details. |
250 | -# |
251 | -# You should have received a copy of the GNU General Public License |
252 | -# along with cloudspacesclient. If not, see <http://www.gnu.org/licenses/>. |
253 | - |
254 | -"""Unit tests for the Cloudspaces API client.""" |
255 | - |
256 | -import json |
257 | -import unittest |
258 | - |
259 | -import mock |
260 | - |
261 | -import cloudspacesclient |
262 | -from cloudspacesclient.tests.unit import utils |
263 | - |
264 | -import testscenarios |
265 | - |
266 | - |
267 | -# List of API Methods, each item is a tuple with the method name, the request |
268 | -# type and the list of required arguments. |
269 | -_API_METHODS = [ |
270 | - ('get_user_representation', 'get', []), |
271 | - ('get_metadata', 'get', ['dummynodeid']), |
272 | - ('create_file', 'post', ['dummyfilename']) |
273 | -] |
274 | - |
275 | - |
276 | -class CloudspacesAPIClientResponseTestCase( |
277 | - testscenarios.TestWithScenarios): |
278 | - |
279 | - def setUp(self): |
280 | - super(CloudspacesAPIClientResponseTestCase, self).setUp() |
281 | - self.api_client = cloudspacesclient.CloudspacesAPIClient( |
282 | - 'dummy url', 'dummy auth') |
283 | - |
284 | - scenarios = [ |
285 | - (api_method, dict( |
286 | - api_method=api_method, request_type=request_type, args=args)) |
287 | - for (api_method, request_type, args) in _API_METHODS |
288 | - ] |
289 | - |
290 | - def test_call_api_method_should_return_json(self): |
291 | - with mock.patch('requests.' + self.request_type) as request_mock: |
292 | - request_mock.return_value = utils.RequestResponseMock( |
293 | - ok=True, content=json.dumps("{'test': 'content'}")) |
294 | - response = getattr(self.api_client, self.api_method)(*self.args) |
295 | - |
296 | - self.assertEqual(response, "{'test': 'content'}") |
297 | - |
298 | - def test_call_api_method_failure_should_raise_exception(self): |
299 | - with mock.patch('requests.' + self.request_type) as request_mock: |
300 | - request_mock.return_value = utils.RequestResponseMock( |
301 | - ok=False, status_code='test error code', reason='test reason') |
302 | - with self.assertRaises(cloudspacesclient.APIException) as e: |
303 | - getattr(self.api_client, self.api_method)(*self.args) |
304 | - |
305 | - self.assertEqual(str(e.exception), 'test error code: test reason') |
306 | - |
307 | - |
308 | -class CloudspacesAPIClientTestCase(unittest.TestCase): |
309 | - |
310 | - def setUp(self): |
311 | - super(CloudspacesAPIClientTestCase, self).setUp() |
312 | - self.api_client = cloudspacesclient.CloudspacesAPIClient( |
313 | - 'http://example.com/cloudspaces/', 'test auth') |
314 | - self.request_headers = { |
315 | - 'Content-Type': 'application/json', |
316 | - 'Accept': 'application/json' |
317 | - } |
318 | - |
319 | - def test_get_user_representation_request(self): |
320 | - with mock.patch('requests.get') as get_mock: |
321 | - get_mock.return_value = utils.RequestResponseMock( |
322 | - ok=True, content=json.dumps("{'test': 'content'}")) |
323 | - self.api_client.get_user_representation() |
324 | - |
325 | - get_mock.assert_called_once_with( |
326 | - 'http://example.com/cloudspaces/', auth='test auth', |
327 | - headers=self.request_headers) |
328 | - |
329 | - def test_get_metadata_request(self): |
330 | - with mock.patch('requests.get') as get_mock: |
331 | - get_mock.return_value = utils.RequestResponseMock( |
332 | - ok=True, content=json.dumps("{'test': 'content'}")) |
333 | - self.api_client.get_metadata('testnodeid') |
334 | - |
335 | - get_mock.assert_called_once_with( |
336 | - 'http://example.com/cloudspaces/metadata/testnodeid', |
337 | - auth='test auth', headers=self.request_headers) |
338 | - |
339 | - def test_create_file_with_folder_id(self): |
340 | - with mock.patch('requests.post') as post_mock: |
341 | - post_mock.return_value = utils.RequestResponseMock( |
342 | - ok=True, content=json.dumps("{'test': 'content'}")) |
343 | - self.api_client.create_file( |
344 | - 'test file.txt', folder_node_id='testfoldernodeid') |
345 | - |
346 | - post_mock.assert_called_once_with( |
347 | - 'http://example.com/cloudspaces/content/testfoldernodeid', |
348 | - auth='test auth', headers=self.request_headers, |
349 | - data=json.dumps({'file_name': 'test file.txt'})) |
350 | - |
351 | - def test_create_file_without_folder_id(self): |
352 | - with mock.patch('requests.post') as post_mock: |
353 | - post_mock.return_value = utils.RequestResponseMock( |
354 | - ok=True, content=json.dumps("{'test': 'content'}")) |
355 | - self.api_client.create_file('test file.txt') |
356 | - |
357 | - post_mock.assert_called_once_with( |
358 | - 'http://example.com/cloudspaces/content/', |
359 | - auth='test auth', headers=self.request_headers, |
360 | - data=json.dumps({'file_name': 'test file.txt'})) |
361 | |
362 | === modified file 'src/cloudspacesclient/tests/unit/test_schemas.py' |
363 | --- src/cloudspacesclient/tests/unit/test_schemas.py 2013-11-27 15:47:59 +0000 |
364 | +++ src/cloudspacesclient/tests/unit/test_schemas.py 2013-12-03 14:19:38 +0000 |
365 | @@ -22,6 +22,7 @@ |
366 | |
367 | import testscenarios |
368 | import validictory |
369 | +from validictory import validator |
370 | |
371 | from cloudspacesclient import schemas |
372 | |
373 | @@ -183,12 +184,14 @@ |
374 | |
375 | class ResponseSchemaTestCase(unittest.TestCase): |
376 | |
377 | - def assert_raises_validation_error(self, json, schema): |
378 | + def assert_raises_validation_error( |
379 | + self, json, schema, validator_cls=validator.SchemaValidator): |
380 | self.assertRaises( |
381 | validictory.ValidationError, |
382 | validictory.validate, |
383 | json, |
384 | - schema |
385 | + schema, |
386 | + validator_cls=validator_cls |
387 | ) |
388 | |
389 | |
390 | @@ -258,6 +261,12 @@ |
391 | return wrong_types |
392 | |
393 | |
394 | +class _SchemaValidatorWithoutFormatValidation(validator.SchemaValidator): |
395 | + |
396 | + def register_format_validator(self, format_name, format_validator_fun): |
397 | + pass |
398 | + |
399 | + |
400 | class WrongPropertiesValuesTestCase( |
401 | testscenarios.TestWithScenarios, ResponseSchemaTestCase): |
402 | |
403 | @@ -270,7 +279,7 @@ |
404 | value=wrong_value)) |
405 | for object_ in _OBJECTS |
406 | for property_, types in ( |
407 | - object_.get('required_properties').items() + |
408 | + object_.get('required_properties').items() | |
409 | object_.get('optional_properties').items() |
410 | ) |
411 | for wrong_type, wrong_value in _get_wrong_types(types).items() |
412 | @@ -282,7 +291,14 @@ |
413 | |
414 | def test_json_with_wrong_property_value(self): |
415 | self.json[self.property_] = self.value |
416 | - self.assert_raises_validation_error(self.json, self.schema) |
417 | + # XXX We use a validator without format validation because sometimes |
418 | + # python will change the order of the schema and validictory will check |
419 | + # the format before the type, raising the wrong error. |
420 | + # Bug reported: https://github.com/sunlightlabs/validictory/issues/64 |
421 | + # We should change to the default validator once the bug is fixed. |
422 | + # --elopio - 2013-11-29 |
423 | + self.assert_raises_validation_error( |
424 | + self.json, self.schema, _SchemaValidatorWithoutFormatValidation) |
425 | |
426 | |
427 | class ObjectExtraPropertiesTestCase( |
428 | |
429 | === modified file 'src/cloudspacesclient/tests/unit/test_ubuntuone.py' |
430 | --- src/cloudspacesclient/tests/unit/test_ubuntuone.py 2013-11-20 05:06:14 +0000 |
431 | +++ src/cloudspacesclient/tests/unit/test_ubuntuone.py 2013-12-03 14:19:38 +0000 |
432 | @@ -17,7 +17,6 @@ |
433 | |
434 | """Unit tests for the Ubuntu One server adapter for Cloudspaces tests.""" |
435 | |
436 | -import contextlib |
437 | import unittest |
438 | |
439 | import mock |
440 | @@ -119,7 +118,7 @@ |
441 | 'Failed to register SSO user. ' + str(sso_exception)) |
442 | self.assertFalse(self.server.create_u1_user_mock.called) |
443 | |
444 | - def test_get_auth_credentials_should_return_oauth1(self): |
445 | + def test_get_auth_session_should_return_oauth1session(self): |
446 | self.server.sso_login_mock.return_value = { |
447 | 'consumer_key': 'test consumer key', |
448 | 'consumer_secret': 'test consumer secret', |
449 | @@ -128,7 +127,7 @@ |
450 | } |
451 | user = ubuntuone.User.make_unique(unique_id='id') |
452 | |
453 | - auth = self.server.get_auth_credentials(user) |
454 | + session = self.server.get_auth_session(user) |
455 | |
456 | self.server.sso_login_mock.assert_called_once_with( |
457 | { |
458 | @@ -137,26 +136,28 @@ |
459 | 'token_name': 'Cloudspaces API test', |
460 | } |
461 | ) |
462 | - self.assertIsInstance(auth, requests_oauthlib.OAuth1) |
463 | - self.assertEqual(auth.client.client_key, 'test consumer key') |
464 | - self.assertEqual(auth.client.client_secret, 'test consumer secret') |
465 | - self.assertEqual(auth.client.resource_owner_key, 'test token key') |
466 | - self.assertEqual( |
467 | - auth.client.resource_owner_secret, 'test token secret') |
468 | + self.assertIsInstance(session, requests_oauthlib.OAuth1Session) |
469 | + self.assertEqual( |
470 | + session._client.client.client_key, 'test consumer key') |
471 | + self.assertEqual( |
472 | + session._client.client.client_secret, 'test consumer secret') |
473 | + self.assertEqual( |
474 | + session._client.client.resource_owner_key, 'test token key') |
475 | + self.assertEqual( |
476 | + session._client.client.resource_owner_secret, 'test token secret') |
477 | |
478 | def test_get_u1_api_client(self): |
479 | - with contextlib.nested( |
480 | - mock.patch('cloudspacesclient.config.get'), |
481 | - mock.patch.object(self.server, 'get_auth_credentials') |
482 | - ) as (config_mock, credentials_mock): |
483 | - config_mock.return_value = 'http://example.com' |
484 | - credentials_mock.return_value = 'test credentials' |
485 | - client = self.server._get_u1_api_client('dummy user') |
486 | + with mock.patch('cloudspacesclient.config.get') as config_mock: |
487 | + with mock.patch.object( |
488 | + self.server, 'get_auth_session') as session_mock: |
489 | + config_mock.return_value = 'http://example.com' |
490 | + session_mock.return_value = 'test session' |
491 | + client = self.server._get_u1_api_client('dummy user') |
492 | |
493 | self.assertIsInstance(client, ubuntuone.UbuntuOneAPIClient) |
494 | self.assertEqual( |
495 | client.service_root_url, 'http://example.com/api/') |
496 | - self.assertEqual(client.auth, 'test credentials') |
497 | + self.assertEqual(client.session, 'test session') |
498 | |
499 | def test_create_test_user_should_create_user_in_u1(self): |
500 | self.server.create_test_user() |
501 | @@ -178,25 +179,28 @@ |
502 | |
503 | def setUp(self): |
504 | super(UbuntuOneAPITestCase, self).setUp() |
505 | + self.session_mock = mock.Mock() |
506 | self.api_client = ubuntuone.UbuntuOneAPIClient( |
507 | - 'dummy url', 'dummy auth') |
508 | + 'dummy url', self.session_mock) |
509 | |
510 | def test_get_account_info_should_return_request(self): |
511 | - with mock.patch('requests.get') as get_mock: |
512 | - get_mock.return_value = utils.RequestResponseMock( |
513 | - ok=True, status_code=200, content='test content') |
514 | - response = self.api_client.get_account_info() |
515 | + mock_attributes = {'get.return_value': utils.RequestResponseMock( |
516 | + ok=True, status_code=200, content='test content') |
517 | + } |
518 | + self.session_mock.configure_mock(**mock_attributes) |
519 | + response = self.api_client.get_account_info() |
520 | |
521 | self.assertTrue(response.ok) |
522 | self.assertEqual(response.status_code, 200) |
523 | self.assertEqual(response.content, 'test content') |
524 | |
525 | def test_get_account_info_failure(self): |
526 | - with mock.patch('requests.get') as get_mock: |
527 | - get_mock.return_value = utils.RequestResponseMock( |
528 | - ok=False, status_code='test error code', reason='test reason') |
529 | - with self.assertRaises(ubuntuone.APIException) as e: |
530 | - self.api_client.get_account_info() |
531 | + mock_attributes = {'get.return_value': utils.RequestResponseMock( |
532 | + ok=False, status_code='test error code', reason='test reason') |
533 | + } |
534 | + self.session_mock.configure_mock(**mock_attributes) |
535 | + with self.assertRaises(ubuntuone.APIException) as e: |
536 | + self.api_client.get_account_info() |
537 | |
538 | self.assertEqual(str(e.exception), 'test error code: test reason') |
539 | |
540 | |
541 | === modified file 'src/cloudspacesclient/ubuntuone.py' |
542 | --- src/cloudspacesclient/ubuntuone.py 2013-11-26 16:13:41 +0000 |
543 | +++ src/cloudspacesclient/ubuntuone.py 2013-12-03 14:19:38 +0000 |
544 | @@ -17,10 +17,9 @@ |
545 | |
546 | """Ubuntu One server adapter for Cloudspaces tests.""" |
547 | |
548 | -import urlparse |
549 | +import urllib.parse |
550 | import uuid |
551 | |
552 | -import requests |
553 | import requests_oauthlib |
554 | import ssoclient.v2 |
555 | |
556 | @@ -89,7 +88,7 @@ |
557 | |
558 | def _get_sso_api_client(self): |
559 | return ssoclient.v2.V2ApiClient( |
560 | - urlparse.urljoin(self._get_sso_server_url(), 'api/v2')) |
561 | + urllib.parse.urljoin(self._get_sso_server_url(), 'api/v2')) |
562 | |
563 | def _get_sso_server_url(self): |
564 | return config.get('ubuntuone', 'sso_server_url') |
565 | @@ -102,9 +101,9 @@ |
566 | 'Failed to create U1 user. ' + str(e)) |
567 | |
568 | def _get_u1_api_client(self, user): |
569 | - url = urlparse.urljoin(self._get_ubuntuone_server_url(), 'api/') |
570 | - auth = self.get_auth_credentials(user) |
571 | - return UbuntuOneAPIClient(url, auth) |
572 | + url = urllib.parse.urljoin(self._get_ubuntuone_server_url(), 'api/') |
573 | + auth_session = self.get_auth_session(user) |
574 | + return UbuntuOneAPIClient(url, auth_session) |
575 | |
576 | def _get_ubuntuone_server_url(self): |
577 | return config.get('ubuntuone', 'ubuntuone_server_url') |
578 | @@ -113,8 +112,8 @@ |
579 | # Currently we can't delete users from U1 and SSO. |
580 | pass |
581 | |
582 | - def get_auth_credentials(self, user): |
583 | - """Return the auth credentials to sign the Cloudspaces API requests. |
584 | + def get_auth_session(self, user): |
585 | + """Return the auth session to sign the Cloudspaces API requests. |
586 | |
587 | :parameter user: An object with the user information. |
588 | |
589 | @@ -124,7 +123,7 @@ |
590 | password=user.password, |
591 | token_name='Cloudspaces API test') |
592 | response = self._get_sso_api_client().login(data) |
593 | - return requests_oauthlib.OAuth1( |
594 | + return requests_oauthlib.OAuth1Session( |
595 | response.get('consumer_key'), response.get('consumer_secret'), |
596 | response.get('token_key'), response.get('token_secret')) |
597 | |
598 | @@ -141,10 +140,10 @@ |
599 | |
600 | content_type = JSON_MIME_TYPE |
601 | |
602 | - def __init__(self, service_root_url, auth): |
603 | + def __init__(self, service_root_url, session): |
604 | super(UbuntuOneAPIClient, self).__init__() |
605 | self.service_root_url = service_root_url |
606 | - self.auth = auth |
607 | + self.session = session |
608 | |
609 | def create_user(self): |
610 | """Create the authenticated user in Ubuntu One, if it doesn't exist.""" |
611 | @@ -153,9 +152,8 @@ |
612 | |
613 | def get_account_info(self): |
614 | """Get the account information of the authenticated user.""" |
615 | - url = urlparse.urljoin(self.service_root_url, 'account/') |
616 | - response = requests.get( |
617 | - url, auth=self.auth, headers=self._get_headers()) |
618 | + url = urllib.parse.urljoin(self.service_root_url, 'account/') |
619 | + response = self.session.get(url, headers=self._get_headers()) |
620 | if not response.ok: |
621 | raise APIException( |
622 | "{0}: {1}".format(response.status_code, response.reason)) |
Approved