Merge lp:~matiasb/click-toolbelt/channels-handler-removed into lp:click-toolbelt

Proposed by Matias Bordese on 2016-02-09
Status: Merged
Approved by: Matias Bordese on 2016-02-10
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
Reviewer Review Type Date Requested Status
Matt Goodall (community) 2016-02-09 Approve on 2016-02-10
Review via email: mp+285525@code.launchpad.net

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.
Matt Goodall (matt-goodall) wrote :

lgtm

review: Approve

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'})

Subscribers

People subscribed via source and target branches