diff -r 193e7ad92900 Doc/library/pprint.rst --- a/Doc/library/pprint.rst Mon Apr 15 11:59:35 2013 +0100 +++ b/Doc/library/pprint.rst Mon Apr 15 09:45:38 2013 -0400 @@ -331,3 +331,14 @@ 'written in Python', 'version': '12.3.0'}, 'urls': [{...}, {...}]} + +Long bytes objects will also be wrapped, though they will always display at +least one byte per line: + + >>> pprint.pprint(b"\n\n\n\n\n\n", width=1) + b'\n'\ + b'\n'\ + b'\n'\ + b'\n'\ + b'\n'\ + b'\n' diff -r 193e7ad92900 Lib/pprint.py --- a/Lib/pprint.py Mon Apr 15 11:59:35 2013 +0100 +++ b/Lib/pprint.py Mon Apr 15 09:45:38 2013 -0400 @@ -240,7 +240,7 @@ write(endchar) return - if issubclass(typ, str) and len(object) > 0 and r is str.__repr__: + if issubclass(typ, str) and _len(object) > 0 and r is str.__repr__: def _str_parts(s): """ Return a list of string literals comprising the repr() @@ -255,10 +255,10 @@ # A list of alternating (non-space, space) strings parts = re.split(r'(\s+)', line) + [''] current = '' - for i in range(0, len(parts), 2): + for i in range(0, _len(parts), 2): part = parts[i] + parts[i+1] candidate = current + part - if len(repr(candidate)) > max_width: + if _len(repr(candidate)) > max_width: if current: yield repr(current) current = part @@ -271,6 +271,37 @@ write('\n' + ' '*indent) write(rep) return + + if issubclass(typ, bytes) and _len(object) > 1 and \ + r is bytes.__repr__: + # 0 or 1 length bytes will always be un-wrapped + def _bytes_parts(b): + """Return a list of bytes literals comprising the repr() + of the given butes using literal concatenation.""" + offset = 1 + chunk = b[:1] + chunk_len = _len(repr(chunk)+"\\") + end_b = _len(b) + while offset < end_b: + p = b[offset:offset+1] + rp = repr(p)[2:-1] # -- Get the repr of just this byte + rp_len = _len(rp) + if (rp_len + chunk_len) > max_width: + yield repr(chunk)+"\\" + chunk = b'' + chunk_len = 4 + chunk += p + chunk_len += rp_len + offset += 1 + + if chunk: + yield repr(chunk) + + for i, rep in enumerate(_bytes_parts(object)): + if i > 0: + write('\n' + ' '*indent) + write(rep) + return write(rep) def _repr(self, object, context, level): diff -r 193e7ad92900 Lib/test/test_pprint.py --- a/Lib/test/test_pprint.py Mon Apr 15 11:59:35 2013 +0100 +++ b/Lib/test/test_pprint.py Mon Apr 15 09:45:38 2013 -0400 @@ -513,6 +513,73 @@ formatted = pprint.pformat(special, width=width) self.assertEqual(eval("(" + formatted + ")"), special) + def test_bytes_wrap(self): + # pprint tries to wrap long bytes literals intelligently + def _t_raw(formatted, width): + def _t_line(line, eval_line, cant_be_zero): + line_bytes = len(eval(eval_line)) + if cant_be_zero: + self.assertNotEqual(0, line_bytes) + if line_bytes>1: + self.assertLessEqual(len(line), width, formatted) + + lines = formatted.split("\n") + if len(lines)>1: + for line in lines[:-1]: + # -- Must end w/ continuation + self.assertEqual("\\", line[-1], line) + _t_line(line, line[:-1], cant_be_zero=True) + _t_line(lines[-1], lines[-1], cant_be_zero=True) + + else: + _t_line(formatted, formatted, cant_be_zero=False) + + + def _t(input, width, expected): + formatted = pprint.pformat(input, width=width) + if issubclass(type(input), bytes): + _t_raw(formatted, width) + self.assertEqual(formatted, expected) + self.assertEqual(eval(formatted), input) + + _t(b'', 20, "b''") + _t(b'\n', 20, "b'\\n'") + _t(b'a', 20, "b'a'") + _t(b'\x00', 20, "b'\\x00'") + _t(b'\\', 20, "b'\\\\'") + _t(b'\n\n\n\n\n\n', 5, """\ +b'\\n'\\ +b'\\n'\\ +b'\\n'\\ +b'\\n'\\ +b'\\n'\\ +b'\\n'""") + + # -- Worst case, always print one byte per line if width is less than + _t(b'\n\n\n\n\n\n', 1, """\ +b'\\n'\\ +b'\\n'\\ +b'\\n'\\ +b'\\n'\\ +b'\\n'\\ +b'\\n'""") + _t(b'\n\n\n\n\n\n', 1000, "b'\\n\\n\\n\\n\\n\\n'") + + _t(b'\x00\xff'*20, 79, """\ +b'\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff'\\ +b'\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff'\\ +b'\\x00\\xff\\x00\\xff'""") + + _t({"a":b'\x00\xff'*20,"c":b'\n'}, 79, """\ +{'a': b'\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff'\\ + b'\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff'\\ + b'\\x00\\xff\\x00\\xff\\x00\\xff\\x00\\xff', + 'c': b'\\n'}""") + # -- Be sure to exercise the len==1 short circuit + _t({"a":b"\n", "c":b"\x00"}, 5, """\ +{'a': b'\\n', + 'c': b'\\x00'}""") + class DottedPrettyPrinter(pprint.PrettyPrinter):