1# 2# Test suite 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 11import unittest 12 13from textwrap import TextWrapper, wrap, fill, dedent, indent, shorten 14 15 16class 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 46class 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 = """\ 82This is a paragraph that already has 83line breaks. But some of its lines are much longer than the others, 84so it needs to be wrapped. 85Some lines are \ttabbed too. 86What 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 479class 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 def test_placeholder_backtrack(self): 563 # Test special case when max_lines insufficient, but what 564 # would be last wrapped line so long the placeholder cannot 565 # be added there without violence. So, textwrap backtracks, 566 # adding placeholder to the penultimate line. 567 text = 'Good grief Python features are advancing quickly!' 568 self.check_wrap(text, 12, 569 ['Good grief', 'Python*****'], 570 max_lines=3, 571 placeholder='*****') 572 573 574class LongWordTestCase (BaseTestCase): 575 def setUp(self): 576 self.wrapper = TextWrapper() 577 self.text = '''\ 578Did you say "supercalifragilisticexpialidocious?" 579How *do* you spell that odd word, anyways? 580''' 581 582 def test_break_long(self): 583 # Wrap text with long words and lots of punctuation 584 585 self.check_wrap(self.text, 30, 586 ['Did you say "supercalifragilis', 587 'ticexpialidocious?" How *do*', 588 'you spell that odd word,', 589 'anyways?']) 590 self.check_wrap(self.text, 50, 591 ['Did you say "supercalifragilisticexpialidocious?"', 592 'How *do* you spell that odd word, anyways?']) 593 594 # SF bug 797650. Prevent an infinite loop by making sure that at 595 # least one character gets split off on every pass. 596 self.check_wrap('-'*10+'hello', 10, 597 ['----------', 598 ' h', 599 ' e', 600 ' l', 601 ' l', 602 ' o'], 603 subsequent_indent = ' '*15) 604 605 # bug 1146. Prevent a long word to be wrongly wrapped when the 606 # preceding word is exactly one character shorter than the width 607 self.check_wrap(self.text, 12, 608 ['Did you say ', 609 '"supercalifr', 610 'agilisticexp', 611 'ialidocious?', 612 '" How *do*', 613 'you spell', 614 'that odd', 615 'word,', 616 'anyways?']) 617 618 def test_nobreak_long(self): 619 # Test with break_long_words disabled 620 self.wrapper.break_long_words = 0 621 self.wrapper.width = 30 622 expect = ['Did you say', 623 '"supercalifragilisticexpialidocious?"', 624 'How *do* you spell that odd', 625 'word, anyways?' 626 ] 627 result = self.wrapper.wrap(self.text) 628 self.check(result, expect) 629 630 # Same thing with kwargs passed to standalone wrap() function. 631 result = wrap(self.text, width=30, break_long_words=0) 632 self.check(result, expect) 633 634 def test_max_lines_long(self): 635 self.check_wrap(self.text, 12, 636 ['Did you say ', 637 '"supercalifr', 638 'agilisticexp', 639 '[...]'], 640 max_lines=4) 641 642 643class IndentTestCases(BaseTestCase): 644 645 # called before each test method 646 def setUp(self): 647 self.text = '''\ 648This paragraph will be filled, first without any indentation, 649and then with some (including a hanging indent).''' 650 651 652 def test_fill(self): 653 # Test the fill() method 654 655 expect = '''\ 656This paragraph will be filled, first 657without any indentation, and then with 658some (including a hanging indent).''' 659 660 result = fill(self.text, 40) 661 self.check(result, expect) 662 663 664 def test_initial_indent(self): 665 # Test initial_indent parameter 666 667 expect = [" This paragraph will be filled,", 668 "first without any indentation, and then", 669 "with some (including a hanging indent)."] 670 result = wrap(self.text, 40, initial_indent=" ") 671 self.check(result, expect) 672 673 expect = "\n".join(expect) 674 result = fill(self.text, 40, initial_indent=" ") 675 self.check(result, expect) 676 677 678 def test_subsequent_indent(self): 679 # Test subsequent_indent parameter 680 681 expect = '''\ 682 * This paragraph will be filled, first 683 without any indentation, and then 684 with some (including a hanging 685 indent).''' 686 687 result = fill(self.text, 40, 688 initial_indent=" * ", subsequent_indent=" ") 689 self.check(result, expect) 690 691 692# Despite the similar names, DedentTestCase is *not* the inverse 693# of IndentTestCase! 694class DedentTestCase(unittest.TestCase): 695 696 def assertUnchanged(self, text): 697 """assert that dedent() has no effect on 'text'""" 698 self.assertEqual(text, dedent(text)) 699 700 def test_dedent_nomargin(self): 701 # No lines indented. 702 text = "Hello there.\nHow are you?\nOh good, I'm glad." 703 self.assertUnchanged(text) 704 705 # Similar, with a blank line. 706 text = "Hello there.\n\nBoo!" 707 self.assertUnchanged(text) 708 709 # Some lines indented, but overall margin is still zero. 710 text = "Hello there.\n This is indented." 711 self.assertUnchanged(text) 712 713 # Again, add a blank line. 714 text = "Hello there.\n\n Boo!\n" 715 self.assertUnchanged(text) 716 717 def test_dedent_even(self): 718 # All lines indented by two spaces. 719 text = " Hello there.\n How are ya?\n Oh good." 720 expect = "Hello there.\nHow are ya?\nOh good." 721 self.assertEqual(expect, dedent(text)) 722 723 # Same, with blank lines. 724 text = " Hello there.\n\n How are ya?\n Oh good.\n" 725 expect = "Hello there.\n\nHow are ya?\nOh good.\n" 726 self.assertEqual(expect, dedent(text)) 727 728 # Now indent one of the blank lines. 729 text = " Hello there.\n \n How are ya?\n Oh good.\n" 730 expect = "Hello there.\n\nHow are ya?\nOh good.\n" 731 self.assertEqual(expect, dedent(text)) 732 733 def test_dedent_uneven(self): 734 # Lines indented unevenly. 735 text = '''\ 736 def foo(): 737 while 1: 738 return foo 739 ''' 740 expect = '''\ 741def foo(): 742 while 1: 743 return foo 744''' 745 self.assertEqual(expect, dedent(text)) 746 747 # Uneven indentation with a blank line. 748 text = " Foo\n Bar\n\n Baz\n" 749 expect = "Foo\n Bar\n\n Baz\n" 750 self.assertEqual(expect, dedent(text)) 751 752 # Uneven indentation with a whitespace-only line. 753 text = " Foo\n Bar\n \n Baz\n" 754 expect = "Foo\n Bar\n\n Baz\n" 755 self.assertEqual(expect, dedent(text)) 756 757 def test_dedent_declining(self): 758 # Uneven indentation with declining indent level. 759 text = " Foo\n Bar\n" # 5 spaces, then 4 760 expect = " Foo\nBar\n" 761 self.assertEqual(expect, dedent(text)) 762 763 # Declining indent level with blank line. 764 text = " Foo\n\n Bar\n" # 5 spaces, blank, then 4 765 expect = " Foo\n\nBar\n" 766 self.assertEqual(expect, dedent(text)) 767 768 # Declining indent level with whitespace only line. 769 text = " Foo\n \n Bar\n" # 5 spaces, then 4, then 4 770 expect = " Foo\n\nBar\n" 771 self.assertEqual(expect, dedent(text)) 772 773 # dedent() should not mangle internal tabs 774 def test_dedent_preserve_internal_tabs(self): 775 text = " hello\tthere\n how are\tyou?" 776 expect = "hello\tthere\nhow are\tyou?" 777 self.assertEqual(expect, dedent(text)) 778 779 # make sure that it preserves tabs when it's not making any 780 # changes at all 781 self.assertEqual(expect, dedent(expect)) 782 783 # dedent() should not mangle tabs in the margin (i.e. 784 # tabs and spaces both count as margin, but are *not* 785 # considered equivalent) 786 def test_dedent_preserve_margin_tabs(self): 787 text = " hello there\n\thow are you?" 788 self.assertUnchanged(text) 789 790 # same effect even if we have 8 spaces 791 text = " hello there\n\thow are you?" 792 self.assertUnchanged(text) 793 794 # dedent() only removes whitespace that can be uniformly removed! 795 text = "\thello there\n\thow are you?" 796 expect = "hello there\nhow are you?" 797 self.assertEqual(expect, dedent(text)) 798 799 text = " \thello there\n \thow are you?" 800 self.assertEqual(expect, dedent(text)) 801 802 text = " \t hello there\n \t how are you?" 803 self.assertEqual(expect, dedent(text)) 804 805 text = " \thello there\n \t how are you?" 806 expect = "hello there\n how are you?" 807 self.assertEqual(expect, dedent(text)) 808 809 # test margin is smaller than smallest indent 810 text = " \thello there\n \thow are you?\n \tI'm fine, thanks" 811 expect = " \thello there\n \thow are you?\n\tI'm fine, thanks" 812 self.assertEqual(expect, dedent(text)) 813 814 815# Test textwrap.indent 816class IndentTestCase(unittest.TestCase): 817 # The examples used for tests. If any of these change, the expected 818 # results in the various test cases must also be updated. 819 # The roundtrip cases are separate, because textwrap.dedent doesn't 820 # handle Windows line endings 821 ROUNDTRIP_CASES = ( 822 # Basic test case 823 "Hi.\nThis is a test.\nTesting.", 824 # Include a blank line 825 "Hi.\nThis is a test.\n\nTesting.", 826 # Include leading and trailing blank lines 827 "\nHi.\nThis is a test.\nTesting.\n", 828 ) 829 CASES = ROUNDTRIP_CASES + ( 830 # Use Windows line endings 831 "Hi.\r\nThis is a test.\r\nTesting.\r\n", 832 # Pathological case 833 "\nHi.\r\nThis is a test.\n\r\nTesting.\r\n\n", 834 ) 835 836 def test_indent_nomargin_default(self): 837 # indent should do nothing if 'prefix' is empty. 838 for text in self.CASES: 839 self.assertEqual(indent(text, ''), text) 840 841 def test_indent_nomargin_explicit_default(self): 842 # The same as test_indent_nomargin, but explicitly requesting 843 # the default behaviour by passing None as the predicate 844 for text in self.CASES: 845 self.assertEqual(indent(text, '', None), text) 846 847 def test_indent_nomargin_all_lines(self): 848 # The same as test_indent_nomargin, but using the optional 849 # predicate argument 850 predicate = lambda line: True 851 for text in self.CASES: 852 self.assertEqual(indent(text, '', predicate), text) 853 854 def test_indent_no_lines(self): 855 # Explicitly skip indenting any lines 856 predicate = lambda line: False 857 for text in self.CASES: 858 self.assertEqual(indent(text, ' ', predicate), text) 859 860 def test_roundtrip_spaces(self): 861 # A whitespace prefix should roundtrip with dedent 862 for text in self.ROUNDTRIP_CASES: 863 self.assertEqual(dedent(indent(text, ' ')), text) 864 865 def test_roundtrip_tabs(self): 866 # A whitespace prefix should roundtrip with dedent 867 for text in self.ROUNDTRIP_CASES: 868 self.assertEqual(dedent(indent(text, '\t\t')), text) 869 870 def test_roundtrip_mixed(self): 871 # A whitespace prefix should roundtrip with dedent 872 for text in self.ROUNDTRIP_CASES: 873 self.assertEqual(dedent(indent(text, ' \t \t ')), text) 874 875 def test_indent_default(self): 876 # Test default indenting of lines that are not whitespace only 877 prefix = ' ' 878 expected = ( 879 # Basic test case 880 " Hi.\n This is a test.\n Testing.", 881 # Include a blank line 882 " Hi.\n This is a test.\n\n Testing.", 883 # Include leading and trailing blank lines 884 "\n Hi.\n This is a test.\n Testing.\n", 885 # Use Windows line endings 886 " Hi.\r\n This is a test.\r\n Testing.\r\n", 887 # Pathological case 888 "\n Hi.\r\n This is a test.\n\r\n Testing.\r\n\n", 889 ) 890 for text, expect in zip(self.CASES, expected): 891 self.assertEqual(indent(text, prefix), expect) 892 893 def test_indent_explicit_default(self): 894 # Test default indenting of lines that are not whitespace only 895 prefix = ' ' 896 expected = ( 897 # Basic test case 898 " Hi.\n This is a test.\n Testing.", 899 # Include a blank line 900 " Hi.\n This is a test.\n\n Testing.", 901 # Include leading and trailing blank lines 902 "\n Hi.\n This is a test.\n Testing.\n", 903 # Use Windows line endings 904 " Hi.\r\n This is a test.\r\n Testing.\r\n", 905 # Pathological case 906 "\n Hi.\r\n This is a test.\n\r\n Testing.\r\n\n", 907 ) 908 for text, expect in zip(self.CASES, expected): 909 self.assertEqual(indent(text, prefix, None), expect) 910 911 def test_indent_all_lines(self): 912 # Add 'prefix' to all lines, including whitespace-only ones. 913 prefix = ' ' 914 expected = ( 915 # Basic test case 916 " Hi.\n This is a test.\n Testing.", 917 # Include a blank line 918 " Hi.\n This is a test.\n \n Testing.", 919 # Include leading and trailing blank lines 920 " \n Hi.\n This is a test.\n Testing.\n", 921 # Use Windows line endings 922 " Hi.\r\n This is a test.\r\n Testing.\r\n", 923 # Pathological case 924 " \n Hi.\r\n This is a test.\n \r\n Testing.\r\n \n", 925 ) 926 predicate = lambda line: True 927 for text, expect in zip(self.CASES, expected): 928 self.assertEqual(indent(text, prefix, predicate), expect) 929 930 def test_indent_empty_lines(self): 931 # Add 'prefix' solely to whitespace-only lines. 932 prefix = ' ' 933 expected = ( 934 # Basic test case 935 "Hi.\nThis is a test.\nTesting.", 936 # Include a blank line 937 "Hi.\nThis is a test.\n \nTesting.", 938 # Include leading and trailing blank lines 939 " \nHi.\nThis is a test.\nTesting.\n", 940 # Use Windows line endings 941 "Hi.\r\nThis is a test.\r\nTesting.\r\n", 942 # Pathological case 943 " \nHi.\r\nThis is a test.\n \r\nTesting.\r\n \n", 944 ) 945 predicate = lambda line: not line.strip() 946 for text, expect in zip(self.CASES, expected): 947 self.assertEqual(indent(text, prefix, predicate), expect) 948 949 950class ShortenTestCase(BaseTestCase): 951 952 def check_shorten(self, text, width, expect, **kwargs): 953 result = shorten(text, width, **kwargs) 954 self.check(result, expect) 955 956 def test_simple(self): 957 # Simple case: just words, spaces, and a bit of punctuation 958 text = "Hello there, how are you this fine day? I'm glad to hear it!" 959 960 self.check_shorten(text, 18, "Hello there, [...]") 961 self.check_shorten(text, len(text), text) 962 self.check_shorten(text, len(text) - 1, 963 "Hello there, how are you this fine day? " 964 "I'm glad to [...]") 965 966 def test_placeholder(self): 967 text = "Hello there, how are you this fine day? I'm glad to hear it!" 968 969 self.check_shorten(text, 17, "Hello there,$$", placeholder='$$') 970 self.check_shorten(text, 18, "Hello there, how$$", placeholder='$$') 971 self.check_shorten(text, 18, "Hello there, $$", placeholder=' $$') 972 self.check_shorten(text, len(text), text, placeholder='$$') 973 self.check_shorten(text, len(text) - 1, 974 "Hello there, how are you this fine day? " 975 "I'm glad to hear$$", placeholder='$$') 976 977 def test_empty_string(self): 978 self.check_shorten("", 6, "") 979 980 def test_whitespace(self): 981 # Whitespace collapsing 982 text = """ 983 This is a paragraph that already has 984 line breaks and \t tabs too.""" 985 self.check_shorten(text, 62, 986 "This is a paragraph that already has line " 987 "breaks and tabs too.") 988 self.check_shorten(text, 61, 989 "This is a paragraph that already has line " 990 "breaks and [...]") 991 992 self.check_shorten("hello world! ", 12, "hello world!") 993 self.check_shorten("hello world! ", 11, "hello [...]") 994 # The leading space is trimmed from the placeholder 995 # (it would be ugly otherwise). 996 self.check_shorten("hello world! ", 10, "[...]") 997 998 def test_width_too_small_for_placeholder(self): 999 shorten("x" * 20, width=8, placeholder="(......)") 1000 with self.assertRaises(ValueError): 1001 shorten("x" * 20, width=8, placeholder="(.......)") 1002 1003 def test_first_word_too_long_but_placeholder_fits(self): 1004 self.check_shorten("Helloo", 5, "[...]") 1005 1006 1007if __name__ == '__main__': 1008 unittest.main() 1009