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

Skip to content

Commit f451112

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.
1 parent 32c4915 commit f451112

6 files changed

Lines changed: 103 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
@@ -2973,6 +2973,60 @@ class TestHelpBiggerOptionals(HelpTestCase):
29732973
0.1
29742974
'''
29752975

2976+
class TestShortColumns(HelpTestCase):
2977+
'''Test extremely small number of columns.
2978+
2979+
TestCase prevents "COLUMNS" from being too small in the tests themselves,
2980+
but we don't want any exceptions thrown in such case. Only ugly representation.
2981+
'''
2982+
def setUp(self):
2983+
env = support.EnvironmentVarGuard()
2984+
env.set("COLUMNS", '15')
2985+
self.addCleanup(env.__exit__)
2986+
2987+
parser_signature = TestHelpBiggerOptionals.parser_signature
2988+
argument_signatures = TestHelpBiggerOptionals.argument_signatures
2989+
argument_group_signatures = TestHelpBiggerOptionals.argument_group_signatures
2990+
usage = '''\
2991+
usage: PROG
2992+
[-h]
2993+
[-v]
2994+
[-x]
2995+
[--y Y]
2996+
foo
2997+
bar
2998+
'''
2999+
help = usage + '''\
3000+
3001+
DESCRIPTION
3002+
3003+
positional arguments:
3004+
foo
3005+
FOO HELP
3006+
bar
3007+
BAR HELP
3008+
3009+
optional arguments:
3010+
-h, --help
3011+
show this
3012+
help
3013+
message and
3014+
exit
3015+
-v, --version
3016+
show
3017+
program's
3018+
version
3019+
number and
3020+
exit
3021+
-x
3022+
X HELP
3023+
--y Y
3024+
Y HELP
3025+
3026+
EPILOG
3027+
'''
3028+
version = TestHelpBiggerOptionals.version
3029+
29763030

29773031
class TestHelpBiggerOptionalGroups(HelpTestCase):
29783032
"""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/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ Marius Gedminas
430430
Thomas Gellekum
431431
Gabriel Genellina
432432
Christos Georgiou
433+
Elazar Gershuni
433434
Ben Gertzfield
434435
Nadim Ghaznavi
435436
Dinu Gherman

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ Core and Builtins
4343
Library
4444
-------
4545

46+
- Issue #13107: argparse and optparse no longer raises an exception when output
47+
a help on environment with too small COLUMNS. Based on patch by
48+
Elazar Gershuni.
49+
4650
- Issue #20207: Always disable SSLv2 except when PROTOCOL_SSLv2 is explicitly
4751
asked for.
4852

0 commit comments

Comments
 (0)