Skip to content
Snippets Groups Projects
Commit 606644c1 authored by Pavlo Shchelokovskyy's avatar Pavlo Shchelokovskyy Committed by Pavlo Shchelokovskyy
Browse files

Handle complex objects in yaml formatter better

this patch adds special handling of objects that have either 'toDict'
or 'to_dict' method, converting those to dictionary before passing
them to pyYaml.

The main immediate aim is to support instances of
openstack.utils.Munch class in the YAML output.

Story: 2010906
Task: 48728
Change-Id: If3718477533987b6b88b27ac639c6689a2e4b327
parent 6096869f
No related branches found
No related tags found
No related merge requests found
......@@ -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)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment