[3.11] gh-101640: Make argparse _print_message catch any write error (GH-101802) (#104250)

gh-101640: Make argparse _print_message catch any write error (GH-101802)

* In particular, don't exit when trying to print to stderr = None.
* Add tests

(cherry picked from commit 42f54d1f92)

Co-authored-by: Oleg Iarygin <oleg@arhadthedev.net>
Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu>
This commit is contained in:
Miss Islington (bot) 2023-05-06 16:17:27 -07:00 committed by GitHub
parent 10ee19b737
commit cf1c25fd6e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 3 deletions

View file

@ -2602,9 +2602,11 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
def _print_message(self, message, file=None):
if message:
if file is None:
file = _sys.stderr
file.write(message)
file = file or _sys.stderr
try:
file.write(message)
except (AttributeError, OSError):
pass
# ===============
# Exiting methods

View file

@ -1,5 +1,7 @@
# Author: Steven J. Bethard <steven.bethard@gmail.com>.
import contextlib
import functools
import inspect
import io
import operator
@ -35,6 +37,35 @@ class StdIOBuffer(io.TextIOWrapper):
return self.buffer.raw.getvalue().decode('utf-8')
class StdStreamTest(unittest.TestCase):
def test_skip_invalid_stderr(self):
parser = argparse.ArgumentParser()
with (
contextlib.redirect_stderr(None),
mock.patch('argparse._sys.exit')
):
parser.exit(status=0, message='foo')
def test_skip_invalid_stdout(self):
parser = argparse.ArgumentParser()
for func in (
parser.print_usage,
parser.print_help,
functools.partial(parser.parse_args, ['-h'])
):
with (
self.subTest(func=func),
contextlib.redirect_stdout(None),
# argparse uses stderr as a fallback
StdIOBuffer() as mocked_stderr,
contextlib.redirect_stderr(mocked_stderr),
mock.patch('argparse._sys.exit'),
):
func()
self.assertRegex(mocked_stderr.getvalue(), r'usage:')
class TestCase(unittest.TestCase):
def setUp(self):

View file

@ -0,0 +1 @@
:class:`argparse.ArgumentParser` now catches errors when writing messages, such as when :data:`sys.stderr` is ``None``. Patch by Oleg Iarygin.