blob: 904c79091dd7b44e38d2e7e27260960d7feb58d1 [file] [log] [blame]
Greg Ward3dc94e12002-08-22 18:37:50 +00001#
2# Test script for the textwrap module.
3#
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
Greg Wardf6765782002-08-22 18:35:49 +000012from test import test_support
Greg Ward90c0b072002-08-22 18:11:10 +000013
Greg Ward9e082f42003-05-08 01:58:26 +000014from textwrap import TextWrapper, wrap, fill, dedent
Greg Ward90c0b072002-08-22 18:11:10 +000015
16
Greg Ward13c53c62002-08-22 18:57:26 +000017class BaseTestCase(unittest.TestCase):
Greg Ward90c0b072002-08-22 18:11:10 +000018 '''Parent class with utility methods for textwrap tests.'''
19
20 def show(self, textin):
21 if isinstance(textin, list):
22 result = []
23 for i in range(len(textin)):
24 result.append(" %d: %r" % (i, textin[i]))
25 result = '\n'.join(result)
26 elif isinstance(textin, (str, unicode)):
27 result = " %s\n" % repr(textin)
28 return result
29
30
31 def check(self, result, expect):
Guido van Rossum327af772002-08-22 20:13:47 +000032 self.assertEquals(result, expect,
Greg Ward9ad15a32002-08-22 19:47:27 +000033 'expected:\n%s\nbut got:\n%s' % (
34 self.show(expect), self.show(result)))
Greg Ward90c0b072002-08-22 18:11:10 +000035
Guido van Rossumeb287a22002-10-02 15:47:32 +000036 def check_wrap(self, text, width, expect, **kwargs):
37 result = wrap(text, width, **kwargs)
Greg Wardee413842002-08-22 18:55:38 +000038 self.check(result, expect)
39
Greg Wardd1a72a02002-10-31 16:11:18 +000040 def check_split(self, text, expect):
41 result = self.wrapper._split(text)
Greg Ward715debd2002-08-22 21:16:25 +000042 self.assertEquals(result, expect,
43 "\nexpected %r\n"
44 "but got %r" % (expect, result))
45
Greg Ward90c0b072002-08-22 18:11:10 +000046
Greg Ward13c53c62002-08-22 18:57:26 +000047class WrapTestCase(BaseTestCase):
Greg Ward90c0b072002-08-22 18:11:10 +000048
Greg Ward90c0b072002-08-22 18:11:10 +000049 def setUp(self):
50 self.wrapper = TextWrapper(width=45, fix_sentence_endings=True)
51
Greg Wardf6765782002-08-22 18:35:49 +000052 def test_simple(self):
Guido van Rossum327af772002-08-22 20:13:47 +000053 # Simple case: just words, spaces, and a bit of punctuation
Greg Ward90c0b072002-08-22 18:11:10 +000054
Greg Wardee413842002-08-22 18:55:38 +000055 text = "Hello there, how are you this fine day? I'm glad to hear it!"
Greg Ward90c0b072002-08-22 18:11:10 +000056
Greg Wardee413842002-08-22 18:55:38 +000057 self.check_wrap(text, 12,
58 ["Hello there,",
59 "how are you",
60 "this fine",
61 "day? I'm",
62 "glad to hear",
63 "it!"])
64 self.check_wrap(text, 42,
65 ["Hello there, how are you this fine day?",
66 "I'm glad to hear it!"])
67 self.check_wrap(text, 80, [text])
Greg Ward90c0b072002-08-22 18:11:10 +000068
69
Greg Wardf6765782002-08-22 18:35:49 +000070 def test_whitespace(self):
Guido van Rossum327af772002-08-22 20:13:47 +000071 # Whitespace munging and end-of-sentence detection
Greg Ward90c0b072002-08-22 18:11:10 +000072
Greg Wardee413842002-08-22 18:55:38 +000073 text = """\
Greg Ward90c0b072002-08-22 18:11:10 +000074This is a paragraph that already has
75line breaks. But some of its lines are much longer than the others,
76so it needs to be wrapped.
77Some lines are \ttabbed too.
78What a mess!
79"""
80
Greg Wardee413842002-08-22 18:55:38 +000081 expect = ["This is a paragraph that already has line",
82 "breaks. But some of its lines are much",
83 "longer than the others, so it needs to be",
84 "wrapped. Some lines are tabbed too. What a",
85 "mess!"]
Greg Ward90c0b072002-08-22 18:11:10 +000086
Greg Wardee413842002-08-22 18:55:38 +000087 result = self.wrapper.wrap(text)
Greg Ward90c0b072002-08-22 18:11:10 +000088 self.check(result, expect)
89
Greg Wardee413842002-08-22 18:55:38 +000090 result = self.wrapper.fill(text)
Greg Ward90c0b072002-08-22 18:11:10 +000091 self.check(result, '\n'.join(expect))
92
93
Greg Wardf6765782002-08-22 18:35:49 +000094 def test_wrap_short(self):
Guido van Rossum327af772002-08-22 20:13:47 +000095 # Wrapping to make short lines longer
Greg Ward90c0b072002-08-22 18:11:10 +000096
Greg Wardee413842002-08-22 18:55:38 +000097 text = "This is a\nshort paragraph."
Greg Ward90c0b072002-08-22 18:11:10 +000098
Greg Wardee413842002-08-22 18:55:38 +000099 self.check_wrap(text, 20, ["This is a short",
100 "paragraph."])
101 self.check_wrap(text, 40, ["This is a short paragraph."])
Greg Ward90c0b072002-08-22 18:11:10 +0000102
103
Guido van Rossumeb287a22002-10-02 15:47:32 +0000104 def test_wrap_short_1line(self):
105 # Test endcases
106
107 text = "This is a short line."
108
109 self.check_wrap(text, 30, ["This is a short line."])
110 self.check_wrap(text, 30, ["(1) This is a short line."],
111 initial_indent="(1) ")
112
113
Greg Wardf6765782002-08-22 18:35:49 +0000114 def test_hyphenated(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000115 # Test breaking hyphenated words
Greg Ward90c0b072002-08-22 18:11:10 +0000116
Greg Wardee413842002-08-22 18:55:38 +0000117 text = ("this-is-a-useful-feature-for-"
118 "reformatting-posts-from-tim-peters'ly")
Greg Ward90c0b072002-08-22 18:11:10 +0000119
Greg Wardee413842002-08-22 18:55:38 +0000120 self.check_wrap(text, 40,
121 ["this-is-a-useful-feature-for-",
122 "reformatting-posts-from-tim-peters'ly"])
123 self.check_wrap(text, 41,
124 ["this-is-a-useful-feature-for-",
125 "reformatting-posts-from-tim-peters'ly"])
126 self.check_wrap(text, 42,
127 ["this-is-a-useful-feature-for-reformatting-",
128 "posts-from-tim-peters'ly"])
Greg Ward90c0b072002-08-22 18:11:10 +0000129
Greg Ward9ad15a32002-08-22 19:47:27 +0000130 def test_em_dash(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000131 # Test text with em-dashes
Greg Ward9ad15a32002-08-22 19:47:27 +0000132 text = "Em-dashes should be written -- thus."
133 self.check_wrap(text, 25,
134 ["Em-dashes should be",
135 "written -- thus."])
136
137 # Probe the boundaries of the properly written em-dash,
138 # ie. " -- ".
139 self.check_wrap(text, 29,
140 ["Em-dashes should be written",
141 "-- thus."])
142 expect = ["Em-dashes should be written --",
143 "thus."]
144 self.check_wrap(text, 30, expect)
145 self.check_wrap(text, 35, expect)
146 self.check_wrap(text, 36,
147 ["Em-dashes should be written -- thus."])
Guido van Rossum327af772002-08-22 20:13:47 +0000148
Greg Ward9ad15a32002-08-22 19:47:27 +0000149 # The improperly written em-dash is handled too, because
150 # it's adjacent to non-whitespace on both sides.
151 text = "You can also do--this or even---this."
152 expect = ["You can also do",
153 "--this or even",
154 "---this."]
155 self.check_wrap(text, 15, expect)
156 self.check_wrap(text, 16, expect)
157 expect = ["You can also do--",
158 "this or even---",
159 "this."]
160 self.check_wrap(text, 17, expect)
161 self.check_wrap(text, 19, expect)
162 expect = ["You can also do--this or even",
163 "---this."]
164 self.check_wrap(text, 29, expect)
165 self.check_wrap(text, 31, expect)
166 expect = ["You can also do--this or even---",
167 "this."]
168 self.check_wrap(text, 32, expect)
169 self.check_wrap(text, 35, expect)
170
171 # All of the above behaviour could be deduced by probing the
172 # _split() method.
173 text = "Here's an -- em-dash and--here's another---and another!"
Greg Ward9ad15a32002-08-22 19:47:27 +0000174 expect = ["Here's", " ", "an", " ", "--", " ", "em-", "dash", " ",
175 "and", "--", "here's", " ", "another", "---",
176 "and", " ", "another!"]
Greg Wardd1a72a02002-10-31 16:11:18 +0000177 self.check_split(text, expect)
Greg Ward90c0b072002-08-22 18:11:10 +0000178
Greg Wardc6edb372002-08-22 21:27:05 +0000179 text = "and then--bam!--he was gone"
180 expect = ["and", " ", "then", "--", "bam!", "--",
181 "he", " ", "was", " ", "gone"]
Greg Wardd1a72a02002-10-31 16:11:18 +0000182 self.check_split(text, expect)
Greg Wardc6edb372002-08-22 21:27:05 +0000183
184
Greg Ward34f995b2002-08-22 21:10:07 +0000185 def test_unix_options (self):
186 # Test that Unix-style command-line options are wrapped correctly.
187 # Both Optik (OptionParser) and Docutils rely on this behaviour!
188
189 text = "You should use the -n option, or --dry-run in its long form."
190 self.check_wrap(text, 20,
191 ["You should use the",
192 "-n option, or --dry-",
193 "run in its long",
194 "form."])
195 self.check_wrap(text, 21,
196 ["You should use the -n",
197 "option, or --dry-run",
198 "in its long form."])
199 expect = ["You should use the -n option, or",
200 "--dry-run in its long form."]
201 self.check_wrap(text, 32, expect)
202 self.check_wrap(text, 34, expect)
203 self.check_wrap(text, 35, expect)
204 self.check_wrap(text, 38, expect)
205 expect = ["You should use the -n option, or --dry-",
206 "run in its long form."]
207 self.check_wrap(text, 39, expect)
208 self.check_wrap(text, 41, expect)
209 expect = ["You should use the -n option, or --dry-run",
210 "in its long form."]
211 self.check_wrap(text, 42, expect)
212
Greg Ward24a1c9c2002-08-22 21:12:54 +0000213 # Again, all of the above can be deduced from _split().
214 text = "the -n option, or --dry-run or --dryrun"
Greg Ward24a1c9c2002-08-22 21:12:54 +0000215 expect = ["the", " ", "-n", " ", "option,", " ", "or", " ",
216 "--dry-", "run", " ", "or", " ", "--dryrun"]
Greg Wardd1a72a02002-10-31 16:11:18 +0000217 self.check_split(text, expect)
218
219 def test_funky_hyphens (self):
220 # Screwy edge cases cooked up by David Goodger. All reported
221 # in SF bug #596434.
222 self.check_split("what the--hey!", ["what", " ", "the", "--", "hey!"])
223 self.check_split("what the--", ["what", " ", "the--"])
224 self.check_split("what the--.", ["what", " ", "the--."])
225 self.check_split("--text--.", ["--text--."])
226
Greg Wardcc55cb92003-05-07 01:19:22 +0000227 # When I first read bug #596434, this is what I thought David
228 # was talking about. I was wrong; these have always worked
229 # fine. The real problem is tested in test_funky_parens()
230 # below...
Greg Wardd1a72a02002-10-31 16:11:18 +0000231 self.check_split("--option", ["--option"])
232 self.check_split("--option-opt", ["--option-", "opt"])
Greg Wardcc55cb92003-05-07 01:19:22 +0000233 self.check_split("foo --option-opt bar",
234 ["foo", " ", "--option-", "opt", " ", "bar"])
235
236 def test_funky_parens (self):
237 # Second part of SF bug #596434: long option strings inside
238 # parentheses.
239 self.check_split("foo (--option) bar",
240 ["foo", " ", "(--option)", " ", "bar"])
241
242 # Related stuff -- make sure parens work in simpler contexts.
243 self.check_split("foo (bar) baz",
244 ["foo", " ", "(bar)", " ", "baz"])
245 self.check_split("blah (ding dong), wubba",
246 ["blah", " ", "(ding", " ", "dong),",
247 " ", "wubba"])
Greg Ward24a1c9c2002-08-22 21:12:54 +0000248
Greg Ward24cbbcb2002-12-09 16:27:15 +0000249 def test_initial_whitespace(self):
250 # SF bug #622849 reported inconsistent handling of leading
251 # whitespace; let's test that a bit, shall we?
252 text = " This is a sentence with leading whitespace."
253 self.check_wrap(text, 50,
254 [" This is a sentence with leading whitespace."])
255 self.check_wrap(text, 30,
256 [" This is a sentence with", "leading whitespace."])
257
Greg Wardc7e3c5e2002-12-09 16:32:41 +0000258 def test_unicode(self):
259 # *Very* simple test of wrapping Unicode strings. I'm sure
260 # there's more to it than this, but let's at least make
261 # sure textwrap doesn't crash on Unicode input!
262 text = u"Hello there, how are you today?"
263 self.check_wrap(text, 50, [u"Hello there, how are you today?"])
264 self.check_wrap(text, 20, [u"Hello there, how are", "you today?"])
265 olines = self.wrapper.wrap(text)
266 assert isinstance(olines, list) and isinstance(olines[0], unicode)
267 otext = self.wrapper.fill(text)
268 assert isinstance(otext, unicode)
269
Greg Ward90c0b072002-08-22 18:11:10 +0000270 def test_split(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000271 # Ensure that the standard _split() method works as advertised
272 # in the comments
Greg Ward90c0b072002-08-22 18:11:10 +0000273
Greg Wardee413842002-08-22 18:55:38 +0000274 text = "Hello there -- you goof-ball, use the -b option!"
Greg Ward90c0b072002-08-22 18:11:10 +0000275
Greg Wardee413842002-08-22 18:55:38 +0000276 result = self.wrapper._split(text)
Greg Ward90c0b072002-08-22 18:11:10 +0000277 self.check(result,
278 ["Hello", " ", "there", " ", "--", " ", "you", " ", "goof-",
279 "ball,", " ", "use", " ", "the", " ", "-b", " ", "option!"])
280
Greg Ward49128572003-05-07 00:54:42 +0000281 def test_bad_width(self):
282 # Ensure that width <= 0 is caught.
283 text = "Whatever, it doesn't matter."
284 self.assertRaises(ValueError, wrap, text, 0)
285 self.assertRaises(ValueError, wrap, text, -1)
286
Greg Ward90c0b072002-08-22 18:11:10 +0000287
Greg Wardfd030e42002-08-22 19:02:37 +0000288class LongWordTestCase (BaseTestCase):
289 def setUp(self):
290 self.wrapper = TextWrapper()
Greg Ward24cbbcb2002-12-09 16:27:15 +0000291 self.text = '''\
Greg Ward90c0b072002-08-22 18:11:10 +0000292Did you say "supercalifragilisticexpialidocious?"
293How *do* you spell that odd word, anyways?
294'''
Greg Wardfd030e42002-08-22 19:02:37 +0000295
296 def test_break_long(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000297 # Wrap text with long words and lots of punctuation
Greg Wardfd030e42002-08-22 19:02:37 +0000298
299 self.check_wrap(self.text, 30,
Greg Wardee413842002-08-22 18:55:38 +0000300 ['Did you say "supercalifragilis',
301 'ticexpialidocious?" How *do*',
302 'you spell that odd word,',
303 'anyways?'])
Greg Wardfd030e42002-08-22 19:02:37 +0000304 self.check_wrap(self.text, 50,
Greg Wardee413842002-08-22 18:55:38 +0000305 ['Did you say "supercalifragilisticexpialidocious?"',
306 'How *do* you spell that odd word, anyways?'])
Greg Ward90c0b072002-08-22 18:11:10 +0000307
308
Guido van Rossum327af772002-08-22 20:13:47 +0000309 def test_nobreak_long(self):
310 # Test with break_long_words disabled
Greg Ward90c0b072002-08-22 18:11:10 +0000311 self.wrapper.break_long_words = 0
312 self.wrapper.width = 30
Greg Wardee413842002-08-22 18:55:38 +0000313 expect = ['Did you say',
314 '"supercalifragilisticexpialidocious?"',
315 'How *do* you spell that odd',
316 'word, anyways?'
Guido van Rossum327af772002-08-22 20:13:47 +0000317 ]
Greg Wardfd030e42002-08-22 19:02:37 +0000318 result = self.wrapper.wrap(self.text)
Greg Ward90c0b072002-08-22 18:11:10 +0000319 self.check(result, expect)
320
321 # Same thing with kwargs passed to standalone wrap() function.
Greg Wardfd030e42002-08-22 19:02:37 +0000322 result = wrap(self.text, width=30, break_long_words=0)
Greg Ward90c0b072002-08-22 18:11:10 +0000323 self.check(result, expect)
324
325
Greg Ward13c53c62002-08-22 18:57:26 +0000326class IndentTestCases(BaseTestCase):
Greg Ward90c0b072002-08-22 18:11:10 +0000327
328 # called before each test method
329 def setUp(self):
Greg Wardf69d3c92002-08-22 19:06:45 +0000330 self.text = '''\
Greg Ward90c0b072002-08-22 18:11:10 +0000331This paragraph will be filled, first without any indentation,
332and then with some (including a hanging indent).'''
333
334
Greg Wardf6765782002-08-22 18:35:49 +0000335 def test_fill(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000336 # Test the fill() method
Greg Ward90c0b072002-08-22 18:11:10 +0000337
338 expect = '''\
339This paragraph will be filled, first
340without any indentation, and then with
341some (including a hanging indent).'''
342
Greg Wardf69d3c92002-08-22 19:06:45 +0000343 result = fill(self.text, 40)
Greg Ward90c0b072002-08-22 18:11:10 +0000344 self.check(result, expect)
345
346
Greg Wardf6765782002-08-22 18:35:49 +0000347 def test_initial_indent(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000348 # Test initial_indent parameter
Greg Ward90c0b072002-08-22 18:11:10 +0000349
Greg Wardf69d3c92002-08-22 19:06:45 +0000350 expect = [" This paragraph will be filled,",
351 "first without any indentation, and then",
352 "with some (including a hanging indent)."]
353 result = wrap(self.text, 40, initial_indent=" ")
Greg Ward90c0b072002-08-22 18:11:10 +0000354 self.check(result, expect)
355
Greg Wardf69d3c92002-08-22 19:06:45 +0000356 expect = "\n".join(expect)
357 result = fill(self.text, 40, initial_indent=" ")
Greg Ward90c0b072002-08-22 18:11:10 +0000358 self.check(result, expect)
359
360
Greg Wardf6765782002-08-22 18:35:49 +0000361 def test_subsequent_indent(self):
Guido van Rossum327af772002-08-22 20:13:47 +0000362 # Test subsequent_indent parameter
Greg Ward90c0b072002-08-22 18:11:10 +0000363
364 expect = '''\
365 * This paragraph will be filled, first
366 without any indentation, and then
367 with some (including a hanging
368 indent).'''
369
Greg Wardf69d3c92002-08-22 19:06:45 +0000370 result = fill(self.text, 40,
371 initial_indent=" * ", subsequent_indent=" ")
Greg Ward90c0b072002-08-22 18:11:10 +0000372 self.check(result, expect)
373
374
Greg Ward9e082f42003-05-08 01:58:26 +0000375# Despite the similar names, DedentTestCase is *not* the inverse
376# of IndentTestCase!
377class DedentTestCase(unittest.TestCase):
378
379 def test_dedent_nomargin(self):
380 # No lines indented.
381 text = "Hello there.\nHow are you?\nOh good, I'm glad."
382 self.assertEquals(dedent(text), text)
383
384 # Similar, with a blank line.
385 text = "Hello there.\n\nBoo!"
386 self.assertEquals(dedent(text), text)
387
388 # Some lines indented, but overall margin is still zero.
389 text = "Hello there.\n This is indented."
390 self.assertEquals(dedent(text), text)
391
392 # Again, add a blank line.
393 text = "Hello there.\n\n Boo!\n"
394 self.assertEquals(dedent(text), text)
395
396 def test_dedent_even(self):
397 # All lines indented by two spaces.
398 text = " Hello there.\n How are ya?\n Oh good."
399 expect = "Hello there.\nHow are ya?\nOh good."
400 self.assertEquals(dedent(text), expect)
401
402 # Same, with blank lines.
403 text = " Hello there.\n\n How are ya?\n Oh good.\n"
404 expect = "Hello there.\n\nHow are ya?\nOh good.\n"
405 self.assertEquals(dedent(text), expect)
406
407 # Now indent one of the blank lines.
408 text = " Hello there.\n \n How are ya?\n Oh good.\n"
409 expect = "Hello there.\n\nHow are ya?\nOh good.\n"
410 self.assertEquals(dedent(text), expect)
411
412 def test_dedent_uneven(self):
413 # Lines indented unevenly.
414 text = '''\
415 def foo():
416 while 1:
417 return foo
418 '''
419 expect = '''\
420def foo():
421 while 1:
422 return foo
423'''
424 self.assertEquals(dedent(text), expect)
425
426 # Uneven indentation with a blank line.
427 text = " Foo\n Bar\n\n Baz\n"
428 expect = "Foo\n Bar\n\n Baz\n"
429 self.assertEquals(dedent(text), expect)
430
431 # Uneven indentation with a whitespace-only line.
432 text = " Foo\n Bar\n \n Baz\n"
433 expect = "Foo\n Bar\n\n Baz\n"
434 self.assertEquals(dedent(text), expect)
435
436
437
Greg Wardf6765782002-08-22 18:35:49 +0000438def test_main():
Greg Ward9e082f42003-05-08 01:58:26 +0000439 test_support.run_unittest(WrapTestCase,
440 LongWordTestCase,
441 IndentTestCases,
442 DedentTestCase)
Greg Wardf6765782002-08-22 18:35:49 +0000443
Greg Ward90c0b072002-08-22 18:11:10 +0000444if __name__ == '__main__':
Greg Wardf6765782002-08-22 18:35:49 +0000445 test_main()