blob: 36c15cc03cb4c06592987cf8ea3fcb8991722a82 [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
Antoine Pitrou389dec82013-08-12 22:39:09 +020045 def check_shorten(self, text, width, expect, **kwargs):
46 result = shorten(text, width, **kwargs)
47 self.check(result, expect)
48
Greg Ward90c0b072002-08-22 18:11:10 +000049
Greg Ward13c53c62002-08-22 18:57:26 +000050class WrapTestCase(BaseTestCase):
Greg Ward90c0b072002-08-22 18:11:10 +000051
Greg Ward90c0b072002-08-22 18:11:10 +000052 def setUp(self):
Greg Wardf0ba7642004-05-13 01:53:10 +000053 self.wrapper = TextWrapper(width=45)
Greg Ward90c0b072002-08-22 18:11:10 +000054
Greg Wardf6765782002-08-22 18:35:49 +000055 def test_simple(self):
Guido van Rossum327af772002-08-22 20:13:47 +000056 # Simple case: just words, spaces, and a bit of punctuation
Greg Ward90c0b072002-08-22 18:11:10 +000057
Greg Wardee413842002-08-22 18:55:38 +000058 text = "Hello there, how are you this fine day? I'm glad to hear it!"
Greg Ward90c0b072002-08-22 18:11:10 +000059
Greg Wardee413842002-08-22 18:55:38 +000060 self.check_wrap(text, 12,
61 ["Hello there,",
62 "how are you",
63 "this fine",
64 "day? I'm",
65 "glad to hear",
66 "it!"])
67 self.check_wrap(text, 42,
68 ["Hello there, how are you this fine day?",
69 "I'm glad to hear it!"])
70 self.check_wrap(text, 80, [text])
Greg Ward90c0b072002-08-22 18:11:10 +000071
R David Murray1585b702012-09-08 13:13:25 -040072 def test_empty_string(self):
73 # Check that wrapping the empty string returns an empty list.
74 self.check_wrap("", 6, [])
75 self.check_wrap("", 6, [], drop_whitespace=False)
76
77 def test_empty_string_with_initial_indent(self):
78 # Check that the empty string is not indented.
79 self.check_wrap("", 6, [], initial_indent="++")
80 self.check_wrap("", 6, [], initial_indent="++", drop_whitespace=False)
Greg Ward90c0b072002-08-22 18:11:10 +000081
Greg Wardf6765782002-08-22 18:35:49 +000082 def test_whitespace(self):
Guido van Rossum327af772002-08-22 20:13:47 +000083 # Whitespace munging and end-of-sentence detection
Greg Ward90c0b072002-08-22 18:11:10 +000084
Greg Wardee413842002-08-22 18:55:38 +000085 text = """\
Greg Ward90c0b072002-08-22 18:11:10 +000086This is a paragraph that already has
87line breaks. But some of its lines are much longer than the others,
88so it needs to be wrapped.
89Some lines are \ttabbed too.
90What a mess!
91"""
92
Greg Wardee413842002-08-22 18:55:38 +000093 expect = ["This is a paragraph that already has line",
94 "breaks. But some of its lines are much",
95 "longer than the others, so it needs to be",
96 "wrapped. Some lines are tabbed too. What a",
97 "mess!"]
Greg Ward90c0b072002-08-22 18:11:10 +000098
Greg Wardf0ba7642004-05-13 01:53:10 +000099 wrapper = TextWrapper(45, fix_sentence_endings=True)
100 result = wrapper.wrap(text)
Greg Ward90c0b072002-08-22 18:11:10 +0000101 self.check(result, expect)
102
Greg Wardf0ba7642004-05-13 01:53:10 +0000103 result = wrapper.fill(text)
Greg Ward90c0b072002-08-22 18:11:10 +0000104 self.check(result, '\n'.join(expect))
105
Hynek Schlawackd5272592012-05-19 13:33:11 +0200106 text = "\tTest\tdefault\t\ttabsize."
107 expect = [" Test default tabsize."]
108 self.check_wrap(text, 80, expect)
109
110 text = "\tTest\tcustom\t\ttabsize."
111 expect = [" Test custom tabsize."]
112 self.check_wrap(text, 80, expect, tabsize=4)
113
Greg Wardf0ba7642004-05-13 01:53:10 +0000114 def test_fix_sentence_endings(self):
115 wrapper = TextWrapper(60, fix_sentence_endings=True)
Greg Ward90c0b072002-08-22 18:11:10 +0000116
Greg Wardf0ba7642004-05-13 01:53:10 +0000117 # SF #847346: ensure that fix_sentence_endings=True does the
118 # right thing even on input short enough that it doesn't need to
119 # be wrapped.
120 text = "A short line. Note the single space."
121 expect = ["A short line. Note the single space."]
122 self.check(wrapper.wrap(text), expect)
123
124 # Test some of the hairy end cases that _fix_sentence_endings()
125 # is supposed to handle (the easy stuff is tested in
126 # test_whitespace() above).
127 text = "Well, Doctor? What do you think?"
128 expect = ["Well, Doctor? What do you think?"]
129 self.check(wrapper.wrap(text), expect)
130
131 text = "Well, Doctor?\nWhat do you think?"
132 self.check(wrapper.wrap(text), expect)
133
134 text = 'I say, chaps! Anyone for "tennis?"\nHmmph!'
135 expect = ['I say, chaps! Anyone for "tennis?" Hmmph!']
136 self.check(wrapper.wrap(text), expect)
137
138 wrapper.width = 20
139 expect = ['I say, chaps!', 'Anyone for "tennis?"', 'Hmmph!']
140 self.check(wrapper.wrap(text), expect)
141
142 text = 'And she said, "Go to hell!"\nCan you believe that?'
143 expect = ['And she said, "Go to',
144 'hell!" Can you',
145 'believe that?']
146 self.check(wrapper.wrap(text), expect)
147
148 wrapper.width = 60
149 expect = ['And she said, "Go to hell!" Can you believe that?']
150 self.check(wrapper.wrap(text), expect)
Tim Peters27f88362004-07-08 04:22:35 +0000151
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000152 text = 'File stdio.h is nice.'
153 expect = ['File stdio.h is nice.']
154 self.check(wrapper.wrap(text), expect)
155
Greg Wardf6765782002-08-22 18:35:49 +0000156 def test_wrap_short(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000157 # Wrapping to make short lines longer
Greg Ward90c0b072002-08-22 18:11:10 +0000158
Greg Wardee413842002-08-22 18:55:38 +0000159 text = "This is a\nshort paragraph."
Greg Ward90c0b072002-08-22 18:11:10 +0000160
Greg Wardee413842002-08-22 18:55:38 +0000161 self.check_wrap(text, 20, ["This is a short",
162 "paragraph."])
163 self.check_wrap(text, 40, ["This is a short paragraph."])
Greg Ward90c0b072002-08-22 18:11:10 +0000164
165
Guido van Rossumeb287a22002-10-02 15:47:32 +0000166 def test_wrap_short_1line(self):
167 # Test endcases
168
169 text = "This is a short line."
170
171 self.check_wrap(text, 30, ["This is a short line."])
172 self.check_wrap(text, 30, ["(1) This is a short line."],
173 initial_indent="(1) ")
174
175
Greg Wardf6765782002-08-22 18:35:49 +0000176 def test_hyphenated(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000177 # Test breaking hyphenated words
Greg Ward90c0b072002-08-22 18:11:10 +0000178
Greg Wardee413842002-08-22 18:55:38 +0000179 text = ("this-is-a-useful-feature-for-"
180 "reformatting-posts-from-tim-peters'ly")
Greg Ward90c0b072002-08-22 18:11:10 +0000181
Greg Wardee413842002-08-22 18:55:38 +0000182 self.check_wrap(text, 40,
183 ["this-is-a-useful-feature-for-",
184 "reformatting-posts-from-tim-peters'ly"])
185 self.check_wrap(text, 41,
186 ["this-is-a-useful-feature-for-",
187 "reformatting-posts-from-tim-peters'ly"])
188 self.check_wrap(text, 42,
189 ["this-is-a-useful-feature-for-reformatting-",
190 "posts-from-tim-peters'ly"])
Greg Ward90c0b072002-08-22 18:11:10 +0000191
Greg Ward40407942005-03-05 02:53:17 +0000192 def test_hyphenated_numbers(self):
193 # Test that hyphenated numbers (eg. dates) are not broken like words.
194 text = ("Python 1.0.0 was released on 1994-01-26. Python 1.0.1 was\n"
195 "released on 1994-02-15.")
196
197 self.check_wrap(text, 30, ['Python 1.0.0 was released on',
198 '1994-01-26. Python 1.0.1 was',
199 'released on 1994-02-15.'])
200 self.check_wrap(text, 40, ['Python 1.0.0 was released on 1994-01-26.',
201 'Python 1.0.1 was released on 1994-02-15.'])
202
203 text = "I do all my shopping at 7-11."
204 self.check_wrap(text, 25, ["I do all my shopping at",
205 "7-11."])
206 self.check_wrap(text, 27, ["I do all my shopping at",
207 "7-11."])
208 self.check_wrap(text, 29, ["I do all my shopping at 7-11."])
209
Greg Ward9ad15a32002-08-22 19:47:27 +0000210 def test_em_dash(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000211 # Test text with em-dashes
Greg Ward9ad15a32002-08-22 19:47:27 +0000212 text = "Em-dashes should be written -- thus."
213 self.check_wrap(text, 25,
214 ["Em-dashes should be",
215 "written -- thus."])
216
217 # Probe the boundaries of the properly written em-dash,
218 # ie. " -- ".
219 self.check_wrap(text, 29,
220 ["Em-dashes should be written",
221 "-- thus."])
222 expect = ["Em-dashes should be written --",
223 "thus."]
224 self.check_wrap(text, 30, expect)
225 self.check_wrap(text, 35, expect)
226 self.check_wrap(text, 36,
227 ["Em-dashes should be written -- thus."])
Guido van Rossum327af772002-08-22 20:13:47 +0000228
Greg Ward9ad15a32002-08-22 19:47:27 +0000229 # The improperly written em-dash is handled too, because
230 # it's adjacent to non-whitespace on both sides.
231 text = "You can also do--this or even---this."
232 expect = ["You can also do",
233 "--this or even",
234 "---this."]
235 self.check_wrap(text, 15, expect)
236 self.check_wrap(text, 16, expect)
237 expect = ["You can also do--",
238 "this or even---",
239 "this."]
240 self.check_wrap(text, 17, expect)
241 self.check_wrap(text, 19, expect)
242 expect = ["You can also do--this or even",
243 "---this."]
244 self.check_wrap(text, 29, expect)
245 self.check_wrap(text, 31, expect)
246 expect = ["You can also do--this or even---",
247 "this."]
248 self.check_wrap(text, 32, expect)
249 self.check_wrap(text, 35, expect)
250
251 # All of the above behaviour could be deduced by probing the
252 # _split() method.
253 text = "Here's an -- em-dash and--here's another---and another!"
Greg Ward9ad15a32002-08-22 19:47:27 +0000254 expect = ["Here's", " ", "an", " ", "--", " ", "em-", "dash", " ",
255 "and", "--", "here's", " ", "another", "---",
256 "and", " ", "another!"]
Greg Wardd1a72a02002-10-31 16:11:18 +0000257 self.check_split(text, expect)
Greg Ward90c0b072002-08-22 18:11:10 +0000258
Greg Wardc6edb372002-08-22 21:27:05 +0000259 text = "and then--bam!--he was gone"
260 expect = ["and", " ", "then", "--", "bam!", "--",
261 "he", " ", "was", " ", "gone"]
Greg Wardd1a72a02002-10-31 16:11:18 +0000262 self.check_split(text, expect)
Greg Wardc6edb372002-08-22 21:27:05 +0000263
264
Greg Ward34f995b2002-08-22 21:10:07 +0000265 def test_unix_options (self):
266 # Test that Unix-style command-line options are wrapped correctly.
267 # Both Optik (OptionParser) and Docutils rely on this behaviour!
268
269 text = "You should use the -n option, or --dry-run in its long form."
270 self.check_wrap(text, 20,
271 ["You should use the",
272 "-n option, or --dry-",
273 "run in its long",
274 "form."])
275 self.check_wrap(text, 21,
276 ["You should use the -n",
277 "option, or --dry-run",
278 "in its long form."])
279 expect = ["You should use the -n option, or",
280 "--dry-run in its long form."]
281 self.check_wrap(text, 32, expect)
282 self.check_wrap(text, 34, expect)
283 self.check_wrap(text, 35, expect)
284 self.check_wrap(text, 38, expect)
285 expect = ["You should use the -n option, or --dry-",
286 "run in its long form."]
287 self.check_wrap(text, 39, expect)
288 self.check_wrap(text, 41, expect)
289 expect = ["You should use the -n option, or --dry-run",
290 "in its long form."]
291 self.check_wrap(text, 42, expect)
292
Greg Ward24a1c9c2002-08-22 21:12:54 +0000293 # Again, all of the above can be deduced from _split().
294 text = "the -n option, or --dry-run or --dryrun"
Greg Ward24a1c9c2002-08-22 21:12:54 +0000295 expect = ["the", " ", "-n", " ", "option,", " ", "or", " ",
296 "--dry-", "run", " ", "or", " ", "--dryrun"]
Greg Wardd1a72a02002-10-31 16:11:18 +0000297 self.check_split(text, expect)
298
299 def test_funky_hyphens (self):
300 # Screwy edge cases cooked up by David Goodger. All reported
301 # in SF bug #596434.
302 self.check_split("what the--hey!", ["what", " ", "the", "--", "hey!"])
303 self.check_split("what the--", ["what", " ", "the--"])
304 self.check_split("what the--.", ["what", " ", "the--."])
305 self.check_split("--text--.", ["--text--."])
306
Greg Wardcc55cb92003-05-07 01:19:22 +0000307 # When I first read bug #596434, this is what I thought David
308 # was talking about. I was wrong; these have always worked
309 # fine. The real problem is tested in test_funky_parens()
310 # below...
Greg Wardd1a72a02002-10-31 16:11:18 +0000311 self.check_split("--option", ["--option"])
312 self.check_split("--option-opt", ["--option-", "opt"])
Greg Wardcc55cb92003-05-07 01:19:22 +0000313 self.check_split("foo --option-opt bar",
314 ["foo", " ", "--option-", "opt", " ", "bar"])
315
Greg Ward61864102004-06-03 01:59:41 +0000316 def test_punct_hyphens(self):
317 # Oh bother, SF #965425 found another problem with hyphens --
318 # hyphenated words in single quotes weren't handled correctly.
319 # In fact, the bug is that *any* punctuation around a hyphenated
320 # word was handled incorrectly, except for a leading "--", which
321 # was special-cased for Optik and Docutils. So test a variety
322 # of styles of punctuation around a hyphenated word.
323 # (Actually this is based on an Optik bug report, #813077).
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 self.check_split("the (wibble-wobble) widget",
329 ['the', ' ', "(wibble-", "wobble)", ' ', 'widget'])
330 self.check_split("the ['wibble-wobble'] widget",
331 ['the', ' ', "['wibble-", "wobble']", ' ', 'widget'])
332
Greg Wardcc55cb92003-05-07 01:19:22 +0000333 def test_funky_parens (self):
334 # Second part of SF bug #596434: long option strings inside
335 # parentheses.
336 self.check_split("foo (--option) bar",
337 ["foo", " ", "(--option)", " ", "bar"])
338
339 # Related stuff -- make sure parens work in simpler contexts.
340 self.check_split("foo (bar) baz",
341 ["foo", " ", "(bar)", " ", "baz"])
342 self.check_split("blah (ding dong), wubba",
343 ["blah", " ", "(ding", " ", "dong),",
344 " ", "wubba"])
Greg Ward24a1c9c2002-08-22 21:12:54 +0000345
R David Murray1585b702012-09-08 13:13:25 -0400346 def test_drop_whitespace_false(self):
347 # Check that drop_whitespace=False preserves whitespace.
348 # SF patch #1581073
349 text = " This is a sentence with much whitespace."
350 self.check_wrap(text, 10,
351 [" This is a", " ", "sentence ",
352 "with ", "much white", "space."],
353 drop_whitespace=False)
354
355 def test_drop_whitespace_false_whitespace_only(self):
356 # Check that drop_whitespace=False preserves a whitespace-only string.
357 self.check_wrap(" ", 6, [" "], drop_whitespace=False)
358
359 def test_drop_whitespace_false_whitespace_only_with_indent(self):
360 # Check that a whitespace-only string gets indented (when
361 # drop_whitespace is False).
362 self.check_wrap(" ", 6, [" "], drop_whitespace=False,
363 initial_indent=" ")
364
365 def test_drop_whitespace_whitespace_only(self):
366 # Check drop_whitespace on a whitespace-only string.
367 self.check_wrap(" ", 6, [])
368
369 def test_drop_whitespace_leading_whitespace(self):
370 # Check that drop_whitespace does not drop leading whitespace (if
371 # followed by non-whitespace).
Greg Ward24cbbcb2002-12-09 16:27:15 +0000372 # SF bug #622849 reported inconsistent handling of leading
373 # whitespace; let's test that a bit, shall we?
374 text = " This is a sentence with leading whitespace."
375 self.check_wrap(text, 50,
376 [" This is a sentence with leading whitespace."])
377 self.check_wrap(text, 30,
378 [" This is a sentence with", "leading whitespace."])
379
R David Murray1585b702012-09-08 13:13:25 -0400380 def test_drop_whitespace_whitespace_line(self):
381 # Check that drop_whitespace skips the whole line if a non-leading
382 # line consists only of whitespace.
383 text = "abcd efgh"
384 # Include the result for drop_whitespace=False for comparison.
385 self.check_wrap(text, 6, ["abcd", " ", "efgh"],
Guido van Rossumd8faa362007-04-27 19:54:29 +0000386 drop_whitespace=False)
R David Murray1585b702012-09-08 13:13:25 -0400387 self.check_wrap(text, 6, ["abcd", "efgh"])
388
389 def test_drop_whitespace_whitespace_only_with_indent(self):
390 # Check that initial_indent is not applied to a whitespace-only
391 # string. This checks a special case of the fact that dropping
392 # whitespace occurs before indenting.
393 self.check_wrap(" ", 6, [], initial_indent="++")
394
395 def test_drop_whitespace_whitespace_indent(self):
396 # Check that drop_whitespace does not drop whitespace indents.
397 # This checks a special case of the fact that dropping whitespace
398 # occurs before indenting.
399 self.check_wrap("abcd efgh", 6, [" abcd", " efgh"],
400 initial_indent=" ", subsequent_indent=" ")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000401
Greg Ward90c0b072002-08-22 18:11:10 +0000402 def test_split(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000403 # Ensure that the standard _split() method works as advertised
404 # in the comments
Greg Ward90c0b072002-08-22 18:11:10 +0000405
Greg Wardee413842002-08-22 18:55:38 +0000406 text = "Hello there -- you goof-ball, use the -b option!"
Greg Ward90c0b072002-08-22 18:11:10 +0000407
Greg Wardee413842002-08-22 18:55:38 +0000408 result = self.wrapper._split(text)
Greg Ward90c0b072002-08-22 18:11:10 +0000409 self.check(result,
410 ["Hello", " ", "there", " ", "--", " ", "you", " ", "goof-",
411 "ball,", " ", "use", " ", "the", " ", "-b", " ", "option!"])
412
Alexandre Vassalotti5f8ced22008-05-16 00:03:33 +0000413 def test_break_on_hyphens(self):
414 # Ensure that the break_on_hyphens attributes work
415 text = "yaba daba-doo"
416 self.check_wrap(text, 10, ["yaba daba-", "doo"],
417 break_on_hyphens=True)
418 self.check_wrap(text, 10, ["yaba", "daba-doo"],
419 break_on_hyphens=False)
420
Greg Ward49128572003-05-07 00:54:42 +0000421 def test_bad_width(self):
422 # Ensure that width <= 0 is caught.
423 text = "Whatever, it doesn't matter."
424 self.assertRaises(ValueError, wrap, text, 0)
425 self.assertRaises(ValueError, wrap, text, -1)
426
Antoine Pitrou7c59bc62008-12-13 23:20:54 +0000427 def test_no_split_at_umlaut(self):
428 text = "Die Empf\xe4nger-Auswahl"
429 self.check_wrap(text, 13, ["Die", "Empf\xe4nger-", "Auswahl"])
430
431 def test_umlaut_followed_by_dash(self):
432 text = "aa \xe4\xe4-\xe4\xe4"
433 self.check_wrap(text, 7, ["aa \xe4\xe4-", "\xe4\xe4"])
434
Greg Ward90c0b072002-08-22 18:11:10 +0000435
Greg Wardfd030e42002-08-22 19:02:37 +0000436class LongWordTestCase (BaseTestCase):
437 def setUp(self):
438 self.wrapper = TextWrapper()
Greg Ward24cbbcb2002-12-09 16:27:15 +0000439 self.text = '''\
Greg Ward90c0b072002-08-22 18:11:10 +0000440Did you say "supercalifragilisticexpialidocious?"
441How *do* you spell that odd word, anyways?
442'''
Greg Wardfd030e42002-08-22 19:02:37 +0000443
444 def test_break_long(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000445 # Wrap text with long words and lots of punctuation
Greg Wardfd030e42002-08-22 19:02:37 +0000446
447 self.check_wrap(self.text, 30,
Greg Wardee413842002-08-22 18:55:38 +0000448 ['Did you say "supercalifragilis',
449 'ticexpialidocious?" How *do*',
450 'you spell that odd word,',
451 'anyways?'])
Greg Wardfd030e42002-08-22 19:02:37 +0000452 self.check_wrap(self.text, 50,
Greg Wardee413842002-08-22 18:55:38 +0000453 ['Did you say "supercalifragilisticexpialidocious?"',
454 'How *do* you spell that odd word, anyways?'])
Greg Ward90c0b072002-08-22 18:11:10 +0000455
Raymond Hettingerc11dbcd2003-08-30 14:43:55 +0000456 # SF bug 797650. Prevent an infinite loop by making sure that at
457 # least one character gets split off on every pass.
458 self.check_wrap('-'*10+'hello', 10,
459 ['----------',
460 ' h',
461 ' e',
462 ' l',
463 ' l',
464 ' o'],
465 subsequent_indent = ' '*15)
Greg Ward90c0b072002-08-22 18:11:10 +0000466
Georg Brandlfceab5a2008-01-19 20:08:23 +0000467 # bug 1146. Prevent a long word to be wrongly wrapped when the
468 # preceding word is exactly one character shorter than the width
469 self.check_wrap(self.text, 12,
470 ['Did you say ',
471 '"supercalifr',
472 'agilisticexp',
473 'ialidocious?',
474 '" How *do*',
475 'you spell',
476 'that odd',
477 'word,',
478 'anyways?'])
479
Guido van Rossum327af772002-08-22 20:13:47 +0000480 def test_nobreak_long(self):
481 # Test with break_long_words disabled
Greg Ward90c0b072002-08-22 18:11:10 +0000482 self.wrapper.break_long_words = 0
483 self.wrapper.width = 30
Greg Wardee413842002-08-22 18:55:38 +0000484 expect = ['Did you say',
485 '"supercalifragilisticexpialidocious?"',
486 'How *do* you spell that odd',
487 'word, anyways?'
Guido van Rossum327af772002-08-22 20:13:47 +0000488 ]
Greg Wardfd030e42002-08-22 19:02:37 +0000489 result = self.wrapper.wrap(self.text)
Greg Ward90c0b072002-08-22 18:11:10 +0000490 self.check(result, expect)
491
492 # Same thing with kwargs passed to standalone wrap() function.
Greg Wardfd030e42002-08-22 19:02:37 +0000493 result = wrap(self.text, width=30, break_long_words=0)
Greg Ward90c0b072002-08-22 18:11:10 +0000494 self.check(result, expect)
495
496
Greg Ward13c53c62002-08-22 18:57:26 +0000497class IndentTestCases(BaseTestCase):
Greg Ward90c0b072002-08-22 18:11:10 +0000498
499 # called before each test method
500 def setUp(self):
Greg Wardf69d3c92002-08-22 19:06:45 +0000501 self.text = '''\
Greg Ward90c0b072002-08-22 18:11:10 +0000502This paragraph will be filled, first without any indentation,
503and then with some (including a hanging indent).'''
504
505
Greg Wardf6765782002-08-22 18:35:49 +0000506 def test_fill(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000507 # Test the fill() method
Greg Ward90c0b072002-08-22 18:11:10 +0000508
509 expect = '''\
510This paragraph will be filled, first
511without any indentation, and then with
512some (including a hanging indent).'''
513
Greg Wardf69d3c92002-08-22 19:06:45 +0000514 result = fill(self.text, 40)
Greg Ward90c0b072002-08-22 18:11:10 +0000515 self.check(result, expect)
516
517
Greg Wardf6765782002-08-22 18:35:49 +0000518 def test_initial_indent(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000519 # Test initial_indent parameter
Greg Ward90c0b072002-08-22 18:11:10 +0000520
Greg Wardf69d3c92002-08-22 19:06:45 +0000521 expect = [" This paragraph will be filled,",
522 "first without any indentation, and then",
523 "with some (including a hanging indent)."]
524 result = wrap(self.text, 40, initial_indent=" ")
Greg Ward90c0b072002-08-22 18:11:10 +0000525 self.check(result, expect)
526
Greg Wardf69d3c92002-08-22 19:06:45 +0000527 expect = "\n".join(expect)
528 result = fill(self.text, 40, initial_indent=" ")
Greg Ward90c0b072002-08-22 18:11:10 +0000529 self.check(result, expect)
530
531
Greg Wardf6765782002-08-22 18:35:49 +0000532 def test_subsequent_indent(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000533 # Test subsequent_indent parameter
Greg Ward90c0b072002-08-22 18:11:10 +0000534
535 expect = '''\
536 * This paragraph will be filled, first
537 without any indentation, and then
538 with some (including a hanging
539 indent).'''
540
Greg Wardf69d3c92002-08-22 19:06:45 +0000541 result = fill(self.text, 40,
542 initial_indent=" * ", subsequent_indent=" ")
Greg Ward90c0b072002-08-22 18:11:10 +0000543 self.check(result, expect)
544
545
Greg Ward9e082f42003-05-08 01:58:26 +0000546# Despite the similar names, DedentTestCase is *not* the inverse
547# of IndentTestCase!
548class DedentTestCase(unittest.TestCase):
549
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000550 def assertUnchanged(self, text):
551 """assert that dedent() has no effect on 'text'"""
Ezio Melottib3aedd42010-11-20 19:04:17 +0000552 self.assertEqual(text, dedent(text))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000553
Greg Ward9e082f42003-05-08 01:58:26 +0000554 def test_dedent_nomargin(self):
555 # No lines indented.
556 text = "Hello there.\nHow are you?\nOh good, I'm glad."
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000557 self.assertUnchanged(text)
Greg Ward9e082f42003-05-08 01:58:26 +0000558
559 # Similar, with a blank line.
560 text = "Hello there.\n\nBoo!"
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000561 self.assertUnchanged(text)
Greg Ward9e082f42003-05-08 01:58:26 +0000562
563 # Some lines indented, but overall margin is still zero.
564 text = "Hello there.\n This is indented."
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000565 self.assertUnchanged(text)
Greg Ward9e082f42003-05-08 01:58:26 +0000566
567 # Again, add a blank line.
568 text = "Hello there.\n\n Boo!\n"
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000569 self.assertUnchanged(text)
Greg Ward9e082f42003-05-08 01:58:26 +0000570
571 def test_dedent_even(self):
572 # All lines indented by two spaces.
573 text = " Hello there.\n How are ya?\n Oh good."
574 expect = "Hello there.\nHow are ya?\nOh good."
Ezio Melottib3aedd42010-11-20 19:04:17 +0000575 self.assertEqual(expect, dedent(text))
Greg Ward9e082f42003-05-08 01:58:26 +0000576
577 # Same, with blank lines.
578 text = " Hello there.\n\n How are ya?\n Oh good.\n"
579 expect = "Hello there.\n\nHow are ya?\nOh good.\n"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000580 self.assertEqual(expect, dedent(text))
Greg Ward9e082f42003-05-08 01:58:26 +0000581
582 # Now indent one of the blank lines.
583 text = " Hello there.\n \n How are ya?\n Oh good.\n"
584 expect = "Hello there.\n\nHow are ya?\nOh good.\n"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000585 self.assertEqual(expect, dedent(text))
Greg Ward9e082f42003-05-08 01:58:26 +0000586
587 def test_dedent_uneven(self):
588 # Lines indented unevenly.
589 text = '''\
590 def foo():
591 while 1:
592 return foo
593 '''
594 expect = '''\
595def foo():
596 while 1:
597 return foo
598'''
Ezio Melottib3aedd42010-11-20 19:04:17 +0000599 self.assertEqual(expect, dedent(text))
Greg Ward9e082f42003-05-08 01:58:26 +0000600
601 # Uneven indentation with a blank line.
602 text = " Foo\n Bar\n\n Baz\n"
603 expect = "Foo\n Bar\n\n Baz\n"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000604 self.assertEqual(expect, dedent(text))
Greg Ward9e082f42003-05-08 01:58:26 +0000605
606 # Uneven indentation with a whitespace-only line.
607 text = " Foo\n Bar\n \n Baz\n"
608 expect = "Foo\n Bar\n\n Baz\n"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000609 self.assertEqual(expect, dedent(text))
Greg Ward9e082f42003-05-08 01:58:26 +0000610
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000611 # dedent() should not mangle internal tabs
612 def test_dedent_preserve_internal_tabs(self):
613 text = " hello\tthere\n how are\tyou?"
614 expect = "hello\tthere\nhow are\tyou?"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000615 self.assertEqual(expect, dedent(text))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000616
617 # make sure that it preserves tabs when it's not making any
618 # changes at all
Ezio Melottib3aedd42010-11-20 19:04:17 +0000619 self.assertEqual(expect, dedent(expect))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000620
621 # dedent() should not mangle tabs in the margin (i.e.
622 # tabs and spaces both count as margin, but are *not*
623 # considered equivalent)
624 def test_dedent_preserve_margin_tabs(self):
625 text = " hello there\n\thow are you?"
626 self.assertUnchanged(text)
627
628 # same effect even if we have 8 spaces
629 text = " hello there\n\thow are you?"
630 self.assertUnchanged(text)
631
632 # dedent() only removes whitespace that can be uniformly removed!
633 text = "\thello there\n\thow are you?"
634 expect = "hello there\nhow are you?"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000635 self.assertEqual(expect, dedent(text))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000636
637 text = " \thello there\n \thow are you?"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000638 self.assertEqual(expect, dedent(text))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000639
640 text = " \t hello there\n \t how are you?"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000641 self.assertEqual(expect, dedent(text))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000642
643 text = " \thello there\n \t how are you?"
644 expect = "hello there\n how are you?"
Ezio Melottib3aedd42010-11-20 19:04:17 +0000645 self.assertEqual(expect, dedent(text))
Greg Ward9e082f42003-05-08 01:58:26 +0000646
647
Nick Coghlan4fae8cd2012-06-11 23:07:51 +1000648# Test textwrap.indent
649class IndentTestCase(unittest.TestCase):
650 # The examples used for tests. If any of these change, the expected
651 # results in the various test cases must also be updated.
652 # The roundtrip cases are separate, because textwrap.dedent doesn't
653 # handle Windows line endings
654 ROUNDTRIP_CASES = (
655 # Basic test case
656 "Hi.\nThis is a test.\nTesting.",
657 # Include a blank line
658 "Hi.\nThis is a test.\n\nTesting.",
659 # Include leading and trailing blank lines
660 "\nHi.\nThis is a test.\nTesting.\n",
661 )
662 CASES = ROUNDTRIP_CASES + (
663 # Use Windows line endings
664 "Hi.\r\nThis is a test.\r\nTesting.\r\n",
665 # Pathological case
666 "\nHi.\r\nThis is a test.\n\r\nTesting.\r\n\n",
667 )
668
669 def test_indent_nomargin_default(self):
670 # indent should do nothing if 'prefix' is empty.
671 for text in self.CASES:
672 self.assertEqual(indent(text, ''), text)
673
674 def test_indent_nomargin_explicit_default(self):
675 # The same as test_indent_nomargin, but explicitly requesting
676 # the default behaviour by passing None as the predicate
677 for text in self.CASES:
678 self.assertEqual(indent(text, '', None), text)
679
680 def test_indent_nomargin_all_lines(self):
681 # The same as test_indent_nomargin, but using the optional
682 # predicate argument
683 predicate = lambda line: True
684 for text in self.CASES:
685 self.assertEqual(indent(text, '', predicate), text)
686
687 def test_indent_no_lines(self):
688 # Explicitly skip indenting any lines
689 predicate = lambda line: False
690 for text in self.CASES:
691 self.assertEqual(indent(text, ' ', predicate), text)
692
693 def test_roundtrip_spaces(self):
694 # A whitespace prefix should roundtrip with dedent
695 for text in self.ROUNDTRIP_CASES:
696 self.assertEqual(dedent(indent(text, ' ')), text)
697
698 def test_roundtrip_tabs(self):
699 # A whitespace prefix should roundtrip with dedent
700 for text in self.ROUNDTRIP_CASES:
701 self.assertEqual(dedent(indent(text, '\t\t')), text)
702
703 def test_roundtrip_mixed(self):
704 # A whitespace prefix should roundtrip with dedent
705 for text in self.ROUNDTRIP_CASES:
706 self.assertEqual(dedent(indent(text, ' \t \t ')), text)
707
708 def test_indent_default(self):
709 # Test default indenting of lines that are not whitespace only
710 prefix = ' '
711 expected = (
712 # Basic test case
713 " Hi.\n This is a test.\n Testing.",
714 # Include a blank line
715 " Hi.\n This is a test.\n\n Testing.",
716 # Include leading and trailing blank lines
717 "\n Hi.\n This is a test.\n Testing.\n",
718 # Use Windows line endings
719 " Hi.\r\n This is a test.\r\n Testing.\r\n",
720 # Pathological case
721 "\n Hi.\r\n This is a test.\n\r\n Testing.\r\n\n",
722 )
723 for text, expect in zip(self.CASES, expected):
724 self.assertEqual(indent(text, prefix), expect)
725
726 def test_indent_explicit_default(self):
727 # Test default indenting of lines that are not whitespace only
728 prefix = ' '
729 expected = (
730 # Basic test case
731 " Hi.\n This is a test.\n Testing.",
732 # Include a blank line
733 " Hi.\n This is a test.\n\n Testing.",
734 # Include leading and trailing blank lines
735 "\n Hi.\n This is a test.\n Testing.\n",
736 # Use Windows line endings
737 " Hi.\r\n This is a test.\r\n Testing.\r\n",
738 # Pathological case
739 "\n Hi.\r\n This is a test.\n\r\n Testing.\r\n\n",
740 )
741 for text, expect in zip(self.CASES, expected):
742 self.assertEqual(indent(text, prefix, None), expect)
743
744 def test_indent_all_lines(self):
745 # Add 'prefix' to all lines, including whitespace-only ones.
746 prefix = ' '
747 expected = (
748 # Basic test case
749 " Hi.\n This is a test.\n Testing.",
750 # Include a blank line
751 " Hi.\n This is a test.\n \n Testing.",
752 # Include leading and trailing blank lines
753 " \n Hi.\n This is a test.\n Testing.\n",
754 # Use Windows line endings
755 " Hi.\r\n This is a test.\r\n Testing.\r\n",
756 # Pathological case
757 " \n Hi.\r\n This is a test.\n \r\n Testing.\r\n \n",
758 )
759 predicate = lambda line: True
760 for text, expect in zip(self.CASES, expected):
761 self.assertEqual(indent(text, prefix, predicate), expect)
762
763 def test_indent_empty_lines(self):
764 # Add 'prefix' solely to whitespace-only lines.
765 prefix = ' '
766 expected = (
767 # Basic test case
768 "Hi.\nThis is a test.\nTesting.",
769 # Include a blank line
770 "Hi.\nThis is a test.\n \nTesting.",
771 # Include leading and trailing blank lines
772 " \nHi.\nThis is a test.\nTesting.\n",
773 # Use Windows line endings
774 "Hi.\r\nThis is a test.\r\nTesting.\r\n",
775 # Pathological case
776 " \nHi.\r\nThis is a test.\n \r\nTesting.\r\n \n",
777 )
778 predicate = lambda line: not line.strip()
779 for text, expect in zip(self.CASES, expected):
780 self.assertEqual(indent(text, prefix, predicate), expect)
781
782
Antoine Pitrou389dec82013-08-12 22:39:09 +0200783class ShortenTestCase(BaseTestCase):
784
785 def test_simple(self):
786 # Simple case: just words, spaces, and a bit of punctuation
787 text = "Hello there, how are you this fine day? I'm glad to hear it!"
788
Antoine Pitrouc5930562013-08-16 22:31:12 +0200789 self.check_shorten(text, 18, "Hello there, [...]")
Antoine Pitrou389dec82013-08-12 22:39:09 +0200790 self.check_shorten(text, len(text), text)
791 self.check_shorten(text, len(text) - 1,
792 "Hello there, how are you this fine day? "
Antoine Pitrouc5930562013-08-16 22:31:12 +0200793 "I'm glad to [...]")
Antoine Pitrou389dec82013-08-12 22:39:09 +0200794
795 def test_placeholder(self):
796 text = "Hello there, how are you this fine day? I'm glad to hear it!"
797
798 self.check_shorten(text, 17, "Hello there,$$", placeholder='$$')
799 self.check_shorten(text, 18, "Hello there, how$$", placeholder='$$')
800 self.check_shorten(text, 18, "Hello there, $$", placeholder=' $$')
801 self.check_shorten(text, len(text), text, placeholder='$$')
802 self.check_shorten(text, len(text) - 1,
803 "Hello there, how are you this fine day? "
804 "I'm glad to hear$$", placeholder='$$')
805
806 def test_empty_string(self):
807 self.check_shorten("", 6, "")
808
809 def test_whitespace(self):
810 # Whitespace collapsing
811 text = """
812 This is a paragraph that already has
813 line breaks and \t tabs too."""
814 self.check_shorten(text, 62,
815 "This is a paragraph that already has line "
816 "breaks and tabs too.")
817 self.check_shorten(text, 61,
818 "This is a paragraph that already has line "
Antoine Pitrouc5930562013-08-16 22:31:12 +0200819 "breaks and [...]")
Antoine Pitrou389dec82013-08-12 22:39:09 +0200820
821 self.check_shorten("hello world! ", 12, "hello world!")
Antoine Pitrouc5930562013-08-16 22:31:12 +0200822 self.check_shorten("hello world! ", 11, "hello [...]")
Antoine Pitrou389dec82013-08-12 22:39:09 +0200823 # The leading space is trimmed from the placeholder
824 # (it would be ugly otherwise).
Antoine Pitrouc5930562013-08-16 22:31:12 +0200825 self.check_shorten("hello world! ", 10, "[...]")
Antoine Pitrou389dec82013-08-12 22:39:09 +0200826
827 def test_width_too_small_for_placeholder(self):
828 wrapper = TextWrapper(width=8)
829 wrapper.shorten("x" * 20, placeholder="(......)")
830 with self.assertRaises(ValueError):
831 wrapper.shorten("x" * 20, placeholder="(.......)")
832
833 def test_first_word_too_long_but_placeholder_fits(self):
Antoine Pitrouc5930562013-08-16 22:31:12 +0200834 self.check_shorten("Helloo", 5, "[...]")
Antoine Pitrou389dec82013-08-12 22:39:09 +0200835
Greg Wardf6765782002-08-22 18:35:49 +0000836
Greg Ward90c0b072002-08-22 18:11:10 +0000837if __name__ == '__main__':
Antoine Pitrou389dec82013-08-12 22:39:09 +0200838 unittest.main()