Skip to content

Commit 9fc4366

Browse files
GH-139809: Fix argparse subcommand prog not respecting color environment variables (#139818)
1 parent a310b3a commit 9fc4366

File tree

3 files changed

+18
-2
lines changed

3 files changed

+18
-2
lines changed

Lib/argparse.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1959,7 +1959,9 @@ def add_subparsers(self, **kwargs):
19591959
# prog defaults to the usage message of this parser, skipping
19601960
# optional arguments and with no "usage:" prefix
19611961
if kwargs.get('prog') is None:
1962-
formatter = self._get_formatter()
1962+
# Create formatter without color to avoid storing ANSI codes in prog
1963+
formatter = self.formatter_class(prog=self.prog)
1964+
formatter._set_color(False)
19631965
positionals = self._get_positional_actions()
19641966
groups = self._mutually_exclusive_groups
19651967
formatter.add_usage(None, positionals, groups, '')

Lib/test/test_argparse.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
captured_stderr,
2323
force_not_colorized,
2424
force_not_colorized_test_class,
25+
swap_attr,
2526
)
2627
from test.support import import_helper
2728
from test.support import os_helper
@@ -7128,7 +7129,8 @@ class TestColorized(TestCase):
71287129
def setUp(self):
71297130
super().setUp()
71307131
# Ensure color even if ran with NO_COLOR=1
7131-
_colorize.can_colorize = lambda *args, **kwargs: True
7132+
self.enterContext(swap_attr(_colorize, 'can_colorize',
7133+
lambda *args, **kwargs: True))
71327134
self.theme = _colorize.get_theme(force_color=True).argparse
71337135

71347136
def test_argparse_color(self):
@@ -7355,6 +7357,17 @@ def __init__(self, prog):
73557357
{short_b}+f{reset}, {long_b}++foo{reset} {label_b}FOO{reset} foo help
73567358
'''))
73577359

7360+
def test_subparser_prog_is_stored_without_color(self):
7361+
parser = argparse.ArgumentParser(prog='complex', color=True)
7362+
sub = parser.add_subparsers(dest='command')
7363+
demo_parser = sub.add_parser('demo')
7364+
7365+
self.assertNotIn('\x1b[', demo_parser.prog)
7366+
7367+
demo_parser.color = False
7368+
help_text = demo_parser.format_help()
7369+
self.assertNotIn('\x1b[', help_text)
7370+
73587371

73597372
class TestModule(unittest.TestCase):
73607373
def test_deprecated__version__(self):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Prevent premature colorization of subparser ``prog`` in :meth:`argparse.ArgumentParser.add_subparsers` to respect color environment variable changes after parser creation.

0 commit comments

Comments
 (0)