Util methods for column name backward compatibility

Add two util methods for handling column name backward compatibility,
that can be used in commands of ShowOne and Lister class.

Change-Id: I1fb62219b092346ea380099811cbd082cae5bafe
Partial-Bug: #1657956
This commit is contained in:
Rui Chen 2017-02-20 17:14:12 +08:00
parent 62a17ed479
commit 11b6e92d2d
2 changed files with 131 additions and 0 deletions

View File

@ -322,6 +322,75 @@ class TestUtils(test_utils.TestCase):
) )
self.assertEqual("0", utils.format_size(None)) 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): class NoUniqueMatch(Exception):
pass pass

View File

@ -15,6 +15,7 @@
"""Common client utilities""" """Common client utilities"""
import copy
import getpass import getpass
import logging import logging
import os import os
@ -27,6 +28,9 @@ from osc_lib import exceptions
from osc_lib.i18n import _ from osc_lib.i18n import _
LOG = logging.getLogger(__name__)
def build_kwargs_dict(arg_name, value): def build_kwargs_dict(arg_name, value):
"""Return a dictionary containing `arg_name` if `value` is set.""" """Return a dictionary containing `arg_name` if `value` is set."""
kwargs = {} kwargs = {}
@ -526,3 +530,61 @@ def format_size(size):
stripped = padded.rstrip('0').rstrip('.') stripped = padded.rstrip('0').rstrip('.')
return '%s%s' % (stripped, suffix[index]) 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