Stream generated JSON.

This commit is contained in:
Tom Ritchford
2014-08-27 20:54:42 -04:00
committed by Nik Bougalis
parent c65fb91878
commit 95c1c5f54e
9 changed files with 124 additions and 47 deletions

View File

@@ -7,6 +7,7 @@ import os
from ripple.ledger import LedgerNumber
from ripple.util import File
from ripple.util import Log
from ripple.util import PrettyPrint
from ripple.util import Range
from ripple.util.Function import Function
@@ -159,6 +160,8 @@ if ARGS.window < 0:
raise ValueError('Window cannot be negative: --window=%d' %
ARGS.window)
PrettyPrint.INDENT = (ARGS.indent * ' ')
_loaders = bool(ARGS.server) + bool(ARGS.rippled)
if not _loaders:

View File

@@ -1,21 +0,0 @@
from __future__ import absolute_import, division, print_function, unicode_literals
from ripple.ledger.Args import ARGS
from functools import wraps
import json
def pretty_print(item):
return json.dumps(item,
sort_keys=True,
indent=ARGS.indent,
separators=(',', ': '))
def pretty(f):
""""A decorator on a function that makes its results pretty """
@wraps(f)
def wrapper(*args, **kwds):
result = list(f(*args, **kwds))
return pretty_print(result)
return wrapper

View File

@@ -1,9 +1,9 @@
from __future__ import absolute_import, division, print_function, unicode_literals
from ripple.ledger.Args import ARGS
from ripple.ledger.PrettyPrint import pretty_print
from ripple.util import Log
from ripple.util import Range
from ripple.util.PrettyPrint import pretty_print
SAFE = True

View File

@@ -1,9 +1,9 @@
from __future__ import absolute_import, division, print_function, unicode_literals
from ripple.ledger.Args import ARGS
from ripple.ledger.PrettyPrint import pretty_print
from ripple.util import Log
from ripple.util import Range
from ripple.util.PrettyPrint import pretty_print
SAFE = True

View File

@@ -12,5 +12,4 @@ HELP = """print
Print the ledgers to stdout. The default command."""
def run_print(server):
for x in ARGS.display(server, SearchLedgers.search(server)):
print(x)
ARGS.display(print, server, SearchLedgers.search(server))

View File

@@ -5,11 +5,11 @@ from functools import wraps
import jsonpath_rw
from ripple.ledger.Args import ARGS
from ripple.ledger.PrettyPrint import pretty_print
from ripple.util import Dict
from ripple.util import Log
from ripple.util import Range
from ripple.util.Decimal import Decimal
from ripple.util.PrettyPrint import pretty_print, Streamer
TRANSACT_FIELDS = (
'accepted',
@@ -33,33 +33,30 @@ LEDGER_FIELDS = (
def _dict_filter(d, keys):
return dict((k, v) for (k, v) in d.items() if k in keys)
def ledger_number(server, numbers):
yield Range.to_string(numbers)
def ledger_number(print, server, numbers):
print(Range.to_string(numbers))
def display(f):
"""A decorator for displays that just print JSON"""
@wraps(f)
def wrapper(server, numbers, *args, **kwds):
def wrapper(printer, server, numbers, *args):
streamer = Streamer(printer=printer)
for number in numbers:
ledger = server.get_ledger(number, ARGS.full)
if ledger:
yield pretty_print(f(ledger, *args, **kwds))
streamer.add(number, f(ledger, *args))
streamer.finish()
return wrapper
def json(f):
"""A decorator for displays that print JSON, extracted by a path"""
def extractor(f):
@wraps(f)
def wrapper(server, numbers, path, *args, **kwds):
def wrapper(printer, server, numbers, *paths):
try:
path_expr = jsonpath_rw.parse(path)
find = jsonpath_rw.parse('|'.join(paths)).find
except:
raise ValueError("Can't understand jsonpath '%s'." % path)
for number in numbers:
ledger = server.get_ledger(number, ARGS.full)
if ledger:
finds = path_expr.find(ledger)
yield pretty_print(f(finds, *args, **kwds))
def fn(ledger, *args):
return f(find(ledger), *args)
display(fn)(printer, server, numbers)
return wrapper
@display
@@ -67,6 +64,7 @@ def ledger(ledger, full=False):
if ARGS.full:
if full:
return ledger
ledger = Dict.prune(ledger, 1, False)
return _dict_filter(ledger, LEDGER_FIELDS)
@@ -79,11 +77,11 @@ def prune(ledger, level=1):
def transact(ledger):
return _dict_filter(ledger, TRANSACT_FIELDS)
@json
@extractor
def extract(finds):
return dict((str(f.full_path), str(f.value)) for f in finds)
@json
@extractor
def sum(finds):
d = Decimal()
for f in finds:

View File

@@ -52,10 +52,10 @@ class Function(object):
default_path += '.'
self.function = default_path + self.function
p, m = self.function.rsplit('.', 1)
try:
mod = importlib.import_module(p)
except:
raise ValueError('Can\'t find Python module "%s"' % p)
mod = importlib.import_module(p)
# Errors in modules are swallowed here.
# except:
# raise ValueError('Can\'t find Python module "%s"' % p)
try:
self.function = getattr(mod, m)

View File

@@ -0,0 +1,42 @@
from __future__ import absolute_import, division, print_function, unicode_literals
from functools import wraps
import json
SEPARATORS = ',', ': '
INDENT = ' '
def pretty_print(item):
return json.dumps(item,
sort_keys=True,
indent=len(INDENT),
separators=SEPARATORS)
class Streamer(object):
def __init__(self, printer=print):
# No automatic spacing or carriage returns.
self.printer = lambda *args: printer(*args, end='', sep='')
self.first_key = True
def add(self, key, value):
if self.first_key:
self.first_key = False
self.printer('{')
else:
self.printer(',')
self.printer('\n', INDENT, '"', str(key), '": ')
pp = pretty_print(value).splitlines()
if len(pp) > 1:
for i, line in enumerate(pp):
if i > 0:
self.printer('\n', INDENT)
self.printer(line)
else:
self.printer(pp[0])
def finish(self):
if not self.first_key:
self.first_key = True
self.printer('\n}')

View File

@@ -0,0 +1,56 @@
from __future__ import absolute_import, division, print_function, unicode_literals
from ripple.util import PrettyPrint
from unittest import TestCase
class test_PrettyPrint(TestCase):
def setUp(self):
self._results = []
self.printer = PrettyPrint.Streamer(printer=self.printer)
def printer(self, *args, **kwds):
self._results.extend(args)
def run_test(self, expected, *args):
for i in range(0, len(args), 2):
self.printer.add(args[i], args[i + 1])
self.printer.finish()
self.assertEquals(''.join(self._results), expected)
def test_simple_printer(self):
self.run_test(
'{\n "foo": "bar"\n}',
'foo', 'bar')
def test_multiple_lines(self):
self.run_test(
'{\n "foo": "bar",\n "baz": 5\n}',
'foo', 'bar', 'baz', 5)
def test_multiple_lines(self):
self.run_test(
"""
{
"foo": {
"bar": 1,
"baz": true
},
"bang": "bing"
}
""".strip(), 'foo', {'bar': 1, 'baz': True}, 'bang', 'bing')
def test_multiple_lines_with_list(self):
self.run_test(
"""
{
"foo": [
"bar",
1
],
"baz": [
23,
42
]
}
""".strip(), 'foo', ['bar', 1], 'baz', [23, 42])