mirror of
https://github.com/python/cpython.git
synced 2025-10-02 05:12:23 +00:00
[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:
parent
10ee19b737
commit
cf1c25fd6e
3 changed files with 37 additions and 3 deletions
|
@ -2602,9 +2602,11 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
|
||||||
|
|
||||||
def _print_message(self, message, file=None):
|
def _print_message(self, message, file=None):
|
||||||
if message:
|
if message:
|
||||||
if file is None:
|
file = file or _sys.stderr
|
||||||
file = _sys.stderr
|
try:
|
||||||
file.write(message)
|
file.write(message)
|
||||||
|
except (AttributeError, OSError):
|
||||||
|
pass
|
||||||
|
|
||||||
# ===============
|
# ===============
|
||||||
# Exiting methods
|
# Exiting methods
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
# Author: Steven J. Bethard <steven.bethard@gmail.com>.
|
# Author: Steven J. Bethard <steven.bethard@gmail.com>.
|
||||||
|
|
||||||
|
import contextlib
|
||||||
|
import functools
|
||||||
import inspect
|
import inspect
|
||||||
import io
|
import io
|
||||||
import operator
|
import operator
|
||||||
|
@ -35,6 +37,35 @@ class StdIOBuffer(io.TextIOWrapper):
|
||||||
return self.buffer.raw.getvalue().decode('utf-8')
|
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):
|
class TestCase(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
:class:`argparse.ArgumentParser` now catches errors when writing messages, such as when :data:`sys.stderr` is ``None``. Patch by Oleg Iarygin.
|
Loading…
Add table
Add a link
Reference in a new issue