2
# Test suite for the textwrap module.
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.
8
# $Id: test_textwrap.py 67747 2008-12-13 23:20:54Z antoine.pitrou $
12
from test import support
14
from textwrap import TextWrapper, wrap, fill, dedent
17
class BaseTestCase(unittest.TestCase):
18
'''Parent class with utility methods for textwrap tests.'''
20
def show(self, textin):
21
if isinstance(textin, list):
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):
27
result = " %s\n" % repr(textin)
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)))
36
def check_wrap(self, text, width, expect, **kwargs):
37
result = wrap(text, width, **kwargs)
38
self.check(result, expect)
40
def check_split(self, text, expect):
41
result = self.wrapper._split(text)
42
self.assertEquals(result, expect,
44
"but got %r" % (expect, result))
47
class WrapTestCase(BaseTestCase):
50
self.wrapper = TextWrapper(width=45)
52
def test_simple(self):
53
# Simple case: just words, spaces, and a bit of punctuation
55
text = "Hello there, how are you this fine day? I'm glad to hear it!"
57
self.check_wrap(text, 12,
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])
70
def test_whitespace(self):
71
# Whitespace munging and end-of-sentence detection
74
This is a paragraph that already has
75
line breaks. But some of its lines are much longer than the others,
76
so it needs to be wrapped.
77
Some lines are \ttabbed too.
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",
87
wrapper = TextWrapper(45, fix_sentence_endings=True)
88
result = wrapper.wrap(text)
89
self.check(result, expect)
91
result = wrapper.fill(text)
92
self.check(result, '\n'.join(expect))
94
def test_fix_sentence_endings(self):
95
wrapper = TextWrapper(60, fix_sentence_endings=True)
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
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)
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)
111
text = "Well, Doctor?\nWhat do you think?"
112
self.check(wrapper.wrap(text), expect)
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)
119
expect = ['I say, chaps!', 'Anyone for "tennis?"', 'Hmmph!']
120
self.check(wrapper.wrap(text), expect)
122
text = 'And she said, "Go to hell!"\nCan you believe that?'
123
expect = ['And she said, "Go to',
126
self.check(wrapper.wrap(text), expect)
129
expect = ['And she said, "Go to hell!" Can you believe that?']
130
self.check(wrapper.wrap(text), expect)
132
text = 'File stdio.h is nice.'
133
expect = ['File stdio.h is nice.']
134
self.check(wrapper.wrap(text), expect)
136
def test_wrap_short(self):
137
# Wrapping to make short lines longer
139
text = "This is a\nshort paragraph."
141
self.check_wrap(text, 20, ["This is a short",
143
self.check_wrap(text, 40, ["This is a short paragraph."])
146
def test_wrap_short_1line(self):
149
text = "This is a short line."
151
self.check_wrap(text, 30, ["This is a short line."])
152
self.check_wrap(text, 30, ["(1) This is a short line."],
153
initial_indent="(1) ")
156
def test_hyphenated(self):
157
# Test breaking hyphenated words
159
text = ("this-is-a-useful-feature-for-"
160
"reformatting-posts-from-tim-peters'ly")
162
self.check_wrap(text, 40,
163
["this-is-a-useful-feature-for-",
164
"reformatting-posts-from-tim-peters'ly"])
165
self.check_wrap(text, 41,
166
["this-is-a-useful-feature-for-",
167
"reformatting-posts-from-tim-peters'ly"])
168
self.check_wrap(text, 42,
169
["this-is-a-useful-feature-for-reformatting-",
170
"posts-from-tim-peters'ly"])
172
def test_hyphenated_numbers(self):
173
# Test that hyphenated numbers (eg. dates) are not broken like words.
174
text = ("Python 1.0.0 was released on 1994-01-26. Python 1.0.1 was\n"
175
"released on 1994-02-15.")
177
self.check_wrap(text, 30, ['Python 1.0.0 was released on',
178
'1994-01-26. Python 1.0.1 was',
179
'released on 1994-02-15.'])
180
self.check_wrap(text, 40, ['Python 1.0.0 was released on 1994-01-26.',
181
'Python 1.0.1 was released on 1994-02-15.'])
183
text = "I do all my shopping at 7-11."
184
self.check_wrap(text, 25, ["I do all my shopping at",
186
self.check_wrap(text, 27, ["I do all my shopping at",
188
self.check_wrap(text, 29, ["I do all my shopping at 7-11."])
190
def test_em_dash(self):
191
# Test text with em-dashes
192
text = "Em-dashes should be written -- thus."
193
self.check_wrap(text, 25,
194
["Em-dashes should be",
197
# Probe the boundaries of the properly written em-dash,
199
self.check_wrap(text, 29,
200
["Em-dashes should be written",
202
expect = ["Em-dashes should be written --",
204
self.check_wrap(text, 30, expect)
205
self.check_wrap(text, 35, expect)
206
self.check_wrap(text, 36,
207
["Em-dashes should be written -- thus."])
209
# The improperly written em-dash is handled too, because
210
# it's adjacent to non-whitespace on both sides.
211
text = "You can also do--this or even---this."
212
expect = ["You can also do",
215
self.check_wrap(text, 15, expect)
216
self.check_wrap(text, 16, expect)
217
expect = ["You can also do--",
220
self.check_wrap(text, 17, expect)
221
self.check_wrap(text, 19, expect)
222
expect = ["You can also do--this or even",
224
self.check_wrap(text, 29, expect)
225
self.check_wrap(text, 31, expect)
226
expect = ["You can also do--this or even---",
228
self.check_wrap(text, 32, expect)
229
self.check_wrap(text, 35, expect)
231
# All of the above behaviour could be deduced by probing the
233
text = "Here's an -- em-dash and--here's another---and another!"
234
expect = ["Here's", " ", "an", " ", "--", " ", "em-", "dash", " ",
235
"and", "--", "here's", " ", "another", "---",
236
"and", " ", "another!"]
237
self.check_split(text, expect)
239
text = "and then--bam!--he was gone"
240
expect = ["and", " ", "then", "--", "bam!", "--",
241
"he", " ", "was", " ", "gone"]
242
self.check_split(text, expect)
245
def test_unix_options (self):
246
# Test that Unix-style command-line options are wrapped correctly.
247
# Both Optik (OptionParser) and Docutils rely on this behaviour!
249
text = "You should use the -n option, or --dry-run in its long form."
250
self.check_wrap(text, 20,
251
["You should use the",
252
"-n option, or --dry-",
255
self.check_wrap(text, 21,
256
["You should use the -n",
257
"option, or --dry-run",
258
"in its long form."])
259
expect = ["You should use the -n option, or",
260
"--dry-run in its long form."]
261
self.check_wrap(text, 32, expect)
262
self.check_wrap(text, 34, expect)
263
self.check_wrap(text, 35, expect)
264
self.check_wrap(text, 38, expect)
265
expect = ["You should use the -n option, or --dry-",
266
"run in its long form."]
267
self.check_wrap(text, 39, expect)
268
self.check_wrap(text, 41, expect)
269
expect = ["You should use the -n option, or --dry-run",
271
self.check_wrap(text, 42, expect)
273
# Again, all of the above can be deduced from _split().
274
text = "the -n option, or --dry-run or --dryrun"
275
expect = ["the", " ", "-n", " ", "option,", " ", "or", " ",
276
"--dry-", "run", " ", "or", " ", "--dryrun"]
277
self.check_split(text, expect)
279
def test_funky_hyphens (self):
280
# Screwy edge cases cooked up by David Goodger. All reported
282
self.check_split("what the--hey!", ["what", " ", "the", "--", "hey!"])
283
self.check_split("what the--", ["what", " ", "the--"])
284
self.check_split("what the--.", ["what", " ", "the--."])
285
self.check_split("--text--.", ["--text--."])
287
# When I first read bug #596434, this is what I thought David
288
# was talking about. I was wrong; these have always worked
289
# fine. The real problem is tested in test_funky_parens()
291
self.check_split("--option", ["--option"])
292
self.check_split("--option-opt", ["--option-", "opt"])
293
self.check_split("foo --option-opt bar",
294
["foo", " ", "--option-", "opt", " ", "bar"])
296
def test_punct_hyphens(self):
297
# Oh bother, SF #965425 found another problem with hyphens --
298
# hyphenated words in single quotes weren't handled correctly.
299
# In fact, the bug is that *any* punctuation around a hyphenated
300
# word was handled incorrectly, except for a leading "--", which
301
# was special-cased for Optik and Docutils. So test a variety
302
# of styles of punctuation around a hyphenated word.
303
# (Actually this is based on an Optik bug report, #813077).
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
self.check_split("the (wibble-wobble) widget",
309
['the', ' ', "(wibble-", "wobble)", ' ', 'widget'])
310
self.check_split("the ['wibble-wobble'] widget",
311
['the', ' ', "['wibble-", "wobble']", ' ', 'widget'])
313
def test_funky_parens (self):
314
# Second part of SF bug #596434: long option strings inside
316
self.check_split("foo (--option) bar",
317
["foo", " ", "(--option)", " ", "bar"])
319
# Related stuff -- make sure parens work in simpler contexts.
320
self.check_split("foo (bar) baz",
321
["foo", " ", "(bar)", " ", "baz"])
322
self.check_split("blah (ding dong), wubba",
323
["blah", " ", "(ding", " ", "dong),",
326
def test_initial_whitespace(self):
327
# SF bug #622849 reported inconsistent handling of leading
328
# whitespace; let's test that a bit, shall we?
329
text = " This is a sentence with leading whitespace."
330
self.check_wrap(text, 50,
331
[" This is a sentence with leading whitespace."])
332
self.check_wrap(text, 30,
333
[" This is a sentence with", "leading whitespace."])
335
def test_no_drop_whitespace(self):
337
text = " This is a sentence with much whitespace."
338
self.check_wrap(text, 10,
339
[" This is a", " ", "sentence ",
340
"with ", "much white", "space."],
341
drop_whitespace=False)
343
def test_split(self):
344
# Ensure that the standard _split() method works as advertised
347
text = "Hello there -- you goof-ball, use the -b option!"
349
result = self.wrapper._split(text)
351
["Hello", " ", "there", " ", "--", " ", "you", " ", "goof-",
352
"ball,", " ", "use", " ", "the", " ", "-b", " ", "option!"])
354
def test_break_on_hyphens(self):
355
# Ensure that the break_on_hyphens attributes work
356
text = "yaba daba-doo"
357
self.check_wrap(text, 10, ["yaba daba-", "doo"],
358
break_on_hyphens=True)
359
self.check_wrap(text, 10, ["yaba", "daba-doo"],
360
break_on_hyphens=False)
362
def test_bad_width(self):
363
# Ensure that width <= 0 is caught.
364
text = "Whatever, it doesn't matter."
365
self.assertRaises(ValueError, wrap, text, 0)
366
self.assertRaises(ValueError, wrap, text, -1)
368
def test_no_split_at_umlaut(self):
369
text = "Die Empf\xe4nger-Auswahl"
370
self.check_wrap(text, 13, ["Die", "Empf\xe4nger-", "Auswahl"])
372
def test_umlaut_followed_by_dash(self):
373
text = "aa \xe4\xe4-\xe4\xe4"
374
self.check_wrap(text, 7, ["aa \xe4\xe4-", "\xe4\xe4"])
377
class LongWordTestCase (BaseTestCase):
379
self.wrapper = TextWrapper()
381
Did you say "supercalifragilisticexpialidocious?"
382
How *do* you spell that odd word, anyways?
385
def test_break_long(self):
386
# Wrap text with long words and lots of punctuation
388
self.check_wrap(self.text, 30,
389
['Did you say "supercalifragilis',
390
'ticexpialidocious?" How *do*',
391
'you spell that odd word,',
393
self.check_wrap(self.text, 50,
394
['Did you say "supercalifragilisticexpialidocious?"',
395
'How *do* you spell that odd word, anyways?'])
397
# SF bug 797650. Prevent an infinite loop by making sure that at
398
# least one character gets split off on every pass.
399
self.check_wrap('-'*10+'hello', 10,
406
subsequent_indent = ' '*15)
408
# bug 1146. Prevent a long word to be wrongly wrapped when the
409
# preceding word is exactly one character shorter than the width
410
self.check_wrap(self.text, 12,
421
def test_nobreak_long(self):
422
# Test with break_long_words disabled
423
self.wrapper.break_long_words = 0
424
self.wrapper.width = 30
425
expect = ['Did you say',
426
'"supercalifragilisticexpialidocious?"',
427
'How *do* you spell that odd',
430
result = self.wrapper.wrap(self.text)
431
self.check(result, expect)
433
# Same thing with kwargs passed to standalone wrap() function.
434
result = wrap(self.text, width=30, break_long_words=0)
435
self.check(result, expect)
438
class IndentTestCases(BaseTestCase):
440
# called before each test method
443
This paragraph will be filled, first without any indentation,
444
and then with some (including a hanging indent).'''
448
# Test the fill() method
451
This paragraph will be filled, first
452
without any indentation, and then with
453
some (including a hanging indent).'''
455
result = fill(self.text, 40)
456
self.check(result, expect)
459
def test_initial_indent(self):
460
# Test initial_indent parameter
462
expect = [" This paragraph will be filled,",
463
"first without any indentation, and then",
464
"with some (including a hanging indent)."]
465
result = wrap(self.text, 40, initial_indent=" ")
466
self.check(result, expect)
468
expect = "\n".join(expect)
469
result = fill(self.text, 40, initial_indent=" ")
470
self.check(result, expect)
473
def test_subsequent_indent(self):
474
# Test subsequent_indent parameter
477
* This paragraph will be filled, first
478
without any indentation, and then
479
with some (including a hanging
482
result = fill(self.text, 40,
483
initial_indent=" * ", subsequent_indent=" ")
484
self.check(result, expect)
487
# Despite the similar names, DedentTestCase is *not* the inverse
489
class DedentTestCase(unittest.TestCase):
491
def assertUnchanged(self, text):
492
"""assert that dedent() has no effect on 'text'"""
493
self.assertEquals(text, dedent(text))
495
def test_dedent_nomargin(self):
497
text = "Hello there.\nHow are you?\nOh good, I'm glad."
498
self.assertUnchanged(text)
500
# Similar, with a blank line.
501
text = "Hello there.\n\nBoo!"
502
self.assertUnchanged(text)
504
# Some lines indented, but overall margin is still zero.
505
text = "Hello there.\n This is indented."
506
self.assertUnchanged(text)
508
# Again, add a blank line.
509
text = "Hello there.\n\n Boo!\n"
510
self.assertUnchanged(text)
512
def test_dedent_even(self):
513
# All lines indented by two spaces.
514
text = " Hello there.\n How are ya?\n Oh good."
515
expect = "Hello there.\nHow are ya?\nOh good."
516
self.assertEquals(expect, dedent(text))
518
# Same, with blank lines.
519
text = " Hello there.\n\n How are ya?\n Oh good.\n"
520
expect = "Hello there.\n\nHow are ya?\nOh good.\n"
521
self.assertEquals(expect, dedent(text))
523
# Now indent one of the blank lines.
524
text = " Hello there.\n \n How are ya?\n Oh good.\n"
525
expect = "Hello there.\n\nHow are ya?\nOh good.\n"
526
self.assertEquals(expect, dedent(text))
528
def test_dedent_uneven(self):
529
# Lines indented unevenly.
540
self.assertEquals(expect, dedent(text))
542
# Uneven indentation with a blank line.
543
text = " Foo\n Bar\n\n Baz\n"
544
expect = "Foo\n Bar\n\n Baz\n"
545
self.assertEquals(expect, dedent(text))
547
# Uneven indentation with a whitespace-only line.
548
text = " Foo\n Bar\n \n Baz\n"
549
expect = "Foo\n Bar\n\n Baz\n"
550
self.assertEquals(expect, dedent(text))
552
# dedent() should not mangle internal tabs
553
def test_dedent_preserve_internal_tabs(self):
554
text = " hello\tthere\n how are\tyou?"
555
expect = "hello\tthere\nhow are\tyou?"
556
self.assertEquals(expect, dedent(text))
558
# make sure that it preserves tabs when it's not making any
560
self.assertEquals(expect, dedent(expect))
562
# dedent() should not mangle tabs in the margin (i.e.
563
# tabs and spaces both count as margin, but are *not*
564
# considered equivalent)
565
def test_dedent_preserve_margin_tabs(self):
566
text = " hello there\n\thow are you?"
567
self.assertUnchanged(text)
569
# same effect even if we have 8 spaces
570
text = " hello there\n\thow are you?"
571
self.assertUnchanged(text)
573
# dedent() only removes whitespace that can be uniformly removed!
574
text = "\thello there\n\thow are you?"
575
expect = "hello there\nhow are you?"
576
self.assertEquals(expect, dedent(text))
578
text = " \thello there\n \thow are you?"
579
self.assertEquals(expect, dedent(text))
581
text = " \t hello there\n \t how are you?"
582
self.assertEquals(expect, dedent(text))
584
text = " \thello there\n \t how are you?"
585
expect = "hello there\n how are you?"
586
self.assertEquals(expect, dedent(text))
590
support.run_unittest(WrapTestCase,
595
if __name__ == '__main__':