Merge lp:~cjohnston/uci-engine/cli-requests into lp:uci-engine

Proposed by Chris Johnston
Status: Merged
Approved by: Chris Johnston
Approved revision: 502
Merged at revision: 518
Proposed branch: lp:~cjohnston/uci-engine/cli-requests
Merge into: lp:uci-engine
Diff against target: 782 lines (+202/-160)
11 files modified
cli/ci_cli/image.py (+5/-4)
cli/ci_cli/status.py (+5/-4)
cli/ci_cli/tests/__init__.py (+43/-0)
cli/ci_cli/tests/test_cli.py (+56/-44)
cli/ci_cli/tests/test_get_ticket_status.py (+31/-31)
cli/ci_cli/tests/test_image.py (+22/-38)
cli/ci_cli/tests/test_utils.py (+13/-12)
cli/ci_cli/utils.py (+9/-14)
cli/setup.py (+1/-0)
cli/ubuntu-ci (+16/-13)
debian/control (+1/-0)
To merge this branch: bzr merge lp:~cjohnston/uci-engine/cli-requests
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Andy Doan (community) Approve
Chris Johnston (community) Needs Resubmitting
Review via email: mp+220960@code.launchpad.net

Commit message

Switch the CLI to use python-requests

Description of the change

Swiftclient is already using python-requests, and I think that using python-requests will make working with the gatekeeper easier so lets switch to using it for the CLI.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:499
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~cjohnston/uci-engine/cli-requests/+merge/220960/+edit-commit-message

http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/701/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/701/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:499
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/703/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/703/rebuild

review: Approve (continuous-integration)
Revision history for this message
Andy Doan (doanac) wrote :

nothing major, but 3 comments

500. By Chris Johnston

Remove double code block for exceptions

501. By Chris Johnston

Update test to call ConnectionError on socket.error

502. By Chris Johnston

More cleanup

Revision history for this message
Chris Johnston (cjohnston) :
review: Needs Resubmitting
Revision history for this message
Andy Doan (doanac) :
review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:502
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/706/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/706/rebuild

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'cli/ci_cli/image.py'
2--- cli/ci_cli/image.py 2014-05-07 14:56:11 +0000
3+++ cli/ci_cli/image.py 2014-05-27 09:44:30 +0000
4@@ -15,7 +15,8 @@
5
6 import os
7 import sys
8-import urllib2
9+
10+from requests import exceptions
11
12 from ci_cli import utils
13 from ci_utils import (
14@@ -41,11 +42,11 @@
15 url = artifact_base + '?type__exact=IMAGE&ticket__exact={}'.format(
16 ticket)
17 return utils.get(url)
18- except urllib2.HTTPError, exc:
19- if exc.code == 404 and ticket:
20+ except exceptions.HTTPError, exc:
21+ if exc.response.status_code == 404 and ticket:
22 sys.exit("Ticket number {} not found.".format(ticket))
23 raise
24- except urllib2.URLError, exc:
25+ except exceptions.ConnectionError, exc:
26 raise
27
28
29
30=== modified file 'cli/ci_cli/status.py'
31--- cli/ci_cli/status.py 2014-05-07 14:56:11 +0000
32+++ cli/ci_cli/status.py 2014-05-27 09:44:30 +0000
33@@ -14,7 +14,8 @@
34 # with this program. If not, see <http://www.gnu.org/licenses/>.
35
36 import sys
37-import urllib2
38+
39+from requests import exceptions
40
41 from ci_cli import utils
42
43@@ -27,11 +28,11 @@
44 else:
45 url = utils.CI_URL + utils.TICKET_BASE
46 data = utils.get(url)
47- except urllib2.HTTPError, exc:
48- if exc.code == 404 and args.ticket:
49+ except exceptions.HTTPError, exc:
50+ if exc.response.status_code == 404 and args.ticket:
51 sys.exit("Ticket number {} not found.".format(args.ticket))
52 raise
53- except urllib2.URLError, exc:
54+ except exceptions.ConnectionError, exc:
55 raise
56
57 if args.ticket:
58
59=== modified file 'cli/ci_cli/tests/__init__.py'
60--- cli/ci_cli/tests/__init__.py 2014-05-07 17:57:12 +0000
61+++ cli/ci_cli/tests/__init__.py 2014-05-27 09:44:30 +0000
62@@ -17,10 +17,13 @@
63 import imp
64 import os
65 import sys
66+import json
67
68 from cStringIO import StringIO
69 from contextlib import contextmanager
70
71+from requests import exceptions
72+
73 from ci_cli import utils
74 from ci_utils.testing import TestCaseWithGnupg
75
76@@ -54,6 +57,46 @@
77 utils.CI_URL = utils.AUTH_CONFIG['ci_url']
78
79
80+class FakeRequestsReturn:
81+ """Object to mock the return of python-requests return."""
82+
83+ def __init__(self, code, content, reason=None):
84+ self.status_code = code
85+ self.content = content
86+ self.reason = reason
87+
88+ def raise_for_status(self):
89+ if 400 == self.status_code:
90+ error = '%s Client Error: %s' % (self.status_code, self.reason)
91+ e = exceptions.ConnectionError(error)
92+ raise e
93+ elif 400 < self.status_code < 500:
94+ error = '%s Client Error: %s' % (self.status_code, self.reason)
95+ e = exceptions.HTTPError(error, response=self)
96+ raise e
97+ elif 500 <= self.status_code < 600:
98+ error = '%s Server Error: %s' % (self.status_code, self.reason)
99+ e = exceptions.HTTPError(error, response=self)
100+ raise e
101+ else:
102+ pass
103+
104+ def __repr__(self):
105+ return self.content
106+
107+ def __iter__(self):
108+ return (line for line in self.content.split("\n"))
109+
110+ def read(self):
111+ return self.content
112+
113+ def json(self):
114+ return json.loads(self.content)
115+
116+ def _status_code(self):
117+ pass
118+
119+
120 class MainScriptTestCase(TestCaseWithGnupg):
121 """Load the 'ubuntu-ci' script module for tests.
122
123
124=== modified file 'cli/ci_cli/tests/test_cli.py'
125--- cli/ci_cli/tests/test_cli.py 2014-05-12 15:49:28 +0000
126+++ cli/ci_cli/tests/test_cli.py 2014-05-27 09:44:30 +0000
127@@ -21,7 +21,6 @@
128 import mock
129 import socket
130 from testfixtures import LogCapture
131-import urllib2
132
133 from ci_cli import utils
134 from ci_cli.tests import (
135@@ -29,6 +28,7 @@
136 capture_stdout,
137 mock_load_config,
138 MainScriptTestCase,
139+ FakeRequestsReturn,
140 )
141 from ci_cli.ticket import new_ticket
142 from ci_utils.testing import get_test_file_path
143@@ -41,9 +41,10 @@
144 class CLICommandsTestCase(MainScriptTestCase):
145 """Tests cli basic commands."""
146
147- @mock.patch('urllib2.urlopen')
148+ @mock.patch('requests.get')
149 @mock.patch('ci_cli.utils.load_config', side_effect=mock_load_config())
150- def test_ticket_status_one_ticket(self, mock_load_config, mock_urlopen):
151+ def test_ticket_status_one_ticket(self, mock_load_config,
152+ mock_requests):
153 """Verify cli status command when providing ticket number."""
154 data = {
155 "current_workflow_step": str(TicketWorkflowStep.IMAGE_BUILDING),
156@@ -58,9 +59,9 @@
157 "added_binaries": "mynewpackage",
158 "removed_binaries": "myoldpackage",
159 }
160- resp = mock.Mock()
161- resp.read.return_value = json.dumps(data)
162- mock_urlopen.return_value = resp
163+ mock_requests.side_effect = [
164+ FakeRequestsReturn(200, json.dumps(data))
165+ ]
166 args = ['status', '-t', '5']
167 with capture_stdout(self.cli.main, args) as cm:
168 self.assertEquals(
169@@ -76,11 +77,11 @@
170 'Removed binaries: myoldpackage\n'.format(
171 str(TicketWorkflowStep.IMAGE_BUILDING),
172 str(TicketWorkflowStepStatus.INPROGRESS)))
173- mock_urlopen.assert_called_once()
174+ mock_requests.assert_called_once()
175
176- @mock.patch('urllib2.urlopen')
177+ @mock.patch('requests.get')
178 @mock.patch('ci_cli.utils.load_config', side_effect=mock_load_config())
179- def test_ticket_status_all_tickets(self, mock_load_config, mock_urlopen):
180+ def test_ticket_status_all_tickets(self, mock_load_config, mock_requests):
181 """Verify cli status command for multiple tickets."""
182 data = {
183 "objects": [
184@@ -98,16 +99,16 @@
185 },
186 ]
187 }
188- resp = mock.Mock()
189- resp.read.return_value = json.dumps(data)
190- mock_urlopen.return_value = resp
191+ mock_requests.side_effect = [
192+ FakeRequestsReturn(200, json.dumps(data))
193+ ]
194 args = ['status']
195 with capture_stdout(self.cli.main, args) as cm:
196 self.assertEquals(
197 cm,
198 "Ticket #5, My cool feature is 100 110\n" +
199 "Ticket #6, Ubuntu bug fix is 100 110\n")
200- mock_urlopen.assert_called_once()
201+ mock_requests.assert_called_once()
202
203 @mock.patch('ci_cli.ticket.SubTicket._process')
204 @mock.patch('ci_cli.utils.post',
205@@ -154,83 +155,94 @@
206 self.assertTrue("foobar" in new_ticket_.subtickets)
207 self.assertTrue("barfoo" in new_ticket_.subtickets)
208
209- @mock.patch('urllib2.urlopen')
210+ @mock.patch('requests.get')
211 @mock.patch('ci_cli.utils.load_config', side_effect=mock_load_config())
212- def test_ts_server_returns_urlerror(self, mock_load_config, mock_urlopen):
213+ def test_ts_server_returns_urlerror(self, mock_load_config, mock_requests):
214 """Test cli response to ts server refusing connection (111)."""
215- mock_urlopen.side_effect = urllib2.URLError(reason=socket.error(111,
216- "Connection refused"))
217+ mock_requests.side_effect = [
218+ FakeRequestsReturn(
219+ 400, '', socket.error(111, "Connection refused"))
220+ ]
221 args = ['status']
222 with LogCapture() as lc:
223 logger = logging.getLogger()
224 self.cli.main(args, log=logger)
225- mock_urlopen.assert_called_once()
226+ mock_requests.assert_called_once()
227 self.assertTrue("Cannot reach the server at %s." % utils.CI_URL in
228+ lc.records[0].msg, lc.records[0].msg)
229+ self.assertTrue("Connection refused" in lc.records[0].msg,
230 lc.records[0].msg)
231- self.assertTrue("Connection refused" in lc.records[0].msg)
232
233- @mock.patch('urllib2.urlopen')
234+ @mock.patch('requests.get')
235 @mock.patch('ci_cli.utils.load_config', side_effect=mock_load_config())
236 def test_ts_server_returns_internal_server_error(self, mock_load_config,
237- mock_urlopen):
238+ mock_requests):
239 """Test cli response to ts server returning error 500."""
240- mock_urlopen.side_effect = urllib2.HTTPError(None, 500,
241- "INTERNAL SERVER ERROR",
242- None, None)
243+ mock_requests.side_effect = [
244+ FakeRequestsReturn(
245+ 500, "", "INTERNAL SERVER ERROR"
246+ )
247+ ]
248 args = ['status']
249 with LogCapture() as lc:
250 logger = logging.getLogger()
251 self.cli.main(args, log=logger)
252- mock_urlopen.assert_called_once()
253+ mock_requests.assert_called_once()
254 self.assertEquals("Server at {} reported internal error. Maybe a "
255 "database hiccup?".format(utils.CI_URL),
256 lc.records[0].msg)
257
258- @mock.patch('urllib2.urlopen')
259+ @mock.patch('requests.get')
260 @mock.patch('ci_cli.utils.load_config', side_effect=mock_load_config())
261 def test_ts_server_returns_url_not_found(self, mock_load_config,
262- mock_urlopen):
263+ mock_requests):
264 """Test cli response to ts server returning 404 error."""
265- mock_urlopen.side_effect = urllib2.HTTPError(None, 404,
266- "Server Not Found",
267- None, None)
268+ mock_requests.side_effect = [
269+ FakeRequestsReturn(404, '', 'Not Found')
270+ ]
271 args = ['status']
272 with LogCapture() as lc:
273 logger = logging.getLogger()
274 self.cli.main(args, log=logger)
275- mock_urlopen.assert_called_once()
276- self.assertEquals("Server at {} not found. Is 'ci_url' correctly "
277- "set? (HTTP Error 404: Server Not Found)".format(
278- utils.CI_URL), lc.records[0].msg)
279+ mock_requests.assert_called_once()
280+ self.assertEquals("Server at {} not found. Is 'ci_url' correctly "
281+ "set? (404 Client Error: Not Found)".format(
282+ utils.CI_URL), lc.records[0].msg)
283
284- @mock.patch('urllib2.urlopen')
285+ @mock.patch('requests.get')
286 @mock.patch('ci_cli.utils.load_config', side_effect=mock_load_config())
287 def test_ts_server_returns_bad_status_line(self, mock_load_config,
288- mock_urlopen):
289+ mock_requests):
290 """Test cli response to ts server returning BadStatusLine."""
291 args = ['status']
292- mock_urlopen.side_effect = httplib.BadStatusLine('')
293+ mock_requests.side_effect = httplib.BadStatusLine('')
294 with LogCapture() as lc:
295 logger = logging.getLogger()
296 self.cli.main(args, log=logger)
297- mock_urlopen.assert_called_once()
298+ mock_requests.assert_called_once()
299 self.assertEquals("Server at {} replied with an empty response. Is "
300 "'ci_url' pointing to the correct service?".format(
301 utils.CI_URL), lc.records[0].msg)
302
303- @mock.patch('urllib2.urlopen')
304+ @mock.patch('requests.get')
305 @mock.patch('ci_cli.utils.load_config', side_effect=mock_load_config())
306 def test_ts_server_returns_other_httperror(self, mock_load_config,
307- mock_urlopen):
308+ mock_requests):
309 """Test cli response to ts server returning HTTPError."""
310- mock_urlopen.side_effect = urllib2.HTTPError(None, 403, "Forbidden",
311- None, None)
312+ mock_requests.side_effect = [
313+ FakeRequestsReturn(403, '', 'Forbidden')
314+ ]
315 args = ['status']
316 with LogCapture() as lc:
317 logger = logging.getLogger()
318 self.cli.main(args, log=logger)
319- mock_urlopen.assert_called_once()
320- self.assertEquals("HTTP Error 403: Forbidden", lc.records[0].msg)
321+ mock_requests.assert_called_once()
322+ self.assertEquals(
323+ "Cannot reach the server at {}. Please, check your "
324+ "configuration file ({}): is 'ci_url' correctly set? "
325+ "Is the server up and reachable from this machine? "
326+ "(403 Client Error: Forbidden).".format(
327+ utils.CI_URL, utils.DEF_CFG), lc.records[0].msg)
328
329
330 class CliArgumentsTestCase(MainScriptTestCase):
331
332=== modified file 'cli/ci_cli/tests/test_get_ticket_status.py'
333--- cli/ci_cli/tests/test_get_ticket_status.py 2014-05-12 15:49:28 +0000
334+++ cli/ci_cli/tests/test_get_ticket_status.py 2014-05-27 09:44:30 +0000
335@@ -17,11 +17,11 @@
336
337 import mock
338 import json
339-import urllib2
340
341 from ci_cli.tests import (
342 capture_stdout,
343 MainScriptTestCase,
344+ FakeRequestsReturn,
345 )
346 from ci_utils.ticket_states import (
347 TicketWorkflowStep,
348@@ -31,8 +31,8 @@
349
350 class GetTicketStatus(MainScriptTestCase):
351
352- @mock.patch('urllib2.urlopen')
353- def test_get_single_ticket_status(self, mock_urlopen):
354+ @mock.patch('requests.get')
355+ def test_get_single_ticket_status(self, mock_requests):
356 data = {
357 "current_workflow_step": str(TicketWorkflowStep.IMAGE_BUILDING),
358 "status": str(TicketWorkflowStepStatus.INPROGRESS),
359@@ -46,9 +46,9 @@
360 "added_binaries": "mynewpackage",
361 "removed_binaries": "myoldpackage",
362 }
363- resp = mock.Mock()
364- resp.read.return_value = json.dumps(data)
365- mock_urlopen.return_value = resp
366+ mock_requests.side_effect = [
367+ FakeRequestsReturn(200, json.dumps(data))
368+ ]
369 args = self.cli.parse_arguments(['status', '-t', '100'])
370 with capture_stdout(args.func, args) as cm:
371 self.assertEqual(
372@@ -64,10 +64,10 @@
373 str(TicketWorkflowStep.IMAGE_BUILDING),
374 str(TicketWorkflowStepStatus.INPROGRESS)),
375 cm)
376- mock_urlopen.assert_called_once()
377+ mock_requests.assert_called_once()
378
379- @mock.patch('urllib2.urlopen')
380- def test_get_ticket_status_unicode(self, mock_urlopen):
381+ @mock.patch('requests.get')
382+ def test_get_ticket_status_unicode(self, mock_requests):
383 data = {
384 "current_workflow_step": str(TicketWorkflowStep.IMAGE_BUILDING),
385 "status": str(TicketWorkflowStepStatus.INPROGRESS),
386@@ -81,9 +81,9 @@
387 "added_binaries": "mynewpackage",
388 "removed_binaries": "myoldpackage",
389 }
390- resp = mock.Mock()
391- resp.read.return_value = json.dumps(data)
392- mock_urlopen.return_value = resp
393+ mock_requests.side_effect = [
394+ FakeRequestsReturn(200, json.dumps(data))
395+ ]
396 args = self.cli.parse_arguments(['status', '-t', '100'])
397 with capture_stdout(args.func, args) as cm:
398 self.assertEqual(
399@@ -99,10 +99,10 @@
400 str(TicketWorkflowStep.IMAGE_BUILDING),
401 str(TicketWorkflowStepStatus.INPROGRESS)),
402 cm)
403- mock_urlopen.assert_called_once()
404+ mock_requests.assert_called_once()
405
406- @mock.patch('urllib2.urlopen')
407- def test_get_single_failed_ticket_status(self, mock_urlopen):
408+ @mock.patch('requests.get')
409+ def test_get_single_failed_ticket_status(self, mock_requests):
410 data = {
411 "current_workflow_step": str(TicketWorkflowStep.FAILED),
412 "status": str(TicketWorkflowStepStatus.FAILED),
413@@ -116,9 +116,9 @@
414 "added_binaries": "mynewpackage",
415 "removed_binaries": "myoldpackage",
416 }
417- resp = mock.Mock()
418- resp.read.return_value = json.dumps(data)
419- mock_urlopen.return_value = resp
420+ mock_requests.side_effect = [
421+ FakeRequestsReturn(200, json.dumps(data))
422+ ]
423 args = self.cli.parse_arguments(['status', '-t', '100'])
424 with capture_stdout(args.func, args) as cm:
425 self.assertEqual(
426@@ -133,10 +133,10 @@
427 'Removed binaries: myoldpackage\n'.format(
428 str(TicketWorkflowStepStatus.FAILED)),
429 cm)
430- mock_urlopen.assert_called_once()
431+ mock_requests.assert_called_once()
432
433- @mock.patch('urllib2.urlopen')
434- def test_get_all_ticket_status(self, mock_urlopen):
435+ @mock.patch('requests.get')
436+ def test_get_all_ticket_status(self, mock_requests):
437 data = {
438 "objects": [
439 {
440@@ -165,9 +165,9 @@
441 },
442 ]
443 }
444- resp = mock.Mock()
445- resp.read.return_value = json.dumps(data)
446- mock_urlopen.return_value = resp
447+ mock_requests.side_effect = [
448+ FakeRequestsReturn(200, json.dumps(data))
449+ ]
450 args = self.cli.parse_arguments(['status'])
451 with capture_stdout(args.func, args) as cm:
452 self.assertEqual(
453@@ -176,15 +176,15 @@
454 "Ticket #7, Upstream bug fix is 100 110\n" +
455 "Ticket #9, Other new feature is 100 110\n",
456 cm)
457- mock_urlopen.assert_called_once()
458+ mock_requests.assert_called_once()
459
460- @mock.patch('urllib2.urlopen')
461- def test_get_status_404_response(self, mock_urlopen):
462- mock_urlopen.side_effect = urllib2.HTTPError("http://example.com",
463- 404, "Not Found", "",
464- None)
465+ @mock.patch('requests.get')
466+ def test_get_status_404_response(self, mock_requests):
467+ mock_requests.side_effect = [
468+ FakeRequestsReturn(404, '', 'Not Found')
469+ ]
470 args = self.cli.parse_arguments(['status', '-t', '99'])
471 with self.assertRaises(SystemExit) as cm:
472 args.func(args)
473- mock_urlopen.assert_called_once()
474+ mock_requests.assert_called_once()
475 self.assertEqual("Ticket number 99 not found.", cm.exception.message)
476
477=== modified file 'cli/ci_cli/tests/test_image.py'
478--- cli/ci_cli/tests/test_image.py 2014-05-07 14:56:11 +0000
479+++ cli/ci_cli/tests/test_image.py 2014-05-27 09:44:30 +0000
480@@ -26,26 +26,10 @@
481 from ci_cli.tests import (
482 capture_stdout,
483 MainScriptTestCase,
484+ FakeRequestsReturn,
485 )
486
487
488-class FakeUrlOpenReturn:
489- """Object to mock the return of urllib2.urlopen."""
490-
491- def __init__(self, code, content):
492- self.code = code
493- self.content = content
494-
495- def __repr__(self):
496- return self.content
497-
498- def __iter__(self):
499- return (line for line in self.content.split("\n"))
500-
501- def read(self):
502- return self.content
503-
504-
505 artifact_data = {
506 "objects": [
507 {
508@@ -88,11 +72,11 @@
509 if os.path.exists(self.image_path):
510 os.remove(self.image_path)
511
512- @mock.patch('urllib2.urlopen')
513+ @mock.patch('requests.get')
514 @mock.patch('ci_utils.data_store.create_for_ticket')
515- def test_get_ticket_image(self, mock_create_datastore, mock_urlopen):
516- mock_urlopen.side_effect = [
517- FakeUrlOpenReturn(200, json.dumps(artifact_data))]
518+ def test_get_ticket_image(self, mock_create_datastore, mock_requests):
519+ mock_requests.side_effect = [
520+ FakeRequestsReturn(200, json.dumps(artifact_data))]
521 mock_datastore = mock.Mock()
522 mock_datastore.get_file.return_value = buffer(" ")
523 mock_create_datastore.return_value = mock_datastore
524@@ -106,12 +90,12 @@
525 "Image file can be found at: {}\n".format(self.image_path))
526 mock_datastore.assert_called_once()
527
528- @mock.patch('urllib2.urlopen')
529+ @mock.patch('requests.get')
530 @mock.patch('ci_utils.data_store.create_for_ticket')
531 def test_get_ticket_image_not_found(self, mock_create_datastore,
532- mock_urlopen):
533- mock_urlopen.side_effect = [
534- FakeUrlOpenReturn(200, json.dumps(artifact_data))]
535+ mock_requests):
536+ mock_requests.side_effect = [
537+ FakeRequestsReturn(200, json.dumps(artifact_data))]
538 mock_datastore = mock.Mock()
539 mock_datastore.get_file.side_effect = data_store.DataStoreException(
540 "Failed to get file: d62d3d9a-ac3d-11e3-847d-fa163eaf5928.img, "
541@@ -125,12 +109,12 @@
542 with self.assertRaises(ImageObjectNotFound):
543 args.func(args)
544
545- @mock.patch('urllib2.urlopen')
546+ @mock.patch('requests.get')
547 @mock.patch('ci_utils.data_store.DataStore')
548 def test_get_ticket_image_already_exists(self, mock_data_store,
549- mock_urlopen):
550- mock_urlopen.side_effect = [
551- FakeUrlOpenReturn(200, json.dumps(artifact_data))]
552+ mock_requests):
553+ mock_requests.side_effect = [
554+ FakeRequestsReturn(200, json.dumps(artifact_data))]
555 open(self.image_path, 'a').close()
556 args = self.cli.parse_arguments(['get_image', '-t', '4', '-n',
557 self.image_path])
558@@ -139,13 +123,13 @@
559 "{} already exists.\n".format(self.image_path),
560 cm)
561
562- @mock.patch('urllib2.urlopen')
563+ @mock.patch('requests.get')
564 @mock.patch('ci_utils.data_store.create_for_ticket')
565 def test_get_last_completed_ticket_image(self, mock_create_datastore,
566- mock_urlopen):
567- mock_urlopen.side_effect = [
568- FakeUrlOpenReturn(200, json.dumps(ticket_data)),
569- FakeUrlOpenReturn(200, json.dumps(artifact_data))
570+ mock_requests):
571+ mock_requests.side_effect = [
572+ FakeRequestsReturn(200, json.dumps(ticket_data)),
573+ FakeRequestsReturn(200, json.dumps(artifact_data))
574 ]
575 mock_datastore = mock.Mock()
576 mock_datastore.get_file.return_value = buffer(" ")
577@@ -159,11 +143,11 @@
578 "Image file can be found at: {}\n".format(self.image_path))
579 mock_datastore.assert_called_once()
580
581- @mock.patch('urllib2.urlopen')
582- def test_get_last_completed_ticket_none_complete(self, mock_urlopen):
583+ @mock.patch('requests.get')
584+ def test_get_last_completed_ticket_none_complete(self, mock_requests):
585 data = {'objects': []}
586- mock_urlopen.side_effect = [
587- FakeUrlOpenReturn(200, json.dumps(data))]
588+ mock_requests.side_effect = [
589+ FakeRequestsReturn(200, json.dumps(data))]
590 args = self.cli.parse_arguments(['get_image', '-n', self.image_path])
591 with self.assertRaises(SystemExit) as cm:
592 args.func(args)
593
594=== modified file 'cli/ci_cli/tests/test_utils.py'
595--- cli/ci_cli/tests/test_utils.py 2014-05-07 17:57:12 +0000
596+++ cli/ci_cli/tests/test_utils.py 2014-05-27 09:44:30 +0000
597@@ -21,6 +21,7 @@
598 import tempfile
599
600 from ci_cli import utils
601+from ci_cli.tests import FakeRequestsReturn
602 from ci_utils.testing import TestCaseWithGnupg
603
604
605@@ -47,24 +48,24 @@
606 location = 'http://www.example.com/api/v1/ticket/abc/123/'
607 self.assertRaises(ValueError, utils.parse_id, location)
608
609- @mock.patch('urllib2.urlopen')
610- def test_get_sourcepackage_uri(self, mock_urlopen):
611+ @mock.patch('requests.get')
612+ def test_get_sourcepackage_uri(self, mock_requests):
613 data = {"objects": [{"resource_uri": "/api/v1/sourcepackage/4/"}]}
614- resp = mock.Mock()
615- resp.read.return_value = json.dumps(data)
616- mock_urlopen.return_value = resp
617+ mock_requests.side_effect = [
618+ FakeRequestsReturn(200, json.dumps(data))
619+ ]
620 uri = utils.get_sourcepackage_uri('foobar')
621- mock_urlopen.assert_called_once()
622+ mock_requests.assert_called_once()
623 self.assertEquals(uri, '/api/v1/sourcepackage/4/')
624
625- @mock.patch('urllib2.urlopen')
626- def test_get_sourcepackage_uri_not_found(self, mock_urlopen):
627+ @mock.patch('requests.get')
628+ def test_get_sourcepackage_uri_not_found(self, mock_requests):
629 data = {"objects": []}
630- resp = mock.Mock()
631- resp.read.return_value = json.dumps(data)
632- mock_urlopen.return_value = resp
633+ mock_requests.side_effect = [
634+ FakeRequestsReturn(200, json.dumps(data))
635+ ]
636 uri = utils.get_sourcepackage_uri('foobar')
637- mock_urlopen.assert_called_once()
638+ mock_requests.assert_called_once()
639 self.assertEquals(uri, '')
640
641 def test_load_config(self):
642
643=== modified file 'cli/ci_cli/utils.py'
644--- cli/ci_cli/utils.py 2014-04-08 13:27:01 +0000
645+++ cli/ci_cli/utils.py 2014-05-27 09:44:30 +0000
646@@ -17,8 +17,8 @@
647 import json
648 import logging
649 import sys
650-import urllib2
651 import yaml
652+import requests
653
654 from ci_utils import data_store
655
656@@ -72,22 +72,19 @@
657
658
659 def post(url, data, headers=HEADERS, patch=False):
660- req = urllib2.Request(url=url, data=json.dumps(data), headers=HEADERS)
661- f = urllib2.urlopen(req)
662- return f.info().dict['location']
663+ req = requests.post(url=url, data=json.dumps(data), headers=HEADERS)
664+ resp = req.headers
665+ return resp['location']
666
667
668 def patch(url, data, headers=HEADERS):
669- req = urllib2.Request(url=url, data=json.dumps(data), headers=HEADERS)
670- req.get_method = lambda: 'PATCH'
671- urllib2.urlopen(req)
672+ requests.patch(url=url, data=json.dumps(data), headers=HEADERS)
673
674
675 def get(url):
676- f = urllib2.urlopen(url)
677-
678- json_data = f.read()
679- return json.loads(json_data)
680+ r = requests.get(url)
681+ r.raise_for_status()
682+ return r.json()
683
684
685 def parse_id(location):
686@@ -101,9 +98,7 @@
687
688 def get_sourcepackage_uri(sourcepackage):
689 url = CI_URL + SOURCEPACKAGE_BASE + '?name__iexact=' + sourcepackage
690- f = urllib2.urlopen(url)
691- json_data = f.read()
692- data = json.loads(json_data)
693+ data = get(url)
694 try:
695 sourcepackage_uri = data['objects'][0]['resource_uri']
696 return sourcepackage_uri
697
698=== modified file 'cli/setup.py'
699--- cli/setup.py 2014-05-07 17:33:32 +0000
700+++ cli/setup.py 2014-05-27 09:44:30 +0000
701@@ -27,6 +27,7 @@
702 'dput>=1.6',
703 'lazr.enum>=1.1.2',
704 'PyYAML==3.10',
705+ 'requests==2.2.1',
706 'mock==1.0.1',
707 'testfixtures>=3.0.1',
708 'python-gnupg>=0.3.6',
709
710=== modified file 'cli/ubuntu-ci'
711--- cli/ubuntu-ci 2014-05-07 14:56:11 +0000
712+++ cli/ubuntu-ci 2014-05-27 09:44:30 +0000
713@@ -19,7 +19,8 @@
714 import logging
715 import os
716 import sys
717-import urllib2
718+
719+from requests import exceptions
720
721 from ci_cli import (
722 ticket,
723@@ -78,8 +79,8 @@
724 help='Ticket to display status of. Leave off '
725 'for last successful ticket')
726 image_parser.add_argument('-n', '--name',
727- help='Desired file name (and path) for the '
728- 'downloaded image', required=True)
729+ help='Desired file name (and path) for the '
730+ 'downloaded image', required=True)
731 image_parser.set_defaults(func=image.get_image)
732 return parser.parse_args(args)
733
734@@ -153,10 +154,16 @@
735 except image.ImageObjectNotFound as exc:
736 log.error("Image cannot be downloaded: {} ({})".format(exc.filename,
737 str(exc)))
738- except urllib2.URLError as exc:
739- if isinstance(exc, urllib2.HTTPError):
740- reason = exc.reason
741- code = exc.code
742+ except exceptions.RequestException as exc:
743+ error = ("Cannot reach the server at {}. Please, check your "
744+ "configuration file ({}): is 'ci_url' correctly set? "
745+ "Is the server up and reachable from this machine? "
746+ "({}).".format(utils.CI_URL, utils.DEF_CFG, str(exc)))
747+ if isinstance(exc, exceptions.HTTPError):
748+ code = None
749+ if exc.response:
750+ code = exc.response.status_code
751+
752 if code == 500:
753 log.error("Server at {} reported internal error. Maybe a "
754 "database hiccup?".format(utils.CI_URL))
755@@ -164,13 +171,9 @@
756 log.error("Server at {} not found. Is 'ci_url' correctly "
757 "set? ({})".format(utils.CI_URL, str(exc)))
758 else:
759- log.error(str(exc))
760+ log.error(error)
761 else:
762- reason = exc.reason
763- log.error("Cannot reach the server at {}. Please, check your "
764- "configuration file ({}): is 'ci_url' correctly set? "
765- "Is the server up and reachable from this machine? "
766- "({}).".format(utils.CI_URL, utils.DEF_CFG, reason))
767+ log.error(error)
768 except data_store.DataStoreException as exc:
769 log.error("Data Store Error: {}".format(exc))
770 except Exception:
771
772=== modified file 'debian/control'
773--- debian/control 2014-05-15 16:12:18 +0000
774+++ debian/control 2014-05-27 09:44:30 +0000
775@@ -32,6 +32,7 @@
776 python-lazr.enum (>= 1.1.2-0~),
777 python-yaml (>= 3.10-2),
778 python-swiftclient,
779+ python-requests (>=2.2.1),
780 uci-utils (= ${binary:Version}),
781 ${misc:Depends},
782 ${python:Depends}

Subscribers

People subscribed via source and target branches