source: trunk/essentials/dev-lang/python/Lib/test/test_textwrap.py@ 3326

Last change on this file since 3326 was 3225, checked in by bird, 19 years ago

Python 2.5

File size: 21.0 KB
Line 
1#
2# Test suite for the textwrap module.
3#
4# Original tests written by Greg Ward <[email protected]>.
5# Converted to PyUnit by Peter Hansen <[email protected]>.
6# Currently maintained by Greg Ward.
7#
8# $Id: test_textwrap.py 46863 2006-06-11 19:42:51Z tim.peters $
9#
10
11import unittest
12from test import test_support
13
14from textwrap import TextWrapper, wrap, fill, dedent
15
16
17class BaseTestCase(unittest.TestCase):
18 '''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, basestring):
27 result = " %s\n" % repr(textin)
28 return result
29
30
31 def check(self, result, expect):
32 self.assertEquals(result, expect,
33 'expected:\n%s\nbut got:\n%s' % (
34 self.show(expect), self.show(result)))
35
36 def check_wrap(self, text, width, expect, **kwargs):
37 result = wrap(text, width, **kwargs)
38 self.check(result, expect)
39
40 def check_split(self, text, expect):
41 result = self.wrapper._split(text)
42 self.assertEquals(result, expect,
43 "\nexpected %r\n"
44 "but got %r" % (expect, result))
45
46
47class WrapTestCase(BaseTestCase):
48
49 def setUp(self):
50 self.wrapper = TextWrapper(width=45)
51
52 def test_simple(self):
53 # Simple case: just words, spaces, and a bit of punctuation
54
55 text = "Hello there, how are you this fine day? I'm glad to hear it!"
56
57 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])
68
69
70 def test_whitespace(self):
71 # Whitespace munging and end-of-sentence detection
72
73 text = """\
74This 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
81 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!"]
86
87 wrapper = TextWrapper(45, fix_sentence_endings=True)
88 result = wrapper.wrap(text)
89 self.check(result, expect)
90
91 result = wrapper.fill(text)
92 self.check(result, '\n'.join(expect))
93
94 def test_fix_sentence_endings(self):
95 wrapper = TextWrapper(60, fix_sentence_endings=True)
96
97 # SF #847346: ensure that fix_sentence_endings=True does the
98 # right thing even on input short enough that it doesn't need to
99 # be wrapped.
100 text = "A short line. Note the single space."
101 expect = ["A short line. Note the single space."]
102 self.check(wrapper.wrap(text), expect)
103
104 # Test some of the hairy end cases that _fix_sentence_endings()
105 # is supposed to handle (the easy stuff is tested in
106 # test_whitespace() above).
107 text = "Well, Doctor? What do you think?"
108 expect = ["Well, Doctor? What do you think?"]
109 self.check(wrapper.wrap(text), expect)
110
111 text = "Well, Doctor?\nWhat do you think?"
112 self.check(wrapper.wrap(text), expect)
113
114 text = 'I say, chaps! Anyone for "tennis?"\nHmmph!'
115 expect = ['I say, chaps! Anyone for "tennis?" Hmmph!']
116 self.check(wrapper.wrap(text), expect)
117
118 wrapper.width = 20
119 expect = ['I say, chaps!', 'Anyone for "tennis?"', 'Hmmph!']
120 self.check(wrapper.wrap(text), expect)
121
122 text = 'And she said, "Go to hell!"\nCan you believe that?'
123 expect = ['And she said, "Go to',
124 'hell!" Can you',
125 'believe that?']
126 self.check(wrapper.wrap(text), expect)
127
128 wrapper.width = 60
129 expect = ['And she said, "Go to hell!" Can you believe that?']
130 self.check(wrapper.wrap(text), expect)
131
132 def test_wrap_short(self):
133 # Wrapping to make short lines longer
134
135 text = "This is a\nshort paragraph."
136
137 self.check_wrap(text, 20, ["This is a short",
138 "paragraph."])
139 self.check_wrap(text, 40, ["This is a short paragraph."])
140
141
142 def test_wrap_short_1line(self):
143 # Test endcases
144
145 text = "This is a short line."
146
147 self.check_wrap(text, 30, ["This is a short line."])
148 self.check_wrap(text, 30, ["(1) This is a short line."],
149 initial_indent="(1) ")
150
151
152 def test_hyphenated(self):
153 # Test breaking hyphenated words
154
155 text = ("this-is-a-useful-feature-for-"
156 "reformatting-posts-from-tim-peters'ly")
157
158 self.check_wrap(text, 40,
159 ["this-is-a-useful-feature-for-",
160 "reformatting-posts-from-tim-peters'ly"])
161 self.check_wrap(text, 41,
162 ["this-is-a-useful-feature-for-",
163 "reformatting-posts-from-tim-peters'ly"])
164 self.check_wrap(text, 42,
165 ["this-is-a-useful-feature-for-reformatting-",
166 "posts-from-tim-peters'ly"])
167
168 def test_hyphenated_numbers(self):
169 # Test that hyphenated numbers (eg. dates) are not broken like words.
170 text = ("Python 1.0.0 was released on 1994-01-26. Python 1.0.1 was\n"
171 "released on 1994-02-15.")
172
173 self.check_wrap(text, 30, ['Python 1.0.0 was released on',
174 '1994-01-26. Python 1.0.1 was',
175 'released on 1994-02-15.'])
176 self.check_wrap(text, 40, ['Python 1.0.0 was released on 1994-01-26.',
177 'Python 1.0.1 was released on 1994-02-15.'])
178
179 text = "I do all my shopping at 7-11."
180 self.check_wrap(text, 25, ["I do all my shopping at",
181 "7-11."])
182 self.check_wrap(text, 27, ["I do all my shopping at",
183 "7-11."])
184 self.check_wrap(text, 29, ["I do all my shopping at 7-11."])
185
186 def test_em_dash(self):
187 # Test text with em-dashes
188 text = "Em-dashes should be written -- thus."
189 self.check_wrap(text, 25,
190 ["Em-dashes should be",
191 "written -- thus."])
192
193 # Probe the boundaries of the properly written em-dash,
194 # ie. " -- ".
195 self.check_wrap(text, 29,
196 ["Em-dashes should be written",
197 "-- thus."])
198 expect = ["Em-dashes should be written --",
199 "thus."]
200 self.check_wrap(text, 30, expect)
201 self.check_wrap(text, 35, expect)
202 self.check_wrap(text, 36,
203 ["Em-dashes should be written -- thus."])
204
205 # The improperly written em-dash is handled too, because
206 # it's adjacent to non-whitespace on both sides.
207 text = "You can also do--this or even---this."
208 expect = ["You can also do",
209 "--this or even",
210 "---this."]
211 self.check_wrap(text, 15, expect)
212 self.check_wrap(text, 16, expect)
213 expect = ["You can also do--",
214 "this or even---",
215 "this."]
216 self.check_wrap(text, 17, expect)
217 self.check_wrap(text, 19, expect)
218 expect = ["You can also do--this or even",
219 "---this."]
220 self.check_wrap(text, 29, expect)
221 self.check_wrap(text, 31, expect)
222 expect = ["You can also do--this or even---",
223 "this."]
224 self.check_wrap(text, 32, expect)
225 self.check_wrap(text, 35, expect)
226
227 # All of the above behaviour could be deduced by probing the
228 # _split() method.
229 text = "Here's an -- em-dash and--here's another---and another!"
230 expect = ["Here's", " ", "an", " ", "--", " ", "em-", "dash", " ",
231 "and", "--", "here's", " ", "another", "---",
232 "and", " ", "another!"]
233 self.check_split(text, expect)
234
235 text = "and then--bam!--he was gone"
236 expect = ["and", " ", "then", "--", "bam!", "--",
237 "he", " ", "was", " ", "gone"]
238 self.check_split(text, expect)
239
240
241 def test_unix_options (self):
242 # Test that Unix-style command-line options are wrapped correctly.
243 # Both Optik (OptionParser) and Docutils rely on this behaviour!
244
245 text = "You should use the -n option, or --dry-run in its long form."
246 self.check_wrap(text, 20,
247 ["You should use the",
248 "-n option, or --dry-",
249 "run in its long",
250 "form."])
251 self.check_wrap(text, 21,
252 ["You should use the -n",
253 "option, or --dry-run",
254 "in its long form."])
255 expect = ["You should use the -n option, or",
256 "--dry-run in its long form."]
257 self.check_wrap(text, 32, expect)
258 self.check_wrap(text, 34, expect)
259 self.check_wrap(text, 35, expect)
260 self.check_wrap(text, 38, expect)
261 expect = ["You should use the -n option, or --dry-",
262 "run in its long form."]
263 self.check_wrap(text, 39, expect)
264 self.check_wrap(text, 41, expect)
265 expect = ["You should use the -n option, or --dry-run",
266 "in its long form."]
267 self.check_wrap(text, 42, expect)
268
269 # Again, all of the above can be deduced from _split().
270 text = "the -n option, or --dry-run or --dryrun"
271 expect = ["the", " ", "-n", " ", "option,", " ", "or", " ",
272 "--dry-", "run", " ", "or", " ", "--dryrun"]
273 self.check_split(text, expect)
274
275 def test_funky_hyphens (self):
276 # Screwy edge cases cooked up by David Goodger. All reported
277 # in SF bug #596434.
278 self.check_split("what the--hey!", ["what", " ", "the", "--", "hey!"])
279 self.check_split("what the--", ["what", " ", "the--"])
280 self.check_split("what the--.", ["what", " ", "the--."])
281 self.check_split("--text--.", ["--text--."])
282
283 # When I first read bug #596434, this is what I thought David
284 # was talking about. I was wrong; these have always worked
285 # fine. The real problem is tested in test_funky_parens()
286 # below...
287 self.check_split("--option", ["--option"])
288 self.check_split("--option-opt", ["--option-", "opt"])
289 self.check_split("foo --option-opt bar",
290 ["foo", " ", "--option-", "opt", " ", "bar"])
291
292 def test_punct_hyphens(self):
293 # Oh bother, SF #965425 found another problem with hyphens --
294 # hyphenated words in single quotes weren't handled correctly.
295 # In fact, the bug is that *any* punctuation around a hyphenated
296 # word was handled incorrectly, except for a leading "--", which
297 # was special-cased for Optik and Docutils. So test a variety
298 # of styles of punctuation around a hyphenated word.
299 # (Actually this is based on an Optik bug report, #813077).
300 self.check_split("the 'wibble-wobble' widget",
301 ['the', ' ', "'wibble-", "wobble'", ' ', 'widget'])
302 self.check_split('the "wibble-wobble" widget',
303 ['the', ' ', '"wibble-', 'wobble"', ' ', 'widget'])
304 self.check_split("the (wibble-wobble) widget",
305 ['the', ' ', "(wibble-", "wobble)", ' ', 'widget'])
306 self.check_split("the ['wibble-wobble'] widget",
307 ['the', ' ', "['wibble-", "wobble']", ' ', 'widget'])
308
309 def test_funky_parens (self):
310 # Second part of SF bug #596434: long option strings inside
311 # parentheses.
312 self.check_split("foo (--option) bar",
313 ["foo", " ", "(--option)", " ", "bar"])
314
315 # Related stuff -- make sure parens work in simpler contexts.
316 self.check_split("foo (bar) baz",
317 ["foo", " ", "(bar)", " ", "baz"])
318 self.check_split("blah (ding dong), wubba",
319 ["blah", " ", "(ding", " ", "dong),",
320 " ", "wubba"])
321
322 def test_initial_whitespace(self):
323 # SF bug #622849 reported inconsistent handling of leading
324 # whitespace; let's test that a bit, shall we?
325 text = " This is a sentence with leading whitespace."
326 self.check_wrap(text, 50,
327 [" This is a sentence with leading whitespace."])
328 self.check_wrap(text, 30,
329 [" This is a sentence with", "leading whitespace."])
330
331 if test_support.have_unicode:
332 def test_unicode(self):
333 # *Very* simple test of wrapping Unicode strings. I'm sure
334 # there's more to it than this, but let's at least make
335 # sure textwrap doesn't crash on Unicode input!
336 text = u"Hello there, how are you today?"
337 self.check_wrap(text, 50, [u"Hello there, how are you today?"])
338 self.check_wrap(text, 20, [u"Hello there, how are", "you today?"])
339 olines = self.wrapper.wrap(text)
340 assert isinstance(olines, list) and isinstance(olines[0], unicode)
341 otext = self.wrapper.fill(text)
342 assert isinstance(otext, unicode)
343
344 def test_split(self):
345 # Ensure that the standard _split() method works as advertised
346 # in the comments
347
348 text = "Hello there -- you goof-ball, use the -b option!"
349
350 result = self.wrapper._split(text)
351 self.check(result,
352 ["Hello", " ", "there", " ", "--", " ", "you", " ", "goof-",
353 "ball,", " ", "use", " ", "the", " ", "-b", " ", "option!"])
354
355 def test_bad_width(self):
356 # Ensure that width <= 0 is caught.
357 text = "Whatever, it doesn't matter."
358 self.assertRaises(ValueError, wrap, text, 0)
359 self.assertRaises(ValueError, wrap, text, -1)
360
361
362class LongWordTestCase (BaseTestCase):
363 def setUp(self):
364 self.wrapper = TextWrapper()
365 self.text = '''\
366Did you say "supercalifragilisticexpialidocious?"
367How *do* you spell that odd word, anyways?
368'''
369
370 def test_break_long(self):
371 # Wrap text with long words and lots of punctuation
372
373 self.check_wrap(self.text, 30,
374 ['Did you say "supercalifragilis',
375 'ticexpialidocious?" How *do*',
376 'you spell that odd word,',
377 'anyways?'])
378 self.check_wrap(self.text, 50,
379 ['Did you say "supercalifragilisticexpialidocious?"',
380 'How *do* you spell that odd word, anyways?'])
381
382 # SF bug 797650. Prevent an infinite loop by making sure that at
383 # least one character gets split off on every pass.
384 self.check_wrap('-'*10+'hello', 10,
385 ['----------',
386 ' h',
387 ' e',
388 ' l',
389 ' l',
390 ' o'],
391 subsequent_indent = ' '*15)
392
393 def test_nobreak_long(self):
394 # Test with break_long_words disabled
395 self.wrapper.break_long_words = 0
396 self.wrapper.width = 30
397 expect = ['Did you say',
398 '"supercalifragilisticexpialidocious?"',
399 'How *do* you spell that odd',
400 'word, anyways?'
401 ]
402 result = self.wrapper.wrap(self.text)
403 self.check(result, expect)
404
405 # Same thing with kwargs passed to standalone wrap() function.
406 result = wrap(self.text, width=30, break_long_words=0)
407 self.check(result, expect)
408
409
410class IndentTestCases(BaseTestCase):
411
412 # called before each test method
413 def setUp(self):
414 self.text = '''\
415This paragraph will be filled, first without any indentation,
416and then with some (including a hanging indent).'''
417
418
419 def test_fill(self):
420 # Test the fill() method
421
422 expect = '''\
423This paragraph will be filled, first
424without any indentation, and then with
425some (including a hanging indent).'''
426
427 result = fill(self.text, 40)
428 self.check(result, expect)
429
430
431 def test_initial_indent(self):
432 # Test initial_indent parameter
433
434 expect = [" This paragraph will be filled,",
435 "first without any indentation, and then",
436 "with some (including a hanging indent)."]
437 result = wrap(self.text, 40, initial_indent=" ")
438 self.check(result, expect)
439
440 expect = "\n".join(expect)
441 result = fill(self.text, 40, initial_indent=" ")
442 self.check(result, expect)
443
444
445 def test_subsequent_indent(self):
446 # Test subsequent_indent parameter
447
448 expect = '''\
449 * This paragraph will be filled, first
450 without any indentation, and then
451 with some (including a hanging
452 indent).'''
453
454 result = fill(self.text, 40,
455 initial_indent=" * ", subsequent_indent=" ")
456 self.check(result, expect)
457
458
459# Despite the similar names, DedentTestCase is *not* the inverse
460# of IndentTestCase!
461class DedentTestCase(unittest.TestCase):
462
463 def assertUnchanged(self, text):
464 """assert that dedent() has no effect on 'text'"""
465 self.assertEquals(text, dedent(text))
466
467 def test_dedent_nomargin(self):
468 # No lines indented.
469 text = "Hello there.\nHow are you?\nOh good, I'm glad."
470 self.assertUnchanged(text)
471
472 # Similar, with a blank line.
473 text = "Hello there.\n\nBoo!"
474 self.assertUnchanged(text)
475
476 # Some lines indented, but overall margin is still zero.
477 text = "Hello there.\n This is indented."
478 self.assertUnchanged(text)
479
480 # Again, add a blank line.
481 text = "Hello there.\n\n Boo!\n"
482 self.assertUnchanged(text)
483
484 def test_dedent_even(self):
485 # All lines indented by two spaces.
486 text = " Hello there.\n How are ya?\n Oh good."
487 expect = "Hello there.\nHow are ya?\nOh good."
488 self.assertEquals(expect, dedent(text))
489
490 # Same, with blank lines.
491 text = " Hello there.\n\n How are ya?\n Oh good.\n"
492 expect = "Hello there.\n\nHow are ya?\nOh good.\n"
493 self.assertEquals(expect, dedent(text))
494
495 # Now indent one of the blank lines.
496 text = " Hello there.\n \n How are ya?\n Oh good.\n"
497 expect = "Hello there.\n\nHow are ya?\nOh good.\n"
498 self.assertEquals(expect, dedent(text))
499
500 def test_dedent_uneven(self):
501 # Lines indented unevenly.
502 text = '''\
503 def foo():
504 while 1:
505 return foo
506 '''
507 expect = '''\
508def foo():
509 while 1:
510 return foo
511'''
512 self.assertEquals(expect, dedent(text))
513
514 # Uneven indentation with a blank line.
515 text = " Foo\n Bar\n\n Baz\n"
516 expect = "Foo\n Bar\n\n Baz\n"
517 self.assertEquals(expect, dedent(text))
518
519 # Uneven indentation with a whitespace-only line.
520 text = " Foo\n Bar\n \n Baz\n"
521 expect = "Foo\n Bar\n\n Baz\n"
522 self.assertEquals(expect, dedent(text))
523
524 # dedent() should not mangle internal tabs
525 def test_dedent_preserve_internal_tabs(self):
526 text = " hello\tthere\n how are\tyou?"
527 expect = "hello\tthere\nhow are\tyou?"
528 self.assertEquals(expect, dedent(text))
529
530 # make sure that it preserves tabs when it's not making any
531 # changes at all
532 self.assertEquals(expect, dedent(expect))
533
534 # dedent() should not mangle tabs in the margin (i.e.
535 # tabs and spaces both count as margin, but are *not*
536 # considered equivalent)
537 def test_dedent_preserve_margin_tabs(self):
538 text = " hello there\n\thow are you?"
539 self.assertUnchanged(text)
540
541 # same effect even if we have 8 spaces
542 text = " hello there\n\thow are you?"
543 self.assertUnchanged(text)
544
545 # dedent() only removes whitespace that can be uniformly removed!
546 text = "\thello there\n\thow are you?"
547 expect = "hello there\nhow are you?"
548 self.assertEquals(expect, dedent(text))
549
550 text = " \thello there\n \thow are you?"
551 self.assertEquals(expect, dedent(text))
552
553 text = " \t hello there\n \t how are you?"
554 self.assertEquals(expect, dedent(text))
555
556 text = " \thello there\n \t how are you?"
557 expect = "hello there\n how are you?"
558 self.assertEquals(expect, dedent(text))
559
560
561def test_main():
562 test_support.run_unittest(WrapTestCase,
563 LongWordTestCase,
564 IndentTestCases,
565 DedentTestCase)
566
567if __name__ == '__main__':
568 test_main()
Note: See TracBrowser for help on using the repository browser.