diff --git a/osc_lib/tests/test_utils.py b/osc_lib/tests/test_utils.py index b1bef70..e4c01a2 100644 --- a/osc_lib/tests/test_utils.py +++ b/osc_lib/tests/test_utils.py @@ -322,6 +322,75 @@ class TestUtils(test_utils.TestCase): ) self.assertEqual("0", utils.format_size(None)) + def test_backward_compat_col_lister(self): + fake_col_headers = ['ID', 'Name', 'Size'] + columns = ['Display Name'] + column_map = {'Display Name': 'Name'} + results = utils.backward_compat_col_lister(fake_col_headers, + columns, + column_map) + self.assertIsInstance(results, list) + self.assertIn('Display Name', results) + self.assertNotIn('Name', results) + self.assertIn('ID', results) + self.assertIn('Size', results) + + def test_backward_compat_col_lister_no_specify_column(self): + fake_col_headers = ['ID', 'Name', 'Size'] + columns = [] + column_map = {'Display Name': 'Name'} + results = utils.backward_compat_col_lister(fake_col_headers, + columns, + column_map) + self.assertIsInstance(results, list) + self.assertNotIn('Display Name', results) + self.assertIn('Name', results) + self.assertIn('ID', results) + self.assertIn('Size', results) + + def test_backward_compat_col_lister_with_tuple_headers(self): + fake_col_headers = ('ID', 'Name', 'Size') + columns = ['Display Name'] + column_map = {'Display Name': 'Name'} + results = utils.backward_compat_col_lister(fake_col_headers, + columns, + column_map) + self.assertIsInstance(results, list) + self.assertIn('Display Name', results) + self.assertNotIn('Name', results) + self.assertIn('ID', results) + self.assertIn('Size', results) + + def test_backward_compat_col_showone(self): + fake_object = {'id': 'fake-id', + 'name': 'fake-name', + 'size': 'fake-size'} + columns = ['display_name'] + column_map = {'display_name': 'name'} + results = utils.backward_compat_col_showone(fake_object, + columns, + column_map) + self.assertIsInstance(results, dict) + self.assertIn('display_name', results) + self.assertIn('id', results) + self.assertNotIn('name', results) + self.assertIn('size', results) + + def test_backward_compat_col_showone_no_specify_column(self): + fake_object = {'id': 'fake-id', + 'name': 'fake-name', + 'size': 'fake-size'} + columns = [] + column_map = {'display_name': 'name'} + results = utils.backward_compat_col_showone(fake_object, + columns, + column_map) + self.assertIsInstance(results, dict) + self.assertNotIn('display_name', results) + self.assertIn('id', results) + self.assertIn('name', results) + self.assertIn('size', results) + class NoUniqueMatch(Exception): pass diff --git a/osc_lib/utils.py b/osc_lib/utils.py index 4f3d34f..dec5490 100644 --- a/osc_lib/utils.py +++ b/osc_lib/utils.py @@ -15,6 +15,7 @@ """Common client utilities""" +import copy import getpass import logging import os @@ -27,6 +28,9 @@ from osc_lib import exceptions from osc_lib.i18n import _ +LOG = logging.getLogger(__name__) + + def build_kwargs_dict(arg_name, value): """Return a dictionary containing `arg_name` if `value` is set.""" kwargs = {} @@ -526,3 +530,61 @@ def format_size(size): stripped = padded.rstrip('0').rstrip('.') return '%s%s' % (stripped, suffix[index]) + + +def backward_compat_col_lister(column_headers, columns, column_map): + """Convert the column headers to keep column backward compatibility. + + Replace the new column name of column headers by old name, so that + the column headers can continue to support to show the old column name by + --column/-c option with old name, like: volume list -c 'Display Name' + + :param column_headers: The column headers to be output in list command. + :param columns: The columns to be output. + :param column_map: The key of map is old column name, the value is new + column name, like: {'old_col': 'new_col'} + """ + if not columns: + return column_headers + # NOTE(RuiChen): column_headers may be a tuple in some code, like: + # volume v1, convert it to a list in order to change + # the column name. + column_headers = list(column_headers) + for old_col, new_col in six.iteritems(column_map): + if old_col in columns: + LOG.warning(_('The column "%(old_column)s" was deprecated, ' + 'please use "%(new_column)s" replace.') % { + 'old_column': old_col, + 'new_column': new_col} + ) + if new_col in column_headers: + column_headers[column_headers.index(new_col)] = old_col + return column_headers + + +def backward_compat_col_showone(show_object, columns, column_map): + """Convert the output object to keep column backward compatibility. + + Replace the new column name of output object by old name, so that + the object can continue to support to show the old column name by + --column/-c option with old name, like: volume show -c 'display_name' + + :param show_object: The object to be output in create/show commands. + :param columns: The columns to be output. + :param column_map: The key of map is old column name, the value is new + column name, like: {'old_col': 'new_col'} + """ + if not columns: + return show_object + + show_object = copy.deepcopy(show_object) + for old_col, new_col in six.iteritems(column_map): + if old_col in columns: + LOG.warning(_('The column "%(old_column)s" was deprecated, ' + 'please use "%(new_column)s" replace.') % { + 'old_column': old_col, + 'new_column': new_col} + ) + if new_col in show_object: + show_object.update({old_col: show_object.pop(new_col)}) + return show_object