Skip to content

Commit 5700fa3

Browse files
committed
Update argparse.py from CPython v3.12.0
1 parent 44438bf commit 5700fa3

File tree

1 file changed

+126
-12
lines changed

1 file changed

+126
-12
lines changed

Lib/test/test_argparse.py

Lines changed: 126 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Author: Steven J. Bethard <steven.bethard@gmail.com>.
22

3+
import contextlib
4+
import functools
35
import inspect
46
import io
57
import operator
@@ -35,6 +37,35 @@ def getvalue(self):
3537
return self.buffer.raw.getvalue().decode('utf-8')
3638

3739

40+
class StdStreamTest(unittest.TestCase):
41+
42+
def test_skip_invalid_stderr(self):
43+
parser = argparse.ArgumentParser()
44+
with (
45+
contextlib.redirect_stderr(None),
46+
mock.patch('argparse._sys.exit')
47+
):
48+
parser.exit(status=0, message='foo')
49+
50+
def test_skip_invalid_stdout(self):
51+
parser = argparse.ArgumentParser()
52+
for func in (
53+
parser.print_usage,
54+
parser.print_help,
55+
functools.partial(parser.parse_args, ['-h'])
56+
):
57+
with (
58+
self.subTest(func=func),
59+
contextlib.redirect_stdout(None),
60+
# argparse uses stderr as a fallback
61+
StdIOBuffer() as mocked_stderr,
62+
contextlib.redirect_stderr(mocked_stderr),
63+
mock.patch('argparse._sys.exit'),
64+
):
65+
func()
66+
self.assertRegex(mocked_stderr.getvalue(), r'usage:')
67+
68+
3869
class TestCase(unittest.TestCase):
3970

4071
def setUp(self):
@@ -734,6 +765,49 @@ def test_const(self):
734765

735766
self.assertIn("got an unexpected keyword argument 'const'", str(cm.exception))
736767

768+
def test_deprecated_init_kw(self):
769+
# See gh-92248
770+
parser = argparse.ArgumentParser()
771+
772+
with self.assertWarns(DeprecationWarning):
773+
parser.add_argument(
774+
'-a',
775+
action=argparse.BooleanOptionalAction,
776+
type=None,
777+
)
778+
with self.assertWarns(DeprecationWarning):
779+
parser.add_argument(
780+
'-b',
781+
action=argparse.BooleanOptionalAction,
782+
type=bool,
783+
)
784+
785+
with self.assertWarns(DeprecationWarning):
786+
parser.add_argument(
787+
'-c',
788+
action=argparse.BooleanOptionalAction,
789+
metavar=None,
790+
)
791+
with self.assertWarns(DeprecationWarning):
792+
parser.add_argument(
793+
'-d',
794+
action=argparse.BooleanOptionalAction,
795+
metavar='d',
796+
)
797+
798+
with self.assertWarns(DeprecationWarning):
799+
parser.add_argument(
800+
'-e',
801+
action=argparse.BooleanOptionalAction,
802+
choices=None,
803+
)
804+
with self.assertWarns(DeprecationWarning):
805+
parser.add_argument(
806+
'-f',
807+
action=argparse.BooleanOptionalAction,
808+
choices=(),
809+
)
810+
737811
class TestBooleanOptionalActionRequired(ParserTestCase):
738812
"""Tests BooleanOptionalAction required"""
739813

@@ -1505,14 +1579,15 @@ class TestArgumentsFromFile(TempDirMixin, ParserTestCase):
15051579
def setUp(self):
15061580
super(TestArgumentsFromFile, self).setUp()
15071581
file_texts = [
1508-
('hello', 'hello world!\n'),
1509-
('recursive', '-a\n'
1510-
'A\n'
1511-
'@hello'),
1512-
('invalid', '@no-such-path\n'),
1582+
('hello', os.fsencode(self.hello) + b'\n'),
1583+
('recursive', b'-a\n'
1584+
b'A\n'
1585+
b'@hello'),
1586+
('invalid', b'@no-such-path\n'),
1587+
('undecodable', self.undecodable + b'\n'),
15131588
]
15141589
for path, text in file_texts:
1515-
with open(path, 'w', encoding="utf-8") as file:
1590+
with open(path, 'wb') as file:
15161591
file.write(text)
15171592

15181593
parser_signature = Sig(fromfile_prefix_chars='@')
@@ -1522,15 +1597,25 @@ def setUp(self):
15221597
Sig('y', nargs='+'),
15231598
]
15241599
failures = ['', '-b', 'X', '@invalid', '@missing']
1600+
hello = 'hello world!' + os_helper.FS_NONASCII
15251601
successes = [
15261602
('X Y', NS(a=None, x='X', y=['Y'])),
15271603
('X -a A Y Z', NS(a='A', x='X', y=['Y', 'Z'])),
1528-
('@hello X', NS(a=None, x='hello world!', y=['X'])),
1529-
('X @hello', NS(a=None, x='X', y=['hello world!'])),
1530-
('-a B @recursive Y Z', NS(a='A', x='hello world!', y=['Y', 'Z'])),
1531-
('X @recursive Z -a B', NS(a='B', x='X', y=['hello world!', 'Z'])),
1604+
('@hello X', NS(a=None, x=hello, y=['X'])),
1605+
('X @hello', NS(a=None, x='X', y=[hello])),
1606+
('-a B @recursive Y Z', NS(a='A', x=hello, y=['Y', 'Z'])),
1607+
('X @recursive Z -a B', NS(a='B', x='X', y=[hello, 'Z'])),
15321608
(["-a", "", "X", "Y"], NS(a='', x='X', y=['Y'])),
15331609
]
1610+
if os_helper.TESTFN_UNDECODABLE:
1611+
undecodable = os_helper.TESTFN_UNDECODABLE.lstrip(b'@')
1612+
decoded_undecodable = os.fsdecode(undecodable)
1613+
successes += [
1614+
('@undecodable X', NS(a=None, x=decoded_undecodable, y=['X'])),
1615+
('X @undecodable', NS(a=None, x='X', y=[decoded_undecodable])),
1616+
]
1617+
else:
1618+
undecodable = b''
15341619

15351620

15361621
class TestArgumentsFromFileConverter(TempDirMixin, ParserTestCase):
@@ -1539,10 +1624,10 @@ class TestArgumentsFromFileConverter(TempDirMixin, ParserTestCase):
15391624
def setUp(self):
15401625
super(TestArgumentsFromFileConverter, self).setUp()
15411626
file_texts = [
1542-
('hello', 'hello world!\n'),
1627+
('hello', b'hello world!\n'),
15431628
]
15441629
for path, text in file_texts:
1545-
with open(path, 'w', encoding="utf-8") as file:
1630+
with open(path, 'wb') as file:
15461631
file.write(text)
15471632

15481633
class FromFileConverterArgumentParser(ErrorRaisingArgumentParser):
@@ -3753,6 +3838,28 @@ class TestHelpUsage(HelpTestCase):
37533838
version = ''
37543839

37553840

3841+
class TestHelpUsageWithParentheses(HelpTestCase):
3842+
parser_signature = Sig(prog='PROG')
3843+
argument_signatures = [
3844+
Sig('positional', metavar='(example) positional'),
3845+
Sig('-p', '--optional', metavar='{1 (option A), 2 (option B)}'),
3846+
]
3847+
3848+
usage = '''\
3849+
usage: PROG [-h] [-p {1 (option A), 2 (option B)}] (example) positional
3850+
'''
3851+
help = usage + '''\
3852+
3853+
positional arguments:
3854+
(example) positional
3855+
3856+
options:
3857+
-h, --help show this help message and exit
3858+
-p {1 (option A), 2 (option B)}, --optional {1 (option A), 2 (option B)}
3859+
'''
3860+
version = ''
3861+
3862+
37563863
class TestHelpOnlyUserGroups(HelpTestCase):
37573864
"""Test basic usage messages"""
37583865

@@ -5219,6 +5326,13 @@ def test_mixed(self):
52195326
self.assertEqual(NS(v=3, spam=True, badger="B"), args)
52205327
self.assertEqual(["C", "--foo", "4"], extras)
52215328

5329+
def test_zero_or_more_optional(self):
5330+
parser = argparse.ArgumentParser()
5331+
parser.add_argument('x', nargs='*', choices=('x', 'y'))
5332+
args = parser.parse_args([])
5333+
self.assertEqual(NS(x=[]), args)
5334+
5335+
52225336
# ===========================
52235337
# parse_intermixed_args tests
52245338
# ===========================

0 commit comments

Comments
 (0)