Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 123e6d5

Browse files
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.
2 parents ba44860 + f451112 commit 123e6d5

5 files changed

Lines changed: 102 additions & 6 deletions

File tree

Lib/argparse.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ def __init__(self,
165165
self._prog = prog
166166
self._indent_increment = indent_increment
167167
self._max_help_position = max_help_position
168+
self._max_help_position = min(max_help_position,
169+
max(width - 20, indent_increment * 2))
168170
self._width = width
169171

170172
self._current_indent = 0
@@ -336,7 +338,7 @@ def get_lines(parts, indent, prefix=None):
336338
else:
337339
line_len = len(indent) - 1
338340
for part in parts:
339-
if line_len + 1 + len(part) > text_width:
341+
if line_len + 1 + len(part) > text_width and line:
340342
lines.append(indent + ' '.join(line))
341343
line = []
342344
line_len = len(indent) - 1
@@ -476,15 +478,15 @@ def _format_actions_usage(self, actions, groups):
476478
def _format_text(self, text):
477479
if '%(prog)' in text:
478480
text = text % dict(prog=self._prog)
479-
text_width = self._width - self._current_indent
481+
text_width = max(self._width - self._current_indent, 11)
480482
indent = ' ' * self._current_indent
481483
return self._fill_text(text, text_width, indent) + '\n\n'
482484

483485
def _format_action(self, action):
484486
# determine the required width and the entry label
485487
help_position = min(self._action_max_length + 2,
486488
self._max_help_position)
487-
help_width = self._width - help_position
489+
help_width = max(self._width - help_position, 11)
488490
action_width = help_position - self._current_indent - 2
489491
action_header = self._format_action_invocation(action)
490492

Lib/optparse.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,14 +209,15 @@ def __init__(self,
209209
short_first):
210210
self.parser = None
211211
self.indent_increment = indent_increment
212-
self.help_position = self.max_help_position = max_help_position
213212
if width is None:
214213
try:
215214
width = int(os.environ['COLUMNS'])
216215
except (KeyError, ValueError):
217216
width = 80
218217
width -= 2
219218
self.width = width
219+
self.help_position = self.max_help_position = \
220+
min(max_help_position, max(width - 20, indent_increment * 2))
220221
self.current_indent = 0
221222
self.level = 0
222223
self.help_width = None # computed later
@@ -261,7 +262,7 @@ def _format_text(self, text):
261262
Format a paragraph of free-form text for inclusion in the
262263
help output at the current indentation level.
263264
"""
264-
text_width = self.width - self.current_indent
265+
text_width = max(self.width - self.current_indent, 11)
265266
indent = " "*self.current_indent
266267
return textwrap.fill(text,
267268
text_width,
@@ -342,7 +343,7 @@ def store_option_strings(self, parser):
342343
self.dedent()
343344
self.dedent()
344345
self.help_position = min(max_len + 2, self.max_help_position)
345-
self.help_width = self.width - self.help_position
346+
self.help_width = max(self.width - self.help_position, 11)
346347

347348
def format_option_strings(self, option):
348349
"""Return a comma-separated list of option strings & metavariables."""

Lib/test/test_argparse.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3005,6 +3005,60 @@ class TestHelpBiggerOptionals(HelpTestCase):
30053005
0.1
30063006
'''
30073007

3008+
class TestShortColumns(HelpTestCase):
3009+
'''Test extremely small number of columns.
3010+
3011+
TestCase prevents "COLUMNS" from being too small in the tests themselves,
3012+
but we don't want any exceptions thrown in such case. Only ugly representation.
3013+
'''
3014+
def setUp(self):
3015+
env = support.EnvironmentVarGuard()
3016+
env.set("COLUMNS", '15')
3017+
self.addCleanup(env.__exit__)
3018+
3019+
parser_signature = TestHelpBiggerOptionals.parser_signature
3020+
argument_signatures = TestHelpBiggerOptionals.argument_signatures
3021+
argument_group_signatures = TestHelpBiggerOptionals.argument_group_signatures
3022+
usage = '''\
3023+
usage: PROG
3024+
[-h]
3025+
[-v]
3026+
[-x]
3027+
[--y Y]
3028+
foo
3029+
bar
3030+
'''
3031+
help = usage + '''\
3032+
3033+
DESCRIPTION
3034+
3035+
positional arguments:
3036+
foo
3037+
FOO HELP
3038+
bar
3039+
BAR HELP
3040+
3041+
optional arguments:
3042+
-h, --help
3043+
show this
3044+
help
3045+
message and
3046+
exit
3047+
-v, --version
3048+
show
3049+
program's
3050+
version
3051+
number and
3052+
exit
3053+
-x
3054+
X HELP
3055+
--y Y
3056+
Y HELP
3057+
3058+
EPILOG
3059+
'''
3060+
version = TestHelpBiggerOptionals.version
3061+
30083062

30093063
class TestHelpBiggerOptionalGroups(HelpTestCase):
30103064
"""Make sure that argument help aligns when options are longer"""

Lib/test/test_optparse.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,6 +1443,39 @@ def test_conflict_override_args(self):
14431443
-h, --help show this help message and exit
14441444
"""
14451445

1446+
_expected_very_help_short_lines = """\
1447+
Usage: bar.py [options]
1448+
1449+
Options:
1450+
-a APPLE
1451+
throw
1452+
APPLEs at
1453+
basket
1454+
-b NUM, --boo=NUM
1455+
shout
1456+
"boo!" NUM
1457+
times (in
1458+
order to
1459+
frighten
1460+
away all
1461+
the evil
1462+
spirits
1463+
that cause
1464+
trouble and
1465+
mayhem)
1466+
--foo=FOO
1467+
store FOO
1468+
in the foo
1469+
list for
1470+
later
1471+
fooing
1472+
-h, --help
1473+
show this
1474+
help
1475+
message and
1476+
exit
1477+
"""
1478+
14461479
class TestHelp(BaseTest):
14471480
def setUp(self):
14481481
self.parser = self.make_parser(80)
@@ -1500,6 +1533,8 @@ def test_wrap_columns(self):
15001533
# we look at $COLUMNS.
15011534
self.parser = self.make_parser(60)
15021535
self.assertHelpEquals(_expected_help_short_lines)
1536+
self.parser = self.make_parser(0)
1537+
self.assertHelpEquals(_expected_very_help_short_lines)
15031538

15041539
def test_help_unicode(self):
15051540
self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ Core and Builtins
2525
Library
2626
-------
2727

28+
- Issue #13107: argparse and optparse no longer raises an exception when output
29+
a help on environment with too small COLUMNS. Based on patch by
30+
Elazar Gershuni.
31+
2832
- Issue #20207: Always disable SSLv2 except when PROTOCOL_SSLv2 is explicitly
2933
asked for.
3034

0 commit comments

Comments
 (0)