Merge "Remove extra CLI formatters"
This commit is contained in:
commit
7c77bacc40
@ -12,107 +12,6 @@
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
|
||||
import prettytable
|
||||
|
||||
|
||||
def pretty_choice_list(l):
|
||||
return ', '.join("'%s'" % i for i in l)
|
||||
|
||||
|
||||
def print_list(objs, fields, formatters={}, custom_labels={}, sortby=0,
|
||||
outfile=sys.stdout):
|
||||
'''Prints a list of objects.
|
||||
|
||||
:param objs: list of objects to print
|
||||
:param fields: list of attributes of the objects to print;
|
||||
attributes beginning with '!' have a special meaning - they
|
||||
should be used with custom field labels and formatters only,
|
||||
and the formatter receives the whole object
|
||||
:param formatters: dict of functions that perform pre-print
|
||||
formatting of attributes (keys are strings from `fields`
|
||||
parameter, values are functions that take one parameter - the
|
||||
attribute)
|
||||
:param custom_labels: dict of label overrides for fields (keys are
|
||||
strings from `fields` parameter, values are custom labels -
|
||||
headers of the table)
|
||||
'''
|
||||
field_labels = [custom_labels.get(f, f) for f in fields]
|
||||
pt = prettytable.PrettyTable([f for f in field_labels],
|
||||
caching=False, print_empty=False)
|
||||
pt.align = 'l'
|
||||
|
||||
for o in objs:
|
||||
row = []
|
||||
for field in fields:
|
||||
if field[0] == '!': # custom field
|
||||
if field in formatters:
|
||||
row.append(formatters[field](o))
|
||||
else:
|
||||
raise KeyError(
|
||||
'Custom field "%s" needs a formatter.' % field)
|
||||
else: # attribute-based field
|
||||
if hasattr(o, field) and field in formatters:
|
||||
row.append(formatters[field](getattr(o, field)))
|
||||
else:
|
||||
row.append(getattr(o, field, ''))
|
||||
pt.add_row(row)
|
||||
print(pt.get_string(sortby=field_labels[sortby]), file=outfile)
|
||||
|
||||
|
||||
def print_dict(d, formatters={}, custom_labels={}, outfile=sys.stdout):
|
||||
'''Prints a dict to the provided file or file-like object.
|
||||
|
||||
:param d: dict to print
|
||||
:param formatters: dict of functions that perform pre-print
|
||||
formatting of dict values (keys are keys from `d` parameter,
|
||||
values are functions that take one parameter - the dict value
|
||||
to format). A wild card formatter can be provided as '*' which
|
||||
will be applied to all fields without a dedicated formatter.
|
||||
:param custom_labels: dict of label overrides for keys (keys are
|
||||
keys from `d` parameter, values are custom labels)
|
||||
'''
|
||||
pt = prettytable.PrettyTable(['Property', 'Value'],
|
||||
caching=False, print_empty=False)
|
||||
pt.align = 'l'
|
||||
|
||||
global_formatter = formatters.get('*')
|
||||
|
||||
for field in d.keys():
|
||||
label = custom_labels.get(field, field)
|
||||
if field in formatters:
|
||||
pt.add_row([label, formatters[field](d[field])])
|
||||
elif global_formatter:
|
||||
pt.add_row([label, global_formatter(d[field])])
|
||||
else:
|
||||
pt.add_row([label, d[field]])
|
||||
print(pt.get_string(sortby='Property'), file=outfile)
|
||||
|
||||
|
||||
def attr_proxy(attr, formatter=lambda a: a, allow_undefined=True):
|
||||
'''Creates a new formatter function. It will format an object for
|
||||
output by printing it's attribute or running another formatter on
|
||||
that attribute.
|
||||
|
||||
:param attr: name of the attribute to look for on an object
|
||||
:param formatter: formatter to run on that attribute (if not given,
|
||||
the attribute is returned as-is)
|
||||
:param allow_undefined: if true, the created function will return
|
||||
None if `attr` is not defined on the formatted object
|
||||
'''
|
||||
def formatter_proxy(obj):
|
||||
try:
|
||||
attr_value = getattr(obj, attr)
|
||||
except AttributeError as e:
|
||||
if allow_undefined:
|
||||
return None
|
||||
else:
|
||||
raise e
|
||||
return formatter(attr_value)
|
||||
|
||||
return formatter_proxy
|
||||
|
||||
|
||||
def attributes_formatter(attributes):
|
||||
"""Given a simple dict format the keyvalue pairs with one on each line.
|
||||
@ -127,20 +26,6 @@ def parameters_v2_formatter(parameters):
|
||||
for parameter in parameters)
|
||||
|
||||
|
||||
def counts_formatter(counts):
|
||||
"""Given a list of dicts that represent Overcloud Roles output the
|
||||
Overcloud Role ID with the num_noces
|
||||
"""
|
||||
|
||||
pretty_counts = []
|
||||
|
||||
for count in counts:
|
||||
line = "{0}={1}".format(count['overcloud_role_id'], count['num_nodes'])
|
||||
pretty_counts.append(line)
|
||||
|
||||
return u"\n".join(pretty_counts)
|
||||
|
||||
|
||||
def list_plan_roles_formatter(roles):
|
||||
"""Given a list of Roles format roles' names into row."""
|
||||
return u", ".join(role.name for role in roles)
|
||||
|
@ -10,70 +10,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
import six
|
||||
|
||||
import tuskarclient.common.formatting as fmt
|
||||
import tuskarclient.tests.utils as tutils
|
||||
from tuskarclient.v2 import plans
|
||||
|
||||
|
||||
class PrintTest(tutils.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(PrintTest, self).setUp()
|
||||
self.outfile = six.StringIO()
|
||||
|
||||
def test_print_dict(self):
|
||||
dict_ = {'k': 'v', 'key': 'value'}
|
||||
formatters = {'key': lambda v: 'custom ' + v}
|
||||
custom_labels = {'k': 'custom_key'}
|
||||
|
||||
fmt.print_dict(dict_, formatters, custom_labels,
|
||||
outfile=self.outfile)
|
||||
self.assertEqual(
|
||||
('+------------+--------------+\n'
|
||||
'| Property | Value |\n'
|
||||
'+------------+--------------+\n'
|
||||
'| custom_key | v |\n'
|
||||
'| key | custom value |\n'
|
||||
'+------------+--------------+\n'),
|
||||
self.outfile.getvalue()
|
||||
)
|
||||
|
||||
def test_print_list(self):
|
||||
fields = ['thing', 'color', '!artistic_name']
|
||||
formatters = {
|
||||
'!artistic_name': lambda obj: '{0} {1}'.format(obj.color,
|
||||
obj.thing),
|
||||
'color': lambda c: c.split(' ')[1],
|
||||
}
|
||||
custom_labels = {'thing': 'name', '!artistic_name': 'artistic name'}
|
||||
|
||||
fmt.print_list(self.objects(), fields, formatters, custom_labels,
|
||||
outfile=self.outfile)
|
||||
self.assertEqual(
|
||||
('+------+-------+-----------------+\n'
|
||||
'| name | color | artistic name |\n'
|
||||
'+------+-------+-----------------+\n'
|
||||
'| moon | green | dark green moon |\n'
|
||||
'| sun | blue | bright blue sun |\n'
|
||||
'+------+-------+-----------------+\n'),
|
||||
self.outfile.getvalue()
|
||||
)
|
||||
|
||||
def test_print_list_custom_field_without_formatter(self):
|
||||
fields = ['!artistic_name']
|
||||
|
||||
self.assertRaises(KeyError, fmt.print_list, self.objects(), fields)
|
||||
|
||||
def objects(self):
|
||||
return [
|
||||
mock.Mock(thing='sun', color='bright blue'),
|
||||
mock.Mock(thing='moon', color='dark green'),
|
||||
]
|
||||
|
||||
|
||||
class FormattersTest(tutils.TestCase):
|
||||
|
||||
def test_attributes_formatter(self):
|
||||
@ -89,18 +30,6 @@ class FormattersTest(tutils.TestCase):
|
||||
fmt.attributes_formatter(attributes),
|
||||
)
|
||||
|
||||
def test_counts_formatter(self):
|
||||
|
||||
resource_link = [
|
||||
{'overcloud_role_id': 1, 'num_nodes': 10},
|
||||
{'overcloud_role_id': 2, 'num_nodes': 20}
|
||||
]
|
||||
|
||||
self.assertEqual(
|
||||
("1=10\n2=20"),
|
||||
fmt.counts_formatter(resource_link),
|
||||
)
|
||||
|
||||
def test_list_plan_roles_formatter(self):
|
||||
roles = plans.Plan(None,
|
||||
{'roles': [{'name': 'foo_role'},
|
||||
|
@ -42,7 +42,7 @@ class BasePlansShellTest(tutils.TestCase):
|
||||
|
||||
class PlansShellTest(BasePlansShellTest):
|
||||
|
||||
@mock.patch('tuskarclient.common.formatting.print_list')
|
||||
@mock.patch('tuskarclient.openstack.common.cliutils.print_list')
|
||||
def test_plan_list(self, mock_print_list):
|
||||
args = empty_args()
|
||||
|
||||
|
@ -35,7 +35,7 @@ class BaseRolesShellTest(tutils.TestCase):
|
||||
|
||||
class RolesShellTest(BaseRolesShellTest):
|
||||
|
||||
@mock.patch('tuskarclient.common.formatting.print_list')
|
||||
@mock.patch('tuskarclient.openstack.common.cliutils.print_list')
|
||||
def test_role_list(self, mock_print_list):
|
||||
args = empty_args()
|
||||
|
||||
|
@ -17,6 +17,7 @@ import sys
|
||||
|
||||
import tuskarclient.common.formatting as fmt
|
||||
from tuskarclient.common import utils
|
||||
from tuskarclient.openstack.common import cliutils
|
||||
|
||||
|
||||
def do_plan_list(tuskar, args, outfile=sys.stdout):
|
||||
@ -28,7 +29,7 @@ def do_plan_list(tuskar, args, outfile=sys.stdout):
|
||||
'roles': fmt.list_plan_roles_formatter,
|
||||
}
|
||||
|
||||
fmt.print_list(plans, fields, formatters, outfile=outfile)
|
||||
cliutils.print_list(plans, fields, formatters, outfile=outfile)
|
||||
|
||||
|
||||
@utils.arg('plan', metavar="<PLAN>",
|
||||
@ -47,7 +48,7 @@ def print_plan_detail(plan, outfile=sys.stdout):
|
||||
'parameters': fmt.parameters_v2_formatter,
|
||||
}
|
||||
plan_dict = plan.to_dict()
|
||||
fmt.print_dict(plan_dict, formatters, outfile=outfile)
|
||||
cliutils.print_dict(plan_dict, formatters, outfile=outfile)
|
||||
|
||||
|
||||
@utils.arg('plan', metavar="<PLAN>",
|
||||
|
@ -14,7 +14,7 @@ from __future__ import print_function
|
||||
|
||||
import sys
|
||||
|
||||
import tuskarclient.common.formatting as fmt
|
||||
from tuskarclient.openstack.common import cliutils
|
||||
|
||||
|
||||
def do_role_list(tuskar, args, outfile=sys.stdout):
|
||||
@ -25,4 +25,4 @@ def do_role_list(tuskar, args, outfile=sys.stdout):
|
||||
formatters = {
|
||||
}
|
||||
|
||||
fmt.print_list(roles, fields, formatters, outfile=outfile)
|
||||
cliutils.print_list(roles, fields, formatters, outfile=outfile)
|
||||
|
Loading…
x
Reference in New Issue
Block a user