blob: 1bba77eb9e08b52369325f0480ee035ce6d8c741 [file] [log] [blame]
Greg Ward3dc94e12002-08-22 18:37:50 +00001#
Greg Ward61864102004-06-03 01:59:41 +00002# Test suite for the textwrap module.
Greg Ward3dc94e12002-08-22 18:37:50 +00003#
4# Original tests written by Greg Ward <gward@python.net>.
5# Converted to PyUnit by Peter Hansen <peter@engcorp.com>.
6# Currently maintained by Greg Ward.
7#
8# $Id$
9#
10
Greg Ward90c0b072002-08-22 18:11:10 +000011import unittest
12
Antoine Pitrou389dec82013-08-12 22:39:09 +020013from textwrap import TextWrapper, wrap, fill, dedent, indent, shorten
Greg Ward90c0b072002-08-22 18:11:10 +000014
15
Greg Ward13c53c62002-08-22 18:57:26 +000016class BaseTestCase(unittest.TestCase):
Greg Ward90c0b072002-08-22 18:11:10 +000017 '''Parent class with utility methods for textwrap tests.'''
18
19 def show(self, textin):
20 if isinstance(textin, list):
21 result = []
22 for i in range(len(textin)):
23 result.append(" %d: %r" % (i, textin[i]))
R David Murray1585b702012-09-08 13:13:25 -040024 result = "\n".join(result) if result else " no lines"
Guido van Rossum3172c5d2007-10-16 18:12:55 +000025 elif isinstance(textin, str):
Greg Ward90c0b072002-08-22 18:11:10 +000026 result = " %s\n" % repr(textin)
27 return result
28
29
30 def check(self, result, expect):
Ezio Melottib3aedd42010-11-20 19:04:17 +000031 self.assertEqual(result, expect,
Greg Ward9ad15a32002-08-22 19:47:27 +000032 'expected:\n%s\nbut got:\n%s' % (
33 self.show(expect), self.show(result)))
Greg Ward90c0b072002-08-22 18:11:10 +000034
Guido van Rossumeb287a22002-10-02 15:47:32 +000035 def check_wrap(self, text, width, expect, **kwargs):
36 result = wrap(text, width, **kwargs)
Greg Wardee413842002-08-22 18:55:38 +000037 self.check(result, expect)
38
Greg Wardd1a72a02002-10-31 16:11:18 +000039 def check_split(self, text, expect):
40 result = self.wrapper._split(text)
Ezio Melottib3aedd42010-11-20 19:04:17 +000041 self.assertEqual(result, expect,
42 "\nexpected %r\n"
43 "but got %r" % (expect, result))
Greg Ward715debd2002-08-22 21:16:25 +000044
Greg Ward90c0b072002-08-22 18:11:10 +000045
Greg Ward13c53c62002-08-22 18:57:26 +000046class WrapTestCase(BaseTestCase):
Greg Ward90c0b072002-08-22 18:11:10 +000047
Greg Ward90c0b072002-08-22 18:11:10 +000048 def setUp(self):
Greg Wardf0ba7642004-05-13 01:53:10 +000049 self.wrapper = TextWrapper(width=45)
Greg Ward90c0b072002-08-22 18:11:10 +000050
Greg Wardf6765782002-08-22 18:35:49 +000051 def test_simple(self):
Guido van Rossum327af772002-08-22 20:13:47 +000052 # Simple case: just words, spaces, and a bit of punctuation
Greg Ward90c0b072002-08-22 18:11:10 +000053
Greg Wardee413842002-08-22 18:55:38 +000054 text = "Hello there, how are you this fine day? I'm glad to hear it!"
Greg Ward90c0b072002-08-22 18:11:10 +000055
Greg Wardee413842002-08-22 18:55:38 +000056 self.check_wrap(text, 12,
57 ["Hello there,",
58 "how are you",
59 "this fine",
60 "day? I'm",
61 "glad to hear",
62 "it!"])
63 self.check_wrap(text, 42,
64 ["Hello there, how are you this fine day?",
65 "I'm glad to hear it!"])
66 self.check_wrap(text, 80, [text])
Greg Ward90c0b072002-08-22 18:11:10 +000067
R David Murray1585b702012-09-08 13:13:25 -040068 def test_empty_string(self):
69 # Check that wrapping the empty string returns an empty list.
70 self.check_wrap("", 6, [])
71 self.check_wrap("", 6, [], drop_whitespace=False)
72
73 def test_empty_string_with_initial_indent(self):
74 # Check that the empty string is not indented.
75 self.check_wrap("", 6, [], initial_indent="++")
76 self.check_wrap("", 6, [], initial_indent="++", drop_whitespace=False)
Greg Ward90c0b072002-08-22 18:11:10 +000077
Greg Wardf6765782002-08-22 18:35:49 +000078 def test_whitespace(self):
Guido van Rossum327af772002-08-22 20:13:47 +000079 # Whitespace munging and end-of-sentence detection
Greg Ward90c0b072002-08-22 18:11:10 +000080
Greg Wardee413842002-08-22 18:55:38 +000081 text = """\
Greg Ward90c0b072002-08-22 18:11:10 +000082This is a paragraph that already has
83line breaks. But some of its lines are much longer than the others,
84so it needs to be wrapped.
85Some lines are \ttabbed too.
86What a mess!
87"""
88
Greg Wardee413842002-08-22 18:55:38 +000089 expect = ["This is a paragraph that already has line",
90 "breaks. But some of its lines are much",
91 "longer than the others, so it needs to be",
92 "wrapped. Some lines are tabbed too. What a",
93 "mess!"]
Greg Ward90c0b072002-08-22 18:11:10 +000094
Greg Wardf0ba7642004-05-13 01:53:10 +000095 wrapper = TextWrapper(45, fix_sentence_endings=True)
96 result = wrapper.wrap(text)
Greg Ward90c0b072002-08-22 18:11:10 +000097 self.check(result, expect)
98
Greg Wardf0ba7642004-05-13 01:53:10 +000099 result = wrapper.fill(text)
Greg Ward90c0b072002-08-22 18:11:10 +0000100 self.check(result, '\n'.join(expect))
101
Hynek Schlawackd5272592012-05-19 13:33:11 +0200102 text = "\tTest\tdefault\t\ttabsize."
103 expect = [" Test default tabsize."]
104 self.check_wrap(text, 80, expect)
105
106 text = "\tTest\tcustom\t\ttabsize."
107 expect = [" Test custom tabsize."]
108 self.check_wrap(text, 80, expect, tabsize=4)
109
Greg Wardf0ba7642004-05-13 01:53:10 +0000110 def test_fix_sentence_endings(self):
111 wrapper = TextWrapper(60, fix_sentence_endings=True)
Greg Ward90c0b072002-08-22 18:11:10 +0000112
Greg Wardf0ba7642004-05-13 01:53:10 +0000113 # SF #847346: ensure that fix_sentence_endings=True does the
114 # right thing even on input short enough that it doesn't need to
115 # be wrapped.
116 text = "A short line. Note the single space."
117 expect = ["A short line. Note the single space."]
118 self.check(wrapper.wrap(text), expect)
119
120 # Test some of the hairy end cases that _fix_sentence_endings()
121 # is supposed to handle (the easy stuff is tested in
122 # test_whitespace() above).
123 text = "Well, Doctor? What do you think?"
124 expect = ["Well, Doctor? What do you think?"]
125 self.check(wrapper.wrap(text), expect)
126
127 text = "Well, Doctor?\nWhat do you think?"
128 self.check(wrapper.wrap(text), expect)
129
130 text = 'I say, chaps! Anyone for "tennis?"\nHmmph!'
131 expect = ['I say, chaps! Anyone for "tennis?" Hmmph!']
132 self.check(wrapper.wrap(text), expect)
133
134 wrapper.width = 20
135 expect = ['I say, chaps!', 'Anyone for "tennis?"', 'Hmmph!']
136 self.check(wrapper.wrap(text), expect)
137
138 text = 'And she said, "Go to hell!"\nCan you believe that?'
139 expect = ['And she said, "Go to',
140 'hell!" Can you',
141 'believe that?']
142 self.check(wrapper.wrap(text), expect)
143
144 wrapper.width = 60
145 expect = ['And she said, "Go to hell!" Can you believe that?']
146 self.check(wrapper.wrap(text), expect)
Tim Peters27f88362004-07-08 04:22:35 +0000147
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000148 text = 'File stdio.h is nice.'
149 expect = ['File stdio.h is nice.']
150 self.check(wrapper.wrap(text), expect)
151
Greg Wardf6765782002-08-22 18:35:49 +0000152 def test_wrap_short(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000153 # Wrapping to make short lines longer
Greg Ward90c0b072002-08-22 18:11:10 +0000154
Greg Wardee413842002-08-22 18:55:38 +0000155 text = "This is a\nshort paragraph."
Greg Ward90c0b072002-08-22 18:11:10 +0000156
Greg Wardee413842002-08-22 18:55:38 +0000157 self.check_wrap(text, 20, ["This is a short",
158 "paragraph."])
159 self.check_wrap(text, 40, ["This is a short paragraph."])
Greg Ward90c0b072002-08-22 18:11:10 +0000160
161
Guido van Rossumeb287a22002-10-02 15:47:32 +0000162 def test_wrap_short_1line(self):
163 # Test endcases
164
165 text = "This is a short line."
166
167 self.check_wrap(text, 30, ["This is a short line."])
168 self.check_wrap(text, 30, ["(1) This is a short line."],
169 initial_indent="(1) ")
170
171
Greg Wardf6765782002-08-22 18:35:49 +0000172 def test_hyphenated(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000173 # Test breaking hyphenated words
Greg Ward90c0b072002-08-22 18:11:10 +0000174
Greg Wardee413842002-08-22 18:55:38 +0000175 text = ("this-is-a-useful-feature-for-"
176 "reformatting-posts-from-tim-peters'ly")
Greg Ward90c0b072002-08-22 18:11:10 +0000177
Greg Wardee413842002-08-22 18:55:38 +0000178 self.check_wrap(text, 40,
179 ["this-is-a-useful-feature-for-",
180 "reformatting-posts-from-tim-peters'ly"])
181 self.check_wrap(text, 41,
182 ["this-is-a-useful-feature-for-",
183 "reformatting-posts-from-tim-peters'ly"])
184 self.check_wrap(text, 42,
185 ["this-is-a-useful-feature-for-reformatting-",
186 "posts-from-tim-peters'ly"])
Greg Ward90c0b072002-08-22 18:11:10 +0000187
Greg Ward40407942005-03-05 02:53:17 +0000188 def test_hyphenated_numbers(self):
189 # Test that hyphenated numbers (eg. dates) are not broken like words.
190 text = ("Python 1.0.0 was released on 1994-01-26. Python 1.0.1 was\n"
191 "released on 1994-02-15.")
192
193 self.check_wrap(text, 30, ['Python 1.0.0 was released on',
194 '1994-01-26. Python 1.0.1 was',
195 'released on 1994-02-15.'])
196 self.check_wrap(text, 40, ['Python 1.0.0 was released on 1994-01-26.',
197 'Python 1.0.1 was released on 1994-02-15.'])
198
199 text = "I do all my shopping at 7-11."
200 self.check_wrap(text, 25, ["I do all my shopping at",
201 "7-11."])
202 self.check_wrap(text, 27, ["I do all my shopping at",
203 "7-11."])
204 self.check_wrap(text, 29, ["I do all my shopping at 7-11."])
205
Greg Ward9ad15a32002-08-22 19:47:27 +0000206 def test_em_dash(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000207 # Test text with em-dashes
Greg Ward9ad15a32002-08-22 19:47:27 +0000208 text = "Em-dashes should be written -- thus."
209 self.check_wrap(text, 25,
210 ["Em-dashes should be",
211 "written -- thus."])
212
213 # Probe the boundaries of the properly written em-dash,
214 # ie. " -- ".
215 self.check_wrap(text, 29,
216 ["Em-dashes should be written",
217 "-- thus."])
218 expect = ["Em-dashes should be written --",
219 "thus."]
220 self.check_wrap(text, 30, expect)
221 self.check_wrap(text, 35, expect)
222 self.check_wrap(text, 36,
223 ["Em-dashes should be written -- thus."])
Guido van Rossum327af772002-08-22 20:13:47 +0000224
Greg Ward9ad15a32002-08-22 19:47:27 +0000225 # The improperly written em-dash is handled too, because
226 # it's adjacent to non-whitespace on both sides.
227 text = "You can also do--this or even---this."
228 expect = ["You can also do",
229 "--this or even",
230 "---this."]
231 self.check_wrap(text, 15, expect)
232 self.check_wrap(text, 16, expect)
233 expect = ["You can also do--",
234 "this or even---",
235 "this."]
236 self.check_wrap(text, 17, expect)
237 self.check_wrap(text, 19, expect)
238 expect = ["You can also do--this or even",
239 "---this."]
240 self.check_wrap(text, 29, expect)
241 self.check_wrap(text, 31, expect)
242 expect = ["You can also do--this or even---",
243 "this."]
244 self.check_wrap(text, 32, expect)
245 self.check_wrap(text, 35, expect)
246
247 # All of the above behaviour could be deduced by probing the
248 # _split() method.
249 text = "Here's an -- em-dash and--here's another---and another!"
Greg Ward9ad15a32002-08-22 19:47:27 +0000250 expect = ["Here's", " ", "an", " ", "--", " ", "em-", "dash", " ",
251 "and", "--", "here's", " ", "another", "---",
252 "and", " ", "another!"]
Greg Wardd1a72a02002-10-31 16:11:18 +0000253 self.check_split(text, expect)
Greg Ward90c0b072002-08-22 18:11:10 +0000254
Greg Wardc6edb372002-08-22 21:27:05 +0000255 text = "and then--bam!--he was gone"
256 expect = ["and", " ", "then", "--", "bam!", "--",
257 "he", " ", "was", " ", "gone"]
Greg Wardd1a72a02002-10-31 16:11:18 +0000258 self.check_split(text, expect)
Greg Wardc6edb372002-08-22 21:27:05 +0000259
260
Greg Ward34f995b2002-08-22 21:10:07 +0000261 def test_unix_options (self):
262 # Test that Unix-style command-line options are wrapped correctly.
263 # Both Optik (OptionParser) and Docutils rely on this behaviour!
264
265 text = "You should use the -n option, or --dry-run in its long form."
266 self.check_wrap(text, 20,
267 ["You should use the",
268 "-n option, or --dry-",
269 "run in its long",
270 "form."])
271 self.check_wrap(text, 21,
272 ["You should use the -n",
273 "option, or --dry-run",
274 "in its long form."])
275 expect = ["You should use the -n option, or",
276 "--dry-run in its long form."]
277 self.check_wrap(text, 32, expect)
278 self.check_wrap(text, 34, expect)
279 self.check_wrap(text, 35, expect)
280 self.check_wrap(text, 38, expect)
281 expect = ["You should use the -n option, or --dry-",
282 "run in its long form."]
283 self.check_wrap(text, 39, expect)
284 self.check_wrap(text, 41, expect)
285 expect = ["You should use the -n option, or --dry-run",
286 "in its long form."]
287 self.check_wrap(text, 42, expect)
288
Greg Ward24a1c9c2002-08-22 21:12:54 +0000289 # Again, all of the above can be deduced from _split().
290 text = "the -n option, or --dry-run or --dryrun"
Greg Ward24a1c9c2002-08-22 21:12:54 +0000291 expect = ["the", " ", "-n", " ", "option,", " ", "or", " ",
292 "--dry-", "run", " ", "or", " ", "--dryrun"]
Greg Wardd1a72a02002-10-31 16:11:18 +0000293 self.check_split(text, expect)
294
295 def test_funky_hyphens (self):
296 # Screwy edge cases cooked up by David Goodger. All reported
297 # in SF bug #596434.
298 self.check_split("what the--hey!", ["what", " ", "the", "--", "hey!"])
299 self.check_split("what the--", ["what", " ", "the--"])
300 self.check_split("what the--.", ["what", " ", "the--."])
301 self.check_split("--text--.", ["--text--."])
302
Greg Wardcc55cb92003-05-07 01:19:22 +0000303 # When I first read bug #596434, this is what I thought David
304 # was talking about. I was wrong; these have always worked
305 # fine. The real problem is tested in test_funky_parens()
306 # below...
Greg Wardd1a72a02002-10-31 16:11:18 +0000307 self.check_split("--option", ["--option"])
308 self.check_split("--option-opt", ["--option-", "opt"])
Greg Wardcc55cb92003-05-07 01:19:22 +0000309 self.check_split("foo --option-opt bar",
310 ["foo", " ", "--option-", "opt", " ", "bar"])
311
Greg Ward61864102004-06-03 01:59:41 +0000312 def test_punct_hyphens(self):
313 # Oh bother, SF #965425 found another problem with hyphens --
314 # hyphenated words in single quotes weren't handled correctly.
315 # In fact, the bug is that *any* punctuation around a hyphenated
316 # word was handled incorrectly, except for a leading "--", which
317 # was special-cased for Optik and Docutils. So test a variety
318 # of styles of punctuation around a hyphenated word.
319 # (Actually this is based on an Optik bug report, #813077).
320 self.check_split("the 'wibble-wobble' widget",
321 ['the', ' ', "'wibble-", "wobble'", ' ', 'widget'])
322 self.check_split('the "wibble-wobble" widget',
323 ['the', ' ', '"wibble-', 'wobble"', ' ', 'widget'])
324 self.check_split("the (wibble-wobble) widget",
325 ['the', ' ', "(wibble-", "wobble)", ' ', 'widget'])
326 self.check_split("the ['wibble-wobble'] widget",
327 ['the', ' ', "['wibble-", "wobble']", ' ', 'widget'])
328
Greg Wardcc55cb92003-05-07 01:19:22 +0000329 def test_funky_parens (self):
330 # Second part of SF bug #596434: long option strings inside
331 # parentheses.
332 self.check_split("foo (--option) bar",
333 ["foo", " ", "(--option)", " ", "bar"])
334
335 # Related stuff -- make sure parens work in simpler contexts.
336 self.check_split("foo (bar) baz",
337 ["foo", " ", "(bar)", " ", "baz"])
338 self.check_split("blah (ding dong), wubba",
339 ["blah", " ", "(ding", " ", "dong),",
340 " ", "wubba"])
Greg Ward24a1c9c2002-08-22 21:12:54 +0000341
R David Murray1585b702012-09-08 13:13:25 -0400342 def test_drop_whitespace_false(self):
343 # Check that drop_whitespace=False preserves whitespace.
344 # SF patch #1581073
345 text = " This is a sentence with much whitespace."
346 self.check_wrap(text, 10,
347 [" This is a", " ", "sentence ",
348 "with ", "much white", "space."],
349 drop_whitespace=False)
350
351 def test_drop_whitespace_false_whitespace_only(self):
352 # Check that drop_whitespace=False preserves a whitespace-only string.
353 self.check_wrap(" ", 6, [" "], drop_whitespace=False)
354
355 def test_drop_whitespace_false_whitespace_only_with_indent(self):
356 # Check that a whitespace-only string gets indented (when
357 # drop_whitespace is False).
358 self.check_wrap(" ", 6, [" "], drop_whitespace=False,
359 initial_indent=" ")
360
361 def test_drop_whitespace_whitespace_only(self):
362 # Check drop_whitespace on a whitespace-only string.
363 self.check_wrap(" ", 6, [])
364
365 def test_drop_whitespace_leading_whitespace(self):
366 # Check that drop_whitespace does not drop leading whitespace (if
367 # followed by non-whitespace).
Greg Ward24cbbcb2002-12-09 16:27:15 +0000368 # SF bug #622849 reported inconsistent handling of leading
369 # whitespace; let's test that a bit, shall we?
370 text = " This is a sentence with leading whitespace."
371 self.check_wrap(text, 50,
372 [" This is a sentence with leading whitespace."])
373 self.check_wrap(text, 30,
374 [" This is a sentence with", "leading whitespace."])
375
R David Murray1585b702012-09-08 13:13:25 -0400376 def test_drop_whitespace_whitespace_line(self):
377 # Check that drop_whitespace skips the whole line if a non-leading
378 # line consists only of whitespace.
379 text = "abcd efgh"
380 # Include the result for drop_whitespace=False for comparison.
381 self.check_wrap(text, 6, ["abcd", " ", "efgh"],
Guido van Rossumd8faa362007-04-27 19:54:29 +0000382 drop_whitespace=False)
R David Murray1585b702012-09-08 13:13:25 -0400383 self.check_wrap(text, 6, ["abcd", "efgh"])
384
385 def test_drop_whitespace_whitespace_only_with_indent(self):
386 # Check that initial_indent is not applied to a whitespace-only
387 # string. This checks a special case of the fact that dropping
388 # whitespace occurs before indenting.
389 self.check_wrap(" ", 6, [], initial_indent="++")
390
391 def test_drop_whitespace_whitespace_indent(self):
392 # Check that drop_whitespace does not drop whitespace indents.
393 # This checks a special case of the fact that dropping whitespace
394 # occurs before indenting.
395 self.check_wrap("abcd efgh", 6, [" abcd", " efgh"],
396 initial_indent=" ", subsequent_indent=" ")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000397
Greg Ward90c0b072002-08-22 18:11:10 +0000398 def test_split(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000399 # Ensure that the standard _split() method works as advertised
400 # in the comments
Greg Ward90c0b072002-08-22 18:11:10 +0000401
Greg Wardee413842002-08-22 18:55:38 +0000402 text = "Hello there -- you goof-ball, use the -b option!"
Greg Ward90c0b072002-08-22 18:11:10 +0000403
Greg Wardee413842002-08-22 18:55:38 +0000404 result = self.wrapper._split(text)
Greg Ward90c0b072002-08-22 18:11:10 +0000405 self.check(result,
406 ["Hello", " ", "there", " ", "--", " ", "you", " ", "goof-",
407 "ball,", " ", "use", " ", "the", " ", "-b", " ", "option!"])
408
Alexandre Vassalotti5f8ced22008-05-16 00:03:33 +0000409 def test_break_on_hyphens(self):
410 # Ensure that the break_on_hyphens attributes work
411 text = "yaba daba-doo"
412 self.check_wrap(text, 10, ["yaba daba-", "doo"],
413 break_on_hyphens=True)
414 self.check_wrap(text, 10, ["yaba", "daba-doo"],
415 break_on_hyphens=False)
416
Greg Ward49128572003-05-07 00:54:42 +0000417 def test_bad_width(self):
418 # Ensure that width <= 0 is caught.
419 text = "Whatever, it doesn't matter."
420 self.assertRaises(ValueError, wrap, text, 0)
421 self.assertRaises(ValueError, wrap, text, -1)
422
Antoine Pitrou7c59bc62008-12-13 23:20:54 +0000423 def test_no_split_at_umlaut(self):
424 text = "Die Empf\xe4nger-Auswahl"
425 self.check_wrap(text, 13, ["Die", "Empf\xe4nger-", "Auswahl"])
426
427 def test_umlaut_followed_by_dash(self):
428 text = "aa \xe4\xe4-\xe4\xe4"
429 self.check_wrap(text, 7, ["aa \xe4\xe4-", "\xe4\xe4"])
430
Greg Ward90c0b072002-08-22 18:11:10 +0000431
Serhiy Storchakaacc9f3f2013-10-15 21:22:54 +0300432class MaxLinesTestCase(BaseTestCase):
433 text = "Hello there, how are you this fine day? I'm glad to hear it!"
434
435 def test_simple(self):
436 self.check_wrap(self.text, 12,
437 ["Hello [...]"],
438 max_lines=0)
439 self.check_wrap(self.text, 12,
440 ["Hello [...]"],
441 max_lines=1)
442 self.check_wrap(self.text, 12,
443 ["Hello there,",
444 "how [...]"],
445 max_lines=2)
446 self.check_wrap(self.text, 13,
447 ["Hello there,",
448 "how are [...]"],
449 max_lines=2)
450 self.check_wrap(self.text, 80, [self.text], max_lines=1)
451 self.check_wrap(self.text, 12,
452 ["Hello there,",
453 "how are you",
454 "this fine",
455 "day? I'm",
456 "glad to hear",
457 "it!"],
458 max_lines=6)
459
460 def test_spaces(self):
461 # strip spaces before placeholder
462 self.check_wrap(self.text, 12,
463 ["Hello there,",
464 "how are you",
465 "this fine",
466 "day? [...]"],
467 max_lines=4)
468 # placeholder at the start of line
469 self.check_wrap(self.text, 6,
470 ["Hello",
471 "[...]"],
472 max_lines=2)
473 # final spaces
474 self.check_wrap(self.text + ' ' * 10, 12,
475 ["Hello there,",
476 "how are you",
477 "this fine",
478 "day? I'm",
479 "glad to hear",
480 "it!"],
481 max_lines=6)
482
483 def test_placeholder(self):
484 self.check_wrap(self.text, 12,
485 ["Hello..."],
486 max_lines=1,
487 placeholder='...')
488 self.check_wrap(self.text, 12,
489 ["Hello there,",
490 "how are..."],
491 max_lines=2,
492 placeholder='...')
493 # long placeholder and indentation
494 with self.assertRaises(ValueError):
495 wrap(self.text, 16, initial_indent=' ',
496 max_lines=1, placeholder=' [truncated]...')
497 with self.assertRaises(ValueError):
498 wrap(self.text, 16, subsequent_indent=' ',
499 max_lines=2, placeholder=' [truncated]...')
500 self.check_wrap(self.text, 16,
501 [" Hello there,",
502 " [truncated]..."],
503 max_lines=2,
504 initial_indent=' ',
505 subsequent_indent=' ',
506 placeholder=' [truncated]...')
507 self.check_wrap(self.text, 16,
508 [" [truncated]..."],
509 max_lines=1,
510 initial_indent=' ',
511 subsequent_indent=' ',
512 placeholder=' [truncated]...')
513 self.check_wrap(self.text, 80, [self.text], placeholder='.' * 1000)
514
515
Greg Wardfd030e42002-08-22 19:02:37 +0000516class LongWordTestCase (BaseTestCase):
517 def setUp(self):
518 self.wrapper = TextWrapper()
Greg Ward24cbbcb2002-12-09 16:27:15 +0000519 self.text = '''\
Greg Ward90c0b072002-08-22 18:11:10 +0000520Did you say "supercalifragilisticexpialidocious?"
521How *do* you spell that odd word, anyways?
522'''
Greg Wardfd030e42002-08-22 19:02:37 +0000523
524 def test_break_long(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000525 # Wrap text with long words and lots of punctuation
Greg Wardfd030e42002-08-22 19:02:37 +0000526
527 self.check_wrap(self.text, 30,
Greg Wardee413842002-08-22 18:55:38 +0000528 ['Did you say "supercalifragilis',
529 'ticexpialidocious?" How *do*',
530 'you spell that odd word,',
531 'anyways?'])
Greg Wardfd030e42002-08-22 19:02:37 +0000532 self.check_wrap(self.text, 50,
Greg Wardee413842002-08-22 18:55:38 +0000533 ['Did you say "supercalifragilisticexpialidocious?"',
534 'How *do* you spell that odd word, anyways?'])
Greg Ward90c0b072002-08-22 18:11:10 +0000535
Raymond Hettingerc11dbcd2003-08-30 14:43:55 +0000536 # SF bug 797650. Prevent an infinite loop by making sure that at
537 # least one character gets split off on every pass.
538 self.check_wrap('-'*10+'hello', 10,
539 ['----------',
540 ' h',
541 ' e',
542 ' l',
543 ' l',
544 ' o'],
545 subsequent_indent = ' '*15)
Greg Ward90c0b072002-08-22 18:11:10 +0000546
Georg Brandlfceab5a2008-01-19 20:08:23 +0000547 # bug 1146. Prevent a long word to be wrongly wrapped when the
548 # preceding word is exactly one character shorter than the width
549 self.check_wrap(self.text, 12,
550 ['Did you say ',
551 '"supercalifr',
552 'agilisticexp',
553 'ialidocious?',
554 '" How *do*',
555 'you spell',
556 'that odd',
557 'word,',
558 'anyways?'])
559
Guido van Rossum327af772002-08-22 20:13:47 +0000560 def test_nobreak_long(self):
561 # Test with break_long_words disabled
Greg Ward90c0b072002-08-22 18:11:10 +0000562 self.wrapper.break_long_words = 0
563 self.wrapper.width = 30
Greg Wardee413842002-08-22 18:55:38 +0000564 expect = ['Did you say',
565 '"supercalifragilisticexpialidocious?"',
566 'How *do* you spell that odd',
567 'word, anyways?'
Guido van Rossum327af772002-08-22 20:13:47 +0000568 ]
Greg Wardfd030e42002-08-22 19:02:37 +0000569 result = self.wrapper.wrap(self.text)
Greg Ward90c0b072002-08-22 18:11:10 +0000570 self.check(result, expect)
571
572 # Same thing with kwargs passed to standalone wrap() function.
Greg Wardfd030e42002-08-22 19:02:37 +0000573 result = wrap(self.text, width=30, break_long_words=0)
Greg Ward90c0b072002-08-22 18:11:10 +0000574 self.check(result, expect)
575
Serhiy Storchakaacc9f3f2013-10-15 21:22:54 +0300576 def test_max_lines_long(self):
577 self.check_wrap(self.text, 12,
578 ['Did you say ',
579 '"supercalifr',
580 'agilisticexp',
581 '[...]'],
582 max_lines=4)
583
Greg Ward90c0b072002-08-22 18:11:10 +0000584
Greg Ward13c53c62002-08-22 18:57:26 +0000585class IndentTestCases(BaseTestCase):
Greg Ward90c0b072002-08-22 18:11:10 +0000586
587 # called before each test method
588 def setUp(self):
Greg Wardf69d3c92002-08-22 19:06:45 +0000589 self.text = '''\
Greg Ward90c0b072002-08-22 18:11:10 +0000590This paragraph will be filled, first without any indentation,
591and then with some (including a hanging indent).'''
592
593
Greg Wardf6765782002-08-22 18:35:49 +0000594 def test_fill(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000595 # Test the fill() method
Greg Ward90c0b072002-08-22 18:11:10 +0000596
597 expect = '''\
598This paragraph will be filled, first
599without any indentation, and then with
600some (including a hanging indent).'''
601
Greg Wardf69d3c92002-08-22 19:06:45 +0000602 result = fill(self.text, 40)
Greg Ward90c0b072002-08-22 18:11:10 +0000603 self.check(result, expect)
604
605
Greg Wardf6765782002-08-22 18:35:49 +0000606 def test_initial_indent(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000607 # Test initial_indent parameter
Greg Ward90c0b072002-08-22 18:11:10 +0000608
Greg Wardf69d3c92002-08-22 19:06:45 +0000609 expect = [" This paragraph will be filled,",
610 "first without any indentation, and then",
611 "with some (including a hanging indent)."]
612 result = wrap(self.text, 40, initial_indent=" ")
Greg Ward90c0b072002-08-22 18:11:10 +0000613 self.check(result, expect)
614
Greg Wardf69d3c92002-08-22 19:06:45 +0000615 expect = "\n".join(expect)
616 result = fill(self.text, 40, initial_indent=" ")
Greg Ward90c0b072002-08-22 18:11:10 +0000617 self.check(result, expect)
618
619
Greg Wardf6765782002-08-22 18:35:49 +0000620 def test_subsequent_indent(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000621 # Test subsequent_indent parameter
Greg Ward90c0b072002-08-22 18:11:10 +0000622
623 expect = '''\
624 * This paragraph will be filled, first
625 without any indentation, and then
626 with some (including a hanging
627 indent).'''
628
Greg Wardf69d3c92002-08-22 19:06:45 +0000629 result = fill(self.text, 40,
630 initial_indent=" * ", subsequent_indent=" ")
Greg Ward90c0b072002-08-22 18:11:10 +0000631 self.check(result, expect)
632
633
Greg Ward9e082f42003-05-08 01:58:26 +0000634# Despite the similar names, DedentTestCase is *not* the inverse
635# of IndentTestCase!
636class DedentTestCase(unittest.TestCase):
637
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000638 def assertUnchanged(self, text):
639 """assert that dedent() has no effect on 'text'"""
Ezio Melottib3aedd42010-11-20 19:04:17 +0000640 self.assertEqual(text, dedent(text))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000641
Greg Ward9e082f42003-05-08 01:58:26 +0000642 def test_dedent_nomargin(self):
643 # No lines indented.
644 text = "Hello there.\nHow are you?\nOh good, I'm glad."
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000645 self.assertUnchanged(text)
Greg Ward9e082f42003-05-08 01:58:26 +0000646
647 # Similar, with a blank line.
648 text = "Hello there.\n\nBoo!"
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000649 self.assertUnchanged(text)
Greg Ward9e082f42003-05-08 01:58:26 +0000650
651 # Some lines indented, but overall margin is still zero.
652 text = "Hello there.\n This is indented."
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000653 self.assertUnchanged(text)
Greg Ward9e082f42003-05-08 01:58:26 +0000654
655 # Again, add a blank line.
656 text = "Hello there.\n\n Boo!\n"
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000657 self.assertUnchanged(text)
Greg Ward9e082f42003-05-08 01:58:26 +0000658
659 def test_dedent_even(self):
660 # All lines indented by two spaces.
661 text = " Hello there.\n How are ya?\n Oh good."
662 expect = "Hello there.\nHow are ya?\nOh good."
Ezio Melottib3aedd42010-11-20 19:04:17 +0000663 self.assertEqual(expect, dedent(text))
Greg Ward9e082f42003-05-08 01:58:26 +0000664
665 # Same, with blank lines.
666 text = " Hello there.\n\n How are ya?\n Oh good.\n"
667 expect = "Hello there.\n\nHow are ya?\nOh good.\n"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000668 self.assertEqual(expect, dedent(text))
Greg Ward9e082f42003-05-08 01:58:26 +0000669
670 # Now indent one of the blank lines.
671 text = " Hello there.\n \n How are ya?\n Oh good.\n"
672 expect = "Hello there.\n\nHow are ya?\nOh good.\n"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000673 self.assertEqual(expect, dedent(text))
Greg Ward9e082f42003-05-08 01:58:26 +0000674
675 def test_dedent_uneven(self):
676 # Lines indented unevenly.
677 text = '''\
678 def foo():
679 while 1:
680 return foo
681 '''
682 expect = '''\
683def foo():
684 while 1:
685 return foo
686'''
Ezio Melottib3aedd42010-11-20 19:04:17 +0000687 self.assertEqual(expect, dedent(text))
Greg Ward9e082f42003-05-08 01:58:26 +0000688
689 # Uneven indentation with a blank line.
690 text = " Foo\n Bar\n\n Baz\n"
691 expect = "Foo\n Bar\n\n Baz\n"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000692 self.assertEqual(expect, dedent(text))
Greg Ward9e082f42003-05-08 01:58:26 +0000693
694 # Uneven indentation with a whitespace-only line.
695 text = " Foo\n Bar\n \n Baz\n"
696 expect = "Foo\n Bar\n\n Baz\n"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000697 self.assertEqual(expect, dedent(text))
Greg Ward9e082f42003-05-08 01:58:26 +0000698
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000699 # dedent() should not mangle internal tabs
700 def test_dedent_preserve_internal_tabs(self):
701 text = " hello\tthere\n how are\tyou?"
702 expect = "hello\tthere\nhow are\tyou?"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000703 self.assertEqual(expect, dedent(text))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000704
705 # make sure that it preserves tabs when it's not making any
706 # changes at all
Ezio Melottib3aedd42010-11-20 19:04:17 +0000707 self.assertEqual(expect, dedent(expect))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000708
709 # dedent() should not mangle tabs in the margin (i.e.
710 # tabs and spaces both count as margin, but are *not*
711 # considered equivalent)
712 def test_dedent_preserve_margin_tabs(self):
713 text = " hello there\n\thow are you?"
714 self.assertUnchanged(text)
715
716 # same effect even if we have 8 spaces
717 text = " hello there\n\thow are you?"
718 self.assertUnchanged(text)
719
720 # dedent() only removes whitespace that can be uniformly removed!
721 text = "\thello there\n\thow are you?"
722 expect = "hello there\nhow are you?"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000723 self.assertEqual(expect, dedent(text))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000724
725 text = " \thello there\n \thow are you?"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000726 self.assertEqual(expect, dedent(text))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000727
728 text = " \t hello there\n \t how are you?"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000729 self.assertEqual(expect, dedent(text))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000730
731 text = " \thello there\n \t how are you?"
732 expect = "hello there\n how are you?"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000733 self.assertEqual(expect, dedent(text))
Greg Ward9e082f42003-05-08 01:58:26 +0000734
735
Nick Coghlan4fae8cd2012-06-11 23:07:51 +1000736# Test textwrap.indent
737class IndentTestCase(unittest.TestCase):
738 # The examples used for tests. If any of these change, the expected
739 # results in the various test cases must also be updated.
740 # The roundtrip cases are separate, because textwrap.dedent doesn't
741 # handle Windows line endings
742 ROUNDTRIP_CASES = (
743 # Basic test case
744 "Hi.\nThis is a test.\nTesting.",
745 # Include a blank line
746 "Hi.\nThis is a test.\n\nTesting.",
747 # Include leading and trailing blank lines
748 "\nHi.\nThis is a test.\nTesting.\n",
749 )
750 CASES = ROUNDTRIP_CASES + (
751 # Use Windows line endings
752 "Hi.\r\nThis is a test.\r\nTesting.\r\n",
753 # Pathological case
754 "\nHi.\r\nThis is a test.\n\r\nTesting.\r\n\n",
755 )
756
757 def test_indent_nomargin_default(self):
758 # indent should do nothing if 'prefix' is empty.
759 for text in self.CASES:
760 self.assertEqual(indent(text, ''), text)
761
762 def test_indent_nomargin_explicit_default(self):
763 # The same as test_indent_nomargin, but explicitly requesting
764 # the default behaviour by passing None as the predicate
765 for text in self.CASES:
766 self.assertEqual(indent(text, '', None), text)
767
768 def test_indent_nomargin_all_lines(self):
769 # The same as test_indent_nomargin, but using the optional
770 # predicate argument
771 predicate = lambda line: True
772 for text in self.CASES:
773 self.assertEqual(indent(text, '', predicate), text)
774
775 def test_indent_no_lines(self):
776 # Explicitly skip indenting any lines
777 predicate = lambda line: False
778 for text in self.CASES:
779 self.assertEqual(indent(text, ' ', predicate), text)
780
781 def test_roundtrip_spaces(self):
782 # A whitespace prefix should roundtrip with dedent
783 for text in self.ROUNDTRIP_CASES:
784 self.assertEqual(dedent(indent(text, ' ')), text)
785
786 def test_roundtrip_tabs(self):
787 # A whitespace prefix should roundtrip with dedent
788 for text in self.ROUNDTRIP_CASES:
789 self.assertEqual(dedent(indent(text, '\t\t')), text)
790
791 def test_roundtrip_mixed(self):
792 # A whitespace prefix should roundtrip with dedent
793 for text in self.ROUNDTRIP_CASES:
794 self.assertEqual(dedent(indent(text, ' \t \t ')), text)
795
796 def test_indent_default(self):
797 # Test default indenting of lines that are not whitespace only
798 prefix = ' '
799 expected = (
800 # Basic test case
801 " Hi.\n This is a test.\n Testing.",
802 # Include a blank line
803 " Hi.\n This is a test.\n\n Testing.",
804 # Include leading and trailing blank lines
805 "\n Hi.\n This is a test.\n Testing.\n",
806 # Use Windows line endings
807 " Hi.\r\n This is a test.\r\n Testing.\r\n",
808 # Pathological case
809 "\n Hi.\r\n This is a test.\n\r\n Testing.\r\n\n",
810 )
811 for text, expect in zip(self.CASES, expected):
812 self.assertEqual(indent(text, prefix), expect)
813
814 def test_indent_explicit_default(self):
815 # Test default indenting of lines that are not whitespace only
816 prefix = ' '
817 expected = (
818 # Basic test case
819 " Hi.\n This is a test.\n Testing.",
820 # Include a blank line
821 " Hi.\n This is a test.\n\n Testing.",
822 # Include leading and trailing blank lines
823 "\n Hi.\n This is a test.\n Testing.\n",
824 # Use Windows line endings
825 " Hi.\r\n This is a test.\r\n Testing.\r\n",
826 # Pathological case
827 "\n Hi.\r\n This is a test.\n\r\n Testing.\r\n\n",
828 )
829 for text, expect in zip(self.CASES, expected):
830 self.assertEqual(indent(text, prefix, None), expect)
831
832 def test_indent_all_lines(self):
833 # Add 'prefix' to all lines, including whitespace-only ones.
834 prefix = ' '
835 expected = (
836 # Basic test case
837 " Hi.\n This is a test.\n Testing.",
838 # Include a blank line
839 " Hi.\n This is a test.\n \n Testing.",
840 # Include leading and trailing blank lines
841 " \n Hi.\n This is a test.\n Testing.\n",
842 # Use Windows line endings
843 " Hi.\r\n This is a test.\r\n Testing.\r\n",
844 # Pathological case
845 " \n Hi.\r\n This is a test.\n \r\n Testing.\r\n \n",
846 )
847 predicate = lambda line: True
848 for text, expect in zip(self.CASES, expected):
849 self.assertEqual(indent(text, prefix, predicate), expect)
850
851 def test_indent_empty_lines(self):
852 # Add 'prefix' solely to whitespace-only lines.
853 prefix = ' '
854 expected = (
855 # Basic test case
856 "Hi.\nThis is a test.\nTesting.",
857 # Include a blank line
858 "Hi.\nThis is a test.\n \nTesting.",
859 # Include leading and trailing blank lines
860 " \nHi.\nThis is a test.\nTesting.\n",
861 # Use Windows line endings
862 "Hi.\r\nThis is a test.\r\nTesting.\r\n",
863 # Pathological case
864 " \nHi.\r\nThis is a test.\n \r\nTesting.\r\n \n",
865 )
866 predicate = lambda line: not line.strip()
867 for text, expect in zip(self.CASES, expected):
868 self.assertEqual(indent(text, prefix, predicate), expect)
869
870
Antoine Pitrou389dec82013-08-12 22:39:09 +0200871class ShortenTestCase(BaseTestCase):
872
Serhiy Storchakaacc9f3f2013-10-15 21:22:54 +0300873 def check_shorten(self, text, width, expect, **kwargs):
874 result = shorten(text, width, **kwargs)
875 self.check(result, expect)
876
Antoine Pitrou389dec82013-08-12 22:39:09 +0200877 def test_simple(self):
878 # Simple case: just words, spaces, and a bit of punctuation
879 text = "Hello there, how are you this fine day? I'm glad to hear it!"
880
Antoine Pitrouc5930562013-08-16 22:31:12 +0200881 self.check_shorten(text, 18, "Hello there, [...]")
Antoine Pitrou389dec82013-08-12 22:39:09 +0200882 self.check_shorten(text, len(text), text)
883 self.check_shorten(text, len(text) - 1,
884 "Hello there, how are you this fine day? "
Antoine Pitrouc5930562013-08-16 22:31:12 +0200885 "I'm glad to [...]")
Antoine Pitrou389dec82013-08-12 22:39:09 +0200886
887 def test_placeholder(self):
888 text = "Hello there, how are you this fine day? I'm glad to hear it!"
889
890 self.check_shorten(text, 17, "Hello there,$$", placeholder='$$')
891 self.check_shorten(text, 18, "Hello there, how$$", placeholder='$$')
892 self.check_shorten(text, 18, "Hello there, $$", placeholder=' $$')
893 self.check_shorten(text, len(text), text, placeholder='$$')
894 self.check_shorten(text, len(text) - 1,
895 "Hello there, how are you this fine day? "
896 "I'm glad to hear$$", placeholder='$$')
897
898 def test_empty_string(self):
899 self.check_shorten("", 6, "")
900
901 def test_whitespace(self):
902 # Whitespace collapsing
903 text = """
904 This is a paragraph that already has
905 line breaks and \t tabs too."""
906 self.check_shorten(text, 62,
907 "This is a paragraph that already has line "
908 "breaks and tabs too.")
909 self.check_shorten(text, 61,
910 "This is a paragraph that already has line "
Antoine Pitrouc5930562013-08-16 22:31:12 +0200911 "breaks and [...]")
Antoine Pitrou389dec82013-08-12 22:39:09 +0200912
913 self.check_shorten("hello world! ", 12, "hello world!")
Antoine Pitrouc5930562013-08-16 22:31:12 +0200914 self.check_shorten("hello world! ", 11, "hello [...]")
Antoine Pitrou389dec82013-08-12 22:39:09 +0200915 # The leading space is trimmed from the placeholder
916 # (it would be ugly otherwise).
Antoine Pitrouc5930562013-08-16 22:31:12 +0200917 self.check_shorten("hello world! ", 10, "[...]")
Antoine Pitrou389dec82013-08-12 22:39:09 +0200918
919 def test_width_too_small_for_placeholder(self):
Serhiy Storchakaacc9f3f2013-10-15 21:22:54 +0300920 shorten("x" * 20, width=8, placeholder="(......)")
Antoine Pitrou389dec82013-08-12 22:39:09 +0200921 with self.assertRaises(ValueError):
Serhiy Storchakaacc9f3f2013-10-15 21:22:54 +0300922 shorten("x" * 20, width=8, placeholder="(.......)")
Antoine Pitrou389dec82013-08-12 22:39:09 +0200923
924 def test_first_word_too_long_but_placeholder_fits(self):
Antoine Pitrouc5930562013-08-16 22:31:12 +0200925 self.check_shorten("Helloo", 5, "[...]")
Antoine Pitrou389dec82013-08-12 22:39:09 +0200926
Greg Wardf6765782002-08-22 18:35:49 +0000927
Greg Ward90c0b072002-08-22 18:11:10 +0000928if __name__ == '__main__':
Antoine Pitrou389dec82013-08-12 22:39:09 +0200929 unittest.main()