Kaydet (Commit) 64c16c33 authored tarafından Antoine Pitrou's avatar Antoine Pitrou

Issue #17150: pprint now uses line continuations to wrap long string literals.

üst 4a8ea9e2
This diff is collapsed.
......@@ -34,6 +34,7 @@ saferepr()
"""
import re
import sys as _sys
from collections import OrderedDict as _OrderedDict
from io import StringIO as _StringIO
......@@ -158,13 +159,10 @@ class PrettyPrinter:
return
rep = self._repr(object, context, level - 1)
typ = _type(object)
sepLines = _len(rep) > (self._width - 1 - indent - allowance)
max_width = self._width - 1 - indent - allowance
sepLines = _len(rep) > max_width
write = stream.write
if self._depth and level > self._depth:
write(rep)
return
if sepLines:
r = getattr(typ, "__repr__", None)
if issubclass(typ, dict):
......@@ -242,6 +240,37 @@ class PrettyPrinter:
write(endchar)
return
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()
of the given string using literal concatenation.
"""
lines = s.splitlines(True)
for i, line in enumerate(lines):
rep = repr(line)
if _len(rep) <= max_width:
yield rep
else:
# A list of alternating (non-space, space) strings
parts = re.split(r'(\s+)', line) + ['']
current = ''
for i in range(0, len(parts), 2):
part = parts[i] + parts[i+1]
candidate = current + part
if len(repr(candidate)) > max_width:
if current:
yield repr(current)
current = part
else:
current = candidate
if current:
yield repr(current)
for i, rep in enumerate(_str_parts(object)):
if i > 0:
write('\n' + ' '*indent)
write(rep)
return
write(rep)
def _repr(self, object, context, level):
......
# -*- coding: utf-8 -*-
import pprint
import test.support
import unittest
......@@ -475,6 +477,42 @@ class QueryTestCase(unittest.TestCase):
self.assertEqual(pprint.pformat(dict.fromkeys(keys, 0)),
'{%r: 0, %r: 0}' % tuple(sorted(keys, key=id)))
def test_str_wrap(self):
# pprint tries to wrap strings intelligently
fox = 'the quick brown fox jumped over a lazy dog'
self.assertEqual(pprint.pformat(fox, width=20), """\
'the quick brown '
'fox jumped over '
'a lazy dog'""")
self.assertEqual(pprint.pformat({'a': 1, 'b': fox, 'c': 2},
width=26), """\
{'a': 1,
'b': 'the quick brown '
'fox jumped over '
'a lazy dog',
'c': 2}""")
# With some special characters
# - \n always triggers a new line in the pprint
# - \t and \n are escaped
# - non-ASCII is allowed
# - an apostrophe doesn't disrupt the pprint
special = "Portons dix bons \"whiskys\"\nà l'avocat goujat\t qui fumait au zoo"
self.assertEqual(pprint.pformat(special, width=20), """\
'Portons dix bons '
'"whiskys"\\n'
"à l'avocat "
'goujat\\t qui '
'fumait au zoo'""")
# An unwrappable string is formatted as its repr
unwrappable = "x" * 100
self.assertEqual(pprint.pformat(unwrappable, width=80), repr(unwrappable))
self.assertEqual(pprint.pformat(''), "''")
# Check that the pprint is a usable repr
special *= 10
for width in range(3, 40):
formatted = pprint.pformat(special, width=width)
self.assertEqual(eval("(" + formatted + ")"), special)
class DottedPrettyPrinter(pprint.PrettyPrinter):
......
......@@ -294,6 +294,9 @@ Core and Builtins
Library
-------
- Issue #17150: pprint now uses line continuations to wrap long string
literals.
- Issue #17488: Change the subprocess.Popen bufsize parameter default value
from unbuffered (0) to buffering (-1) to match the behavior existing code
expects and match the behavior of the subprocess module in Python 2 to avoid
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment