Merge lp:~matiasb/click-toolbelt/channels-handler-removed into lp:click-toolbelt
- channels-handler-removed
- Merge into trunk
Proposed by
Matias Bordese
Status: | Merged |
---|---|
Approved by: | Matias Bordese |
Approved revision: | 58 |
Merged at revision: | 58 |
Proposed branch: | lp:~matiasb/click-toolbelt/channels-handler-removed |
Merge into: | lp:click-toolbelt |
Diff against target: |
526 lines (+0/-485) 6 files modified
click_toolbelt/channels.py (+0/-77) click_toolbelt/tests/test_channels.py (+0/-238) setup.py (+0/-1) storeapi/__init__.py (+0/-1) storeapi/channels.py (+0/-23) storeapi/tests/test_channels.py (+0/-145) |
To merge this branch: | bzr merge lp:~matiasb/click-toolbelt/channels-handler-removed |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Matt Goodall (community) | Approve | ||
Review via email:
|
Commit message
Removed unused/deprecated channels command.
Description of the change
Since 3-dimensions were introduced the previous channels configuration setup does not make sense any more and we are deprecating it. Also, the respective endpoint was never used.
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 | === removed file 'click_toolbelt/channels.py' |
2 | --- click_toolbelt/channels.py 2016-01-08 14:20:09 +0000 |
3 | +++ click_toolbelt/channels.py 1970-01-01 00:00:00 +0000 |
4 | @@ -1,77 +0,0 @@ |
5 | -# Copyright 2015 Canonical Ltd. This software is licensed under the |
6 | -# GNU General Public License version 3 (see the file LICENSE). |
7 | -from __future__ import absolute_import, unicode_literals |
8 | -import json |
9 | -import logging |
10 | - |
11 | -from click_toolbelt.common import ( |
12 | - Command, |
13 | - CommandError, |
14 | -) |
15 | -from storeapi.channels import get_channels, update_channels |
16 | - |
17 | - |
18 | -class Channels(Command): |
19 | - """Get/Update channels configuration for a package.""" |
20 | - |
21 | - log = logging.getLogger(__name__) |
22 | - |
23 | - def get_parser(self, prog_name): |
24 | - parser = super(Channels, self).get_parser(prog_name) |
25 | - parser.add_argument('package_name') |
26 | - parser.add_argument('config_filename', nargs='?') |
27 | - parser.add_argument('--publish', action="store_true") |
28 | - return parser |
29 | - |
30 | - def get_channels_config(self, config_filename, publish=False): |
31 | - """Return config data as expected by channels endpoint.""" |
32 | - if config_filename: |
33 | - with open(config_filename, 'r') as fd: |
34 | - data = json.load(fd) |
35 | - else: |
36 | - data = {} |
37 | - config = {'channels': data, 'publish': publish} |
38 | - return config |
39 | - |
40 | - def show_channels(self, data): |
41 | - """Display given channels config.""" |
42 | - for config in data: |
43 | - value = config.get('current') |
44 | - if value is not None: |
45 | - value = 'Revision %d (version %s)' % ( |
46 | - value.get('revision'), value.get('version')) |
47 | - self.log.info('%s: %s', config.get('channel'), value) |
48 | - |
49 | - def take_action(self, parsed_args): |
50 | - package_name = parsed_args.package_name |
51 | - config_filename = parsed_args.config_filename |
52 | - publish = parsed_args.publish |
53 | - |
54 | - # OAuth session is required |
55 | - session = self.get_oauth_session() |
56 | - if session is None: |
57 | - self.log.info('No valid credentials found.') |
58 | - # raise an exception to exit with proper code |
59 | - raise CommandError() |
60 | - |
61 | - if not publish and config_filename is None: |
62 | - # no changes requested, ask for current config |
63 | - result = get_channels(session, package_name) |
64 | - else: |
65 | - config = self.get_channels_config( |
66 | - config_filename, publish=publish) |
67 | - result = update_channels(session, package_name, config) |
68 | - |
69 | - if not result.get('success', False): |
70 | - self.log.info( |
71 | - 'Could not get information. An error ocurred:\n\n%s\n\n', |
72 | - '\n'.join(result['errors'])) |
73 | - # raise an exception to exit with proper code |
74 | - raise CommandError() |
75 | - |
76 | - errors = result.get('errors', []) |
77 | - for error in errors: |
78 | - self.log.info('ERROR: %s', error) |
79 | - |
80 | - data = result['data'] |
81 | - self.show_channels(data) |
82 | |
83 | === removed file 'click_toolbelt/tests/test_channels.py' |
84 | --- click_toolbelt/tests/test_channels.py 2015-12-11 20:23:04 +0000 |
85 | +++ click_toolbelt/tests/test_channels.py 1970-01-01 00:00:00 +0000 |
86 | @@ -1,238 +0,0 @@ |
87 | -# -*- coding: utf-8 -*- |
88 | -# Copyright 2015 Canonical Ltd. This software is licensed under the |
89 | -# GNU General Public License version 3 (see the file LICENSE). |
90 | -from __future__ import absolute_import, unicode_literals |
91 | -import json |
92 | -import tempfile |
93 | -from collections import namedtuple |
94 | - |
95 | -from mock import call, patch |
96 | - |
97 | -from click_toolbelt.common import CommandError |
98 | -from click_toolbelt.constants import MYAPPS_API_ROOT_URL |
99 | -from click_toolbelt.channels import ( |
100 | - Channels, |
101 | -) |
102 | -from click_toolbelt.tests.test_common import CommandTestCase |
103 | - |
104 | - |
105 | -class ChannelsCommandTestCase(CommandTestCase): |
106 | - command_class = Channels |
107 | - |
108 | - def setUp(self): |
109 | - super(ChannelsCommandTestCase, self).setUp() |
110 | - |
111 | - patcher = patch('click_toolbelt.channels.Channels.log') |
112 | - self.mock_log = patcher.start() |
113 | - self.addCleanup(patcher.stop) |
114 | - |
115 | - self.mock_get = self.mock_get_oauth_session.return_value.get |
116 | - self.mock_post = self.mock_get_oauth_session.return_value.post |
117 | - |
118 | - self.parsed_args = namedtuple( |
119 | - 'parsed_args', 'package_name, config_filename, publish') |
120 | - self.args = self.parsed_args('package.name', None, False) |
121 | - |
122 | - self.channels_data = [ |
123 | - {'channel': 'stable', 'current': {'revision': 2, 'version': '1'}}, |
124 | - {'channel': 'beta', 'current': {'revision': 4, 'version': '1.5'}}, |
125 | - {'channel': 'edge', 'current': None}, |
126 | - ] |
127 | - |
128 | - def assert_show_channels_status(self, errors=None): |
129 | - expected_calls = [] |
130 | - |
131 | - if errors is None: |
132 | - errors = [] |
133 | - for error in errors: |
134 | - error_call = call('ERROR: %s', error) |
135 | - expected_calls.append(error_call) |
136 | - |
137 | - channels = self.channels_data |
138 | - for config in channels: |
139 | - expected = None |
140 | - upload = config['current'] |
141 | - if upload is not None: |
142 | - expected = 'Revision %d (version %s)' % ( |
143 | - upload['revision'], upload['version']) |
144 | - channel_call = call('%s: %s', config['channel'], expected) |
145 | - expected_calls.append(channel_call) |
146 | - self.assertEqual(self.mock_log.info.call_args_list, expected_calls) |
147 | - |
148 | - def assert_update(self, package_name, expected_data): |
149 | - self.mock_post.assert_called_once_with( |
150 | - '%spackage-channels/%s/' % (MYAPPS_API_ROOT_URL, package_name), |
151 | - data=json.dumps(expected_data), |
152 | - headers={'Content-Type': 'application/json'}) |
153 | - |
154 | - def set_channels_get_success_response(self): |
155 | - mock_response = self.mock_get.return_value |
156 | - mock_response.ok = True |
157 | - mock_response.json.return_value = self.channels_data |
158 | - |
159 | - def set_channels_get_error_response(self, error_msg): |
160 | - mock_response = self.mock_get.return_value |
161 | - mock_response.ok = False |
162 | - mock_response.text = error_msg |
163 | - |
164 | - def set_channels_post_success_response(self): |
165 | - mock_response = self.mock_post.return_value |
166 | - mock_response.ok = True |
167 | - mock_response.json.return_value = { |
168 | - 'success': True, 'errors': [], 'channels': self.channels_data |
169 | - } |
170 | - |
171 | - def set_channels_post_failed_response(self, error_msg): |
172 | - mock_response = self.mock_post.return_value |
173 | - mock_response.ok = True |
174 | - mock_response.json.return_value = { |
175 | - 'success': True, 'errors': [error_msg], |
176 | - 'channels': self.channels_data |
177 | - } |
178 | - |
179 | - def set_channels_post_error_response(self, error_msg): |
180 | - mock_response = self.mock_post.return_value |
181 | - mock_response.ok = False |
182 | - mock_response.text = error_msg |
183 | - |
184 | - def set_channels_config_file(self, data): |
185 | - mock_channels_file = tempfile.NamedTemporaryFile() |
186 | - with open(mock_channels_file.name, 'wb') as mock_file: |
187 | - data = json.dumps(data) |
188 | - mock_file.write(data.encode('utf-8')) |
189 | - mock_file.flush() |
190 | - return mock_channels_file |
191 | - |
192 | - def test_parser(self): |
193 | - parser = self.command.get_parser('prog_name') |
194 | - # only one argument -- the first item is the default help option |
195 | - self.assertEqual(len(parser._actions), 4) |
196 | - self.assertEqual(parser._actions[0].dest, 'help') |
197 | - # package_name is required |
198 | - self.assertEqual(parser._actions[1].dest, 'package_name') |
199 | - self.assertTrue(parser._actions[1].required) |
200 | - # config_filename is optional |
201 | - self.assertEqual(parser._actions[2].dest, 'config_filename') |
202 | - self.assertFalse(parser._actions[2].required) |
203 | - # publish is optional |
204 | - self.assertEqual(parser._actions[3].dest, 'publish') |
205 | - self.assertFalse(parser._actions[3].required) |
206 | - |
207 | - def test_get_channels_config_from_file(self): |
208 | - channels = {'stable': 2, 'beta': 1} |
209 | - mock_channels_file = self.set_channels_config_file(channels) |
210 | - |
211 | - config = self.command.get_channels_config( |
212 | - mock_channels_file.name, False) |
213 | - |
214 | - expected = {'channels': channels, 'publish': False} |
215 | - self.assertEqual(config, expected) |
216 | - |
217 | - def test_get_channels_config_no_file(self): |
218 | - config = self.command.get_channels_config(None, False) |
219 | - |
220 | - expected = {'channels': {}, 'publish': False} |
221 | - self.assertEqual(config, expected) |
222 | - |
223 | - def test_get_channels_config_do_publish(self): |
224 | - config = self.command.get_channels_config(None, True) |
225 | - |
226 | - expected = {'channels': {}, 'publish': True} |
227 | - self.assertEqual(config, expected) |
228 | - |
229 | - def test_get_channels_config_from_file_and_do_publish(self): |
230 | - channels = {'stable': 2, 'beta': 1} |
231 | - mock_channels_file = self.set_channels_config_file(channels) |
232 | - |
233 | - config = self.command.get_channels_config( |
234 | - mock_channels_file.name, True) |
235 | - |
236 | - expected = {'channels': channels, 'publish': True} |
237 | - self.assertEqual(config, expected) |
238 | - |
239 | - def test_show_channels(self): |
240 | - self.command.show_channels(self.channels_data) |
241 | - self.assert_show_channels_status() |
242 | - |
243 | - def test_take_action_invalid_credentials(self): |
244 | - self.mock_get_oauth_session.return_value = None |
245 | - |
246 | - with self.assertRaises(CommandError): |
247 | - self.command.take_action(self.args) |
248 | - |
249 | - self.mock_log.info.assert_called_once_with( |
250 | - 'No valid credentials found.') |
251 | - |
252 | - def test_take_action_no_update(self): |
253 | - self.set_channels_get_success_response() |
254 | - |
255 | - self.command.take_action(self.args) |
256 | - |
257 | - self.assert_show_channels_status() |
258 | - |
259 | - def test_take_action_with_error(self): |
260 | - error_msg = 'some error' |
261 | - self.set_channels_get_error_response(error_msg) |
262 | - |
263 | - with self.assertRaises(CommandError): |
264 | - self.command.take_action(self.args) |
265 | - |
266 | - self.mock_log.info.assert_called_once_with( |
267 | - 'Could not get information. An error ocurred:\n\n%s\n\n', |
268 | - 'some error') |
269 | - |
270 | - def test_take_action_update_with_error(self): |
271 | - error_msg = 'some error' |
272 | - self.set_channels_post_error_response(error_msg) |
273 | - |
274 | - args = self.parsed_args('package.name', None, True) |
275 | - with self.assertRaises(CommandError): |
276 | - self.command.take_action(args) |
277 | - |
278 | - self.mock_log.info.assert_called_once_with( |
279 | - 'Could not get information. An error ocurred:\n\n%s\n\n', |
280 | - 'some error') |
281 | - |
282 | - def test_take_action_update_publish(self): |
283 | - self.set_channels_post_success_response() |
284 | - |
285 | - args = self.parsed_args('package.name', None, True) |
286 | - self.command.take_action(args) |
287 | - |
288 | - expected = {'channels': {}, 'publish': True} |
289 | - self.assert_update('package.name', expected) |
290 | - self.assert_show_channels_status() |
291 | - |
292 | - def test_take_action_update_channels(self): |
293 | - self.set_channels_post_success_response() |
294 | - channels = {'stable': 2, 'beta': 1} |
295 | - mock_channels_file = self.set_channels_config_file(channels) |
296 | - |
297 | - args = self.parsed_args('package.name', mock_channels_file.name, False) |
298 | - self.command.take_action(args) |
299 | - |
300 | - expected = {'channels': channels, 'publish': False} |
301 | - self.assert_update('package.name', expected) |
302 | - self.assert_show_channels_status() |
303 | - |
304 | - def test_take_action_update_channels_and_publish(self): |
305 | - self.set_channels_post_success_response() |
306 | - channels = {'stable': 2, 'beta': 1} |
307 | - mock_channels_file = self.set_channels_config_file(channels) |
308 | - |
309 | - args = self.parsed_args('package.name', mock_channels_file.name, True) |
310 | - self.command.take_action(args) |
311 | - |
312 | - expected = {'channels': channels, 'publish': True} |
313 | - self.assert_update('package.name', expected) |
314 | - self.assert_show_channels_status() |
315 | - |
316 | - def test_take_action_update_channels_fails(self): |
317 | - self.set_channels_post_failed_response('some error') |
318 | - |
319 | - args = self.parsed_args('package.name', None, True) |
320 | - self.command.take_action(args) |
321 | - |
322 | - expected = {'channels': {}, 'publish': True} |
323 | - self.assert_update('package.name', expected) |
324 | - self.assert_show_channels_status(errors=['some error']) |
325 | |
326 | === modified file 'setup.py' |
327 | --- setup.py 2016-01-08 14:02:28 +0000 |
328 | +++ setup.py 2016-02-09 20:11:50 +0000 |
329 | @@ -61,7 +61,6 @@ |
330 | 'login = click_toolbelt.login:Login', |
331 | 'upload = click_toolbelt.upload:Upload', |
332 | 'info = click_toolbelt.info:Info', |
333 | - 'channels = click_toolbelt.channels:Channels', |
334 | ], |
335 | }, |
336 | |
337 | |
338 | === modified file 'storeapi/__init__.py' |
339 | --- storeapi/__init__.py 2015-12-21 18:41:57 +0000 |
340 | +++ storeapi/__init__.py 2016-02-09 20:11:50 +0000 |
341 | @@ -1,7 +1,6 @@ |
342 | # Copyright 2015 Canonical Ltd. This software is licensed under the |
343 | # GNU General Public License version 3 (see the file LICENSE). |
344 | |
345 | -from .channels import get_channels, update_channels # noqa |
346 | from .info import get_info # noqa |
347 | from ._login import login # noqa |
348 | from ._upload import upload # noqa |
349 | |
350 | === removed file 'storeapi/channels.py' |
351 | --- storeapi/channels.py 2016-01-08 14:20:09 +0000 |
352 | +++ storeapi/channels.py 1970-01-01 00:00:00 +0000 |
353 | @@ -1,23 +0,0 @@ |
354 | -# -*- coding: utf-8 -*- |
355 | -# Copyright 2015 Canonical Ltd. This software is licensed under the |
356 | -# GNU General Public License version 3 (see the file LICENSE). |
357 | -from __future__ import absolute_import, unicode_literals |
358 | - |
359 | -from storeapi.common import myapps_api_call |
360 | - |
361 | - |
362 | -def get_channels(session, package_name): |
363 | - """Get current channels config for package through API.""" |
364 | - channels_endpoint = 'package-channels/%s/' % package_name |
365 | - return myapps_api_call(channels_endpoint, session=session) |
366 | - |
367 | - |
368 | -def update_channels(session, package_name, data): |
369 | - """Update current channels config for package through API.""" |
370 | - channels_endpoint = 'package-channels/%s/' % package_name |
371 | - result = myapps_api_call(channels_endpoint, method='POST', |
372 | - data=data, session=session) |
373 | - if result['success']: |
374 | - result['errors'] = result['data']['errors'] |
375 | - result['data'] = result['data']['channels'] |
376 | - return result |
377 | |
378 | === removed file 'storeapi/tests/test_channels.py' |
379 | --- storeapi/tests/test_channels.py 2016-01-08 14:20:13 +0000 |
380 | +++ storeapi/tests/test_channels.py 1970-01-01 00:00:00 +0000 |
381 | @@ -1,145 +0,0 @@ |
382 | -# -*- coding: utf-8 -*- |
383 | -# Copyright 2015 Canonical Ltd. This software is licensed under the |
384 | -# GNU General Public License version 3 (see the file LICENSE). |
385 | -from __future__ import absolute_import, unicode_literals |
386 | -import json |
387 | -from unittest import TestCase |
388 | - |
389 | -from mock import patch |
390 | - |
391 | -from storeapi.channels import get_channels, update_channels |
392 | - |
393 | - |
394 | -class ChannelsAPITestCase(TestCase): |
395 | - |
396 | - def setUp(self): |
397 | - super(ChannelsAPITestCase, self).setUp() |
398 | - |
399 | - # setup patches |
400 | - oauth_session = 'storeapi.common.get_oauth_session' |
401 | - patcher = patch(oauth_session) |
402 | - self.mock_get_oauth_session = patcher.start() |
403 | - self.mock_session = self.mock_get_oauth_session.return_value |
404 | - self.addCleanup(patcher.stop) |
405 | - |
406 | - self.mock_get = self.mock_session.get |
407 | - self.mock_post = self.mock_session.post |
408 | - |
409 | - self.channels_data = [ |
410 | - {'channel': 'stable', 'current': {'revision': 2, 'version': '1'}}, |
411 | - {'channel': 'beta', 'current': {'revision': 4, 'version': '1.5'}}, |
412 | - {'channel': 'edge', 'current': None}, |
413 | - ] |
414 | - |
415 | - def set_channels_get_success_response(self): |
416 | - mock_response = self.mock_get.return_value |
417 | - mock_response.ok = True |
418 | - mock_response.json.return_value = self.channels_data |
419 | - |
420 | - def set_channels_get_error_response(self, error_msg): |
421 | - mock_response = self.mock_get.return_value |
422 | - mock_response.ok = False |
423 | - mock_response.text = error_msg |
424 | - |
425 | - def set_channels_post_success_response(self): |
426 | - mock_response = self.mock_post.return_value |
427 | - mock_response.ok = True |
428 | - mock_response.json.return_value = { |
429 | - 'success': True, 'errors': [], 'channels': self.channels_data |
430 | - } |
431 | - |
432 | - def set_channels_post_failed_response(self, error_msg): |
433 | - mock_response = self.mock_post.return_value |
434 | - mock_response.ok = True |
435 | - mock_response.json.return_value = { |
436 | - 'success': True, 'errors': [error_msg], |
437 | - 'channels': self.channels_data |
438 | - } |
439 | - |
440 | - def set_channels_post_error_response(self, error_msg): |
441 | - mock_response = self.mock_post.return_value |
442 | - mock_response.ok = False |
443 | - mock_response.text = error_msg |
444 | - |
445 | - def test_get_channels(self): |
446 | - self.set_channels_get_success_response() |
447 | - |
448 | - data = get_channels(self.mock_session, 'package.name') |
449 | - |
450 | - expected = { |
451 | - 'success': True, |
452 | - 'errors': [], |
453 | - 'data': self.channels_data, |
454 | - } |
455 | - self.assertEqual(data, expected) |
456 | - |
457 | - def test_get_channels_with_error_response(self): |
458 | - error_msg = 'some error' |
459 | - self.set_channels_get_error_response(error_msg) |
460 | - |
461 | - data = get_channels(self.mock_session, 'package.name') |
462 | - |
463 | - expected = { |
464 | - 'success': False, |
465 | - 'errors': [error_msg], |
466 | - 'data': None, |
467 | - } |
468 | - self.assertEqual(data, expected) |
469 | - |
470 | - def test_get_channels_uses_environment_variables(self): |
471 | - with patch('storeapi.common.os.environ', |
472 | - {'MYAPPS_API_ROOT_URL': 'http://example.com'}): |
473 | - get_channels(self.mock_session, 'package.name') |
474 | - self.mock_get.assert_called_once_with( |
475 | - 'http://example.com/package-channels/package.name/') |
476 | - |
477 | - def test_update_channels(self): |
478 | - self.set_channels_post_success_response() |
479 | - |
480 | - data = update_channels( |
481 | - self.mock_session, 'package.name', {'stable': 2}) |
482 | - |
483 | - expected = { |
484 | - 'success': True, |
485 | - 'errors': [], |
486 | - 'data': self.channels_data, |
487 | - } |
488 | - self.assertEqual(data, expected) |
489 | - |
490 | - def test_update_channels_with_error_response(self): |
491 | - error_msg = 'some error' |
492 | - self.set_channels_post_error_response(error_msg) |
493 | - |
494 | - data = update_channels( |
495 | - self.mock_session, 'package.name', {'stable': 2}) |
496 | - |
497 | - expected = { |
498 | - 'success': False, |
499 | - 'errors': [error_msg], |
500 | - 'data': None, |
501 | - } |
502 | - self.assertEqual(data, expected) |
503 | - |
504 | - def test_update_channels_with_failed_response(self): |
505 | - error_msg = 'some error' |
506 | - self.set_channels_post_failed_response(error_msg) |
507 | - |
508 | - data = update_channels( |
509 | - self.mock_session, 'package.name', {'stable': 2}) |
510 | - |
511 | - expected = { |
512 | - 'success': True, |
513 | - 'errors': [error_msg], |
514 | - 'data': self.channels_data, |
515 | - } |
516 | - self.assertEqual(data, expected) |
517 | - |
518 | - def test_update_channels_uses_environment_variables(self): |
519 | - with patch('storeapi.common.os.environ', |
520 | - {'MYAPPS_API_ROOT_URL': 'http://example.com'}): |
521 | - update_channels( |
522 | - self.mock_session, 'package.name', {'stable': 2}) |
523 | - self.mock_post.assert_called_once_with( |
524 | - 'http://example.com/package-channels/package.name/', |
525 | - data=json.dumps({'stable': 2}), |
526 | - headers={'Content-Type': 'application/json'}) |
lgtm