Merge #15510: clarify textwrap's handling of whitespace, and add confirming tests.

Patch by Chris Jerdonek.
This commit is contained in:
R David Murray 2012-09-08 13:14:58 -04:00
commit 0fbbce99c3
2 changed files with 69 additions and 14 deletions

View File

@ -25,6 +25,9 @@ otherwise, you should use an instance of :class:`TextWrapper` for efficiency.
Optional keyword arguments correspond to the instance attributes of Optional keyword arguments correspond to the instance attributes of
:class:`TextWrapper`, documented below. *width* defaults to ``70``. :class:`TextWrapper`, documented below. *width* defaults to ``70``.
See the :meth:`TextWrapper.wrap` method for additional details on how
:func:`wrap` behaves.
.. function:: fill(text, width=70, **kwargs) .. function:: fill(text, width=70, **kwargs)
@ -167,15 +170,18 @@ in a block of text.
.. attribute:: drop_whitespace .. attribute:: drop_whitespace
(default: ``True``) If true, whitespace that, after wrapping, happens to (default: ``True``) If true, whitespace at the beginning and ending of
end up at the beginning or end of a line is dropped (leading whitespace in every line (after wrapping but before indenting) is dropped.
the first line is always preserved, though). Whitespace at the beginning of the paragraph, however, is not dropped
if non-whitespace follows it. If whitespace being dropped takes up an
entire line, the whole line is dropped.
.. attribute:: initial_indent .. attribute:: initial_indent
(default: ``''``) String that will be prepended to the first line of (default: ``''``) String that will be prepended to the first line of
wrapped output. Counts towards the length of the first line. wrapped output. Counts towards the length of the first line. The empty
string is not indented.
.. attribute:: subsequent_indent .. attribute:: subsequent_indent
@ -237,7 +243,8 @@ in a block of text.
Wraps the single paragraph in *text* (a string) so every line is at most Wraps the single paragraph in *text* (a string) so every line is at most
:attr:`width` characters long. All wrapping options are taken from :attr:`width` characters long. All wrapping options are taken from
instance attributes of the :class:`TextWrapper` instance. Returns a list instance attributes of the :class:`TextWrapper` instance. Returns a list
of output lines, without final newlines. of output lines, without final newlines. If the wrapped output has no
content, the returned list is empty.
.. method:: fill(text) .. method:: fill(text)

View File

@ -22,7 +22,7 @@ class BaseTestCase(unittest.TestCase):
result = [] result = []
for i in range(len(textin)): for i in range(len(textin)):
result.append(" %d: %r" % (i, textin[i])) result.append(" %d: %r" % (i, textin[i]))
result = '\n'.join(result) result = "\n".join(result) if result else " no lines"
elif isinstance(textin, str): elif isinstance(textin, str):
result = " %s\n" % repr(textin) result = " %s\n" % repr(textin)
return result return result
@ -66,6 +66,15 @@ class WrapTestCase(BaseTestCase):
"I'm glad to hear it!"]) "I'm glad to hear it!"])
self.check_wrap(text, 80, [text]) self.check_wrap(text, 80, [text])
def test_empty_string(self):
# Check that wrapping the empty string returns an empty list.
self.check_wrap("", 6, [])
self.check_wrap("", 6, [], drop_whitespace=False)
def test_empty_string_with_initial_indent(self):
# Check that the empty string is not indented.
self.check_wrap("", 6, [], initial_indent="++")
self.check_wrap("", 6, [], initial_indent="++", drop_whitespace=False)
def test_whitespace(self): def test_whitespace(self):
# Whitespace munging and end-of-sentence detection # Whitespace munging and end-of-sentence detection
@ -331,7 +340,32 @@ What a mess!
["blah", " ", "(ding", " ", "dong),", ["blah", " ", "(ding", " ", "dong),",
" ", "wubba"]) " ", "wubba"])
def test_initial_whitespace(self): def test_drop_whitespace_false(self):
# Check that drop_whitespace=False preserves whitespace.
# SF patch #1581073
text = " This is a sentence with much whitespace."
self.check_wrap(text, 10,
[" This is a", " ", "sentence ",
"with ", "much white", "space."],
drop_whitespace=False)
def test_drop_whitespace_false_whitespace_only(self):
# Check that drop_whitespace=False preserves a whitespace-only string.
self.check_wrap(" ", 6, [" "], drop_whitespace=False)
def test_drop_whitespace_false_whitespace_only_with_indent(self):
# Check that a whitespace-only string gets indented (when
# drop_whitespace is False).
self.check_wrap(" ", 6, [" "], drop_whitespace=False,
initial_indent=" ")
def test_drop_whitespace_whitespace_only(self):
# Check drop_whitespace on a whitespace-only string.
self.check_wrap(" ", 6, [])
def test_drop_whitespace_leading_whitespace(self):
# Check that drop_whitespace does not drop leading whitespace (if
# followed by non-whitespace).
# SF bug #622849 reported inconsistent handling of leading # SF bug #622849 reported inconsistent handling of leading
# whitespace; let's test that a bit, shall we? # whitespace; let's test that a bit, shall we?
text = " This is a sentence with leading whitespace." text = " This is a sentence with leading whitespace."
@ -340,13 +374,27 @@ What a mess!
self.check_wrap(text, 30, self.check_wrap(text, 30,
[" This is a sentence with", "leading whitespace."]) [" This is a sentence with", "leading whitespace."])
def test_no_drop_whitespace(self): def test_drop_whitespace_whitespace_line(self):
# SF patch #1581073 # Check that drop_whitespace skips the whole line if a non-leading
text = " This is a sentence with much whitespace." # line consists only of whitespace.
self.check_wrap(text, 10, text = "abcd efgh"
[" This is a", " ", "sentence ", # Include the result for drop_whitespace=False for comparison.
"with ", "much white", "space."], self.check_wrap(text, 6, ["abcd", " ", "efgh"],
drop_whitespace=False) drop_whitespace=False)
self.check_wrap(text, 6, ["abcd", "efgh"])
def test_drop_whitespace_whitespace_only_with_indent(self):
# Check that initial_indent is not applied to a whitespace-only
# string. This checks a special case of the fact that dropping
# whitespace occurs before indenting.
self.check_wrap(" ", 6, [], initial_indent="++")
def test_drop_whitespace_whitespace_indent(self):
# Check that drop_whitespace does not drop whitespace indents.
# This checks a special case of the fact that dropping whitespace
# occurs before indenting.
self.check_wrap("abcd efgh", 6, [" abcd", " efgh"],
initial_indent=" ", subsequent_indent=" ")
def test_split(self): def test_split(self):
# Ensure that the standard _split() method works as advertised # Ensure that the standard _split() method works as advertised