Skip to content

Commit 1a39ded

Browse files
committed
Merge remote-tracking branch 'upstream/main' into unifyunion
2 parents 0785951 + 95581b3 commit 1a39ded

31 files changed

+458
-260
lines changed

Doc/library/argparse.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1823,7 +1823,7 @@ Sub-commands
18231823
>>>
18241824
>>> # create the parser for the "b" command
18251825
>>> parser_b = subparsers.add_parser('b', help='b help')
1826-
>>> parser_b.add_argument('--baz', choices='XYZ', help='baz help')
1826+
>>> parser_b.add_argument('--baz', choices=('X', 'Y', 'Z'), help='baz help')
18271827
>>>
18281828
>>> # parse some argument lists
18291829
>>> parser.parse_args(['a', '12'])

Doc/library/typing.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2357,7 +2357,9 @@ types.
23572357

23582358
Backward-compatible usage::
23592359

2360-
# For creating a generic NamedTuple on Python 3.11 or lower
2360+
# For creating a generic NamedTuple on Python 3.11
2361+
T = TypeVar("T")
2362+
23612363
class Group(NamedTuple, Generic[T]):
23622364
key: T
23632365
group: list[T]

Include/cpython/longobject.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,9 @@ PyAPI_FUNC(int) _PyLong_Sign(PyObject *v);
7171
absolute value of a long. For example, this returns 1 for 1 and -1, 2
7272
for 2 and -2, and 2 for 3 and -3. It returns 0 for 0.
7373
v must not be NULL, and must be a normalized long.
74-
(uint64_t)-1 is returned and OverflowError set if the true result doesn't
75-
fit in a size_t.
74+
Always successful.
7675
*/
77-
PyAPI_FUNC(uint64_t) _PyLong_NumBits(PyObject *v);
76+
PyAPI_FUNC(int64_t) _PyLong_NumBits(PyObject *v);
7877

7978
/* _PyLong_FromByteArray: View the n unsigned bytes as a binary integer in
8079
base 256, and return a Python int with the same numeric value.

Include/internal/pycore_codecs.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ extern void _PyCodec_Fini(PyInterpreterState *interp);
2121

2222
extern PyObject* _PyCodec_Lookup(const char *encoding);
2323

24+
/*
25+
* Un-register the error handling callback function registered under
26+
* the given 'name'. Only custom error handlers can be un-registered.
27+
*
28+
* - Return -1 and set an exception if 'name' refers to a built-in
29+
* error handling name (e.g., 'strict'), or if an error occurred.
30+
* - Return 0 if no custom error handler can be found for 'name'.
31+
* - Return 1 if the custom error handler was successfully removed.
32+
*/
33+
extern int _PyCodec_UnregisterError(const char *name);
34+
2435
/* Text codec specific encoding and decoding API.
2536
2637
Checks the encoding against a list of codecs which do not

Include/internal/pycore_long.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,10 @@ static inline PyObject* _PyLong_FromUnsignedChar(unsigned char i)
7979
}
8080

8181
// _PyLong_Frexp returns a double x and an exponent e such that the
82-
// true value is approximately equal to x * 2**e. e is >= 0. x is
82+
// true value is approximately equal to x * 2**e. x is
8383
// 0.0 if and only if the input is 0 (in which case, e and x are both
84-
// zeroes); otherwise, 0.5 <= abs(x) < 1.0. On overflow, which is
85-
// possible if the number of bits doesn't fit into a Py_ssize_t, sets
86-
// OverflowError and returns -1.0 for x, 0 for e.
84+
// zeroes); otherwise, 0.5 <= abs(x) < 1.0.
85+
// Always successful.
8786
//
8887
// Export for 'math' shared extension
8988
PyAPI_DATA(double) _PyLong_Frexp(PyLongObject *a, int64_t *e);
@@ -105,10 +104,10 @@ PyAPI_DATA(PyObject*) _PyLong_DivmodNear(PyObject *, PyObject *);
105104
PyAPI_DATA(PyObject*) _PyLong_Format(PyObject *obj, int base);
106105

107106
// Export for 'math' shared extension
108-
PyAPI_DATA(PyObject*) _PyLong_Rshift(PyObject *, uint64_t);
107+
PyAPI_DATA(PyObject*) _PyLong_Rshift(PyObject *, int64_t);
109108

110109
// Export for 'math' shared extension
111-
PyAPI_DATA(PyObject*) _PyLong_Lshift(PyObject *, uint64_t);
110+
PyAPI_DATA(PyObject*) _PyLong_Lshift(PyObject *, int64_t);
112111

113112
PyAPI_FUNC(PyObject*) _PyLong_Add(PyLongObject *left, PyLongObject *right);
114113
PyAPI_FUNC(PyObject*) _PyLong_Multiply(PyLongObject *left, PyLongObject *right);

Lib/argparse.py

Lines changed: 46 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,7 +1224,8 @@ def __call__(self, parser, namespace, values, option_string=None):
12241224
setattr(namespace, key, value)
12251225

12261226
if arg_strings:
1227-
vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, [])
1227+
if not hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR):
1228+
setattr(namespace, _UNRECOGNIZED_ARGS_ATTR, [])
12281229
getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings)
12291230

12301231
class _ExtendAction(_AppendAction):
@@ -1927,11 +1928,11 @@ def _parse_known_args(self, arg_strings, namespace):
19271928
# otherwise, add the arg to the arg strings
19281929
# and note the index if it was an option
19291930
else:
1930-
option_tuple = self._parse_optional(arg_string)
1931-
if option_tuple is None:
1931+
option_tuples = self._parse_optional(arg_string)
1932+
if option_tuples is None:
19321933
pattern = 'A'
19331934
else:
1934-
option_string_indices[i] = option_tuple
1935+
option_string_indices[i] = option_tuples
19351936
pattern = 'O'
19361937
arg_string_pattern_parts.append(pattern)
19371938

@@ -1966,8 +1967,16 @@ def take_action(action, argument_strings, option_string=None):
19661967
def consume_optional(start_index):
19671968

19681969
# get the optional identified at this index
1969-
option_tuple = option_string_indices[start_index]
1970-
action, option_string, sep, explicit_arg = option_tuple
1970+
option_tuples = option_string_indices[start_index]
1971+
# if multiple actions match, the option string was ambiguous
1972+
if len(option_tuples) > 1:
1973+
options = ', '.join([option_string
1974+
for action, option_string, sep, explicit_arg in option_tuples])
1975+
args = {'option': arg_string, 'matches': options}
1976+
msg = _('ambiguous option: %(option)s could match %(matches)s')
1977+
raise ArgumentError(None, msg % args)
1978+
1979+
action, option_string, sep, explicit_arg = option_tuples[0]
19711980

19721981
# identify additional optionals in the same arg string
19731982
# (e.g. -xyz is the same as -x -y -z if no args are required)
@@ -2253,7 +2262,7 @@ def _parse_optional(self, arg_string):
22532262
# if the option string is present in the parser, return the action
22542263
if arg_string in self._option_string_actions:
22552264
action = self._option_string_actions[arg_string]
2256-
return action, arg_string, None, None
2265+
return [(action, arg_string, None, None)]
22572266

22582267
# if it's just a single character, it was meant to be positional
22592268
if len(arg_string) == 1:
@@ -2263,25 +2272,14 @@ def _parse_optional(self, arg_string):
22632272
option_string, sep, explicit_arg = arg_string.partition('=')
22642273
if sep and option_string in self._option_string_actions:
22652274
action = self._option_string_actions[option_string]
2266-
return action, option_string, sep, explicit_arg
2275+
return [(action, option_string, sep, explicit_arg)]
22672276

22682277
# search through all possible prefixes of the option string
22692278
# and all actions in the parser for possible interpretations
22702279
option_tuples = self._get_option_tuples(arg_string)
22712280

2272-
# if multiple actions match, the option string was ambiguous
2273-
if len(option_tuples) > 1:
2274-
options = ', '.join([option_string
2275-
for action, option_string, sep, explicit_arg in option_tuples])
2276-
args = {'option': arg_string, 'matches': options}
2277-
msg = _('ambiguous option: %(option)s could match %(matches)s')
2278-
raise ArgumentError(None, msg % args)
2279-
2280-
# if exactly one action matched, this segmentation is good,
2281-
# so return the parsed action
2282-
elif len(option_tuples) == 1:
2283-
option_tuple, = option_tuples
2284-
return option_tuple
2281+
if option_tuples:
2282+
return option_tuples
22852283

22862284
# if it was not found as an option, but it looks like a negative
22872285
# number, it was meant to be positional
@@ -2296,7 +2294,7 @@ def _parse_optional(self, arg_string):
22962294

22972295
# it was meant to be an optional but there is no such option
22982296
# in this parser (though it might be a valid option in a subparser)
2299-
return None, arg_string, None, None
2297+
return [(None, arg_string, None, None)]
23002298

23012299
def _get_option_tuples(self, option_string):
23022300
result = []
@@ -2319,7 +2317,9 @@ def _get_option_tuples(self, option_string):
23192317
# but multiple character options always have to have their argument
23202318
# separate
23212319
elif option_string[0] in chars and option_string[1] not in chars:
2322-
option_prefix = option_string
2320+
option_prefix, sep, explicit_arg = option_string.partition('=')
2321+
if not sep:
2322+
sep = explicit_arg = None
23232323
short_option_prefix = option_string[:2]
23242324
short_explicit_arg = option_string[2:]
23252325

@@ -2328,9 +2328,9 @@ def _get_option_tuples(self, option_string):
23282328
action = self._option_string_actions[option_string]
23292329
tup = action, option_string, '', short_explicit_arg
23302330
result.append(tup)
2331-
elif option_string.startswith(option_prefix):
2331+
elif self.allow_abbrev and option_string.startswith(option_prefix):
23322332
action = self._option_string_actions[option_string]
2333-
tup = action, option_string, None, None
2333+
tup = action, option_string, sep, explicit_arg
23342334
result.append(tup)
23352335

23362336
# shouldn't ever get here
@@ -2344,43 +2344,40 @@ def _get_nargs_pattern(self, action):
23442344
# in all examples below, we have to allow for '--' args
23452345
# which are represented as '-' in the pattern
23462346
nargs = action.nargs
2347+
# if this is an optional action, -- is not allowed
2348+
option = action.option_strings
23472349

23482350
# the default (None) is assumed to be a single argument
23492351
if nargs is None:
2350-
nargs_pattern = '(-*A-*)'
2352+
nargs_pattern = '([A])' if option else '(-*A-*)'
23512353

23522354
# allow zero or one arguments
23532355
elif nargs == OPTIONAL:
2354-
nargs_pattern = '(-*A?-*)'
2356+
nargs_pattern = '(A?)' if option else '(-*A?-*)'
23552357

23562358
# allow zero or more arguments
23572359
elif nargs == ZERO_OR_MORE:
2358-
nargs_pattern = '(-*[A-]*)'
2360+
nargs_pattern = '(A*)' if option else '(-*[A-]*)'
23592361

23602362
# allow one or more arguments
23612363
elif nargs == ONE_OR_MORE:
2362-
nargs_pattern = '(-*A[A-]*)'
2364+
nargs_pattern = '(A+)' if option else '(-*A[A-]*)'
23632365

23642366
# allow any number of options or arguments
23652367
elif nargs == REMAINDER:
2366-
nargs_pattern = '([-AO]*)'
2368+
nargs_pattern = '([AO]*)' if option else '(.*)'
23672369

23682370
# allow one argument followed by any number of options or arguments
23692371
elif nargs == PARSER:
2370-
nargs_pattern = '(-*A[-AO]*)'
2372+
nargs_pattern = '(A[AO]*)' if option else '(-*A[-AO]*)'
23712373

23722374
# suppress action, like nargs=0
23732375
elif nargs == SUPPRESS:
2374-
nargs_pattern = '(-*-*)'
2376+
nargs_pattern = '()' if option else '(-*)'
23752377

23762378
# all others should be integers
23772379
else:
2378-
nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs)
2379-
2380-
# if this is an optional action, -- is not allowed
2381-
if action.option_strings:
2382-
nargs_pattern = nargs_pattern.replace('-*', '')
2383-
nargs_pattern = nargs_pattern.replace('-', '')
2380+
nargs_pattern = '([AO]{%d})' % nargs if option else '((?:-*A){%d}-*)' % nargs
23842381

23852382
# return the pattern
23862383
return nargs_pattern
@@ -2483,21 +2480,17 @@ def _get_values(self, action, arg_strings):
24832480
value = action.const
24842481
else:
24852482
value = action.default
2486-
if isinstance(value, str):
2483+
if isinstance(value, str) and value is not SUPPRESS:
24872484
value = self._get_value(action, value)
2488-
self._check_value(action, value)
24892485

24902486
# when nargs='*' on a positional, if there were no command-line
24912487
# args, use the default if it is anything other than None
24922488
elif (not arg_strings and action.nargs == ZERO_OR_MORE and
24932489
not action.option_strings):
24942490
if action.default is not None:
24952491
value = action.default
2496-
self._check_value(action, value)
24972492
else:
2498-
# since arg_strings is always [] at this point
2499-
# there is no need to use self._check_value(action, value)
2500-
value = arg_strings
2493+
value = []
25012494

25022495
# single argument or optional argument produces a single value
25032496
elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:
@@ -2554,11 +2547,15 @@ def _get_value(self, action, arg_string):
25542547

25552548
def _check_value(self, action, value):
25562549
# converted value must be one of the choices (if specified)
2557-
if action.choices is not None and value not in action.choices:
2558-
args = {'value': value,
2559-
'choices': ', '.join(map(repr, action.choices))}
2560-
msg = _('invalid choice: %(value)r (choose from %(choices)s)')
2561-
raise ArgumentError(action, msg % args)
2550+
choices = action.choices
2551+
if choices is not None:
2552+
if isinstance(choices, str):
2553+
choices = iter(choices)
2554+
if value not in choices:
2555+
args = {'value': value,
2556+
'choices': ', '.join(map(repr, action.choices))}
2557+
msg = _('invalid choice: %(value)r (choose from %(choices)s)')
2558+
raise ArgumentError(action, msg % args)
25622559

25632560
# =======================
25642561
# Help-formatting methods

Lib/asyncio/staggered.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
class _Done(Exception):
1212
pass
1313

14-
async def staggered_race(coro_fns, delay):
14+
async def staggered_race(coro_fns, delay, *, loop=None):
1515
"""Run coroutines with staggered start times and take the first to finish.
1616
1717
This method takes an iterable of coroutine functions. The first one is
@@ -82,7 +82,13 @@ async def run_one_coro(this_index, coro_fn, this_failed):
8282
raise _Done
8383

8484
try:
85-
async with taskgroups.TaskGroup() as tg:
85+
tg = taskgroups.TaskGroup()
86+
# Intentionally override the loop in the TaskGroup to avoid
87+
# using the running loop, preserving backwards compatibility
88+
# TaskGroup only starts using `_loop` after `__aenter__`
89+
# so overriding it here is safe.
90+
tg._loop = loop
91+
async with tg:
8692
for this_index, coro_fn in enumerate(coro_fns):
8793
this_failed = locks.Event()
8894
exceptions.append(None)

Lib/functools.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,12 @@
1616

1717
from abc import get_cache_token
1818
from collections import namedtuple
19-
# import types, weakref # Deferred to single_dispatch()
19+
# import weakref # Deferred to single_dispatch()
2020
from operator import itemgetter
2121
from reprlib import recursive_repr
22-
from types import MethodType
22+
from types import GenericAlias, MethodType, MappingProxyType, UnionType
2323
from _thread import RLock
2424

25-
# Avoid importing types, so we can speedup import time
26-
GenericAlias = type(list[int])
27-
UnionType = type(int | str)
28-
2925
################################################################################
3026
### update_wrapper() and wraps() decorator
3127
################################################################################
@@ -901,7 +897,7 @@ def singledispatch(func):
901897
# There are many programs that use functools without singledispatch, so we
902898
# trade-off making singledispatch marginally slower for the benefit of
903899
# making start-up of such applications slightly faster.
904-
import types, weakref
900+
import weakref
905901

906902
registry = {}
907903
dispatch_cache = weakref.WeakKeyDictionary()
@@ -1002,7 +998,7 @@ def wrapper(*args, **kw):
1002998
registry[object] = func
1003999
wrapper.register = register
10041000
wrapper.dispatch = dispatch
1005-
wrapper.registry = types.MappingProxyType(registry)
1001+
wrapper.registry = MappingProxyType(registry)
10061002
wrapper._clear_cache = dispatch_cache.clear
10071003
update_wrapper(wrapper, func)
10081004
return wrapper

0 commit comments

Comments
 (0)