summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2014-01-09 21:13:48 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2014-01-09 21:13:48 (GMT)
commit9f8621fa7d3562f472b6a16854df51bfb3fdbd5f (patch)
tree9d858123a00e7b6191bed9748ef1b7bcf90bcdd4
parent3b2afbbf88cb8ba93542641f06c474aab13e50e6 (diff)
downloadcpython-9f8621fa7d3562f472b6a16854df51bfb3fdbd5f.zip
cpython-9f8621fa7d3562f472b6a16854df51bfb3fdbd5f.tar.gz
cpython-9f8621fa7d3562f472b6a16854df51bfb3fdbd5f.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.
-rw-r--r--Lib/argparse.py8
-rw-r--r--Lib/optparse.py7
-rw-r--r--Lib/test/test_argparse.py54
-rw-r--r--Lib/test/test_optparse.py35
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS4
6 files changed, 103 insertions, 6 deletions
diff --git a/Lib/argparse.py b/Lib/argparse.py
index 30bae57..a4009d0 100644
--- a/Lib/argparse.py
+++ b/Lib/argparse.py
@@ -168,6 +168,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
@@ -339,7 +341,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
@@ -478,7 +480,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'
@@ -486,7 +488,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 6c3f456..433276d 100644
--- a/Lib/optparse.py
+++ b/Lib/optparse.py
@@ -204,7 +204,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'])
@@ -212,6 +211,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
@@ -256,7 +257,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,
@@ -337,7 +338,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 30fdf4a..a9b47b7 100644
--- a/Lib/test/test_argparse.py
+++ b/Lib/test/test_argparse.py
@@ -2936,6 +2936,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 = test_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 d4e5bb9..44927d6 100644
--- a/Lib/test/test_optparse.py
+++ b/Lib/test/test_optparse.py
@@ -1444,6 +1444,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)
@@ -1505,6 +1538,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)
diff --git a/Misc/ACKS b/Misc/ACKS
index 209e285..2ea2322 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -357,6 +357,7 @@ Marius Gedminas
Thomas Gellekum
Gabriel Genellina
Christos Georgiou
+Elazar Gershuni
Ben Gertzfield
Nadim Ghaznavi
Dinu Gherman
diff --git a/Misc/NEWS b/Misc/NEWS
index 3d07704..481e901 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -35,6 +35,10 @@ Core and Builtins
Library
-------
+- 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.
+
- Issue #20207: Always disable SSLv2 except when PROTOCOL_SSLv2 is explicitly
asked for.