Issue #17530: pprint now wraps long bytes objects and bytearrays.

This commit is contained in:
Serhiy Storchaka 2015-03-24 19:22:37 +02:00
parent 8e2aa88a40
commit 022f20376a
3 changed files with 149 additions and 0 deletions

View File

@ -283,6 +283,36 @@ class PrettyPrinter:
_dispatch[str.__repr__] = _pprint_str
def _pprint_bytes(self, object, stream, indent, allowance, context, level):
write = stream.write
if len(object) <= 4:
write(repr(object))
return
parens = level == 1
if parens:
indent += 1
allowance += 1
write('(')
delim = ''
for rep in _wrap_bytes_repr(object, self._width - indent, allowance):
write(delim)
write(rep)
if not delim:
delim = '\n' + ' '*indent
if parens:
write(')')
_dispatch[bytes.__repr__] = _pprint_bytes
def _pprint_bytearray(self, object, stream, indent, allowance, context, level):
write = stream.write
write('bytearray(')
self._pprint_bytes(bytes(object), stream, indent + 10,
allowance + 1, context, level + 1)
write(')')
_dispatch[bytearray.__repr__] = _pprint_bytearray
def _format_dict_items(self, items, stream, indent, allowance, context,
level):
write = stream.write
@ -463,5 +493,22 @@ def _perfcheck(object=None):
print("_safe_repr:", t2 - t1)
print("pformat:", t3 - t2)
def _wrap_bytes_repr(object, width, allowance):
current = b''
last = len(object) // 4 * 4
for i in range(0, len(object), 4):
part = object[i: i+4]
candidate = current + part
if i == last:
width -= allowance
if len(repr(candidate)) > width:
if current:
yield repr(current)
current = part
else:
current = candidate
if current:
yield repr(current)
if __name__ == "__main__":
_perfcheck()

View File

@ -658,6 +658,106 @@ frozenset2({0,
self.assertLessEqual(maxwidth, w)
self.assertGreater(maxwidth, w - 3)
def test_bytes_wrap(self):
self.assertEqual(pprint.pformat(b'', width=1), "b''")
self.assertEqual(pprint.pformat(b'abcd', width=1), "b'abcd'")
letters = b'abcdefghijklmnopqrstuvwxyz'
self.assertEqual(pprint.pformat(letters, width=29), repr(letters))
self.assertEqual(pprint.pformat(letters, width=19), """\
(b'abcdefghijkl'
b'mnopqrstuvwxyz')""")
self.assertEqual(pprint.pformat(letters, width=18), """\
(b'abcdefghijkl'
b'mnopqrstuvwx'
b'yz')""")
self.assertEqual(pprint.pformat(letters, width=16), """\
(b'abcdefghijkl'
b'mnopqrstuvwx'
b'yz')""")
special = bytes(range(16))
self.assertEqual(pprint.pformat(special, width=61), repr(special))
self.assertEqual(pprint.pformat(special, width=48), """\
(b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b'
b'\\x0c\\r\\x0e\\x0f')""")
self.assertEqual(pprint.pformat(special, width=32), """\
(b'\\x00\\x01\\x02\\x03'
b'\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b'
b'\\x0c\\r\\x0e\\x0f')""")
self.assertEqual(pprint.pformat(special, width=1), """\
(b'\\x00\\x01\\x02\\x03'
b'\\x04\\x05\\x06\\x07'
b'\\x08\\t\\n\\x0b'
b'\\x0c\\r\\x0e\\x0f')""")
self.assertEqual(pprint.pformat({'a': 1, 'b': letters, 'c': 2},
width=21), """\
{'a': 1,
'b': b'abcdefghijkl'
b'mnopqrstuvwx'
b'yz',
'c': 2}""")
self.assertEqual(pprint.pformat({'a': 1, 'b': letters, 'c': 2},
width=20), """\
{'a': 1,
'b': b'abcdefgh'
b'ijklmnop'
b'qrstuvwxyz',
'c': 2}""")
self.assertEqual(pprint.pformat([[[[[[letters]]]]]], width=25), """\
[[[[[[b'abcdefghijklmnop'
b'qrstuvwxyz']]]]]]""")
self.assertEqual(pprint.pformat([[[[[[special]]]]]], width=41), """\
[[[[[[b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07'
b'\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f']]]]]]""")
# Check that the pprint is a usable repr
for width in range(1, 64):
formatted = pprint.pformat(special, width=width)
self.assertEqual(eval(formatted), special)
formatted = pprint.pformat([special] * 2, width=width)
self.assertEqual(eval(formatted), [special] * 2)
def test_bytearray_wrap(self):
self.assertEqual(pprint.pformat(bytearray(), width=1), "bytearray(b'')")
letters = bytearray(b'abcdefghijklmnopqrstuvwxyz')
self.assertEqual(pprint.pformat(letters, width=40), repr(letters))
self.assertEqual(pprint.pformat(letters, width=28), """\
bytearray(b'abcdefghijkl'
b'mnopqrstuvwxyz')""")
self.assertEqual(pprint.pformat(letters, width=27), """\
bytearray(b'abcdefghijkl'
b'mnopqrstuvwx'
b'yz')""")
self.assertEqual(pprint.pformat(letters, width=25), """\
bytearray(b'abcdefghijkl'
b'mnopqrstuvwx'
b'yz')""")
special = bytearray(range(16))
self.assertEqual(pprint.pformat(special, width=72), repr(special))
self.assertEqual(pprint.pformat(special, width=57), """\
bytearray(b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b'
b'\\x0c\\r\\x0e\\x0f')""")
self.assertEqual(pprint.pformat(special, width=41), """\
bytearray(b'\\x00\\x01\\x02\\x03'
b'\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b'
b'\\x0c\\r\\x0e\\x0f')""")
self.assertEqual(pprint.pformat(special, width=1), """\
bytearray(b'\\x00\\x01\\x02\\x03'
b'\\x04\\x05\\x06\\x07'
b'\\x08\\t\\n\\x0b'
b'\\x0c\\r\\x0e\\x0f')""")
self.assertEqual(pprint.pformat({'a': 1, 'b': letters, 'c': 2},
width=31), """\
{'a': 1,
'b': bytearray(b'abcdefghijkl'
b'mnopqrstuvwx'
b'yz'),
'c': 2}""")
self.assertEqual(pprint.pformat([[[[[letters]]]]], width=37), """\
[[[[[bytearray(b'abcdefghijklmnop'
b'qrstuvwxyz')]]]]]""")
self.assertEqual(pprint.pformat([[[[[special]]]]], width=50), """\
[[[[[bytearray(b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07'
b'\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f')]]]]]""")
class DottedPrettyPrinter(pprint.PrettyPrinter):

View File

@ -26,6 +26,8 @@ Core and Builtins
Library
-------
- Issue #17530: pprint now wraps long bytes objects and bytearrays.
- Issue #22687: Fixed some corner cases in breaking words in tetxtwrap.
Got rid of quadratic complexity in breaking long words.