Implement a json formatter in cliff

This change replaces the cliff-tablib json formatter with an internal
replacement. It differs from the tablib formatter in the following ways:
- by default outputs with an indent of 2 spaces. The --noindent formatting
  argument outputs with no indentation, to save space or to pipe to tools
  which can't handle multi-line input.
- emit_one serialises a simple dict where the column name is the key
and the data item is the value (rather than a list of dicts with
'Field' and 'Value' keys)

The cliff release which contains this change will need a corresponding
cliff-tablib release which removes the json formatter from its setup.py
entry_points.

Change-Id: I7f9b1f339d96ead347a0c9d95ec7004a78d8c9d5
Related-Bug: #1308744
This commit is contained in:
Steve Baker 2015-08-17 15:29:29 +12:00
parent 0a8daff7bd
commit 4e1470d93e
5 changed files with 148 additions and 4 deletions

View File

@ -0,0 +1,30 @@
"""Output formatters for JSON.
"""
import json
from .base import ListFormatter, SingleFormatter
class JSONFormatter(ListFormatter, SingleFormatter):
def add_argument_group(self, parser):
group = parser.add_argument_group(title='json formatter')
group.add_argument(
'--noindent',
action='store_true',
dest='noindent',
help='whether to disable indenting the JSON'
)
def emit_list(self, column_names, data, stdout, parsed_args):
items = []
for item in data:
items.append(dict(zip(column_names, item)))
indent = None if parsed_args.noindent else 2
json.dump(items, stdout, indent=indent)
def emit_one(self, column_names, data, stdout, parsed_args):
one = dict(zip(column_names, data))
indent = None if parsed_args.noindent else 2
json.dump(one, stdout, indent=indent)

View File

@ -0,0 +1,71 @@
#!/usr/bin/env python
from six import StringIO
import json
from cliff.formatters import json_format
import mock
def test_json_format_one():
sf = json_format.JSONFormatter()
c = ('a', 'b', 'c', 'd')
d = ('A', 'B', 'C', '"escape me"')
expected = {
'a': 'A',
'b': 'B',
'c': 'C',
'd': '"escape me"'
}
args = mock.Mock()
sf.add_argument_group(args)
args.noindent = True
output = StringIO()
sf.emit_one(c, d, output, args)
value = output.getvalue()
print(len(value.splitlines()))
assert 1 == len(value.splitlines())
actual = json.loads(value)
assert expected == actual
args.noindent = False
output = StringIO()
sf.emit_one(c, d, output, args)
value = output.getvalue()
assert 6 == len(value.splitlines())
actual = json.loads(value)
assert expected == actual
def test_json_format_list():
sf = json_format.JSONFormatter()
c = ('a', 'b', 'c')
d = (
('A1', 'B1', 'C1'),
('A2', 'B2', 'C2'),
('A3', 'B3', 'C3')
)
expected = [
{'a': 'A1', 'b': 'B1', 'c': 'C1'},
{'a': 'A2', 'b': 'B2', 'c': 'C2'},
{'a': 'A3', 'b': 'B3', 'c': 'C3'}
]
args = mock.Mock()
sf.add_argument_group(args)
args.noindent = True
output = StringIO()
sf.emit_list(c, d, output, args)
value = output.getvalue()
assert 1 == len(value.splitlines())
actual = json.loads(value)
assert expected == actual
args.noindent = False
output = StringIO()
sf.emit_list(c, d, output, args)
value = output.getvalue()
assert 17 == len(value.splitlines())
actual = json.loads(value)
assert expected == actual

View File

@ -114,11 +114,35 @@ mappings.
- Name: cliffdemo
Size: 4096
json
----
The ``json`` formatter produces an array of objects in indented JSON
format.
::
(.venv)$ cliffdemo files -f json
[
{
"Name": "source",
"Size": 4096
},
{
"Name": "Makefile",
"Size": 5569
},
{
"Name": "build",
"Size": 4096
}
]
Other Formatters
----------------
Formatters using tablib_ to produce JSON and HTML are available
as part of `cliff-tablib`_.
A formatter using tablib_ to produce HTML is available as part of
`cliff-tablib`_.
.. _cliff-tablib: https://github.com/dreamhost/cliff-tablib

View File

@ -100,11 +100,28 @@ the field name is the key.
GID: 1000
Modified Time: 1393531476.9587486
json
----
The ``json`` formatter produces a JSON object where the field name
is the key.
::
(.venv)$ cliffdemo file -f json setup.py
{
"Modified Time": 1438726433.8055942,
"GID": 1000,
"UID": 1000,
"Name": "setup.py",
"Size": 1028
}
Other Formatters
----------------
Formatters using tablib_ to produce JSON and HTML are available
as part of `cliff-tablib`_.
A formatter using tablib_ to produce HTML is available as part of
`cliff-tablib`_.
.. _cliff-tablib: https://github.com/dreamhost/cliff-tablib

View File

@ -31,12 +31,14 @@ cliff.formatter.list =
csv = cliff.formatters.commaseparated:CSVLister
value = cliff.formatters.value:ValueFormatter
yaml = cliff.formatters.yaml_format:YAMLFormatter
json = cliff.formatters.json_format:JSONFormatter
cliff.formatter.show =
table = cliff.formatters.table:TableFormatter
shell = cliff.formatters.shell:ShellFormatter
value = cliff.formatters.value:ValueFormatter
yaml = cliff.formatters.yaml_format:YAMLFormatter
json = cliff.formatters.json_format:JSONFormatter
cliff.formatter.completion =
bash = cliff.complete:CompleteBash