17db96d56Sopenharmony_ci#
27db96d56Sopenharmony_ci# Test suite for the textwrap module.
37db96d56Sopenharmony_ci#
47db96d56Sopenharmony_ci# Original tests written by Greg Ward <gward@python.net>.
57db96d56Sopenharmony_ci# Converted to PyUnit by Peter Hansen <peter@engcorp.com>.
67db96d56Sopenharmony_ci# Currently maintained by Greg Ward.
77db96d56Sopenharmony_ci#
87db96d56Sopenharmony_ci# $Id$
97db96d56Sopenharmony_ci#
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_ciimport unittest
127db96d56Sopenharmony_ci
137db96d56Sopenharmony_cifrom textwrap import TextWrapper, wrap, fill, dedent, indent, shorten
147db96d56Sopenharmony_ci
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_ciclass BaseTestCase(unittest.TestCase):
177db96d56Sopenharmony_ci    '''Parent class with utility methods for textwrap tests.'''
187db96d56Sopenharmony_ci
197db96d56Sopenharmony_ci    def show(self, textin):
207db96d56Sopenharmony_ci        if isinstance(textin, list):
217db96d56Sopenharmony_ci            result = []
227db96d56Sopenharmony_ci            for i in range(len(textin)):
237db96d56Sopenharmony_ci                result.append("  %d: %r" % (i, textin[i]))
247db96d56Sopenharmony_ci            result = "\n".join(result) if result else "  no lines"
257db96d56Sopenharmony_ci        elif isinstance(textin, str):
267db96d56Sopenharmony_ci            result = "  %s\n" % repr(textin)
277db96d56Sopenharmony_ci        return result
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ci    def check(self, result, expect):
317db96d56Sopenharmony_ci        self.assertEqual(result, expect,
327db96d56Sopenharmony_ci            'expected:\n%s\nbut got:\n%s' % (
337db96d56Sopenharmony_ci                self.show(expect), self.show(result)))
347db96d56Sopenharmony_ci
357db96d56Sopenharmony_ci    def check_wrap(self, text, width, expect, **kwargs):
367db96d56Sopenharmony_ci        result = wrap(text, width, **kwargs)
377db96d56Sopenharmony_ci        self.check(result, expect)
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_ci    def check_split(self, text, expect):
407db96d56Sopenharmony_ci        result = self.wrapper._split(text)
417db96d56Sopenharmony_ci        self.assertEqual(result, expect,
427db96d56Sopenharmony_ci                         "\nexpected %r\n"
437db96d56Sopenharmony_ci                         "but got  %r" % (expect, result))
447db96d56Sopenharmony_ci
457db96d56Sopenharmony_ci
467db96d56Sopenharmony_ciclass WrapTestCase(BaseTestCase):
477db96d56Sopenharmony_ci
487db96d56Sopenharmony_ci    def setUp(self):
497db96d56Sopenharmony_ci        self.wrapper = TextWrapper(width=45)
507db96d56Sopenharmony_ci
517db96d56Sopenharmony_ci    def test_simple(self):
527db96d56Sopenharmony_ci        # Simple case: just words, spaces, and a bit of punctuation
537db96d56Sopenharmony_ci
547db96d56Sopenharmony_ci        text = "Hello there, how are you this fine day?  I'm glad to hear it!"
557db96d56Sopenharmony_ci
567db96d56Sopenharmony_ci        self.check_wrap(text, 12,
577db96d56Sopenharmony_ci                        ["Hello there,",
587db96d56Sopenharmony_ci                         "how are you",
597db96d56Sopenharmony_ci                         "this fine",
607db96d56Sopenharmony_ci                         "day?  I'm",
617db96d56Sopenharmony_ci                         "glad to hear",
627db96d56Sopenharmony_ci                         "it!"])
637db96d56Sopenharmony_ci        self.check_wrap(text, 42,
647db96d56Sopenharmony_ci                        ["Hello there, how are you this fine day?",
657db96d56Sopenharmony_ci                         "I'm glad to hear it!"])
667db96d56Sopenharmony_ci        self.check_wrap(text, 80, [text])
677db96d56Sopenharmony_ci
687db96d56Sopenharmony_ci    def test_empty_string(self):
697db96d56Sopenharmony_ci        # Check that wrapping the empty string returns an empty list.
707db96d56Sopenharmony_ci        self.check_wrap("", 6, [])
717db96d56Sopenharmony_ci        self.check_wrap("", 6, [], drop_whitespace=False)
727db96d56Sopenharmony_ci
737db96d56Sopenharmony_ci    def test_empty_string_with_initial_indent(self):
747db96d56Sopenharmony_ci        # Check that the empty string is not indented.
757db96d56Sopenharmony_ci        self.check_wrap("", 6, [], initial_indent="++")
767db96d56Sopenharmony_ci        self.check_wrap("", 6, [], initial_indent="++", drop_whitespace=False)
777db96d56Sopenharmony_ci
787db96d56Sopenharmony_ci    def test_whitespace(self):
797db96d56Sopenharmony_ci        # Whitespace munging and end-of-sentence detection
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ci        text = """\
827db96d56Sopenharmony_ciThis is a paragraph that already has
837db96d56Sopenharmony_ciline breaks.  But some of its lines are much longer than the others,
847db96d56Sopenharmony_ciso it needs to be wrapped.
857db96d56Sopenharmony_ciSome lines are \ttabbed too.
867db96d56Sopenharmony_ciWhat a mess!
877db96d56Sopenharmony_ci"""
887db96d56Sopenharmony_ci
897db96d56Sopenharmony_ci        expect = ["This is a paragraph that already has line",
907db96d56Sopenharmony_ci                  "breaks.  But some of its lines are much",
917db96d56Sopenharmony_ci                  "longer than the others, so it needs to be",
927db96d56Sopenharmony_ci                  "wrapped.  Some lines are  tabbed too.  What a",
937db96d56Sopenharmony_ci                  "mess!"]
947db96d56Sopenharmony_ci
957db96d56Sopenharmony_ci        wrapper = TextWrapper(45, fix_sentence_endings=True)
967db96d56Sopenharmony_ci        result = wrapper.wrap(text)
977db96d56Sopenharmony_ci        self.check(result, expect)
987db96d56Sopenharmony_ci
997db96d56Sopenharmony_ci        result = wrapper.fill(text)
1007db96d56Sopenharmony_ci        self.check(result, '\n'.join(expect))
1017db96d56Sopenharmony_ci
1027db96d56Sopenharmony_ci        text = "\tTest\tdefault\t\ttabsize."
1037db96d56Sopenharmony_ci        expect = ["        Test    default         tabsize."]
1047db96d56Sopenharmony_ci        self.check_wrap(text, 80, expect)
1057db96d56Sopenharmony_ci
1067db96d56Sopenharmony_ci        text = "\tTest\tcustom\t\ttabsize."
1077db96d56Sopenharmony_ci        expect = ["    Test    custom      tabsize."]
1087db96d56Sopenharmony_ci        self.check_wrap(text, 80, expect, tabsize=4)
1097db96d56Sopenharmony_ci
1107db96d56Sopenharmony_ci    def test_fix_sentence_endings(self):
1117db96d56Sopenharmony_ci        wrapper = TextWrapper(60, fix_sentence_endings=True)
1127db96d56Sopenharmony_ci
1137db96d56Sopenharmony_ci        # SF #847346: ensure that fix_sentence_endings=True does the
1147db96d56Sopenharmony_ci        # right thing even on input short enough that it doesn't need to
1157db96d56Sopenharmony_ci        # be wrapped.
1167db96d56Sopenharmony_ci        text = "A short line. Note the single space."
1177db96d56Sopenharmony_ci        expect = ["A short line.  Note the single space."]
1187db96d56Sopenharmony_ci        self.check(wrapper.wrap(text), expect)
1197db96d56Sopenharmony_ci
1207db96d56Sopenharmony_ci        # Test some of the hairy end cases that _fix_sentence_endings()
1217db96d56Sopenharmony_ci        # is supposed to handle (the easy stuff is tested in
1227db96d56Sopenharmony_ci        # test_whitespace() above).
1237db96d56Sopenharmony_ci        text = "Well, Doctor? What do you think?"
1247db96d56Sopenharmony_ci        expect = ["Well, Doctor?  What do you think?"]
1257db96d56Sopenharmony_ci        self.check(wrapper.wrap(text), expect)
1267db96d56Sopenharmony_ci
1277db96d56Sopenharmony_ci        text = "Well, Doctor?\nWhat do you think?"
1287db96d56Sopenharmony_ci        self.check(wrapper.wrap(text), expect)
1297db96d56Sopenharmony_ci
1307db96d56Sopenharmony_ci        text = 'I say, chaps! Anyone for "tennis?"\nHmmph!'
1317db96d56Sopenharmony_ci        expect = ['I say, chaps!  Anyone for "tennis?"  Hmmph!']
1327db96d56Sopenharmony_ci        self.check(wrapper.wrap(text), expect)
1337db96d56Sopenharmony_ci
1347db96d56Sopenharmony_ci        wrapper.width = 20
1357db96d56Sopenharmony_ci        expect = ['I say, chaps!', 'Anyone for "tennis?"', 'Hmmph!']
1367db96d56Sopenharmony_ci        self.check(wrapper.wrap(text), expect)
1377db96d56Sopenharmony_ci
1387db96d56Sopenharmony_ci        text = 'And she said, "Go to hell!"\nCan you believe that?'
1397db96d56Sopenharmony_ci        expect = ['And she said, "Go to',
1407db96d56Sopenharmony_ci                  'hell!"  Can you',
1417db96d56Sopenharmony_ci                  'believe that?']
1427db96d56Sopenharmony_ci        self.check(wrapper.wrap(text), expect)
1437db96d56Sopenharmony_ci
1447db96d56Sopenharmony_ci        wrapper.width = 60
1457db96d56Sopenharmony_ci        expect = ['And she said, "Go to hell!"  Can you believe that?']
1467db96d56Sopenharmony_ci        self.check(wrapper.wrap(text), expect)
1477db96d56Sopenharmony_ci
1487db96d56Sopenharmony_ci        text = 'File stdio.h is nice.'
1497db96d56Sopenharmony_ci        expect = ['File stdio.h is nice.']
1507db96d56Sopenharmony_ci        self.check(wrapper.wrap(text), expect)
1517db96d56Sopenharmony_ci
1527db96d56Sopenharmony_ci    def test_wrap_short(self):
1537db96d56Sopenharmony_ci        # Wrapping to make short lines longer
1547db96d56Sopenharmony_ci
1557db96d56Sopenharmony_ci        text = "This is a\nshort paragraph."
1567db96d56Sopenharmony_ci
1577db96d56Sopenharmony_ci        self.check_wrap(text, 20, ["This is a short",
1587db96d56Sopenharmony_ci                                   "paragraph."])
1597db96d56Sopenharmony_ci        self.check_wrap(text, 40, ["This is a short paragraph."])
1607db96d56Sopenharmony_ci
1617db96d56Sopenharmony_ci
1627db96d56Sopenharmony_ci    def test_wrap_short_1line(self):
1637db96d56Sopenharmony_ci        # Test endcases
1647db96d56Sopenharmony_ci
1657db96d56Sopenharmony_ci        text = "This is a short line."
1667db96d56Sopenharmony_ci
1677db96d56Sopenharmony_ci        self.check_wrap(text, 30, ["This is a short line."])
1687db96d56Sopenharmony_ci        self.check_wrap(text, 30, ["(1) This is a short line."],
1697db96d56Sopenharmony_ci                        initial_indent="(1) ")
1707db96d56Sopenharmony_ci
1717db96d56Sopenharmony_ci
1727db96d56Sopenharmony_ci    def test_hyphenated(self):
1737db96d56Sopenharmony_ci        # Test breaking hyphenated words
1747db96d56Sopenharmony_ci
1757db96d56Sopenharmony_ci        text = ("this-is-a-useful-feature-for-"
1767db96d56Sopenharmony_ci                "reformatting-posts-from-tim-peters'ly")
1777db96d56Sopenharmony_ci
1787db96d56Sopenharmony_ci        self.check_wrap(text, 40,
1797db96d56Sopenharmony_ci                        ["this-is-a-useful-feature-for-",
1807db96d56Sopenharmony_ci                         "reformatting-posts-from-tim-peters'ly"])
1817db96d56Sopenharmony_ci        self.check_wrap(text, 41,
1827db96d56Sopenharmony_ci                        ["this-is-a-useful-feature-for-",
1837db96d56Sopenharmony_ci                         "reformatting-posts-from-tim-peters'ly"])
1847db96d56Sopenharmony_ci        self.check_wrap(text, 42,
1857db96d56Sopenharmony_ci                        ["this-is-a-useful-feature-for-reformatting-",
1867db96d56Sopenharmony_ci                         "posts-from-tim-peters'ly"])
1877db96d56Sopenharmony_ci        # The test tests current behavior but is not testing parts of the API.
1887db96d56Sopenharmony_ci        expect = ("this-|is-|a-|useful-|feature-|for-|"
1897db96d56Sopenharmony_ci                  "reformatting-|posts-|from-|tim-|peters'ly").split('|')
1907db96d56Sopenharmony_ci        self.check_wrap(text, 1, expect, break_long_words=False)
1917db96d56Sopenharmony_ci        self.check_split(text, expect)
1927db96d56Sopenharmony_ci
1937db96d56Sopenharmony_ci        self.check_split('e-mail', ['e-mail'])
1947db96d56Sopenharmony_ci        self.check_split('Jelly-O', ['Jelly-O'])
1957db96d56Sopenharmony_ci        # The test tests current behavior but is not testing parts of the API.
1967db96d56Sopenharmony_ci        self.check_split('half-a-crown', 'half-|a-|crown'.split('|'))
1977db96d56Sopenharmony_ci
1987db96d56Sopenharmony_ci    def test_hyphenated_numbers(self):
1997db96d56Sopenharmony_ci        # Test that hyphenated numbers (eg. dates) are not broken like words.
2007db96d56Sopenharmony_ci        text = ("Python 1.0.0 was released on 1994-01-26.  Python 1.0.1 was\n"
2017db96d56Sopenharmony_ci                "released on 1994-02-15.")
2027db96d56Sopenharmony_ci
2037db96d56Sopenharmony_ci        self.check_wrap(text, 30, ['Python 1.0.0 was released on',
2047db96d56Sopenharmony_ci                                   '1994-01-26.  Python 1.0.1 was',
2057db96d56Sopenharmony_ci                                   'released on 1994-02-15.'])
2067db96d56Sopenharmony_ci        self.check_wrap(text, 40, ['Python 1.0.0 was released on 1994-01-26.',
2077db96d56Sopenharmony_ci                                   'Python 1.0.1 was released on 1994-02-15.'])
2087db96d56Sopenharmony_ci        self.check_wrap(text, 1, text.split(), break_long_words=False)
2097db96d56Sopenharmony_ci
2107db96d56Sopenharmony_ci        text = "I do all my shopping at 7-11."
2117db96d56Sopenharmony_ci        self.check_wrap(text, 25, ["I do all my shopping at",
2127db96d56Sopenharmony_ci                                   "7-11."])
2137db96d56Sopenharmony_ci        self.check_wrap(text, 27, ["I do all my shopping at",
2147db96d56Sopenharmony_ci                                   "7-11."])
2157db96d56Sopenharmony_ci        self.check_wrap(text, 29, ["I do all my shopping at 7-11."])
2167db96d56Sopenharmony_ci        self.check_wrap(text, 1, text.split(), break_long_words=False)
2177db96d56Sopenharmony_ci
2187db96d56Sopenharmony_ci    def test_em_dash(self):
2197db96d56Sopenharmony_ci        # Test text with em-dashes
2207db96d56Sopenharmony_ci        text = "Em-dashes should be written -- thus."
2217db96d56Sopenharmony_ci        self.check_wrap(text, 25,
2227db96d56Sopenharmony_ci                        ["Em-dashes should be",
2237db96d56Sopenharmony_ci                         "written -- thus."])
2247db96d56Sopenharmony_ci
2257db96d56Sopenharmony_ci        # Probe the boundaries of the properly written em-dash,
2267db96d56Sopenharmony_ci        # ie. " -- ".
2277db96d56Sopenharmony_ci        self.check_wrap(text, 29,
2287db96d56Sopenharmony_ci                        ["Em-dashes should be written",
2297db96d56Sopenharmony_ci                         "-- thus."])
2307db96d56Sopenharmony_ci        expect = ["Em-dashes should be written --",
2317db96d56Sopenharmony_ci                  "thus."]
2327db96d56Sopenharmony_ci        self.check_wrap(text, 30, expect)
2337db96d56Sopenharmony_ci        self.check_wrap(text, 35, expect)
2347db96d56Sopenharmony_ci        self.check_wrap(text, 36,
2357db96d56Sopenharmony_ci                        ["Em-dashes should be written -- thus."])
2367db96d56Sopenharmony_ci
2377db96d56Sopenharmony_ci        # The improperly written em-dash is handled too, because
2387db96d56Sopenharmony_ci        # it's adjacent to non-whitespace on both sides.
2397db96d56Sopenharmony_ci        text = "You can also do--this or even---this."
2407db96d56Sopenharmony_ci        expect = ["You can also do",
2417db96d56Sopenharmony_ci                  "--this or even",
2427db96d56Sopenharmony_ci                  "---this."]
2437db96d56Sopenharmony_ci        self.check_wrap(text, 15, expect)
2447db96d56Sopenharmony_ci        self.check_wrap(text, 16, expect)
2457db96d56Sopenharmony_ci        expect = ["You can also do--",
2467db96d56Sopenharmony_ci                  "this or even---",
2477db96d56Sopenharmony_ci                  "this."]
2487db96d56Sopenharmony_ci        self.check_wrap(text, 17, expect)
2497db96d56Sopenharmony_ci        self.check_wrap(text, 19, expect)
2507db96d56Sopenharmony_ci        expect = ["You can also do--this or even",
2517db96d56Sopenharmony_ci                  "---this."]
2527db96d56Sopenharmony_ci        self.check_wrap(text, 29, expect)
2537db96d56Sopenharmony_ci        self.check_wrap(text, 31, expect)
2547db96d56Sopenharmony_ci        expect = ["You can also do--this or even---",
2557db96d56Sopenharmony_ci                  "this."]
2567db96d56Sopenharmony_ci        self.check_wrap(text, 32, expect)
2577db96d56Sopenharmony_ci        self.check_wrap(text, 35, expect)
2587db96d56Sopenharmony_ci
2597db96d56Sopenharmony_ci        # All of the above behaviour could be deduced by probing the
2607db96d56Sopenharmony_ci        # _split() method.
2617db96d56Sopenharmony_ci        text = "Here's an -- em-dash and--here's another---and another!"
2627db96d56Sopenharmony_ci        expect = ["Here's", " ", "an", " ", "--", " ", "em-", "dash", " ",
2637db96d56Sopenharmony_ci                  "and", "--", "here's", " ", "another", "---",
2647db96d56Sopenharmony_ci                  "and", " ", "another!"]
2657db96d56Sopenharmony_ci        self.check_split(text, expect)
2667db96d56Sopenharmony_ci
2677db96d56Sopenharmony_ci        text = "and then--bam!--he was gone"
2687db96d56Sopenharmony_ci        expect = ["and", " ", "then", "--", "bam!", "--",
2697db96d56Sopenharmony_ci                  "he", " ", "was", " ", "gone"]
2707db96d56Sopenharmony_ci        self.check_split(text, expect)
2717db96d56Sopenharmony_ci
2727db96d56Sopenharmony_ci
2737db96d56Sopenharmony_ci    def test_unix_options (self):
2747db96d56Sopenharmony_ci        # Test that Unix-style command-line options are wrapped correctly.
2757db96d56Sopenharmony_ci        # Both Optik (OptionParser) and Docutils rely on this behaviour!
2767db96d56Sopenharmony_ci
2777db96d56Sopenharmony_ci        text = "You should use the -n option, or --dry-run in its long form."
2787db96d56Sopenharmony_ci        self.check_wrap(text, 20,
2797db96d56Sopenharmony_ci                        ["You should use the",
2807db96d56Sopenharmony_ci                         "-n option, or --dry-",
2817db96d56Sopenharmony_ci                         "run in its long",
2827db96d56Sopenharmony_ci                         "form."])
2837db96d56Sopenharmony_ci        self.check_wrap(text, 21,
2847db96d56Sopenharmony_ci                        ["You should use the -n",
2857db96d56Sopenharmony_ci                         "option, or --dry-run",
2867db96d56Sopenharmony_ci                         "in its long form."])
2877db96d56Sopenharmony_ci        expect = ["You should use the -n option, or",
2887db96d56Sopenharmony_ci                  "--dry-run in its long form."]
2897db96d56Sopenharmony_ci        self.check_wrap(text, 32, expect)
2907db96d56Sopenharmony_ci        self.check_wrap(text, 34, expect)
2917db96d56Sopenharmony_ci        self.check_wrap(text, 35, expect)
2927db96d56Sopenharmony_ci        self.check_wrap(text, 38, expect)
2937db96d56Sopenharmony_ci        expect = ["You should use the -n option, or --dry-",
2947db96d56Sopenharmony_ci                  "run in its long form."]
2957db96d56Sopenharmony_ci        self.check_wrap(text, 39, expect)
2967db96d56Sopenharmony_ci        self.check_wrap(text, 41, expect)
2977db96d56Sopenharmony_ci        expect = ["You should use the -n option, or --dry-run",
2987db96d56Sopenharmony_ci                  "in its long form."]
2997db96d56Sopenharmony_ci        self.check_wrap(text, 42, expect)
3007db96d56Sopenharmony_ci
3017db96d56Sopenharmony_ci        # Again, all of the above can be deduced from _split().
3027db96d56Sopenharmony_ci        text = "the -n option, or --dry-run or --dryrun"
3037db96d56Sopenharmony_ci        expect = ["the", " ", "-n", " ", "option,", " ", "or", " ",
3047db96d56Sopenharmony_ci                  "--dry-", "run", " ", "or", " ", "--dryrun"]
3057db96d56Sopenharmony_ci        self.check_split(text, expect)
3067db96d56Sopenharmony_ci
3077db96d56Sopenharmony_ci    def test_funky_hyphens (self):
3087db96d56Sopenharmony_ci        # Screwy edge cases cooked up by David Goodger.  All reported
3097db96d56Sopenharmony_ci        # in SF bug #596434.
3107db96d56Sopenharmony_ci        self.check_split("what the--hey!", ["what", " ", "the", "--", "hey!"])
3117db96d56Sopenharmony_ci        self.check_split("what the--", ["what", " ", "the--"])
3127db96d56Sopenharmony_ci        self.check_split("what the--.", ["what", " ", "the--."])
3137db96d56Sopenharmony_ci        self.check_split("--text--.", ["--text--."])
3147db96d56Sopenharmony_ci
3157db96d56Sopenharmony_ci        # When I first read bug #596434, this is what I thought David
3167db96d56Sopenharmony_ci        # was talking about.  I was wrong; these have always worked
3177db96d56Sopenharmony_ci        # fine.  The real problem is tested in test_funky_parens()
3187db96d56Sopenharmony_ci        # below...
3197db96d56Sopenharmony_ci        self.check_split("--option", ["--option"])
3207db96d56Sopenharmony_ci        self.check_split("--option-opt", ["--option-", "opt"])
3217db96d56Sopenharmony_ci        self.check_split("foo --option-opt bar",
3227db96d56Sopenharmony_ci                         ["foo", " ", "--option-", "opt", " ", "bar"])
3237db96d56Sopenharmony_ci
3247db96d56Sopenharmony_ci    def test_punct_hyphens(self):
3257db96d56Sopenharmony_ci        # Oh bother, SF #965425 found another problem with hyphens --
3267db96d56Sopenharmony_ci        # hyphenated words in single quotes weren't handled correctly.
3277db96d56Sopenharmony_ci        # In fact, the bug is that *any* punctuation around a hyphenated
3287db96d56Sopenharmony_ci        # word was handled incorrectly, except for a leading "--", which
3297db96d56Sopenharmony_ci        # was special-cased for Optik and Docutils.  So test a variety
3307db96d56Sopenharmony_ci        # of styles of punctuation around a hyphenated word.
3317db96d56Sopenharmony_ci        # (Actually this is based on an Optik bug report, #813077).
3327db96d56Sopenharmony_ci        self.check_split("the 'wibble-wobble' widget",
3337db96d56Sopenharmony_ci                         ['the', ' ', "'wibble-", "wobble'", ' ', 'widget'])
3347db96d56Sopenharmony_ci        self.check_split('the "wibble-wobble" widget',
3357db96d56Sopenharmony_ci                         ['the', ' ', '"wibble-', 'wobble"', ' ', 'widget'])
3367db96d56Sopenharmony_ci        self.check_split("the (wibble-wobble) widget",
3377db96d56Sopenharmony_ci                         ['the', ' ', "(wibble-", "wobble)", ' ', 'widget'])
3387db96d56Sopenharmony_ci        self.check_split("the ['wibble-wobble'] widget",
3397db96d56Sopenharmony_ci                         ['the', ' ', "['wibble-", "wobble']", ' ', 'widget'])
3407db96d56Sopenharmony_ci
3417db96d56Sopenharmony_ci        # The test tests current behavior but is not testing parts of the API.
3427db96d56Sopenharmony_ci        self.check_split("what-d'you-call-it.",
3437db96d56Sopenharmony_ci                         "what-d'you-|call-|it.".split('|'))
3447db96d56Sopenharmony_ci
3457db96d56Sopenharmony_ci    def test_funky_parens (self):
3467db96d56Sopenharmony_ci        # Second part of SF bug #596434: long option strings inside
3477db96d56Sopenharmony_ci        # parentheses.
3487db96d56Sopenharmony_ci        self.check_split("foo (--option) bar",
3497db96d56Sopenharmony_ci                         ["foo", " ", "(--option)", " ", "bar"])
3507db96d56Sopenharmony_ci
3517db96d56Sopenharmony_ci        # Related stuff -- make sure parens work in simpler contexts.
3527db96d56Sopenharmony_ci        self.check_split("foo (bar) baz",
3537db96d56Sopenharmony_ci                         ["foo", " ", "(bar)", " ", "baz"])
3547db96d56Sopenharmony_ci        self.check_split("blah (ding dong), wubba",
3557db96d56Sopenharmony_ci                         ["blah", " ", "(ding", " ", "dong),",
3567db96d56Sopenharmony_ci                          " ", "wubba"])
3577db96d56Sopenharmony_ci
3587db96d56Sopenharmony_ci    def test_drop_whitespace_false(self):
3597db96d56Sopenharmony_ci        # Check that drop_whitespace=False preserves whitespace.
3607db96d56Sopenharmony_ci        # SF patch #1581073
3617db96d56Sopenharmony_ci        text = " This is a    sentence with     much whitespace."
3627db96d56Sopenharmony_ci        self.check_wrap(text, 10,
3637db96d56Sopenharmony_ci                        [" This is a", "    ", "sentence ",
3647db96d56Sopenharmony_ci                         "with     ", "much white", "space."],
3657db96d56Sopenharmony_ci                        drop_whitespace=False)
3667db96d56Sopenharmony_ci
3677db96d56Sopenharmony_ci    def test_drop_whitespace_false_whitespace_only(self):
3687db96d56Sopenharmony_ci        # Check that drop_whitespace=False preserves a whitespace-only string.
3697db96d56Sopenharmony_ci        self.check_wrap("   ", 6, ["   "], drop_whitespace=False)
3707db96d56Sopenharmony_ci
3717db96d56Sopenharmony_ci    def test_drop_whitespace_false_whitespace_only_with_indent(self):
3727db96d56Sopenharmony_ci        # Check that a whitespace-only string gets indented (when
3737db96d56Sopenharmony_ci        # drop_whitespace is False).
3747db96d56Sopenharmony_ci        self.check_wrap("   ", 6, ["     "], drop_whitespace=False,
3757db96d56Sopenharmony_ci                        initial_indent="  ")
3767db96d56Sopenharmony_ci
3777db96d56Sopenharmony_ci    def test_drop_whitespace_whitespace_only(self):
3787db96d56Sopenharmony_ci        # Check drop_whitespace on a whitespace-only string.
3797db96d56Sopenharmony_ci        self.check_wrap("  ", 6, [])
3807db96d56Sopenharmony_ci
3817db96d56Sopenharmony_ci    def test_drop_whitespace_leading_whitespace(self):
3827db96d56Sopenharmony_ci        # Check that drop_whitespace does not drop leading whitespace (if
3837db96d56Sopenharmony_ci        # followed by non-whitespace).
3847db96d56Sopenharmony_ci        # SF bug #622849 reported inconsistent handling of leading
3857db96d56Sopenharmony_ci        # whitespace; let's test that a bit, shall we?
3867db96d56Sopenharmony_ci        text = " This is a sentence with leading whitespace."
3877db96d56Sopenharmony_ci        self.check_wrap(text, 50,
3887db96d56Sopenharmony_ci                        [" This is a sentence with leading whitespace."])
3897db96d56Sopenharmony_ci        self.check_wrap(text, 30,
3907db96d56Sopenharmony_ci                        [" This is a sentence with", "leading whitespace."])
3917db96d56Sopenharmony_ci
3927db96d56Sopenharmony_ci    def test_drop_whitespace_whitespace_line(self):
3937db96d56Sopenharmony_ci        # Check that drop_whitespace skips the whole line if a non-leading
3947db96d56Sopenharmony_ci        # line consists only of whitespace.
3957db96d56Sopenharmony_ci        text = "abcd    efgh"
3967db96d56Sopenharmony_ci        # Include the result for drop_whitespace=False for comparison.
3977db96d56Sopenharmony_ci        self.check_wrap(text, 6, ["abcd", "    ", "efgh"],
3987db96d56Sopenharmony_ci                        drop_whitespace=False)
3997db96d56Sopenharmony_ci        self.check_wrap(text, 6, ["abcd", "efgh"])
4007db96d56Sopenharmony_ci
4017db96d56Sopenharmony_ci    def test_drop_whitespace_whitespace_only_with_indent(self):
4027db96d56Sopenharmony_ci        # Check that initial_indent is not applied to a whitespace-only
4037db96d56Sopenharmony_ci        # string.  This checks a special case of the fact that dropping
4047db96d56Sopenharmony_ci        # whitespace occurs before indenting.
4057db96d56Sopenharmony_ci        self.check_wrap("  ", 6, [], initial_indent="++")
4067db96d56Sopenharmony_ci
4077db96d56Sopenharmony_ci    def test_drop_whitespace_whitespace_indent(self):
4087db96d56Sopenharmony_ci        # Check that drop_whitespace does not drop whitespace indents.
4097db96d56Sopenharmony_ci        # This checks a special case of the fact that dropping whitespace
4107db96d56Sopenharmony_ci        # occurs before indenting.
4117db96d56Sopenharmony_ci        self.check_wrap("abcd efgh", 6, ["  abcd", "  efgh"],
4127db96d56Sopenharmony_ci                        initial_indent="  ", subsequent_indent="  ")
4137db96d56Sopenharmony_ci
4147db96d56Sopenharmony_ci    def test_split(self):
4157db96d56Sopenharmony_ci        # Ensure that the standard _split() method works as advertised
4167db96d56Sopenharmony_ci        # in the comments
4177db96d56Sopenharmony_ci
4187db96d56Sopenharmony_ci        text = "Hello there -- you goof-ball, use the -b option!"
4197db96d56Sopenharmony_ci
4207db96d56Sopenharmony_ci        result = self.wrapper._split(text)
4217db96d56Sopenharmony_ci        self.check(result,
4227db96d56Sopenharmony_ci             ["Hello", " ", "there", " ", "--", " ", "you", " ", "goof-",
4237db96d56Sopenharmony_ci              "ball,", " ", "use", " ", "the", " ", "-b", " ",  "option!"])
4247db96d56Sopenharmony_ci
4257db96d56Sopenharmony_ci    def test_break_on_hyphens(self):
4267db96d56Sopenharmony_ci        # Ensure that the break_on_hyphens attributes work
4277db96d56Sopenharmony_ci        text = "yaba daba-doo"
4287db96d56Sopenharmony_ci        self.check_wrap(text, 10, ["yaba daba-", "doo"],
4297db96d56Sopenharmony_ci                        break_on_hyphens=True)
4307db96d56Sopenharmony_ci        self.check_wrap(text, 10, ["yaba", "daba-doo"],
4317db96d56Sopenharmony_ci                        break_on_hyphens=False)
4327db96d56Sopenharmony_ci
4337db96d56Sopenharmony_ci    def test_bad_width(self):
4347db96d56Sopenharmony_ci        # Ensure that width <= 0 is caught.
4357db96d56Sopenharmony_ci        text = "Whatever, it doesn't matter."
4367db96d56Sopenharmony_ci        self.assertRaises(ValueError, wrap, text, 0)
4377db96d56Sopenharmony_ci        self.assertRaises(ValueError, wrap, text, -1)
4387db96d56Sopenharmony_ci
4397db96d56Sopenharmony_ci    def test_no_split_at_umlaut(self):
4407db96d56Sopenharmony_ci        text = "Die Empf\xe4nger-Auswahl"
4417db96d56Sopenharmony_ci        self.check_wrap(text, 13, ["Die", "Empf\xe4nger-", "Auswahl"])
4427db96d56Sopenharmony_ci
4437db96d56Sopenharmony_ci    def test_umlaut_followed_by_dash(self):
4447db96d56Sopenharmony_ci        text = "aa \xe4\xe4-\xe4\xe4"
4457db96d56Sopenharmony_ci        self.check_wrap(text, 7, ["aa \xe4\xe4-", "\xe4\xe4"])
4467db96d56Sopenharmony_ci
4477db96d56Sopenharmony_ci    def test_non_breaking_space(self):
4487db96d56Sopenharmony_ci        text = 'This is a sentence with non-breaking\N{NO-BREAK SPACE}space.'
4497db96d56Sopenharmony_ci
4507db96d56Sopenharmony_ci        self.check_wrap(text, 20,
4517db96d56Sopenharmony_ci                        ['This is a sentence',
4527db96d56Sopenharmony_ci                         'with non-',
4537db96d56Sopenharmony_ci                         'breaking\N{NO-BREAK SPACE}space.'],
4547db96d56Sopenharmony_ci                        break_on_hyphens=True)
4557db96d56Sopenharmony_ci
4567db96d56Sopenharmony_ci        self.check_wrap(text, 20,
4577db96d56Sopenharmony_ci                        ['This is a sentence',
4587db96d56Sopenharmony_ci                         'with',
4597db96d56Sopenharmony_ci                         'non-breaking\N{NO-BREAK SPACE}space.'],
4607db96d56Sopenharmony_ci                        break_on_hyphens=False)
4617db96d56Sopenharmony_ci
4627db96d56Sopenharmony_ci    def test_narrow_non_breaking_space(self):
4637db96d56Sopenharmony_ci        text = ('This is a sentence with non-breaking'
4647db96d56Sopenharmony_ci                '\N{NARROW NO-BREAK SPACE}space.')
4657db96d56Sopenharmony_ci
4667db96d56Sopenharmony_ci        self.check_wrap(text, 20,
4677db96d56Sopenharmony_ci                        ['This is a sentence',
4687db96d56Sopenharmony_ci                         'with non-',
4697db96d56Sopenharmony_ci                         'breaking\N{NARROW NO-BREAK SPACE}space.'],
4707db96d56Sopenharmony_ci                        break_on_hyphens=True)
4717db96d56Sopenharmony_ci
4727db96d56Sopenharmony_ci        self.check_wrap(text, 20,
4737db96d56Sopenharmony_ci                        ['This is a sentence',
4747db96d56Sopenharmony_ci                         'with',
4757db96d56Sopenharmony_ci                         'non-breaking\N{NARROW NO-BREAK SPACE}space.'],
4767db96d56Sopenharmony_ci                        break_on_hyphens=False)
4777db96d56Sopenharmony_ci
4787db96d56Sopenharmony_ci
4797db96d56Sopenharmony_ciclass MaxLinesTestCase(BaseTestCase):
4807db96d56Sopenharmony_ci    text = "Hello there, how are you this fine day?  I'm glad to hear it!"
4817db96d56Sopenharmony_ci
4827db96d56Sopenharmony_ci    def test_simple(self):
4837db96d56Sopenharmony_ci        self.check_wrap(self.text, 12,
4847db96d56Sopenharmony_ci                        ["Hello [...]"],
4857db96d56Sopenharmony_ci                        max_lines=0)
4867db96d56Sopenharmony_ci        self.check_wrap(self.text, 12,
4877db96d56Sopenharmony_ci                        ["Hello [...]"],
4887db96d56Sopenharmony_ci                        max_lines=1)
4897db96d56Sopenharmony_ci        self.check_wrap(self.text, 12,
4907db96d56Sopenharmony_ci                        ["Hello there,",
4917db96d56Sopenharmony_ci                         "how [...]"],
4927db96d56Sopenharmony_ci                        max_lines=2)
4937db96d56Sopenharmony_ci        self.check_wrap(self.text, 13,
4947db96d56Sopenharmony_ci                        ["Hello there,",
4957db96d56Sopenharmony_ci                         "how are [...]"],
4967db96d56Sopenharmony_ci                        max_lines=2)
4977db96d56Sopenharmony_ci        self.check_wrap(self.text, 80, [self.text], max_lines=1)
4987db96d56Sopenharmony_ci        self.check_wrap(self.text, 12,
4997db96d56Sopenharmony_ci                        ["Hello there,",
5007db96d56Sopenharmony_ci                         "how are you",
5017db96d56Sopenharmony_ci                         "this fine",
5027db96d56Sopenharmony_ci                         "day?  I'm",
5037db96d56Sopenharmony_ci                         "glad to hear",
5047db96d56Sopenharmony_ci                         "it!"],
5057db96d56Sopenharmony_ci                        max_lines=6)
5067db96d56Sopenharmony_ci
5077db96d56Sopenharmony_ci    def test_spaces(self):
5087db96d56Sopenharmony_ci        # strip spaces before placeholder
5097db96d56Sopenharmony_ci        self.check_wrap(self.text, 12,
5107db96d56Sopenharmony_ci                        ["Hello there,",
5117db96d56Sopenharmony_ci                         "how are you",
5127db96d56Sopenharmony_ci                         "this fine",
5137db96d56Sopenharmony_ci                         "day? [...]"],
5147db96d56Sopenharmony_ci                        max_lines=4)
5157db96d56Sopenharmony_ci        # placeholder at the start of line
5167db96d56Sopenharmony_ci        self.check_wrap(self.text, 6,
5177db96d56Sopenharmony_ci                        ["Hello",
5187db96d56Sopenharmony_ci                         "[...]"],
5197db96d56Sopenharmony_ci                        max_lines=2)
5207db96d56Sopenharmony_ci        # final spaces
5217db96d56Sopenharmony_ci        self.check_wrap(self.text + ' ' * 10, 12,
5227db96d56Sopenharmony_ci                        ["Hello there,",
5237db96d56Sopenharmony_ci                         "how are you",
5247db96d56Sopenharmony_ci                         "this fine",
5257db96d56Sopenharmony_ci                         "day?  I'm",
5267db96d56Sopenharmony_ci                         "glad to hear",
5277db96d56Sopenharmony_ci                         "it!"],
5287db96d56Sopenharmony_ci                        max_lines=6)
5297db96d56Sopenharmony_ci
5307db96d56Sopenharmony_ci    def test_placeholder(self):
5317db96d56Sopenharmony_ci        self.check_wrap(self.text, 12,
5327db96d56Sopenharmony_ci                        ["Hello..."],
5337db96d56Sopenharmony_ci                        max_lines=1,
5347db96d56Sopenharmony_ci                        placeholder='...')
5357db96d56Sopenharmony_ci        self.check_wrap(self.text, 12,
5367db96d56Sopenharmony_ci                        ["Hello there,",
5377db96d56Sopenharmony_ci                         "how are..."],
5387db96d56Sopenharmony_ci                        max_lines=2,
5397db96d56Sopenharmony_ci                        placeholder='...')
5407db96d56Sopenharmony_ci        # long placeholder and indentation
5417db96d56Sopenharmony_ci        with self.assertRaises(ValueError):
5427db96d56Sopenharmony_ci            wrap(self.text, 16, initial_indent='    ',
5437db96d56Sopenharmony_ci                 max_lines=1, placeholder=' [truncated]...')
5447db96d56Sopenharmony_ci        with self.assertRaises(ValueError):
5457db96d56Sopenharmony_ci            wrap(self.text, 16, subsequent_indent='    ',
5467db96d56Sopenharmony_ci                 max_lines=2, placeholder=' [truncated]...')
5477db96d56Sopenharmony_ci        self.check_wrap(self.text, 16,
5487db96d56Sopenharmony_ci                        ["    Hello there,",
5497db96d56Sopenharmony_ci                         "  [truncated]..."],
5507db96d56Sopenharmony_ci                        max_lines=2,
5517db96d56Sopenharmony_ci                        initial_indent='    ',
5527db96d56Sopenharmony_ci                        subsequent_indent='  ',
5537db96d56Sopenharmony_ci                        placeholder=' [truncated]...')
5547db96d56Sopenharmony_ci        self.check_wrap(self.text, 16,
5557db96d56Sopenharmony_ci                        ["  [truncated]..."],
5567db96d56Sopenharmony_ci                        max_lines=1,
5577db96d56Sopenharmony_ci                        initial_indent='  ',
5587db96d56Sopenharmony_ci                        subsequent_indent='    ',
5597db96d56Sopenharmony_ci                        placeholder=' [truncated]...')
5607db96d56Sopenharmony_ci        self.check_wrap(self.text, 80, [self.text], placeholder='.' * 1000)
5617db96d56Sopenharmony_ci
5627db96d56Sopenharmony_ci    def test_placeholder_backtrack(self):
5637db96d56Sopenharmony_ci        # Test special case when max_lines insufficient, but what
5647db96d56Sopenharmony_ci        # would be last wrapped line so long the placeholder cannot
5657db96d56Sopenharmony_ci        # be added there without violence. So, textwrap backtracks,
5667db96d56Sopenharmony_ci        # adding placeholder to the penultimate line.
5677db96d56Sopenharmony_ci        text = 'Good grief Python features are advancing quickly!'
5687db96d56Sopenharmony_ci        self.check_wrap(text, 12,
5697db96d56Sopenharmony_ci                        ['Good grief', 'Python*****'],
5707db96d56Sopenharmony_ci                        max_lines=3,
5717db96d56Sopenharmony_ci                        placeholder='*****')
5727db96d56Sopenharmony_ci
5737db96d56Sopenharmony_ci
5747db96d56Sopenharmony_ciclass LongWordTestCase (BaseTestCase):
5757db96d56Sopenharmony_ci    def setUp(self):
5767db96d56Sopenharmony_ci        self.wrapper = TextWrapper()
5777db96d56Sopenharmony_ci        self.text = '''\
5787db96d56Sopenharmony_ciDid you say "supercalifragilisticexpialidocious?"
5797db96d56Sopenharmony_ciHow *do* you spell that odd word, anyways?
5807db96d56Sopenharmony_ci'''
5817db96d56Sopenharmony_ci
5827db96d56Sopenharmony_ci    def test_break_long(self):
5837db96d56Sopenharmony_ci        # Wrap text with long words and lots of punctuation
5847db96d56Sopenharmony_ci
5857db96d56Sopenharmony_ci        self.check_wrap(self.text, 30,
5867db96d56Sopenharmony_ci                        ['Did you say "supercalifragilis',
5877db96d56Sopenharmony_ci                         'ticexpialidocious?" How *do*',
5887db96d56Sopenharmony_ci                         'you spell that odd word,',
5897db96d56Sopenharmony_ci                         'anyways?'])
5907db96d56Sopenharmony_ci        self.check_wrap(self.text, 50,
5917db96d56Sopenharmony_ci                        ['Did you say "supercalifragilisticexpialidocious?"',
5927db96d56Sopenharmony_ci                         'How *do* you spell that odd word, anyways?'])
5937db96d56Sopenharmony_ci
5947db96d56Sopenharmony_ci        # SF bug 797650.  Prevent an infinite loop by making sure that at
5957db96d56Sopenharmony_ci        # least one character gets split off on every pass.
5967db96d56Sopenharmony_ci        self.check_wrap('-'*10+'hello', 10,
5977db96d56Sopenharmony_ci                        ['----------',
5987db96d56Sopenharmony_ci                         '               h',
5997db96d56Sopenharmony_ci                         '               e',
6007db96d56Sopenharmony_ci                         '               l',
6017db96d56Sopenharmony_ci                         '               l',
6027db96d56Sopenharmony_ci                         '               o'],
6037db96d56Sopenharmony_ci                        subsequent_indent = ' '*15)
6047db96d56Sopenharmony_ci
6057db96d56Sopenharmony_ci        # bug 1146.  Prevent a long word to be wrongly wrapped when the
6067db96d56Sopenharmony_ci        # preceding word is exactly one character shorter than the width
6077db96d56Sopenharmony_ci        self.check_wrap(self.text, 12,
6087db96d56Sopenharmony_ci                        ['Did you say ',
6097db96d56Sopenharmony_ci                         '"supercalifr',
6107db96d56Sopenharmony_ci                         'agilisticexp',
6117db96d56Sopenharmony_ci                         'ialidocious?',
6127db96d56Sopenharmony_ci                         '" How *do*',
6137db96d56Sopenharmony_ci                         'you spell',
6147db96d56Sopenharmony_ci                         'that odd',
6157db96d56Sopenharmony_ci                         'word,',
6167db96d56Sopenharmony_ci                         'anyways?'])
6177db96d56Sopenharmony_ci
6187db96d56Sopenharmony_ci    def test_nobreak_long(self):
6197db96d56Sopenharmony_ci        # Test with break_long_words disabled
6207db96d56Sopenharmony_ci        self.wrapper.break_long_words = 0
6217db96d56Sopenharmony_ci        self.wrapper.width = 30
6227db96d56Sopenharmony_ci        expect = ['Did you say',
6237db96d56Sopenharmony_ci                  '"supercalifragilisticexpialidocious?"',
6247db96d56Sopenharmony_ci                  'How *do* you spell that odd',
6257db96d56Sopenharmony_ci                  'word, anyways?'
6267db96d56Sopenharmony_ci                  ]
6277db96d56Sopenharmony_ci        result = self.wrapper.wrap(self.text)
6287db96d56Sopenharmony_ci        self.check(result, expect)
6297db96d56Sopenharmony_ci
6307db96d56Sopenharmony_ci        # Same thing with kwargs passed to standalone wrap() function.
6317db96d56Sopenharmony_ci        result = wrap(self.text, width=30, break_long_words=0)
6327db96d56Sopenharmony_ci        self.check(result, expect)
6337db96d56Sopenharmony_ci
6347db96d56Sopenharmony_ci    def test_max_lines_long(self):
6357db96d56Sopenharmony_ci        self.check_wrap(self.text, 12,
6367db96d56Sopenharmony_ci                        ['Did you say ',
6377db96d56Sopenharmony_ci                         '"supercalifr',
6387db96d56Sopenharmony_ci                         'agilisticexp',
6397db96d56Sopenharmony_ci                         '[...]'],
6407db96d56Sopenharmony_ci                        max_lines=4)
6417db96d56Sopenharmony_ci
6427db96d56Sopenharmony_ci
6437db96d56Sopenharmony_ciclass LongWordWithHyphensTestCase(BaseTestCase):
6447db96d56Sopenharmony_ci    def setUp(self):
6457db96d56Sopenharmony_ci        self.wrapper = TextWrapper()
6467db96d56Sopenharmony_ci        self.text1 = '''\
6477db96d56Sopenharmony_ciWe used enyzme 2-succinyl-6-hydroxy-2,4-cyclohexadiene-1-carboxylate synthase.
6487db96d56Sopenharmony_ci'''
6497db96d56Sopenharmony_ci        self.text2 = '''\
6507db96d56Sopenharmony_ci1234567890-1234567890--this_is_a_very_long_option_indeed-good-bye"
6517db96d56Sopenharmony_ci'''
6527db96d56Sopenharmony_ci
6537db96d56Sopenharmony_ci    def test_break_long_words_on_hyphen(self):
6547db96d56Sopenharmony_ci        expected = ['We used enyzme 2-succinyl-6-hydroxy-2,4-',
6557db96d56Sopenharmony_ci                    'cyclohexadiene-1-carboxylate synthase.']
6567db96d56Sopenharmony_ci        self.check_wrap(self.text1, 50, expected)
6577db96d56Sopenharmony_ci
6587db96d56Sopenharmony_ci        expected = ['We used', 'enyzme 2-', 'succinyl-', '6-hydroxy-', '2,4-',
6597db96d56Sopenharmony_ci                    'cyclohexad', 'iene-1-', 'carboxylat', 'e', 'synthase.']
6607db96d56Sopenharmony_ci        self.check_wrap(self.text1, 10, expected)
6617db96d56Sopenharmony_ci
6627db96d56Sopenharmony_ci        expected = ['1234567890',  '-123456789', '0--this_is', '_a_very_lo',
6637db96d56Sopenharmony_ci                    'ng_option_', 'indeed-', 'good-bye"']
6647db96d56Sopenharmony_ci        self.check_wrap(self.text2, 10, expected)
6657db96d56Sopenharmony_ci
6667db96d56Sopenharmony_ci    def test_break_long_words_not_on_hyphen(self):
6677db96d56Sopenharmony_ci        expected = ['We used enyzme 2-succinyl-6-hydroxy-2,4-cyclohexad',
6687db96d56Sopenharmony_ci                    'iene-1-carboxylate synthase.']
6697db96d56Sopenharmony_ci        self.check_wrap(self.text1, 50, expected, break_on_hyphens=False)
6707db96d56Sopenharmony_ci
6717db96d56Sopenharmony_ci        expected = ['We used', 'enyzme 2-s', 'uccinyl-6-', 'hydroxy-2,',
6727db96d56Sopenharmony_ci                    '4-cyclohex', 'adiene-1-c', 'arboxylate', 'synthase.']
6737db96d56Sopenharmony_ci        self.check_wrap(self.text1, 10, expected, break_on_hyphens=False)
6747db96d56Sopenharmony_ci
6757db96d56Sopenharmony_ci        expected = ['1234567890',  '-123456789', '0--this_is', '_a_very_lo',
6767db96d56Sopenharmony_ci                    'ng_option_', 'indeed-', 'good-bye"']
6777db96d56Sopenharmony_ci        self.check_wrap(self.text2, 10, expected)
6787db96d56Sopenharmony_ci
6797db96d56Sopenharmony_ci    def test_break_on_hyphen_but_not_long_words(self):
6807db96d56Sopenharmony_ci        expected = ['We used enyzme',
6817db96d56Sopenharmony_ci                    '2-succinyl-6-hydroxy-2,4-cyclohexadiene-1-carboxylate',
6827db96d56Sopenharmony_ci                    'synthase.']
6837db96d56Sopenharmony_ci
6847db96d56Sopenharmony_ci        self.check_wrap(self.text1, 50, expected, break_long_words=False)
6857db96d56Sopenharmony_ci
6867db96d56Sopenharmony_ci        expected = ['We used', 'enyzme',
6877db96d56Sopenharmony_ci                    '2-succinyl-6-hydroxy-2,4-cyclohexadiene-1-carboxylate',
6887db96d56Sopenharmony_ci                    'synthase.']
6897db96d56Sopenharmony_ci        self.check_wrap(self.text1, 10, expected, break_long_words=False)
6907db96d56Sopenharmony_ci
6917db96d56Sopenharmony_ci        expected = ['1234567890',  '-123456789', '0--this_is', '_a_very_lo',
6927db96d56Sopenharmony_ci                    'ng_option_', 'indeed-', 'good-bye"']
6937db96d56Sopenharmony_ci        self.check_wrap(self.text2, 10, expected)
6947db96d56Sopenharmony_ci
6957db96d56Sopenharmony_ci
6967db96d56Sopenharmony_ci    def test_do_not_break_long_words_or_on_hyphens(self):
6977db96d56Sopenharmony_ci        expected = ['We used enyzme',
6987db96d56Sopenharmony_ci                    '2-succinyl-6-hydroxy-2,4-cyclohexadiene-1-carboxylate',
6997db96d56Sopenharmony_ci                    'synthase.']
7007db96d56Sopenharmony_ci        self.check_wrap(self.text1, 50, expected,
7017db96d56Sopenharmony_ci                        break_long_words=False,
7027db96d56Sopenharmony_ci                        break_on_hyphens=False)
7037db96d56Sopenharmony_ci
7047db96d56Sopenharmony_ci        expected = ['We used', 'enyzme',
7057db96d56Sopenharmony_ci                    '2-succinyl-6-hydroxy-2,4-cyclohexadiene-1-carboxylate',
7067db96d56Sopenharmony_ci                    'synthase.']
7077db96d56Sopenharmony_ci        self.check_wrap(self.text1, 10, expected,
7087db96d56Sopenharmony_ci                        break_long_words=False,
7097db96d56Sopenharmony_ci                        break_on_hyphens=False)
7107db96d56Sopenharmony_ci
7117db96d56Sopenharmony_ci        expected = ['1234567890',  '-123456789', '0--this_is', '_a_very_lo',
7127db96d56Sopenharmony_ci                    'ng_option_', 'indeed-', 'good-bye"']
7137db96d56Sopenharmony_ci        self.check_wrap(self.text2, 10, expected)
7147db96d56Sopenharmony_ci
7157db96d56Sopenharmony_ciclass IndentTestCases(BaseTestCase):
7167db96d56Sopenharmony_ci
7177db96d56Sopenharmony_ci    # called before each test method
7187db96d56Sopenharmony_ci    def setUp(self):
7197db96d56Sopenharmony_ci        self.text = '''\
7207db96d56Sopenharmony_ciThis paragraph will be filled, first without any indentation,
7217db96d56Sopenharmony_ciand then with some (including a hanging indent).'''
7227db96d56Sopenharmony_ci
7237db96d56Sopenharmony_ci
7247db96d56Sopenharmony_ci    def test_fill(self):
7257db96d56Sopenharmony_ci        # Test the fill() method
7267db96d56Sopenharmony_ci
7277db96d56Sopenharmony_ci        expect = '''\
7287db96d56Sopenharmony_ciThis paragraph will be filled, first
7297db96d56Sopenharmony_ciwithout any indentation, and then with
7307db96d56Sopenharmony_cisome (including a hanging indent).'''
7317db96d56Sopenharmony_ci
7327db96d56Sopenharmony_ci        result = fill(self.text, 40)
7337db96d56Sopenharmony_ci        self.check(result, expect)
7347db96d56Sopenharmony_ci
7357db96d56Sopenharmony_ci
7367db96d56Sopenharmony_ci    def test_initial_indent(self):
7377db96d56Sopenharmony_ci        # Test initial_indent parameter
7387db96d56Sopenharmony_ci
7397db96d56Sopenharmony_ci        expect = ["     This paragraph will be filled,",
7407db96d56Sopenharmony_ci                  "first without any indentation, and then",
7417db96d56Sopenharmony_ci                  "with some (including a hanging indent)."]
7427db96d56Sopenharmony_ci        result = wrap(self.text, 40, initial_indent="     ")
7437db96d56Sopenharmony_ci        self.check(result, expect)
7447db96d56Sopenharmony_ci
7457db96d56Sopenharmony_ci        expect = "\n".join(expect)
7467db96d56Sopenharmony_ci        result = fill(self.text, 40, initial_indent="     ")
7477db96d56Sopenharmony_ci        self.check(result, expect)
7487db96d56Sopenharmony_ci
7497db96d56Sopenharmony_ci
7507db96d56Sopenharmony_ci    def test_subsequent_indent(self):
7517db96d56Sopenharmony_ci        # Test subsequent_indent parameter
7527db96d56Sopenharmony_ci
7537db96d56Sopenharmony_ci        expect = '''\
7547db96d56Sopenharmony_ci  * This paragraph will be filled, first
7557db96d56Sopenharmony_ci    without any indentation, and then
7567db96d56Sopenharmony_ci    with some (including a hanging
7577db96d56Sopenharmony_ci    indent).'''
7587db96d56Sopenharmony_ci
7597db96d56Sopenharmony_ci        result = fill(self.text, 40,
7607db96d56Sopenharmony_ci                      initial_indent="  * ", subsequent_indent="    ")
7617db96d56Sopenharmony_ci        self.check(result, expect)
7627db96d56Sopenharmony_ci
7637db96d56Sopenharmony_ci
7647db96d56Sopenharmony_ci# Despite the similar names, DedentTestCase is *not* the inverse
7657db96d56Sopenharmony_ci# of IndentTestCase!
7667db96d56Sopenharmony_ciclass DedentTestCase(unittest.TestCase):
7677db96d56Sopenharmony_ci
7687db96d56Sopenharmony_ci    def assertUnchanged(self, text):
7697db96d56Sopenharmony_ci        """assert that dedent() has no effect on 'text'"""
7707db96d56Sopenharmony_ci        self.assertEqual(text, dedent(text))
7717db96d56Sopenharmony_ci
7727db96d56Sopenharmony_ci    def test_dedent_nomargin(self):
7737db96d56Sopenharmony_ci        # No lines indented.
7747db96d56Sopenharmony_ci        text = "Hello there.\nHow are you?\nOh good, I'm glad."
7757db96d56Sopenharmony_ci        self.assertUnchanged(text)
7767db96d56Sopenharmony_ci
7777db96d56Sopenharmony_ci        # Similar, with a blank line.
7787db96d56Sopenharmony_ci        text = "Hello there.\n\nBoo!"
7797db96d56Sopenharmony_ci        self.assertUnchanged(text)
7807db96d56Sopenharmony_ci
7817db96d56Sopenharmony_ci        # Some lines indented, but overall margin is still zero.
7827db96d56Sopenharmony_ci        text = "Hello there.\n  This is indented."
7837db96d56Sopenharmony_ci        self.assertUnchanged(text)
7847db96d56Sopenharmony_ci
7857db96d56Sopenharmony_ci        # Again, add a blank line.
7867db96d56Sopenharmony_ci        text = "Hello there.\n\n  Boo!\n"
7877db96d56Sopenharmony_ci        self.assertUnchanged(text)
7887db96d56Sopenharmony_ci
7897db96d56Sopenharmony_ci    def test_dedent_even(self):
7907db96d56Sopenharmony_ci        # All lines indented by two spaces.
7917db96d56Sopenharmony_ci        text = "  Hello there.\n  How are ya?\n  Oh good."
7927db96d56Sopenharmony_ci        expect = "Hello there.\nHow are ya?\nOh good."
7937db96d56Sopenharmony_ci        self.assertEqual(expect, dedent(text))
7947db96d56Sopenharmony_ci
7957db96d56Sopenharmony_ci        # Same, with blank lines.
7967db96d56Sopenharmony_ci        text = "  Hello there.\n\n  How are ya?\n  Oh good.\n"
7977db96d56Sopenharmony_ci        expect = "Hello there.\n\nHow are ya?\nOh good.\n"
7987db96d56Sopenharmony_ci        self.assertEqual(expect, dedent(text))
7997db96d56Sopenharmony_ci
8007db96d56Sopenharmony_ci        # Now indent one of the blank lines.
8017db96d56Sopenharmony_ci        text = "  Hello there.\n  \n  How are ya?\n  Oh good.\n"
8027db96d56Sopenharmony_ci        expect = "Hello there.\n\nHow are ya?\nOh good.\n"
8037db96d56Sopenharmony_ci        self.assertEqual(expect, dedent(text))
8047db96d56Sopenharmony_ci
8057db96d56Sopenharmony_ci    def test_dedent_uneven(self):
8067db96d56Sopenharmony_ci        # Lines indented unevenly.
8077db96d56Sopenharmony_ci        text = '''\
8087db96d56Sopenharmony_ci        def foo():
8097db96d56Sopenharmony_ci            while 1:
8107db96d56Sopenharmony_ci                return foo
8117db96d56Sopenharmony_ci        '''
8127db96d56Sopenharmony_ci        expect = '''\
8137db96d56Sopenharmony_cidef foo():
8147db96d56Sopenharmony_ci    while 1:
8157db96d56Sopenharmony_ci        return foo
8167db96d56Sopenharmony_ci'''
8177db96d56Sopenharmony_ci        self.assertEqual(expect, dedent(text))
8187db96d56Sopenharmony_ci
8197db96d56Sopenharmony_ci        # Uneven indentation with a blank line.
8207db96d56Sopenharmony_ci        text = "  Foo\n    Bar\n\n   Baz\n"
8217db96d56Sopenharmony_ci        expect = "Foo\n  Bar\n\n Baz\n"
8227db96d56Sopenharmony_ci        self.assertEqual(expect, dedent(text))
8237db96d56Sopenharmony_ci
8247db96d56Sopenharmony_ci        # Uneven indentation with a whitespace-only line.
8257db96d56Sopenharmony_ci        text = "  Foo\n    Bar\n \n   Baz\n"
8267db96d56Sopenharmony_ci        expect = "Foo\n  Bar\n\n Baz\n"
8277db96d56Sopenharmony_ci        self.assertEqual(expect, dedent(text))
8287db96d56Sopenharmony_ci
8297db96d56Sopenharmony_ci    def test_dedent_declining(self):
8307db96d56Sopenharmony_ci        # Uneven indentation with declining indent level.
8317db96d56Sopenharmony_ci        text = "     Foo\n    Bar\n"  # 5 spaces, then 4
8327db96d56Sopenharmony_ci        expect = " Foo\nBar\n"
8337db96d56Sopenharmony_ci        self.assertEqual(expect, dedent(text))
8347db96d56Sopenharmony_ci
8357db96d56Sopenharmony_ci        # Declining indent level with blank line.
8367db96d56Sopenharmony_ci        text = "     Foo\n\n    Bar\n"  # 5 spaces, blank, then 4
8377db96d56Sopenharmony_ci        expect = " Foo\n\nBar\n"
8387db96d56Sopenharmony_ci        self.assertEqual(expect, dedent(text))
8397db96d56Sopenharmony_ci
8407db96d56Sopenharmony_ci        # Declining indent level with whitespace only line.
8417db96d56Sopenharmony_ci        text = "     Foo\n    \n    Bar\n"  # 5 spaces, then 4, then 4
8427db96d56Sopenharmony_ci        expect = " Foo\n\nBar\n"
8437db96d56Sopenharmony_ci        self.assertEqual(expect, dedent(text))
8447db96d56Sopenharmony_ci
8457db96d56Sopenharmony_ci    # dedent() should not mangle internal tabs
8467db96d56Sopenharmony_ci    def test_dedent_preserve_internal_tabs(self):
8477db96d56Sopenharmony_ci        text = "  hello\tthere\n  how are\tyou?"
8487db96d56Sopenharmony_ci        expect = "hello\tthere\nhow are\tyou?"
8497db96d56Sopenharmony_ci        self.assertEqual(expect, dedent(text))
8507db96d56Sopenharmony_ci
8517db96d56Sopenharmony_ci        # make sure that it preserves tabs when it's not making any
8527db96d56Sopenharmony_ci        # changes at all
8537db96d56Sopenharmony_ci        self.assertEqual(expect, dedent(expect))
8547db96d56Sopenharmony_ci
8557db96d56Sopenharmony_ci    # dedent() should not mangle tabs in the margin (i.e.
8567db96d56Sopenharmony_ci    # tabs and spaces both count as margin, but are *not*
8577db96d56Sopenharmony_ci    # considered equivalent)
8587db96d56Sopenharmony_ci    def test_dedent_preserve_margin_tabs(self):
8597db96d56Sopenharmony_ci        text = "  hello there\n\thow are you?"
8607db96d56Sopenharmony_ci        self.assertUnchanged(text)
8617db96d56Sopenharmony_ci
8627db96d56Sopenharmony_ci        # same effect even if we have 8 spaces
8637db96d56Sopenharmony_ci        text = "        hello there\n\thow are you?"
8647db96d56Sopenharmony_ci        self.assertUnchanged(text)
8657db96d56Sopenharmony_ci
8667db96d56Sopenharmony_ci        # dedent() only removes whitespace that can be uniformly removed!
8677db96d56Sopenharmony_ci        text = "\thello there\n\thow are you?"
8687db96d56Sopenharmony_ci        expect = "hello there\nhow are you?"
8697db96d56Sopenharmony_ci        self.assertEqual(expect, dedent(text))
8707db96d56Sopenharmony_ci
8717db96d56Sopenharmony_ci        text = "  \thello there\n  \thow are you?"
8727db96d56Sopenharmony_ci        self.assertEqual(expect, dedent(text))
8737db96d56Sopenharmony_ci
8747db96d56Sopenharmony_ci        text = "  \t  hello there\n  \t  how are you?"
8757db96d56Sopenharmony_ci        self.assertEqual(expect, dedent(text))
8767db96d56Sopenharmony_ci
8777db96d56Sopenharmony_ci        text = "  \thello there\n  \t  how are you?"
8787db96d56Sopenharmony_ci        expect = "hello there\n  how are you?"
8797db96d56Sopenharmony_ci        self.assertEqual(expect, dedent(text))
8807db96d56Sopenharmony_ci
8817db96d56Sopenharmony_ci        # test margin is smaller than smallest indent
8827db96d56Sopenharmony_ci        text = "  \thello there\n   \thow are you?\n \tI'm fine, thanks"
8837db96d56Sopenharmony_ci        expect = " \thello there\n  \thow are you?\n\tI'm fine, thanks"
8847db96d56Sopenharmony_ci        self.assertEqual(expect, dedent(text))
8857db96d56Sopenharmony_ci
8867db96d56Sopenharmony_ci
8877db96d56Sopenharmony_ci# Test textwrap.indent
8887db96d56Sopenharmony_ciclass IndentTestCase(unittest.TestCase):
8897db96d56Sopenharmony_ci    # The examples used for tests. If any of these change, the expected
8907db96d56Sopenharmony_ci    # results in the various test cases must also be updated.
8917db96d56Sopenharmony_ci    # The roundtrip cases are separate, because textwrap.dedent doesn't
8927db96d56Sopenharmony_ci    # handle Windows line endings
8937db96d56Sopenharmony_ci    ROUNDTRIP_CASES = (
8947db96d56Sopenharmony_ci      # Basic test case
8957db96d56Sopenharmony_ci      "Hi.\nThis is a test.\nTesting.",
8967db96d56Sopenharmony_ci      # Include a blank line
8977db96d56Sopenharmony_ci      "Hi.\nThis is a test.\n\nTesting.",
8987db96d56Sopenharmony_ci      # Include leading and trailing blank lines
8997db96d56Sopenharmony_ci      "\nHi.\nThis is a test.\nTesting.\n",
9007db96d56Sopenharmony_ci    )
9017db96d56Sopenharmony_ci    CASES = ROUNDTRIP_CASES + (
9027db96d56Sopenharmony_ci      # Use Windows line endings
9037db96d56Sopenharmony_ci      "Hi.\r\nThis is a test.\r\nTesting.\r\n",
9047db96d56Sopenharmony_ci      # Pathological case
9057db96d56Sopenharmony_ci      "\nHi.\r\nThis is a test.\n\r\nTesting.\r\n\n",
9067db96d56Sopenharmony_ci    )
9077db96d56Sopenharmony_ci
9087db96d56Sopenharmony_ci    def test_indent_nomargin_default(self):
9097db96d56Sopenharmony_ci        # indent should do nothing if 'prefix' is empty.
9107db96d56Sopenharmony_ci        for text in self.CASES:
9117db96d56Sopenharmony_ci            self.assertEqual(indent(text, ''), text)
9127db96d56Sopenharmony_ci
9137db96d56Sopenharmony_ci    def test_indent_nomargin_explicit_default(self):
9147db96d56Sopenharmony_ci        # The same as test_indent_nomargin, but explicitly requesting
9157db96d56Sopenharmony_ci        # the default behaviour by passing None as the predicate
9167db96d56Sopenharmony_ci        for text in self.CASES:
9177db96d56Sopenharmony_ci            self.assertEqual(indent(text, '', None), text)
9187db96d56Sopenharmony_ci
9197db96d56Sopenharmony_ci    def test_indent_nomargin_all_lines(self):
9207db96d56Sopenharmony_ci        # The same as test_indent_nomargin, but using the optional
9217db96d56Sopenharmony_ci        # predicate argument
9227db96d56Sopenharmony_ci        predicate = lambda line: True
9237db96d56Sopenharmony_ci        for text in self.CASES:
9247db96d56Sopenharmony_ci            self.assertEqual(indent(text, '', predicate), text)
9257db96d56Sopenharmony_ci
9267db96d56Sopenharmony_ci    def test_indent_no_lines(self):
9277db96d56Sopenharmony_ci        # Explicitly skip indenting any lines
9287db96d56Sopenharmony_ci        predicate = lambda line: False
9297db96d56Sopenharmony_ci        for text in self.CASES:
9307db96d56Sopenharmony_ci            self.assertEqual(indent(text, '    ', predicate), text)
9317db96d56Sopenharmony_ci
9327db96d56Sopenharmony_ci    def test_roundtrip_spaces(self):
9337db96d56Sopenharmony_ci        # A whitespace prefix should roundtrip with dedent
9347db96d56Sopenharmony_ci        for text in self.ROUNDTRIP_CASES:
9357db96d56Sopenharmony_ci            self.assertEqual(dedent(indent(text, '    ')), text)
9367db96d56Sopenharmony_ci
9377db96d56Sopenharmony_ci    def test_roundtrip_tabs(self):
9387db96d56Sopenharmony_ci        # A whitespace prefix should roundtrip with dedent
9397db96d56Sopenharmony_ci        for text in self.ROUNDTRIP_CASES:
9407db96d56Sopenharmony_ci            self.assertEqual(dedent(indent(text, '\t\t')), text)
9417db96d56Sopenharmony_ci
9427db96d56Sopenharmony_ci    def test_roundtrip_mixed(self):
9437db96d56Sopenharmony_ci        # A whitespace prefix should roundtrip with dedent
9447db96d56Sopenharmony_ci        for text in self.ROUNDTRIP_CASES:
9457db96d56Sopenharmony_ci            self.assertEqual(dedent(indent(text, ' \t  \t ')), text)
9467db96d56Sopenharmony_ci
9477db96d56Sopenharmony_ci    def test_indent_default(self):
9487db96d56Sopenharmony_ci        # Test default indenting of lines that are not whitespace only
9497db96d56Sopenharmony_ci        prefix = '  '
9507db96d56Sopenharmony_ci        expected = (
9517db96d56Sopenharmony_ci          # Basic test case
9527db96d56Sopenharmony_ci          "  Hi.\n  This is a test.\n  Testing.",
9537db96d56Sopenharmony_ci          # Include a blank line
9547db96d56Sopenharmony_ci          "  Hi.\n  This is a test.\n\n  Testing.",
9557db96d56Sopenharmony_ci          # Include leading and trailing blank lines
9567db96d56Sopenharmony_ci          "\n  Hi.\n  This is a test.\n  Testing.\n",
9577db96d56Sopenharmony_ci          # Use Windows line endings
9587db96d56Sopenharmony_ci          "  Hi.\r\n  This is a test.\r\n  Testing.\r\n",
9597db96d56Sopenharmony_ci          # Pathological case
9607db96d56Sopenharmony_ci          "\n  Hi.\r\n  This is a test.\n\r\n  Testing.\r\n\n",
9617db96d56Sopenharmony_ci        )
9627db96d56Sopenharmony_ci        for text, expect in zip(self.CASES, expected):
9637db96d56Sopenharmony_ci            self.assertEqual(indent(text, prefix), expect)
9647db96d56Sopenharmony_ci
9657db96d56Sopenharmony_ci    def test_indent_explicit_default(self):
9667db96d56Sopenharmony_ci        # Test default indenting of lines that are not whitespace only
9677db96d56Sopenharmony_ci        prefix = '  '
9687db96d56Sopenharmony_ci        expected = (
9697db96d56Sopenharmony_ci          # Basic test case
9707db96d56Sopenharmony_ci          "  Hi.\n  This is a test.\n  Testing.",
9717db96d56Sopenharmony_ci          # Include a blank line
9727db96d56Sopenharmony_ci          "  Hi.\n  This is a test.\n\n  Testing.",
9737db96d56Sopenharmony_ci          # Include leading and trailing blank lines
9747db96d56Sopenharmony_ci          "\n  Hi.\n  This is a test.\n  Testing.\n",
9757db96d56Sopenharmony_ci          # Use Windows line endings
9767db96d56Sopenharmony_ci          "  Hi.\r\n  This is a test.\r\n  Testing.\r\n",
9777db96d56Sopenharmony_ci          # Pathological case
9787db96d56Sopenharmony_ci          "\n  Hi.\r\n  This is a test.\n\r\n  Testing.\r\n\n",
9797db96d56Sopenharmony_ci        )
9807db96d56Sopenharmony_ci        for text, expect in zip(self.CASES, expected):
9817db96d56Sopenharmony_ci            self.assertEqual(indent(text, prefix, None), expect)
9827db96d56Sopenharmony_ci
9837db96d56Sopenharmony_ci    def test_indent_all_lines(self):
9847db96d56Sopenharmony_ci        # Add 'prefix' to all lines, including whitespace-only ones.
9857db96d56Sopenharmony_ci        prefix = '  '
9867db96d56Sopenharmony_ci        expected = (
9877db96d56Sopenharmony_ci          # Basic test case
9887db96d56Sopenharmony_ci          "  Hi.\n  This is a test.\n  Testing.",
9897db96d56Sopenharmony_ci          # Include a blank line
9907db96d56Sopenharmony_ci          "  Hi.\n  This is a test.\n  \n  Testing.",
9917db96d56Sopenharmony_ci          # Include leading and trailing blank lines
9927db96d56Sopenharmony_ci          "  \n  Hi.\n  This is a test.\n  Testing.\n",
9937db96d56Sopenharmony_ci          # Use Windows line endings
9947db96d56Sopenharmony_ci          "  Hi.\r\n  This is a test.\r\n  Testing.\r\n",
9957db96d56Sopenharmony_ci          # Pathological case
9967db96d56Sopenharmony_ci          "  \n  Hi.\r\n  This is a test.\n  \r\n  Testing.\r\n  \n",
9977db96d56Sopenharmony_ci        )
9987db96d56Sopenharmony_ci        predicate = lambda line: True
9997db96d56Sopenharmony_ci        for text, expect in zip(self.CASES, expected):
10007db96d56Sopenharmony_ci            self.assertEqual(indent(text, prefix, predicate), expect)
10017db96d56Sopenharmony_ci
10027db96d56Sopenharmony_ci    def test_indent_empty_lines(self):
10037db96d56Sopenharmony_ci        # Add 'prefix' solely to whitespace-only lines.
10047db96d56Sopenharmony_ci        prefix = '  '
10057db96d56Sopenharmony_ci        expected = (
10067db96d56Sopenharmony_ci          # Basic test case
10077db96d56Sopenharmony_ci          "Hi.\nThis is a test.\nTesting.",
10087db96d56Sopenharmony_ci          # Include a blank line
10097db96d56Sopenharmony_ci          "Hi.\nThis is a test.\n  \nTesting.",
10107db96d56Sopenharmony_ci          # Include leading and trailing blank lines
10117db96d56Sopenharmony_ci          "  \nHi.\nThis is a test.\nTesting.\n",
10127db96d56Sopenharmony_ci          # Use Windows line endings
10137db96d56Sopenharmony_ci          "Hi.\r\nThis is a test.\r\nTesting.\r\n",
10147db96d56Sopenharmony_ci          # Pathological case
10157db96d56Sopenharmony_ci          "  \nHi.\r\nThis is a test.\n  \r\nTesting.\r\n  \n",
10167db96d56Sopenharmony_ci        )
10177db96d56Sopenharmony_ci        predicate = lambda line: not line.strip()
10187db96d56Sopenharmony_ci        for text, expect in zip(self.CASES, expected):
10197db96d56Sopenharmony_ci            self.assertEqual(indent(text, prefix, predicate), expect)
10207db96d56Sopenharmony_ci
10217db96d56Sopenharmony_ci
10227db96d56Sopenharmony_ciclass ShortenTestCase(BaseTestCase):
10237db96d56Sopenharmony_ci
10247db96d56Sopenharmony_ci    def check_shorten(self, text, width, expect, **kwargs):
10257db96d56Sopenharmony_ci        result = shorten(text, width, **kwargs)
10267db96d56Sopenharmony_ci        self.check(result, expect)
10277db96d56Sopenharmony_ci
10287db96d56Sopenharmony_ci    def test_simple(self):
10297db96d56Sopenharmony_ci        # Simple case: just words, spaces, and a bit of punctuation
10307db96d56Sopenharmony_ci        text = "Hello there, how are you this fine day? I'm glad to hear it!"
10317db96d56Sopenharmony_ci
10327db96d56Sopenharmony_ci        self.check_shorten(text, 18, "Hello there, [...]")
10337db96d56Sopenharmony_ci        self.check_shorten(text, len(text), text)
10347db96d56Sopenharmony_ci        self.check_shorten(text, len(text) - 1,
10357db96d56Sopenharmony_ci            "Hello there, how are you this fine day? "
10367db96d56Sopenharmony_ci            "I'm glad to [...]")
10377db96d56Sopenharmony_ci
10387db96d56Sopenharmony_ci    def test_placeholder(self):
10397db96d56Sopenharmony_ci        text = "Hello there, how are you this fine day? I'm glad to hear it!"
10407db96d56Sopenharmony_ci
10417db96d56Sopenharmony_ci        self.check_shorten(text, 17, "Hello there,$$", placeholder='$$')
10427db96d56Sopenharmony_ci        self.check_shorten(text, 18, "Hello there, how$$", placeholder='$$')
10437db96d56Sopenharmony_ci        self.check_shorten(text, 18, "Hello there, $$", placeholder=' $$')
10447db96d56Sopenharmony_ci        self.check_shorten(text, len(text), text, placeholder='$$')
10457db96d56Sopenharmony_ci        self.check_shorten(text, len(text) - 1,
10467db96d56Sopenharmony_ci            "Hello there, how are you this fine day? "
10477db96d56Sopenharmony_ci            "I'm glad to hear$$", placeholder='$$')
10487db96d56Sopenharmony_ci
10497db96d56Sopenharmony_ci    def test_empty_string(self):
10507db96d56Sopenharmony_ci        self.check_shorten("", 6, "")
10517db96d56Sopenharmony_ci
10527db96d56Sopenharmony_ci    def test_whitespace(self):
10537db96d56Sopenharmony_ci        # Whitespace collapsing
10547db96d56Sopenharmony_ci        text = """
10557db96d56Sopenharmony_ci            This is a  paragraph that  already has
10567db96d56Sopenharmony_ci            line breaks and \t tabs too."""
10577db96d56Sopenharmony_ci        self.check_shorten(text, 62,
10587db96d56Sopenharmony_ci                             "This is a paragraph that already has line "
10597db96d56Sopenharmony_ci                             "breaks and tabs too.")
10607db96d56Sopenharmony_ci        self.check_shorten(text, 61,
10617db96d56Sopenharmony_ci                             "This is a paragraph that already has line "
10627db96d56Sopenharmony_ci                             "breaks and [...]")
10637db96d56Sopenharmony_ci
10647db96d56Sopenharmony_ci        self.check_shorten("hello      world!  ", 12, "hello world!")
10657db96d56Sopenharmony_ci        self.check_shorten("hello      world!  ", 11, "hello [...]")
10667db96d56Sopenharmony_ci        # The leading space is trimmed from the placeholder
10677db96d56Sopenharmony_ci        # (it would be ugly otherwise).
10687db96d56Sopenharmony_ci        self.check_shorten("hello      world!  ", 10, "[...]")
10697db96d56Sopenharmony_ci
10707db96d56Sopenharmony_ci    def test_width_too_small_for_placeholder(self):
10717db96d56Sopenharmony_ci        shorten("x" * 20, width=8, placeholder="(......)")
10727db96d56Sopenharmony_ci        with self.assertRaises(ValueError):
10737db96d56Sopenharmony_ci            shorten("x" * 20, width=8, placeholder="(.......)")
10747db96d56Sopenharmony_ci
10757db96d56Sopenharmony_ci    def test_first_word_too_long_but_placeholder_fits(self):
10767db96d56Sopenharmony_ci        self.check_shorten("Helloo", 5, "[...]")
10777db96d56Sopenharmony_ci
10787db96d56Sopenharmony_ci
10797db96d56Sopenharmony_ciif __name__ == '__main__':
10807db96d56Sopenharmony_ci    unittest.main()
1081