protobuf: improve prettyprint formatting

pull/25/head
matejcik 6 years ago
parent eed91db880
commit 1e4c1c093e

@ -41,7 +41,7 @@ required:
import binascii
from io import BytesIO
from typing import Any
from typing import Any, Optional
_UVARINT_BUFFER = bytearray(1)
@ -348,37 +348,63 @@ def dump_message(writer, msg):
raise TypeError
def format_message(pb: MessageType, indent: int=0, sep: str= ' ' * 4) -> str:
def format_message(pb: MessageType,
indent: int = 0,
sep: str = ' ' * 4,
truncate_after: Optional[int] = 256,
truncate_to: Optional[int] = 64,
collapse_cointypes: bool = False) -> str:
def mostly_printable(bytes):
if not bytes:
return True
printable = sum(1 for byte in bytes if 0x20 <= byte <= 0x7e)
return printable / len(bytes) > 0.8
def pformat_value(value: Any, indent: int) -> str:
level = sep * indent
leadin = sep * (indent + 1)
if isinstance(value, MessageType):
return format_message(value, indent, sep)
if isinstance(value, list):
lines = []
lines.append('[')
lines += [leadin + pformat_value(x, indent + 1) + ',' for x in value]
lines.append(level + ']')
# short list of simple values
if not value or not isinstance(value[0], MessageType):
return repr(value)
# long list, one line per entry
lines = ['[', level + ']']
lines[1:1] = [leadin + pformat_value(x, indent + 1) + ',' for x in value]
return '\n'.join(lines)
if isinstance(value, dict):
lines = []
lines.append('{')
lines = ['{']
for key, val in sorted(value.items()):
if val is None or val == []:
continue
if key == 'address_n' and isinstance(val, list):
lines.append(leadin + key + ': ' + repr(val) + ',')
else:
lines.append(leadin + key + ': ' + pformat_value(val, indent + 1) + ',')
lines.append(leadin + key + ': ' + pformat_value(val, indent + 1) + ',')
lines.append(level + '}')
return '\n'.join(lines)
if isinstance(value, bytearray):
return 'bytearray(0x{})'.format(binascii.hexlify(value).decode('ascii'))
if isinstance(value, (bytes, bytearray)):
length = len(value)
suffix = ''
if truncate_after and length > truncate_after:
suffix = '...'
value = value[:truncate_to or 0]
if mostly_printable(value):
output = repr(value)
else:
output = '0x' + binascii.hexlify(value).decode('ascii')
return '{} bytes {}{}'.format(length, output, suffix)
return repr(value)
from .messages import Features
pb_dict = pb.__dict__.copy()
if collapse_cointypes and isinstance(pb, Features):
del pb_dict['coins']
pb_dict['coins (shortened)'] = ' '.join(coin.coin_shortcut for coin in pb.coins)
return '{name} ({size} bytes) {content}'.format(
name=pb.__class__.__name__,
size=pb.ByteSize(),
content=pformat_value(pb.__dict__, indent)
content=pformat_value(pb_dict, indent)
)

Loading…
Cancel
Save