Home | History | Annotate | Download | only in test
      1 #
      2 # Test suite for the textwrap module.
      3 #
      4 # Original tests written by Greg Ward <gward (at] python.net>.
      5 # Converted to PyUnit by Peter Hansen <peter (at] engcorp.com>.
      6 # Currently maintained by Greg Ward.
      7 #
      8 # $Id$
      9 #
     10 
     11 import unittest
     12 
     13 from textwrap import TextWrapper, wrap, fill, dedent, indent, shorten
     14 
     15 
     16 class BaseTestCase(unittest.TestCase):
     17     '''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]))
     24             result = "\n".join(result) if result else "  no lines"
     25         elif isinstance(textin, str):
     26             result = "  %s\n" % repr(textin)
     27         return result
     28 
     29 
     30     def check(self, result, expect):
     31         self.assertEqual(result, expect,
     32             'expected:\n%s\nbut got:\n%s' % (
     33                 self.show(expect), self.show(result)))
     34 
     35     def check_wrap(self, text, width, expect, **kwargs):
     36         result = wrap(text, width, **kwargs)
     37         self.check(result, expect)
     38 
     39     def check_split(self, text, expect):
     40         result = self.wrapper._split(text)
     41         self.assertEqual(result, expect,
     42                          "\nexpected %r\n"
     43                          "but got  %r" % (expect, result))
     44 
     45 
     46 class WrapTestCase(BaseTestCase):
     47 
     48     def setUp(self):
     49         self.wrapper = TextWrapper(width=45)
     50 
     51     def test_simple(self):
     52         # Simple case: just words, spaces, and a bit of punctuation
     53 
     54         text = "Hello there, how are you this fine day?  I'm glad to hear it!"
     55 
     56         self.check_wrap(text, 12,
     57                         ["Hello there,",
     58                          "how are you",
     59                          "this fine",
     60                          "day?  I'm",
     61                          "glad to hear",
     62                          "it!"])
     63         self.check_wrap(text, 42,
     64                         ["Hello there, how are you this fine day?",
     65                          "I'm glad to hear it!"])
     66         self.check_wrap(text, 80, [text])
     67 
     68     def test_empty_string(self):
     69         # Check that wrapping the empty string returns an empty list.
     70         self.check_wrap("", 6, [])
     71         self.check_wrap("", 6, [], drop_whitespace=False)
     72 
     73     def test_empty_string_with_initial_indent(self):
     74         # Check that the empty string is not indented.
     75         self.check_wrap("", 6, [], initial_indent="++")
     76         self.check_wrap("", 6, [], initial_indent="++", drop_whitespace=False)
     77 
     78     def test_whitespace(self):
     79         # Whitespace munging and end-of-sentence detection
     80 
     81         text = """\
     82 This is a paragraph that already has
     83 line breaks.  But some of its lines are much longer than the others,
     84 so it needs to be wrapped.
     85 Some lines are \ttabbed too.
     86 What a mess!
     87 """
     88 
     89         expect = ["This is a paragraph that already has line",
     90                   "breaks.  But some of its lines are much",
     91                   "longer than the others, so it needs to be",
     92                   "wrapped.  Some lines are  tabbed too.  What a",
     93                   "mess!"]
     94 
     95         wrapper = TextWrapper(45, fix_sentence_endings=True)
     96         result = wrapper.wrap(text)
     97         self.check(result, expect)
     98 
     99         result = wrapper.fill(text)
    100         self.check(result, '\n'.join(expect))
    101 
    102         text = "\tTest\tdefault\t\ttabsize."
    103         expect = ["        Test    default         tabsize."]
    104         self.check_wrap(text, 80, expect)
    105 
    106         text = "\tTest\tcustom\t\ttabsize."
    107         expect = ["    Test    custom      tabsize."]
    108         self.check_wrap(text, 80, expect, tabsize=4)
    109 
    110     def test_fix_sentence_endings(self):
    111         wrapper = TextWrapper(60, fix_sentence_endings=True)
    112 
    113         # SF #847346: ensure that fix_sentence_endings=True does the
    114         # right thing even on input short enough that it doesn't need to
    115         # be wrapped.
    116         text = "A short line. Note the single space."
    117         expect = ["A short line.  Note the single space."]
    118         self.check(wrapper.wrap(text), expect)
    119 
    120         # Test some of the hairy end cases that _fix_sentence_endings()
    121         # is supposed to handle (the easy stuff is tested in
    122         # test_whitespace() above).
    123         text = "Well, Doctor? What do you think?"
    124         expect = ["Well, Doctor?  What do you think?"]
    125         self.check(wrapper.wrap(text), expect)
    126 
    127         text = "Well, Doctor?\nWhat do you think?"
    128         self.check(wrapper.wrap(text), expect)
    129 
    130         text = 'I say, chaps! Anyone for "tennis?"\nHmmph!'
    131         expect = ['I say, chaps!  Anyone for "tennis?"  Hmmph!']
    132         self.check(wrapper.wrap(text), expect)
    133 
    134         wrapper.width = 20
    135         expect = ['I say, chaps!', 'Anyone for "tennis?"', 'Hmmph!']
    136         self.check(wrapper.wrap(text), expect)
    137 
    138         text = 'And she said, "Go to hell!"\nCan you believe that?'
    139         expect = ['And she said, "Go to',
    140                   'hell!"  Can you',
    141                   'believe that?']
    142         self.check(wrapper.wrap(text), expect)
    143 
    144         wrapper.width = 60
    145         expect = ['And she said, "Go to hell!"  Can you believe that?']
    146         self.check(wrapper.wrap(text), expect)
    147 
    148         text = 'File stdio.h is nice.'
    149         expect = ['File stdio.h is nice.']
    150         self.check(wrapper.wrap(text), expect)
    151 
    152     def test_wrap_short(self):
    153         # Wrapping to make short lines longer
    154 
    155         text = "This is a\nshort paragraph."
    156 
    157         self.check_wrap(text, 20, ["This is a short",
    158                                    "paragraph."])
    159         self.check_wrap(text, 40, ["This is a short paragraph."])
    160 
    161 
    162     def test_wrap_short_1line(self):
    163         # Test endcases
    164 
    165         text = "This is a short line."
    166 
    167         self.check_wrap(text, 30, ["This is a short line."])
    168         self.check_wrap(text, 30, ["(1) This is a short line."],
    169                         initial_indent="(1) ")
    170 
    171 
    172     def test_hyphenated(self):
    173         # Test breaking hyphenated words
    174 
    175         text = ("this-is-a-useful-feature-for-"
    176                 "reformatting-posts-from-tim-peters'ly")
    177 
    178         self.check_wrap(text, 40,
    179                         ["this-is-a-useful-feature-for-",
    180                          "reformatting-posts-from-tim-peters'ly"])
    181         self.check_wrap(text, 41,
    182                         ["this-is-a-useful-feature-for-",
    183                          "reformatting-posts-from-tim-peters'ly"])
    184         self.check_wrap(text, 42,
    185                         ["this-is-a-useful-feature-for-reformatting-",
    186                          "posts-from-tim-peters'ly"])
    187         # The test tests current behavior but is not testing parts of the API.
    188         expect = ("this-|is-|a-|useful-|feature-|for-|"
    189                   "reformatting-|posts-|from-|tim-|peters'ly").split('|')
    190         self.check_wrap(text, 1, expect, break_long_words=False)
    191         self.check_split(text, expect)
    192 
    193         self.check_split('e-mail', ['e-mail'])
    194         self.check_split('Jelly-O', ['Jelly-O'])
    195         # The test tests current behavior but is not testing parts of the API.
    196         self.check_split('half-a-crown', 'half-|a-|crown'.split('|'))
    197 
    198     def test_hyphenated_numbers(self):
    199         # Test that hyphenated numbers (eg. dates) are not broken like words.
    200         text = ("Python 1.0.0 was released on 1994-01-26.  Python 1.0.1 was\n"
    201                 "released on 1994-02-15.")
    202 
    203         self.check_wrap(text, 30, ['Python 1.0.0 was released on',
    204                                    '1994-01-26.  Python 1.0.1 was',
    205                                    'released on 1994-02-15.'])
    206         self.check_wrap(text, 40, ['Python 1.0.0 was released on 1994-01-26.',
    207                                    'Python 1.0.1 was released on 1994-02-15.'])
    208         self.check_wrap(text, 1, text.split(), break_long_words=False)
    209 
    210         text = "I do all my shopping at 7-11."
    211         self.check_wrap(text, 25, ["I do all my shopping at",
    212                                    "7-11."])
    213         self.check_wrap(text, 27, ["I do all my shopping at",
    214                                    "7-11."])
    215         self.check_wrap(text, 29, ["I do all my shopping at 7-11."])
    216         self.check_wrap(text, 1, text.split(), break_long_words=False)
    217 
    218     def test_em_dash(self):
    219         # Test text with em-dashes
    220         text = "Em-dashes should be written -- thus."
    221         self.check_wrap(text, 25,
    222                         ["Em-dashes should be",
    223                          "written -- thus."])
    224 
    225         # Probe the boundaries of the properly written em-dash,
    226         # ie. " -- ".
    227         self.check_wrap(text, 29,
    228                         ["Em-dashes should be written",
    229                          "-- thus."])
    230         expect = ["Em-dashes should be written --",
    231                   "thus."]
    232         self.check_wrap(text, 30, expect)
    233         self.check_wrap(text, 35, expect)
    234         self.check_wrap(text, 36,
    235                         ["Em-dashes should be written -- thus."])
    236 
    237         # The improperly written em-dash is handled too, because
    238         # it's adjacent to non-whitespace on both sides.
    239         text = "You can also do--this or even---this."
    240         expect = ["You can also do",
    241                   "--this or even",
    242                   "---this."]
    243         self.check_wrap(text, 15, expect)
    244         self.check_wrap(text, 16, expect)
    245         expect = ["You can also do--",
    246                   "this or even---",
    247                   "this."]
    248         self.check_wrap(text, 17, expect)
    249         self.check_wrap(text, 19, expect)
    250         expect = ["You can also do--this or even",
    251                   "---this."]
    252         self.check_wrap(text, 29, expect)
    253         self.check_wrap(text, 31, expect)
    254         expect = ["You can also do--this or even---",
    255                   "this."]
    256         self.check_wrap(text, 32, expect)
    257         self.check_wrap(text, 35, expect)
    258 
    259         # All of the above behaviour could be deduced by probing the
    260         # _split() method.
    261         text = "Here's an -- em-dash and--here's another---and another!"
    262         expect = ["Here's", " ", "an", " ", "--", " ", "em-", "dash", " ",
    263                   "and", "--", "here's", " ", "another", "---",
    264                   "and", " ", "another!"]
    265         self.check_split(text, expect)
    266 
    267         text = "and then--bam!--he was gone"
    268         expect = ["and", " ", "then", "--", "bam!", "--",
    269                   "he", " ", "was", " ", "gone"]
    270         self.check_split(text, expect)
    271 
    272 
    273     def test_unix_options (self):
    274         # Test that Unix-style command-line options are wrapped correctly.
    275         # Both Optik (OptionParser) and Docutils rely on this behaviour!
    276 
    277         text = "You should use the -n option, or --dry-run in its long form."
    278         self.check_wrap(text, 20,
    279                         ["You should use the",
    280                          "-n option, or --dry-",
    281                          "run in its long",
    282                          "form."])
    283         self.check_wrap(text, 21,
    284                         ["You should use the -n",
    285                          "option, or --dry-run",
    286                          "in its long form."])
    287         expect = ["You should use the -n option, or",
    288                   "--dry-run in its long form."]
    289         self.check_wrap(text, 32, expect)
    290         self.check_wrap(text, 34, expect)
    291         self.check_wrap(text, 35, expect)
    292         self.check_wrap(text, 38, expect)
    293         expect = ["You should use the -n option, or --dry-",
    294                   "run in its long form."]
    295         self.check_wrap(text, 39, expect)
    296         self.check_wrap(text, 41, expect)
    297         expect = ["You should use the -n option, or --dry-run",
    298                   "in its long form."]
    299         self.check_wrap(text, 42, expect)
    300 
    301         # Again, all of the above can be deduced from _split().
    302         text = "the -n option, or --dry-run or --dryrun"
    303         expect = ["the", " ", "-n", " ", "option,", " ", "or", " ",
    304                   "--dry-", "run", " ", "or", " ", "--dryrun"]
    305         self.check_split(text, expect)
    306 
    307     def test_funky_hyphens (self):
    308         # Screwy edge cases cooked up by David Goodger.  All reported
    309         # in SF bug #596434.
    310         self.check_split("what the--hey!", ["what", " ", "the", "--", "hey!"])
    311         self.check_split("what the--", ["what", " ", "the--"])
    312         self.check_split("what the--.", ["what", " ", "the--."])
    313         self.check_split("--text--.", ["--text--."])
    314 
    315         # When I first read bug #596434, this is what I thought David
    316         # was talking about.  I was wrong; these have always worked
    317         # fine.  The real problem is tested in test_funky_parens()
    318         # below...
    319         self.check_split("--option", ["--option"])
    320         self.check_split("--option-opt", ["--option-", "opt"])
    321         self.check_split("foo --option-opt bar",
    322                          ["foo", " ", "--option-", "opt", " ", "bar"])
    323 
    324     def test_punct_hyphens(self):
    325         # Oh bother, SF #965425 found another problem with hyphens --
    326         # hyphenated words in single quotes weren't handled correctly.
    327         # In fact, the bug is that *any* punctuation around a hyphenated
    328         # word was handled incorrectly, except for a leading "--", which
    329         # was special-cased for Optik and Docutils.  So test a variety
    330         # of styles of punctuation around a hyphenated word.
    331         # (Actually this is based on an Optik bug report, #813077).
    332         self.check_split("the 'wibble-wobble' widget",
    333                          ['the', ' ', "'wibble-", "wobble'", ' ', 'widget'])
    334         self.check_split('the "wibble-wobble" widget',
    335                          ['the', ' ', '"wibble-', 'wobble"', ' ', 'widget'])
    336         self.check_split("the (wibble-wobble) widget",
    337                          ['the', ' ', "(wibble-", "wobble)", ' ', 'widget'])
    338         self.check_split("the ['wibble-wobble'] widget",
    339                          ['the', ' ', "['wibble-", "wobble']", ' ', 'widget'])
    340 
    341         # The test tests current behavior but is not testing parts of the API.
    342         self.check_split("what-d'you-call-it.",
    343                          "what-d'you-|call-|it.".split('|'))
    344 
    345     def test_funky_parens (self):
    346         # Second part of SF bug #596434: long option strings inside
    347         # parentheses.
    348         self.check_split("foo (--option) bar",
    349                          ["foo", " ", "(--option)", " ", "bar"])
    350 
    351         # Related stuff -- make sure parens work in simpler contexts.
    352         self.check_split("foo (bar) baz",
    353                          ["foo", " ", "(bar)", " ", "baz"])
    354         self.check_split("blah (ding dong), wubba",
    355                          ["blah", " ", "(ding", " ", "dong),",
    356                           " ", "wubba"])
    357 
    358     def test_drop_whitespace_false(self):
    359         # Check that drop_whitespace=False preserves whitespace.
    360         # SF patch #1581073
    361         text = " This is a    sentence with     much whitespace."
    362         self.check_wrap(text, 10,
    363                         [" This is a", "    ", "sentence ",
    364                          "with     ", "much white", "space."],
    365                         drop_whitespace=False)
    366 
    367     def test_drop_whitespace_false_whitespace_only(self):
    368         # Check that drop_whitespace=False preserves a whitespace-only string.
    369         self.check_wrap("   ", 6, ["   "], drop_whitespace=False)
    370 
    371     def test_drop_whitespace_false_whitespace_only_with_indent(self):
    372         # Check that a whitespace-only string gets indented (when
    373         # drop_whitespace is False).
    374         self.check_wrap("   ", 6, ["     "], drop_whitespace=False,
    375                         initial_indent="  ")
    376 
    377     def test_drop_whitespace_whitespace_only(self):
    378         # Check drop_whitespace on a whitespace-only string.
    379         self.check_wrap("  ", 6, [])
    380 
    381     def test_drop_whitespace_leading_whitespace(self):
    382         # Check that drop_whitespace does not drop leading whitespace (if
    383         # followed by non-whitespace).
    384         # SF bug #622849 reported inconsistent handling of leading
    385         # whitespace; let's test that a bit, shall we?
    386         text = " This is a sentence with leading whitespace."
    387         self.check_wrap(text, 50,
    388                         [" This is a sentence with leading whitespace."])
    389         self.check_wrap(text, 30,
    390                         [" This is a sentence with", "leading whitespace."])
    391 
    392     def test_drop_whitespace_whitespace_line(self):
    393         # Check that drop_whitespace skips the whole line if a non-leading
    394         # line consists only of whitespace.
    395         text = "abcd    efgh"
    396         # Include the result for drop_whitespace=False for comparison.
    397         self.check_wrap(text, 6, ["abcd", "    ", "efgh"],
    398                         drop_whitespace=False)
    399         self.check_wrap(text, 6, ["abcd", "efgh"])
    400 
    401     def test_drop_whitespace_whitespace_only_with_indent(self):
    402         # Check that initial_indent is not applied to a whitespace-only
    403         # string.  This checks a special case of the fact that dropping
    404         # whitespace occurs before indenting.
    405         self.check_wrap("  ", 6, [], initial_indent="++")
    406 
    407     def test_drop_whitespace_whitespace_indent(self):
    408         # Check that drop_whitespace does not drop whitespace indents.
    409         # This checks a special case of the fact that dropping whitespace
    410         # occurs before indenting.
    411         self.check_wrap("abcd efgh", 6, ["  abcd", "  efgh"],
    412                         initial_indent="  ", subsequent_indent="  ")
    413 
    414     def test_split(self):
    415         # Ensure that the standard _split() method works as advertised
    416         # in the comments
    417 
    418         text = "Hello there -- you goof-ball, use the -b option!"
    419 
    420         result = self.wrapper._split(text)
    421         self.check(result,
    422              ["Hello", " ", "there", " ", "--", " ", "you", " ", "goof-",
    423               "ball,", " ", "use", " ", "the", " ", "-b", " ",  "option!"])
    424 
    425     def test_break_on_hyphens(self):
    426         # Ensure that the break_on_hyphens attributes work
    427         text = "yaba daba-doo"
    428         self.check_wrap(text, 10, ["yaba daba-", "doo"],
    429                         break_on_hyphens=True)
    430         self.check_wrap(text, 10, ["yaba", "daba-doo"],
    431                         break_on_hyphens=False)
    432 
    433     def test_bad_width(self):
    434         # Ensure that width <= 0 is caught.
    435         text = "Whatever, it doesn't matter."
    436         self.assertRaises(ValueError, wrap, text, 0)
    437         self.assertRaises(ValueError, wrap, text, -1)
    438 
    439     def test_no_split_at_umlaut(self):
    440         text = "Die Empf\xe4nger-Auswahl"
    441         self.check_wrap(text, 13, ["Die", "Empf\xe4nger-", "Auswahl"])
    442 
    443     def test_umlaut_followed_by_dash(self):
    444         text = "aa \xe4\xe4-\xe4\xe4"
    445         self.check_wrap(text, 7, ["aa \xe4\xe4-", "\xe4\xe4"])
    446 
    447     def test_non_breaking_space(self):
    448         text = 'This is a sentence with non-breaking\N{NO-BREAK SPACE}space.'
    449 
    450         self.check_wrap(text, 20,
    451                         ['This is a sentence',
    452                          'with non-',
    453                          'breaking\N{NO-BREAK SPACE}space.'],
    454                         break_on_hyphens=True)
    455 
    456         self.check_wrap(text, 20,
    457                         ['This is a sentence',
    458                          'with',
    459                          'non-breaking\N{NO-BREAK SPACE}space.'],
    460                         break_on_hyphens=False)
    461 
    462     def test_narrow_non_breaking_space(self):
    463         text = ('This is a sentence with non-breaking'
    464                 '\N{NARROW NO-BREAK SPACE}space.')
    465 
    466         self.check_wrap(text, 20,
    467                         ['This is a sentence',
    468                          'with non-',
    469                          'breaking\N{NARROW NO-BREAK SPACE}space.'],
    470                         break_on_hyphens=True)
    471 
    472         self.check_wrap(text, 20,
    473                         ['This is a sentence',
    474                          'with',
    475                          'non-breaking\N{NARROW NO-BREAK SPACE}space.'],
    476                         break_on_hyphens=False)
    477 
    478 
    479 class MaxLinesTestCase(BaseTestCase):
    480     text = "Hello there, how are you this fine day?  I'm glad to hear it!"
    481 
    482     def test_simple(self):
    483         self.check_wrap(self.text, 12,
    484                         ["Hello [...]"],
    485                         max_lines=0)
    486         self.check_wrap(self.text, 12,
    487                         ["Hello [...]"],
    488                         max_lines=1)
    489         self.check_wrap(self.text, 12,
    490                         ["Hello there,",
    491                          "how [...]"],
    492                         max_lines=2)
    493         self.check_wrap(self.text, 13,
    494                         ["Hello there,",
    495                          "how are [...]"],
    496                         max_lines=2)
    497         self.check_wrap(self.text, 80, [self.text], max_lines=1)
    498         self.check_wrap(self.text, 12,
    499                         ["Hello there,",
    500                          "how are you",
    501                          "this fine",
    502                          "day?  I'm",
    503                          "glad to hear",
    504                          "it!"],
    505                         max_lines=6)
    506 
    507     def test_spaces(self):
    508         # strip spaces before placeholder
    509         self.check_wrap(self.text, 12,
    510                         ["Hello there,",
    511                          "how are you",
    512                          "this fine",
    513                          "day? [...]"],
    514                         max_lines=4)
    515         # placeholder at the start of line
    516         self.check_wrap(self.text, 6,
    517                         ["Hello",
    518                          "[...]"],
    519                         max_lines=2)
    520         # final spaces
    521         self.check_wrap(self.text + ' ' * 10, 12,
    522                         ["Hello there,",
    523                          "how are you",
    524                          "this fine",
    525                          "day?  I'm",
    526                          "glad to hear",
    527                          "it!"],
    528                         max_lines=6)
    529 
    530     def test_placeholder(self):
    531         self.check_wrap(self.text, 12,
    532                         ["Hello..."],
    533                         max_lines=1,
    534                         placeholder='...')
    535         self.check_wrap(self.text, 12,
    536                         ["Hello there,",
    537                          "how are..."],
    538                         max_lines=2,
    539                         placeholder='...')
    540         # long placeholder and indentation
    541         with self.assertRaises(ValueError):
    542             wrap(self.text, 16, initial_indent='    ',
    543                  max_lines=1, placeholder=' [truncated]...')
    544         with self.assertRaises(ValueError):
    545             wrap(self.text, 16, subsequent_indent='    ',
    546                  max_lines=2, placeholder=' [truncated]...')
    547         self.check_wrap(self.text, 16,
    548                         ["    Hello there,",
    549                          "  [truncated]..."],
    550                         max_lines=2,
    551                         initial_indent='    ',
    552                         subsequent_indent='  ',
    553                         placeholder=' [truncated]...')
    554         self.check_wrap(self.text, 16,
    555                         ["  [truncated]..."],
    556                         max_lines=1,
    557                         initial_indent='  ',
    558                         subsequent_indent='    ',
    559                         placeholder=' [truncated]...')
    560         self.check_wrap(self.text, 80, [self.text], placeholder='.' * 1000)
    561 
    562 
    563 class LongWordTestCase (BaseTestCase):
    564     def setUp(self):
    565         self.wrapper = TextWrapper()
    566         self.text = '''\
    567 Did you say "supercalifragilisticexpialidocious?"
    568 How *do* you spell that odd word, anyways?
    569 '''
    570 
    571     def test_break_long(self):
    572         # Wrap text with long words and lots of punctuation
    573 
    574         self.check_wrap(self.text, 30,
    575                         ['Did you say "supercalifragilis',
    576                          'ticexpialidocious?" How *do*',
    577                          'you spell that odd word,',
    578                          'anyways?'])
    579         self.check_wrap(self.text, 50,
    580                         ['Did you say "supercalifragilisticexpialidocious?"',
    581                          'How *do* you spell that odd word, anyways?'])
    582 
    583         # SF bug 797650.  Prevent an infinite loop by making sure that at
    584         # least one character gets split off on every pass.
    585         self.check_wrap('-'*10+'hello', 10,
    586                         ['----------',
    587                          '               h',
    588                          '               e',
    589                          '               l',
    590                          '               l',
    591                          '               o'],
    592                         subsequent_indent = ' '*15)
    593 
    594         # bug 1146.  Prevent a long word to be wrongly wrapped when the
    595         # preceding word is exactly one character shorter than the width
    596         self.check_wrap(self.text, 12,
    597                         ['Did you say ',
    598                          '"supercalifr',
    599                          'agilisticexp',
    600                          'ialidocious?',
    601                          '" How *do*',
    602                          'you spell',
    603                          'that odd',
    604                          'word,',
    605                          'anyways?'])
    606 
    607     def test_nobreak_long(self):
    608         # Test with break_long_words disabled
    609         self.wrapper.break_long_words = 0
    610         self.wrapper.width = 30
    611         expect = ['Did you say',
    612                   '"supercalifragilisticexpialidocious?"',
    613                   'How *do* you spell that odd',
    614                   'word, anyways?'
    615                   ]
    616         result = self.wrapper.wrap(self.text)
    617         self.check(result, expect)
    618 
    619         # Same thing with kwargs passed to standalone wrap() function.
    620         result = wrap(self.text, width=30, break_long_words=0)
    621         self.check(result, expect)
    622 
    623     def test_max_lines_long(self):
    624         self.check_wrap(self.text, 12,
    625                         ['Did you say ',
    626                          '"supercalifr',
    627                          'agilisticexp',
    628                          '[...]'],
    629                         max_lines=4)
    630 
    631 
    632 class IndentTestCases(BaseTestCase):
    633 
    634     # called before each test method
    635     def setUp(self):
    636         self.text = '''\
    637 This paragraph will be filled, first without any indentation,
    638 and then with some (including a hanging indent).'''
    639 
    640 
    641     def test_fill(self):
    642         # Test the fill() method
    643 
    644         expect = '''\
    645 This paragraph will be filled, first
    646 without any indentation, and then with
    647 some (including a hanging indent).'''
    648 
    649         result = fill(self.text, 40)
    650         self.check(result, expect)
    651 
    652 
    653     def test_initial_indent(self):
    654         # Test initial_indent parameter
    655 
    656         expect = ["     This paragraph will be filled,",
    657                   "first without any indentation, and then",
    658                   "with some (including a hanging indent)."]
    659         result = wrap(self.text, 40, initial_indent="     ")
    660         self.check(result, expect)
    661 
    662         expect = "\n".join(expect)
    663         result = fill(self.text, 40, initial_indent="     ")
    664         self.check(result, expect)
    665 
    666 
    667     def test_subsequent_indent(self):
    668         # Test subsequent_indent parameter
    669 
    670         expect = '''\
    671   * This paragraph will be filled, first
    672     without any indentation, and then
    673     with some (including a hanging
    674     indent).'''
    675 
    676         result = fill(self.text, 40,
    677                       initial_indent="  * ", subsequent_indent="    ")
    678         self.check(result, expect)
    679 
    680 
    681 # Despite the similar names, DedentTestCase is *not* the inverse
    682 # of IndentTestCase!
    683 class DedentTestCase(unittest.TestCase):
    684 
    685     def assertUnchanged(self, text):
    686         """assert that dedent() has no effect on 'text'"""
    687         self.assertEqual(text, dedent(text))
    688 
    689     def test_dedent_nomargin(self):
    690         # No lines indented.
    691         text = "Hello there.\nHow are you?\nOh good, I'm glad."
    692         self.assertUnchanged(text)
    693 
    694         # Similar, with a blank line.
    695         text = "Hello there.\n\nBoo!"
    696         self.assertUnchanged(text)
    697 
    698         # Some lines indented, but overall margin is still zero.
    699         text = "Hello there.\n  This is indented."
    700         self.assertUnchanged(text)
    701 
    702         # Again, add a blank line.
    703         text = "Hello there.\n\n  Boo!\n"
    704         self.assertUnchanged(text)
    705 
    706     def test_dedent_even(self):
    707         # All lines indented by two spaces.
    708         text = "  Hello there.\n  How are ya?\n  Oh good."
    709         expect = "Hello there.\nHow are ya?\nOh good."
    710         self.assertEqual(expect, dedent(text))
    711 
    712         # Same, with blank lines.
    713         text = "  Hello there.\n\n  How are ya?\n  Oh good.\n"
    714         expect = "Hello there.\n\nHow are ya?\nOh good.\n"
    715         self.assertEqual(expect, dedent(text))
    716 
    717         # Now indent one of the blank lines.
    718         text = "  Hello there.\n  \n  How are ya?\n  Oh good.\n"
    719         expect = "Hello there.\n\nHow are ya?\nOh good.\n"
    720         self.assertEqual(expect, dedent(text))
    721 
    722     def test_dedent_uneven(self):
    723         # Lines indented unevenly.
    724         text = '''\
    725         def foo():
    726             while 1:
    727                 return foo
    728         '''
    729         expect = '''\
    730 def foo():
    731     while 1:
    732         return foo
    733 '''
    734         self.assertEqual(expect, dedent(text))
    735 
    736         # Uneven indentation with a blank line.
    737         text = "  Foo\n    Bar\n\n   Baz\n"
    738         expect = "Foo\n  Bar\n\n Baz\n"
    739         self.assertEqual(expect, dedent(text))
    740 
    741         # Uneven indentation with a whitespace-only line.
    742         text = "  Foo\n    Bar\n \n   Baz\n"
    743         expect = "Foo\n  Bar\n\n Baz\n"
    744         self.assertEqual(expect, dedent(text))
    745 
    746     # dedent() should not mangle internal tabs
    747     def test_dedent_preserve_internal_tabs(self):
    748         text = "  hello\tthere\n  how are\tyou?"
    749         expect = "hello\tthere\nhow are\tyou?"
    750         self.assertEqual(expect, dedent(text))
    751 
    752         # make sure that it preserves tabs when it's not making any
    753         # changes at all
    754         self.assertEqual(expect, dedent(expect))
    755 
    756     # dedent() should not mangle tabs in the margin (i.e.
    757     # tabs and spaces both count as margin, but are *not*
    758     # considered equivalent)
    759     def test_dedent_preserve_margin_tabs(self):
    760         text = "  hello there\n\thow are you?"
    761         self.assertUnchanged(text)
    762 
    763         # same effect even if we have 8 spaces
    764         text = "        hello there\n\thow are you?"
    765         self.assertUnchanged(text)
    766 
    767         # dedent() only removes whitespace that can be uniformly removed!
    768         text = "\thello there\n\thow are you?"
    769         expect = "hello there\nhow are you?"
    770         self.assertEqual(expect, dedent(text))
    771 
    772         text = "  \thello there\n  \thow are you?"
    773         self.assertEqual(expect, dedent(text))
    774 
    775         text = "  \t  hello there\n  \t  how are you?"
    776         self.assertEqual(expect, dedent(text))
    777 
    778         text = "  \thello there\n  \t  how are you?"
    779         expect = "hello there\n  how are you?"
    780         self.assertEqual(expect, dedent(text))
    781 
    782         # test margin is smaller than smallest indent
    783         text = "  \thello there\n   \thow are you?\n \tI'm fine, thanks"
    784         expect = " \thello there\n  \thow are you?\n\tI'm fine, thanks"
    785         self.assertEqual(expect, dedent(text))
    786 
    787 
    788 # Test textwrap.indent
    789 class IndentTestCase(unittest.TestCase):
    790     # The examples used for tests. If any of these change, the expected
    791     # results in the various test cases must also be updated.
    792     # The roundtrip cases are separate, because textwrap.dedent doesn't
    793     # handle Windows line endings
    794     ROUNDTRIP_CASES = (
    795       # Basic test case
    796       "Hi.\nThis is a test.\nTesting.",
    797       # Include a blank line
    798       "Hi.\nThis is a test.\n\nTesting.",
    799       # Include leading and trailing blank lines
    800       "\nHi.\nThis is a test.\nTesting.\n",
    801     )
    802     CASES = ROUNDTRIP_CASES + (
    803       # Use Windows line endings
    804       "Hi.\r\nThis is a test.\r\nTesting.\r\n",
    805       # Pathological case
    806       "\nHi.\r\nThis is a test.\n\r\nTesting.\r\n\n",
    807     )
    808 
    809     def test_indent_nomargin_default(self):
    810         # indent should do nothing if 'prefix' is empty.
    811         for text in self.CASES:
    812             self.assertEqual(indent(text, ''), text)
    813 
    814     def test_indent_nomargin_explicit_default(self):
    815         # The same as test_indent_nomargin, but explicitly requesting
    816         # the default behaviour by passing None as the predicate
    817         for text in self.CASES:
    818             self.assertEqual(indent(text, '', None), text)
    819 
    820     def test_indent_nomargin_all_lines(self):
    821         # The same as test_indent_nomargin, but using the optional
    822         # predicate argument
    823         predicate = lambda line: True
    824         for text in self.CASES:
    825             self.assertEqual(indent(text, '', predicate), text)
    826 
    827     def test_indent_no_lines(self):
    828         # Explicitly skip indenting any lines
    829         predicate = lambda line: False
    830         for text in self.CASES:
    831             self.assertEqual(indent(text, '    ', predicate), text)
    832 
    833     def test_roundtrip_spaces(self):
    834         # A whitespace prefix should roundtrip with dedent
    835         for text in self.ROUNDTRIP_CASES:
    836             self.assertEqual(dedent(indent(text, '    ')), text)
    837 
    838     def test_roundtrip_tabs(self):
    839         # A whitespace prefix should roundtrip with dedent
    840         for text in self.ROUNDTRIP_CASES:
    841             self.assertEqual(dedent(indent(text, '\t\t')), text)
    842 
    843     def test_roundtrip_mixed(self):
    844         # A whitespace prefix should roundtrip with dedent
    845         for text in self.ROUNDTRIP_CASES:
    846             self.assertEqual(dedent(indent(text, ' \t  \t ')), text)
    847 
    848     def test_indent_default(self):
    849         # Test default indenting of lines that are not whitespace only
    850         prefix = '  '
    851         expected = (
    852           # Basic test case
    853           "  Hi.\n  This is a test.\n  Testing.",
    854           # Include a blank line
    855           "  Hi.\n  This is a test.\n\n  Testing.",
    856           # Include leading and trailing blank lines
    857           "\n  Hi.\n  This is a test.\n  Testing.\n",
    858           # Use Windows line endings
    859           "  Hi.\r\n  This is a test.\r\n  Testing.\r\n",
    860           # Pathological case
    861           "\n  Hi.\r\n  This is a test.\n\r\n  Testing.\r\n\n",
    862         )
    863         for text, expect in zip(self.CASES, expected):
    864             self.assertEqual(indent(text, prefix), expect)
    865 
    866     def test_indent_explicit_default(self):
    867         # Test default indenting of lines that are not whitespace only
    868         prefix = '  '
    869         expected = (
    870           # Basic test case
    871           "  Hi.\n  This is a test.\n  Testing.",
    872           # Include a blank line
    873           "  Hi.\n  This is a test.\n\n  Testing.",
    874           # Include leading and trailing blank lines
    875           "\n  Hi.\n  This is a test.\n  Testing.\n",
    876           # Use Windows line endings
    877           "  Hi.\r\n  This is a test.\r\n  Testing.\r\n",
    878           # Pathological case
    879           "\n  Hi.\r\n  This is a test.\n\r\n  Testing.\r\n\n",
    880         )
    881         for text, expect in zip(self.CASES, expected):
    882             self.assertEqual(indent(text, prefix, None), expect)
    883 
    884     def test_indent_all_lines(self):
    885         # Add 'prefix' to all lines, including whitespace-only ones.
    886         prefix = '  '
    887         expected = (
    888           # Basic test case
    889           "  Hi.\n  This is a test.\n  Testing.",
    890           # Include a blank line
    891           "  Hi.\n  This is a test.\n  \n  Testing.",
    892           # Include leading and trailing blank lines
    893           "  \n  Hi.\n  This is a test.\n  Testing.\n",
    894           # Use Windows line endings
    895           "  Hi.\r\n  This is a test.\r\n  Testing.\r\n",
    896           # Pathological case
    897           "  \n  Hi.\r\n  This is a test.\n  \r\n  Testing.\r\n  \n",
    898         )
    899         predicate = lambda line: True
    900         for text, expect in zip(self.CASES, expected):
    901             self.assertEqual(indent(text, prefix, predicate), expect)
    902 
    903     def test_indent_empty_lines(self):
    904         # Add 'prefix' solely to whitespace-only lines.
    905         prefix = '  '
    906         expected = (
    907           # Basic test case
    908           "Hi.\nThis is a test.\nTesting.",
    909           # Include a blank line
    910           "Hi.\nThis is a test.\n  \nTesting.",
    911           # Include leading and trailing blank lines
    912           "  \nHi.\nThis is a test.\nTesting.\n",
    913           # Use Windows line endings
    914           "Hi.\r\nThis is a test.\r\nTesting.\r\n",
    915           # Pathological case
    916           "  \nHi.\r\nThis is a test.\n  \r\nTesting.\r\n  \n",
    917         )
    918         predicate = lambda line: not line.strip()
    919         for text, expect in zip(self.CASES, expected):
    920             self.assertEqual(indent(text, prefix, predicate), expect)
    921 
    922 
    923 class ShortenTestCase(BaseTestCase):
    924 
    925     def check_shorten(self, text, width, expect, **kwargs):
    926         result = shorten(text, width, **kwargs)
    927         self.check(result, expect)
    928 
    929     def test_simple(self):
    930         # Simple case: just words, spaces, and a bit of punctuation
    931         text = "Hello there, how are you this fine day? I'm glad to hear it!"
    932 
    933         self.check_shorten(text, 18, "Hello there, [...]")
    934         self.check_shorten(text, len(text), text)
    935         self.check_shorten(text, len(text) - 1,
    936             "Hello there, how are you this fine day? "
    937             "I'm glad to [...]")
    938 
    939     def test_placeholder(self):
    940         text = "Hello there, how are you this fine day? I'm glad to hear it!"
    941 
    942         self.check_shorten(text, 17, "Hello there,$$", placeholder='$$')
    943         self.check_shorten(text, 18, "Hello there, how$$", placeholder='$$')
    944         self.check_shorten(text, 18, "Hello there, $$", placeholder=' $$')
    945         self.check_shorten(text, len(text), text, placeholder='$$')
    946         self.check_shorten(text, len(text) - 1,
    947             "Hello there, how are you this fine day? "
    948             "I'm glad to hear$$", placeholder='$$')
    949 
    950     def test_empty_string(self):
    951         self.check_shorten("", 6, "")
    952 
    953     def test_whitespace(self):
    954         # Whitespace collapsing
    955         text = """
    956             This is a  paragraph that  already has
    957             line breaks and \t tabs too."""
    958         self.check_shorten(text, 62,
    959                              "This is a paragraph that already has line "
    960                              "breaks and tabs too.")
    961         self.check_shorten(text, 61,
    962                              "This is a paragraph that already has line "
    963                              "breaks and [...]")
    964 
    965         self.check_shorten("hello      world!  ", 12, "hello world!")
    966         self.check_shorten("hello      world!  ", 11, "hello [...]")
    967         # The leading space is trimmed from the placeholder
    968         # (it would be ugly otherwise).
    969         self.check_shorten("hello      world!  ", 10, "[...]")
    970 
    971     def test_width_too_small_for_placeholder(self):
    972         shorten("x" * 20, width=8, placeholder="(......)")
    973         with self.assertRaises(ValueError):
    974             shorten("x" * 20, width=8, placeholder="(.......)")
    975 
    976     def test_first_word_too_long_but_placeholder_fits(self):
    977         self.check_shorten("Helloo", 5, "[...]")
    978 
    979 
    980 if __name__ == '__main__':
    981     unittest.main()
    982