Add formattable column base classes

Currently, we use utils.format_dict(), utils.format_list(),
utils.format_list_of_dicts to make column value can be easy to read by
human, but osc support to format the CLI output into several format,
like: json, shell, csv, yaml, most of these should be understand by
program and code, so keeping the column content as the original value
make sense, like {u'name': u'RuiChen'} than name='RuiChen'

Add some base formattable column classes into osc-lib in order to all
the osc plugins can use it.

Change-Id: I024a42bdd100d2541043bf4caf7b003b169be2a9
Implements: blueprint osc-formattable-columns
This commit is contained in:
Rui Chen 2017-03-13 16:30:50 +08:00
parent 18d869469a
commit 17b1cf3454
4 changed files with 174 additions and 0 deletions

View File

@ -0,0 +1,47 @@
# Copyright 2017 Huawei, Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
"""Formattable column for specify content type"""
from cliff import columns
from osc_lib import utils
class DictColumn(columns.FormattableColumn):
"""Format column for dict content"""
def human_readable(self):
return utils.format_dict(self._value)
class DictListColumn(columns.FormattableColumn):
"""Format column for dict, key is string, value is list"""
def human_readable(self):
return utils.format_dict_of_list(self._value)
class ListColumn(columns.FormattableColumn):
"""Format column for list content"""
def human_readable(self):
return utils.format_list(self._value)
class ListDictColumn(columns.FormattableColumn):
"""Format column for list of dict content"""
def human_readable(self):
return utils.format_list_of_dicts(self._value)

View File

@ -0,0 +1,65 @@
# Copyright 2017 Huawei, Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
from osc_lib.cli import format_columns
from osc_lib.tests import utils
class TestDictColumn(utils.TestCase):
def test_dict_column(self):
dict_content = {
'key1': 'value1',
'key2': 'value2',
}
col = format_columns.DictColumn(dict_content)
self.assertEqual(dict_content, col.machine_readable())
self.assertEqual("key1='value1', key2='value2'", col.human_readable())
class TestDictListColumn(utils.TestCase):
def test_dict_list_column(self):
dict_list_content = {'public': ['2001:db8::8', '172.24.4.6'],
'private': ['2000:db7::7', '192.24.4.6']}
col = format_columns.DictListColumn(dict_list_content)
self.assertEqual(dict_list_content, col.machine_readable())
self.assertEqual('private=192.24.4.6, 2000:db7::7; '
'public=172.24.4.6, 2001:db8::8',
col.human_readable())
class TestListColumn(utils.TestCase):
def test_list_column(self):
list_content = [
'key1',
'key2',
]
col = format_columns.ListColumn(list_content)
self.assertEqual(list_content, col.machine_readable())
self.assertEqual("key1, key2", col.human_readable())
class TestListDictColumn(utils.TestCase):
def test_list_dict_column(self):
list_dict_content = [
{'key1': 'value1'},
{'key2': 'value2'},
]
col = format_columns.ListDictColumn(list_dict_content)
self.assertEqual(list_dict_content, col.machine_readable())
self.assertEqual("key1='value1'\nkey2='value2'", col.human_readable())

View File

@ -569,6 +569,43 @@ class TestFindResource(test_utils.TestCase):
utils.format_dict({'e': 'f', 'c': 'd', 'a': 'b'}))
self.assertIsNone(utils.format_dict(None))
def test_format_dict_of_list(self):
expected = "a=a1, a2; b=b1, b2; c=c1, c2; e="
self.assertEqual(expected,
utils.format_dict_of_list({'a': ['a2', 'a1'],
'b': ['b2', 'b1'],
'c': ['c1', 'c2'],
'd': None,
'e': []})
)
self.assertEqual(expected,
utils.format_dict_of_list({'c': ['c1', 'c2'],
'a': ['a2', 'a1'],
'b': ['b2', 'b1'],
'e': []})
)
self.assertIsNone(utils.format_dict_of_list(None))
def test_format_dict_of_list_with_separator(self):
expected = "a=a1, a2\nb=b1, b2\nc=c1, c2\ne="
self.assertEqual(expected,
utils.format_dict_of_list({'a': ['a2', 'a1'],
'b': ['b2', 'b1'],
'c': ['c1', 'c2'],
'd': None,
'e': []},
separator='\n')
)
self.assertEqual(expected,
utils.format_dict_of_list({'c': ['c1', 'c2'],
'a': ['a2', 'a1'],
'b': ['b2', 'b1'],
'e': []},
separator='\n')
)
self.assertIsNone(utils.format_dict_of_list(None,
separator='\n'))
def test_format_list(self):
expected = 'a, b, c'
self.assertEqual(expected, utils.format_list(['a', 'b', 'c']))

View File

@ -264,6 +264,31 @@ def format_dict(data):
return output[:-2]
def format_dict_of_list(data, separator='; '):
"""Return a formatted string of key value pair
:param data: a dict, key is string, value is a list of string, for example:
{u'public': [u'2001:db8::8', u'172.24.4.6']}
:param separator: the separator to use between key/value pair
(default: '; ')
:return: a string formatted to {'key1'=['value1', 'value2']} with separated
by separator
"""
if data is None:
return None
output = []
for key in sorted(data):
value = data[key]
if value is None:
continue
value_str = format_list(value)
group = "%s=%s" % (key, value_str)
output.append(group)
return separator.join(output)
def format_list(data, separator=', '):
"""Return a formatted strings