Merge "Handle complex objects in yaml formatter better"

This commit is contained in:
Zuul 2023-09-11 09:24:42 +00:00 committed by Gerrit Code Review
commit 3ee0725a09
2 changed files with 66 additions and 9 deletions

@ -17,6 +17,17 @@ from . import base
from cliff import columns
def _yaml_friendly(value):
if isinstance(value, columns.FormattableColumn):
return value.machine_readable()
elif hasattr(value, "toDict"):
return value.toDict()
elif hasattr(value, "to_dict"):
return value.to_dict()
else:
return value
class YAMLFormatter(base.ListFormatter, base.SingleFormatter):
def add_argument_group(self, parser):
@ -29,10 +40,7 @@ class YAMLFormatter(base.ListFormatter, base.SingleFormatter):
items = []
for item in data:
items.append(
{n: (i.machine_readable()
if isinstance(i, columns.FormattableColumn)
else i)
for n, i in zip(column_names, item)}
{n: _yaml_friendly(i) for n, i in zip(column_names, item)}
)
yaml.safe_dump(items, stream=stdout, default_flow_style=False)
@ -41,9 +49,5 @@ class YAMLFormatter(base.ListFormatter, base.SingleFormatter):
import yaml
for key, value in zip(column_names, data):
dict_data = {
key: (value.machine_readable()
if isinstance(value, columns.FormattableColumn)
else value)
}
dict_data = {key: _yaml_friendly(value)}
yaml.safe_dump(dict_data, stream=stdout, default_flow_style=False)

@ -22,6 +22,23 @@ from cliff.tests import base
from cliff.tests import test_columns
class _toDict:
def __init__(self, **kwargs):
self._data = kwargs
def toDict(self):
return self._data
class _to_Dict:
def __init__(self, **kwargs):
self._data = kwargs
def to_dict(self):
return self._data
class TestYAMLFormatter(base.TestBase):
def test_format_one(self):
@ -98,3 +115,39 @@ class TestYAMLFormatter(base.TestBase):
sf.emit_list(c, d, output, args)
actual = yaml.safe_load(output.getvalue())
self.assertEqual(expected, actual)
def test_one_custom_object(self):
sf = yaml_format.YAMLFormatter()
c = ('a', 'b', 'toDict', 'to_dict')
d = ('A', 'B', _toDict(spam="ham"), _to_Dict(ham="eggs"))
expected = {
'a': 'A',
'b': 'B',
'toDict': {"spam": "ham"},
'to_dict': {"ham": "eggs"}
}
output = StringIO()
args = mock.Mock()
sf.emit_one(c, d, output, args)
actual = yaml.safe_load(output.getvalue())
self.assertEqual(expected, actual)
def test_list_custom_object(self):
sf = yaml_format.YAMLFormatter()
c = ('a', 'toDict', 'to_dict')
d = (
('A1', _toDict(B=1), _to_Dict(C=1)),
('A2', _toDict(B=2), _to_Dict(C=2)),
('A3', _toDict(B=3), _to_Dict(C=3))
)
expected = [
{'a': 'A1', 'toDict': {'B': 1}, 'to_dict': {'C': 1}},
{'a': 'A2', 'toDict': {'B': 2}, 'to_dict': {'C': 2}},
{'a': 'A3', 'toDict': {'B': 3}, 'to_dict': {'C': 3}}
]
output = StringIO()
args = mock.Mock()
sf.add_argument_group(args)
sf.emit_list(c, d, output, args)
actual = yaml.safe_load(output.getvalue())
self.assertEqual(expected, actual)