diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2014-01-09 21:18:41 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2014-01-09 21:18:41 (GMT) |
commit | 123e6d5b4b17e182cfa49b0913bfc0b77ecb2585 (patch) | |
tree | b172af053a1970f2530d1771f81b97b1430d4d5d /Lib | |
parent | ba44860c118f375c81db1f82ac4714992a37a22e (diff) | |
parent | f451112413b9ea8940c8c3a902cddf701c62d17f (diff) | |
download | cpython-123e6d5b4b17e182cfa49b0913bfc0b77ecb2585.zip cpython-123e6d5b4b17e182cfa49b0913bfc0b77ecb2585.tar.gz cpython-123e6d5b4b17e182cfa49b0913bfc0b77ecb2585.tar.bz2 |
Issue #13107: argparse and optparse no longer raises an exception when output
a help on environment with too small COLUMNS. Based on patch by
Elazar Gershuni.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/argparse.py | 8 | ||||
-rw-r--r-- | Lib/optparse.py | 7 | ||||
-rw-r--r-- | Lib/test/test_argparse.py | 54 | ||||
-rw-r--r-- | Lib/test/test_optparse.py | 35 |
4 files changed, 98 insertions, 6 deletions
diff --git a/Lib/argparse.py b/Lib/argparse.py index 9520e0e..5ad7e13 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -165,6 +165,8 @@ class HelpFormatter(object): self._prog = prog self._indent_increment = indent_increment self._max_help_position = max_help_position + self._max_help_position = min(max_help_position, + max(width - 20, indent_increment * 2)) self._width = width self._current_indent = 0 @@ -336,7 +338,7 @@ class HelpFormatter(object): else: line_len = len(indent) - 1 for part in parts: - if line_len + 1 + len(part) > text_width: + if line_len + 1 + len(part) > text_width and line: lines.append(indent + ' '.join(line)) line = [] line_len = len(indent) - 1 @@ -476,7 +478,7 @@ class HelpFormatter(object): def _format_text(self, text): if '%(prog)' in text: text = text % dict(prog=self._prog) - text_width = self._width - self._current_indent + text_width = max(self._width - self._current_indent, 11) indent = ' ' * self._current_indent return self._fill_text(text, text_width, indent) + '\n\n' @@ -484,7 +486,7 @@ class HelpFormatter(object): # determine the required width and the entry label help_position = min(self._action_max_length + 2, self._max_help_position) - help_width = self._width - help_position + help_width = max(self._width - help_position, 11) action_width = help_position - self._current_indent - 2 action_header = self._format_action_invocation(action) diff --git a/Lib/optparse.py b/Lib/optparse.py index 22405d5..be0145f 100644 --- a/Lib/optparse.py +++ b/Lib/optparse.py @@ -209,7 +209,6 @@ class HelpFormatter: short_first): self.parser = None self.indent_increment = indent_increment - self.help_position = self.max_help_position = max_help_position if width is None: try: width = int(os.environ['COLUMNS']) @@ -217,6 +216,8 @@ class HelpFormatter: width = 80 width -= 2 self.width = width + self.help_position = self.max_help_position = \ + min(max_help_position, max(width - 20, indent_increment * 2)) self.current_indent = 0 self.level = 0 self.help_width = None # computed later @@ -261,7 +262,7 @@ class HelpFormatter: Format a paragraph of free-form text for inclusion in the help output at the current indentation level. """ - text_width = self.width - self.current_indent + text_width = max(self.width - self.current_indent, 11) indent = " "*self.current_indent return textwrap.fill(text, text_width, @@ -342,7 +343,7 @@ class HelpFormatter: self.dedent() self.dedent() self.help_position = min(max_len + 2, self.max_help_position) - self.help_width = self.width - self.help_position + self.help_width = max(self.width - self.help_position, 11) def format_option_strings(self, option): """Return a comma-separated list of option strings & metavariables.""" diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index c10c590..25ba9e6 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -3005,6 +3005,60 @@ class TestHelpBiggerOptionals(HelpTestCase): 0.1 ''' +class TestShortColumns(HelpTestCase): + '''Test extremely small number of columns. + + TestCase prevents "COLUMNS" from being too small in the tests themselves, + but we don't want any exceptions thrown in such case. Only ugly representation. + ''' + def setUp(self): + env = support.EnvironmentVarGuard() + env.set("COLUMNS", '15') + self.addCleanup(env.__exit__) + + parser_signature = TestHelpBiggerOptionals.parser_signature + argument_signatures = TestHelpBiggerOptionals.argument_signatures + argument_group_signatures = TestHelpBiggerOptionals.argument_group_signatures + usage = '''\ + usage: PROG + [-h] + [-v] + [-x] + [--y Y] + foo + bar + ''' + help = usage + '''\ + + DESCRIPTION + + positional arguments: + foo + FOO HELP + bar + BAR HELP + + optional arguments: + -h, --help + show this + help + message and + exit + -v, --version + show + program's + version + number and + exit + -x + X HELP + --y Y + Y HELP + + EPILOG + ''' + version = TestHelpBiggerOptionals.version + class TestHelpBiggerOptionalGroups(HelpTestCase): """Make sure that argument help aligns when options are longer""" diff --git a/Lib/test/test_optparse.py b/Lib/test/test_optparse.py index 9473011..3c8c612 100644 --- a/Lib/test/test_optparse.py +++ b/Lib/test/test_optparse.py @@ -1443,6 +1443,39 @@ Options: -h, --help show this help message and exit """ +_expected_very_help_short_lines = """\ +Usage: bar.py [options] + +Options: + -a APPLE + throw + APPLEs at + basket + -b NUM, --boo=NUM + shout + "boo!" NUM + times (in + order to + frighten + away all + the evil + spirits + that cause + trouble and + mayhem) + --foo=FOO + store FOO + in the foo + list for + later + fooing + -h, --help + show this + help + message and + exit +""" + class TestHelp(BaseTest): def setUp(self): self.parser = self.make_parser(80) @@ -1500,6 +1533,8 @@ class TestHelp(BaseTest): # we look at $COLUMNS. self.parser = self.make_parser(60) self.assertHelpEquals(_expected_help_short_lines) + self.parser = self.make_parser(0) + self.assertHelpEquals(_expected_very_help_short_lines) def test_help_unicode(self): self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE) |