Skip to content

Commit 47e20e9

Browse files
authored
Merge branch 'main' into broken-echo
2 parents a200849 + b3b0d75 commit 47e20e9

File tree

13 files changed

+722
-542
lines changed

13 files changed

+722
-542
lines changed

Doc/library/argparse.rst

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ ArgumentParser objects
7474
prefix_chars='-', fromfile_prefix_chars=None, \
7575
argument_default=None, conflict_handler='error', \
7676
add_help=True, allow_abbrev=True, exit_on_error=True, \
77-
*, suggest_on_error=False, color=True)
77+
*, suggest_on_error=True, color=True)
7878
7979
Create a new :class:`ArgumentParser` object. All parameters should be passed
8080
as keyword arguments. Each parameter has its own more detailed description
@@ -117,7 +117,7 @@ ArgumentParser objects
117117
error info when an error occurs. (default: ``True``)
118118

119119
* suggest_on_error_ - Enables suggestions for mistyped argument choices
120-
and subparser names (default: ``False``)
120+
and subparser names (default: ``True``)
121121

122122
* color_ - Allow color output (default: ``True``)
123123

@@ -134,6 +134,9 @@ ArgumentParser objects
134134
.. versionchanged:: 3.14
135135
*suggest_on_error* and *color* parameters were added.
136136

137+
.. versionchanged:: 3.15
138+
*suggest_on_error* default changed to ``True``.
139+
137140
The following sections describe how each of these are used.
138141

139142

@@ -596,13 +599,11 @@ suggest_on_error
596599
^^^^^^^^^^^^^^^^
597600

598601
By default, when a user passes an invalid argument choice or subparser name,
599-
:class:`ArgumentParser` will exit with error info and list the permissible
600-
argument choices (if specified) or subparser names as part of the error message.
601-
602-
If the user would like to enable suggestions for mistyped argument choices and
603-
subparser names, the feature can be enabled by setting ``suggest_on_error`` to
604-
``True``. Note that this only applies for arguments when the choices specified
605-
are strings::
602+
:class:`ArgumentParser` will exit with error info and provide suggestions for
603+
mistyped arguments. The error message will list the permissible argument
604+
choices (if specified) or subparser names, along with a "maybe you meant"
605+
suggestion if a close match is found. Note that this only applies for arguments
606+
when the choices specified are strings::
606607

607608
>>> parser = argparse.ArgumentParser(description='Process some integers.',
608609
suggest_on_error=True)
@@ -612,16 +613,14 @@ are strings::
612613
>>> parser.parse_args(['--action', 'sumn', 1, 2, 3])
613614
tester.py: error: argument --action: invalid choice: 'sumn', maybe you meant 'sum'? (choose from 'sum', 'max')
614615

615-
If you're writing code that needs to be compatible with older Python versions
616-
and want to opportunistically use ``suggest_on_error`` when it's available, you
617-
can set it as an attribute after initializing the parser instead of using the
618-
keyword argument::
616+
You can disable suggestions by setting ``suggest_on_error`` to ``False``::
619617

620-
>>> parser = argparse.ArgumentParser(description='Process some integers.')
621-
>>> parser.suggest_on_error = True
618+
>>> parser = argparse.ArgumentParser(description='Process some integers.',
619+
suggest_on_error=False)
622620

623621
.. versionadded:: 3.14
624-
622+
.. versionchanged:: 3.15
623+
Changed default value of ``suggest_on_error`` from ``False`` to ``True``.
625624

626625
color
627626
^^^^^

Doc/whatsnew/3.15.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,13 @@ New modules
317317
Improved modules
318318
================
319319

320+
argparse
321+
--------
322+
323+
* Changed the *suggest_on_error* parameter of :class:`argparse.ArgumentParser` to
324+
default to ``True``. This enables suggestions for mistyped arguments by default.
325+
(Contributed by Jakob Schluse in :gh:`140450`.)
326+
320327
calendar
321328
--------
322329

Grammar/python.gram

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,7 @@ mapping_pattern[pattern_ty]:
626626
CHECK(asdl_pattern_seq*, _PyPegen_get_patterns(p, items)),
627627
NULL,
628628
EXTRA) }
629+
| invalid_mapping_pattern
629630

630631
items_pattern[asdl_seq*]:
631632
| ','.key_value_pattern+
@@ -1490,6 +1491,10 @@ invalid_class_pattern:
14901491
PyPegen_first_item(a, pattern_ty),
14911492
PyPegen_last_item(a, pattern_ty),
14921493
"positional patterns follow keyword patterns") }
1494+
invalid_mapping_pattern:
1495+
| '{' (items_pattern ',')? rest=double_star_pattern ',' items_pattern ','? '}' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
1496+
rest,
1497+
"double star pattern must be the last (right-most) subpattern in the mapping pattern") }
14931498
invalid_class_argument_pattern[asdl_pattern_seq*]:
14941499
| [positional_patterns ','] keyword_patterns ',' a=positional_patterns { a }
14951500
invalid_if_stmt:

Lib/argparse.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,7 +1857,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
18571857
- exit_on_error -- Determines whether or not ArgumentParser exits with
18581858
error info when an error occurs
18591859
- suggest_on_error - Enables suggestions for mistyped argument choices
1860-
and subparser names (default: ``False``)
1860+
and subparser names (default: ``True``)
18611861
- color - Allow color output in help messages (default: ``False``)
18621862
"""
18631863

@@ -1876,7 +1876,7 @@ def __init__(self,
18761876
allow_abbrev=True,
18771877
exit_on_error=True,
18781878
*,
1879-
suggest_on_error=False,
1879+
suggest_on_error=True,
18801880
color=True,
18811881
):
18821882
superinit = super(ArgumentParser, self).__init__

Lib/test/test_argparse.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2287,7 +2287,7 @@ class TestArgumentAndSubparserSuggestions(TestCase):
22872287
"""Test error handling and suggestion when a user makes a typo"""
22882288

22892289
def test_wrong_argument_error_with_suggestions(self):
2290-
parser = ErrorRaisingArgumentParser(suggest_on_error=True)
2290+
parser = ErrorRaisingArgumentParser()
22912291
parser.add_argument('foo', choices=['bar', 'baz'])
22922292
with self.assertRaises(ArgumentParserError) as excinfo:
22932293
parser.parse_args(('bazz',))
@@ -2307,7 +2307,7 @@ def test_wrong_argument_error_no_suggestions(self):
23072307
)
23082308

23092309
def test_wrong_argument_subparsers_with_suggestions(self):
2310-
parser = ErrorRaisingArgumentParser(suggest_on_error=True)
2310+
parser = ErrorRaisingArgumentParser()
23112311
subparsers = parser.add_subparsers(required=True)
23122312
subparsers.add_parser('foo')
23132313
subparsers.add_parser('bar')
@@ -2331,18 +2331,19 @@ def test_wrong_argument_subparsers_no_suggestions(self):
23312331
excinfo.exception.stderr,
23322332
)
23332333

2334-
def test_wrong_argument_no_suggestion_implicit(self):
2335-
parser = ErrorRaisingArgumentParser()
2334+
def test_wrong_argument_with_suggestion_explicit(self):
2335+
parser = ErrorRaisingArgumentParser(suggest_on_error=True)
23362336
parser.add_argument('foo', choices=['bar', 'baz'])
23372337
with self.assertRaises(ArgumentParserError) as excinfo:
23382338
parser.parse_args(('bazz',))
23392339
self.assertIn(
2340-
"error: argument foo: invalid choice: 'bazz' (choose from bar, baz)",
2340+
"error: argument foo: invalid choice: 'bazz', maybe you meant"
2341+
" 'baz'? (choose from bar, baz)",
23412342
excinfo.exception.stderr,
23422343
)
23432344

23442345
def test_suggestions_choices_empty(self):
2345-
parser = ErrorRaisingArgumentParser(suggest_on_error=True)
2346+
parser = ErrorRaisingArgumentParser()
23462347
parser.add_argument('foo', choices=[])
23472348
with self.assertRaises(ArgumentParserError) as excinfo:
23482349
parser.parse_args(('bazz',))
@@ -2352,7 +2353,7 @@ def test_suggestions_choices_empty(self):
23522353
)
23532354

23542355
def test_suggestions_choices_int(self):
2355-
parser = ErrorRaisingArgumentParser(suggest_on_error=True)
2356+
parser = ErrorRaisingArgumentParser()
23562357
parser.add_argument('foo', choices=[1, 2])
23572358
with self.assertRaises(ArgumentParserError) as excinfo:
23582359
parser.parse_args(('3',))
@@ -2362,7 +2363,7 @@ def test_suggestions_choices_int(self):
23622363
)
23632364

23642365
def test_suggestions_choices_mixed_types(self):
2365-
parser = ErrorRaisingArgumentParser(suggest_on_error=True)
2366+
parser = ErrorRaisingArgumentParser()
23662367
parser.add_argument('foo', choices=[1, '2'])
23672368
with self.assertRaises(ArgumentParserError) as excinfo:
23682369
parser.parse_args(('3',))

Lib/test/test_capi/test_float.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import math
22
import random
3+
import platform
34
import sys
45
import unittest
56
import warnings
@@ -197,6 +198,10 @@ def test_pack_unpack_roundtrip_for_nans(self):
197198
# PyFloat_Pack/Unpack*() API. See also gh-130317 and
198199
# e.g. https://developercommunity.visualstudio.com/t/155064
199200
signaling = 0
201+
if platform.machine().startswith('parisc'):
202+
# HP PA RISC uses 0 for quiet, see:
203+
# https://en.wikipedia.org/wiki/NaN#Encoding
204+
signaling = 1
200205
quiet = int(not signaling)
201206
if size == 8:
202207
payload = random.randint(signaling, 0x7ffffffffffff)

Lib/test/test_exceptions.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,16 @@ def testSyntaxErrorOffset(self):
252252
check('[\nfile\nfor str(file)\nin\n[]\n]', 3, 5)
253253
check('[file for\n str(file) in []]', 2, 2)
254254
check("ages = {'Alice'=22, 'Bob'=23}", 1, 9)
255-
check('match ...:\n case {**rest, "key": value}:\n ...', 2, 19)
255+
check(dedent("""\
256+
match ...:
257+
case {**rest1, "after": after}:
258+
...
259+
"""), 2, 11)
260+
check(dedent("""\
261+
match ...:
262+
case {"before": before, **rest2, "after": after}:
263+
...
264+
"""), 2, 29)
256265
check("[a b c d e f]", 1, 2)
257266
check("for x yfff:", 1, 7)
258267
check("f(a for a in b, c)", 1, 3, 1, 15)

Lib/test/test_struct.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import math
66
import operator
77
import unittest
8+
import platform
89
import struct
910
import sys
1011
import weakref
@@ -917,10 +918,17 @@ def test_half_float(self):
917918

918919
# Check that packing produces a bit pattern representing a quiet NaN:
919920
# all exponent bits and the msb of the fraction should all be 1.
921+
if platform.machine().startswith('parisc'):
922+
# HP PA RISC uses 0 for quiet, see:
923+
# https://en.wikipedia.org/wiki/NaN#Encoding
924+
expected = 0x7c
925+
else:
926+
expected = 0x7e
927+
920928
packed = struct.pack('<e', math.nan)
921-
self.assertEqual(packed[1] & 0x7e, 0x7e)
929+
self.assertEqual(packed[1] & 0x7e, expected)
922930
packed = struct.pack('<e', -math.nan)
923-
self.assertEqual(packed[1] & 0x7e, 0x7e)
931+
self.assertEqual(packed[1] & 0x7e, expected)
924932

925933
# Checks for round-to-even behavior
926934
format_bits_float__rounding_list = [

Lib/test/test_syntax.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -370,12 +370,6 @@
370370
Traceback (most recent call last):
371371
SyntaxError: invalid syntax
372372
373-
>>> match ...:
374-
... case {**rest, "key": value}:
375-
... ...
376-
Traceback (most recent call last):
377-
SyntaxError: invalid syntax
378-
379373
>>> match ...:
380374
... case {**_}:
381375
... ...
@@ -2240,7 +2234,7 @@
22402234
Traceback (most recent call last):
22412235
SyntaxError: invalid character '£' (U+00A3)
22422236
2243-
Invalid pattern matching constructs:
2237+
Invalid pattern matching constructs:
22442238
22452239
>>> match ...:
22462240
... case 42 as _:
@@ -2302,6 +2296,24 @@
23022296
Traceback (most recent call last):
23032297
SyntaxError: positional patterns follow keyword patterns
23042298
2299+
>>> match ...:
2300+
... case {**double_star, "spam": "eggs"}:
2301+
... ...
2302+
Traceback (most recent call last):
2303+
SyntaxError: double star pattern must be the last (right-most) subpattern in the mapping pattern
2304+
2305+
>>> match ...:
2306+
... case {"foo": 1, **double_star, "spam": "eggs"}:
2307+
... ...
2308+
Traceback (most recent call last):
2309+
SyntaxError: double star pattern must be the last (right-most) subpattern in the mapping pattern
2310+
2311+
>>> match ...:
2312+
... case {"spam": "eggs", "b": {**d, "ham": "bacon"}}:
2313+
... ...
2314+
Traceback (most recent call last):
2315+
SyntaxError: double star pattern must be the last (right-most) subpattern in the mapping pattern
2316+
23052317
Uses of the star operator which should fail:
23062318
23072319
A[:*b]

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,6 +1681,7 @@ David Scherer
16811681
Wolfgang Scherer
16821682
Felix Scherz
16831683
Hynek Schlawack
1684+
Jakob Schluse
16841685
Bob Schmertz
16851686
Gregor Schmid
16861687
Ralf Schmitt

0 commit comments

Comments
 (0)