Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions Lib/argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,10 @@ def __init__(
self._whitespace_matcher = _re.compile(r'\s+', _re.ASCII)
self._long_break_matcher = _re.compile(r'\n\n\n+')

def _set_color(self, color):
def _set_color(self, color, *, file=None):
from _colorize import can_colorize, decolor, get_theme

if color and can_colorize():
if color and can_colorize(file=file):
self._theme = get_theme(force_color=True).argparse
self._decolor = decolor
else:
Expand Down Expand Up @@ -2693,14 +2693,16 @@ def _check_value(self, action, value):
# Help-formatting methods
# =======================

def format_usage(self):
formatter = self._get_formatter()
def format_usage(self, formatter=None):
if formatter is None:
formatter = self._get_formatter()
formatter.add_usage(self.usage, self._actions,
self._mutually_exclusive_groups)
return formatter.format_help()

def format_help(self):
formatter = self._get_formatter()
def format_help(self, formatter=None):
if formatter is None:
formatter = self._get_formatter()

# usage
formatter.add_usage(self.usage, self._actions,
Expand All @@ -2722,9 +2724,9 @@ def format_help(self):
# determine help from format above
return formatter.format_help()

def _get_formatter(self):
def _get_formatter(self, file=None):
formatter = self.formatter_class(prog=self.prog)
formatter._set_color(self.color)
formatter._set_color(self.color, file=file)
return formatter

# =====================
Expand All @@ -2734,12 +2736,14 @@ def _get_formatter(self):
def print_usage(self, file=None):
if file is None:
file = _sys.stdout
self._print_message(self.format_usage(), file)
formatter = self._get_formatter(file=file)
self._print_message(self.format_usage(formatter=formatter), file)

def print_help(self, file=None):
if file is None:
file = _sys.stdout
self._print_message(self.format_help(), file)
formatter = self._get_formatter(file=file)
self._print_message(self.format_help(formatter=formatter), file)

def _print_message(self, message, file=None):
if message:
Expand Down
34 changes: 34 additions & 0 deletions Lib/test/test_argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -7370,6 +7370,40 @@ def test_subparser_prog_is_stored_without_color(self):
help_text = demo_parser.format_help()
self.assertNotIn('\x1b[', help_text)

def test_print_help_uses_target_file_for_color_decision(self):
parser = argparse.ArgumentParser(prog='PROG', color=True)
parser.add_argument('--opt')
output = io.StringIO()
calls = []

def fake_can_colorize(*, file=None):
calls.append(file)
return file is None

with swap_attr(_colorize, 'can_colorize', fake_can_colorize):
parser.print_help(file=output)

self.assertIs(calls[-1], output)
self.assertIn(output, calls)
self.assertNotIn('\x1b[', output.getvalue())

def test_print_usage_uses_target_file_for_color_decision(self):
parser = argparse.ArgumentParser(prog='PROG', color=True)
parser.add_argument('--opt')
output = io.StringIO()
calls = []

def fake_can_colorize(*, file=None):
calls.append(file)
return file is None

with swap_attr(_colorize, 'can_colorize', fake_can_colorize):
parser.print_usage(file=output)

self.assertIs(calls[-1], output)
self.assertIn(output, calls)
self.assertNotIn('\x1b[', output.getvalue())


class TestModule(unittest.TestCase):
def test_deprecated__version__(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Distinguish stdout and stderr when colorizing output in argparse module.
Loading