Skip to content

Commit 11774d6

Browse files
committed
update to python 3.12.3
1 parent 6851859 commit 11774d6

File tree

122 files changed

+1654
-1203
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

122 files changed

+1654
-1203
lines changed

.github/workflows/CI_build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ jobs:
4343
if: matrix.build_configuration == 'Release'
4444
working-directory: installer
4545
run: |
46-
$env:PYTHONBUILDDIR_X64='..\packages\python.3.12.2\tools'
47-
$env:PYTHONBUILDDIR='..\packages\pythonx86.3.12.2\tools'
46+
$env:PYTHONBUILDDIR_X64='..\packages\python.3.12.3\tools'
47+
$env:PYTHONBUILDDIR='..\packages\pythonx86.3.12.3\tools'
4848
Rename-Item -Path ".\buildPaths.bat.orig" -NewName "buildPaths.bat"
4949
$env:WIX_PATH="C:\Program Files (x86)\WiX Toolset v3.11\bin"
5050
$env:PATH = $env:PATH + ';' + $env:WIX_PATH

PythonLib/full/_pyio.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1209,7 +1209,8 @@ def _readinto(self, buf, read1):
12091209
return written
12101210

12111211
def tell(self):
1212-
return _BufferedIOMixin.tell(self) - len(self._read_buf) + self._read_pos
1212+
# GH-95782: Keep return value non-negative
1213+
return max(_BufferedIOMixin.tell(self) - len(self._read_buf) + self._read_pos, 0)
12131214

12141215
def seek(self, pos, whence=0):
12151216
if whence not in valid_seek_flags:

PythonLib/full/argparse.py

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ def format_help(self):
225225
# add the heading if the section was non-empty
226226
if self.heading is not SUPPRESS and self.heading is not None:
227227
current_indent = self.formatter._current_indent
228-
heading = '%*s%s:\n' % (current_indent, '', self.heading)
228+
heading_text = _('%(heading)s:') % dict(heading=self.heading)
229+
heading = '%*s%s\n' % (current_indent, '', heading_text)
229230
else:
230231
heading = ''
231232

@@ -415,6 +416,8 @@ def _format_actions_usage(self, actions, groups):
415416
suppressed_actions_count += 1
416417

417418
exposed_actions_count = group_action_count - suppressed_actions_count
419+
if not exposed_actions_count:
420+
continue
418421

419422
if not group.required:
420423
if start in inserts:
@@ -720,7 +723,7 @@ def _get_help_string(self, action):
720723
if action.default is not SUPPRESS:
721724
defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
722725
if action.option_strings or action.nargs in defaulting_nargs:
723-
help += ' (default: %(default)s)'
726+
help += _(' (default: %(default)s)')
724727
return help
725728

726729

@@ -1149,7 +1152,9 @@ def __init__(self,
11491152
version=None,
11501153
dest=SUPPRESS,
11511154
default=SUPPRESS,
1152-
help="show program's version number and exit"):
1155+
help=None):
1156+
if help is None:
1157+
help = _("show program's version number and exit")
11531158
super(_VersionAction, self).__init__(
11541159
option_strings=option_strings,
11551160
dest=dest,
@@ -2004,7 +2009,7 @@ def consume_optional(start_index):
20042009

20052010
# get the optional identified at this index
20062011
option_tuple = option_string_indices[start_index]
2007-
action, option_string, explicit_arg = option_tuple
2012+
action, option_string, sep, explicit_arg = option_tuple
20082013

20092014
# identify additional optionals in the same arg string
20102015
# (e.g. -xyz is the same as -x -y -z if no args are required)
@@ -2031,18 +2036,27 @@ def consume_optional(start_index):
20312036
and option_string[1] not in chars
20322037
and explicit_arg != ''
20332038
):
2039+
if sep or explicit_arg[0] in chars:
2040+
msg = _('ignored explicit argument %r')
2041+
raise ArgumentError(action, msg % explicit_arg)
20342042
action_tuples.append((action, [], option_string))
20352043
char = option_string[0]
20362044
option_string = char + explicit_arg[0]
2037-
new_explicit_arg = explicit_arg[1:] or None
20382045
optionals_map = self._option_string_actions
20392046
if option_string in optionals_map:
20402047
action = optionals_map[option_string]
2041-
explicit_arg = new_explicit_arg
2048+
explicit_arg = explicit_arg[1:]
2049+
if not explicit_arg:
2050+
sep = explicit_arg = None
2051+
elif explicit_arg[0] == '=':
2052+
sep = '='
2053+
explicit_arg = explicit_arg[1:]
2054+
else:
2055+
sep = ''
20422056
else:
2043-
msg = _('ignored explicit argument %r')
2044-
raise ArgumentError(action, msg % explicit_arg)
2045-
2057+
extras.append(char + explicit_arg)
2058+
stop = start_index + 1
2059+
break
20462060
# if the action expect exactly one argument, we've
20472061
# successfully matched the option; exit the loop
20482062
elif arg_count == 1:
@@ -2262,18 +2276,17 @@ def _parse_optional(self, arg_string):
22622276
# if the option string is present in the parser, return the action
22632277
if arg_string in self._option_string_actions:
22642278
action = self._option_string_actions[arg_string]
2265-
return action, arg_string, None
2279+
return action, arg_string, None, None
22662280

22672281
# if it's just a single character, it was meant to be positional
22682282
if len(arg_string) == 1:
22692283
return None
22702284

22712285
# if the option string before the "=" is present, return the action
2272-
if '=' in arg_string:
2273-
option_string, explicit_arg = arg_string.split('=', 1)
2274-
if option_string in self._option_string_actions:
2275-
action = self._option_string_actions[option_string]
2276-
return action, option_string, explicit_arg
2286+
option_string, sep, explicit_arg = arg_string.partition('=')
2287+
if sep and option_string in self._option_string_actions:
2288+
action = self._option_string_actions[option_string]
2289+
return action, option_string, sep, explicit_arg
22772290

22782291
# search through all possible prefixes of the option string
22792292
# and all actions in the parser for possible interpretations
@@ -2282,7 +2295,7 @@ def _parse_optional(self, arg_string):
22822295
# if multiple actions match, the option string was ambiguous
22832296
if len(option_tuples) > 1:
22842297
options = ', '.join([option_string
2285-
for action, option_string, explicit_arg in option_tuples])
2298+
for action, option_string, sep, explicit_arg in option_tuples])
22862299
args = {'option': arg_string, 'matches': options}
22872300
msg = _('ambiguous option: %(option)s could match %(matches)s')
22882301
self.error(msg % args)
@@ -2306,7 +2319,7 @@ def _parse_optional(self, arg_string):
23062319

23072320
# it was meant to be an optional but there is no such option
23082321
# in this parser (though it might be a valid option in a subparser)
2309-
return None, arg_string, None
2322+
return None, arg_string, None, None
23102323

23112324
def _get_option_tuples(self, option_string):
23122325
result = []
@@ -2316,34 +2329,31 @@ def _get_option_tuples(self, option_string):
23162329
chars = self.prefix_chars
23172330
if option_string[0] in chars and option_string[1] in chars:
23182331
if self.allow_abbrev:
2319-
if '=' in option_string:
2320-
option_prefix, explicit_arg = option_string.split('=', 1)
2321-
else:
2322-
option_prefix = option_string
2323-
explicit_arg = None
2332+
option_prefix, sep, explicit_arg = option_string.partition('=')
2333+
if not sep:
2334+
sep = explicit_arg = None
23242335
for option_string in self._option_string_actions:
23252336
if option_string.startswith(option_prefix):
23262337
action = self._option_string_actions[option_string]
2327-
tup = action, option_string, explicit_arg
2338+
tup = action, option_string, sep, explicit_arg
23282339
result.append(tup)
23292340

23302341
# single character options can be concatenated with their arguments
23312342
# but multiple character options always have to have their argument
23322343
# separate
23332344
elif option_string[0] in chars and option_string[1] not in chars:
23342345
option_prefix = option_string
2335-
explicit_arg = None
23362346
short_option_prefix = option_string[:2]
23372347
short_explicit_arg = option_string[2:]
23382348

23392349
for option_string in self._option_string_actions:
23402350
if option_string == short_option_prefix:
23412351
action = self._option_string_actions[option_string]
2342-
tup = action, option_string, short_explicit_arg
2352+
tup = action, option_string, '', short_explicit_arg
23432353
result.append(tup)
23442354
elif option_string.startswith(option_prefix):
23452355
action = self._option_string_actions[option_string]
2346-
tup = action, option_string, explicit_arg
2356+
tup = action, option_string, None, None
23472357
result.append(tup)
23482358

23492359
# shouldn't ever get here

PythonLib/full/ast.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,14 +1268,18 @@ def visit_JoinedStr(self, node):
12681268
quote_type = quote_types[0]
12691269
self.write(f"{quote_type}{value}{quote_type}")
12701270

1271-
def _write_fstring_inner(self, node, scape_newlines=False):
1271+
def _write_fstring_inner(self, node, is_format_spec=False):
12721272
if isinstance(node, JoinedStr):
12731273
# for both the f-string itself, and format_spec
12741274
for value in node.values:
1275-
self._write_fstring_inner(value, scape_newlines=scape_newlines)
1275+
self._write_fstring_inner(value, is_format_spec=is_format_spec)
12761276
elif isinstance(node, Constant) and isinstance(node.value, str):
12771277
value = node.value.replace("{", "{{").replace("}", "}}")
1278-
if scape_newlines:
1278+
1279+
if is_format_spec:
1280+
value = value.replace("\\", "\\\\")
1281+
value = value.replace("'", "\\'")
1282+
value = value.replace('"', '\\"')
12791283
value = value.replace("\n", "\\n")
12801284
self.write(value)
12811285
elif isinstance(node, FormattedValue):
@@ -1299,10 +1303,7 @@ def unparse_inner(inner):
12991303
self.write(f"!{chr(node.conversion)}")
13001304
if node.format_spec:
13011305
self.write(":")
1302-
self._write_fstring_inner(
1303-
node.format_spec,
1304-
scape_newlines=True
1305-
)
1306+
self._write_fstring_inner(node.format_spec, is_format_spec=True)
13061307

13071308
def visit_Name(self, node):
13081309
self.write(node.id)

PythonLib/full/asyncio/base_events.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
from . import sslproto
4646
from . import staggered
4747
from . import tasks
48+
from . import timeouts
4849
from . import transports
4950
from . import trsock
5051
from .log import logger
@@ -596,23 +597,24 @@ async def shutdown_default_executor(self, timeout=None):
596597
thread = threading.Thread(target=self._do_shutdown, args=(future,))
597598
thread.start()
598599
try:
599-
await future
600-
finally:
601-
thread.join(timeout)
602-
603-
if thread.is_alive():
600+
async with timeouts.timeout(timeout):
601+
await future
602+
except TimeoutError:
604603
warnings.warn("The executor did not finishing joining "
605-
f"its threads within {timeout} seconds.",
606-
RuntimeWarning, stacklevel=2)
604+
f"its threads within {timeout} seconds.",
605+
RuntimeWarning, stacklevel=2)
607606
self._default_executor.shutdown(wait=False)
607+
else:
608+
thread.join()
608609

609610
def _do_shutdown(self, future):
610611
try:
611612
self._default_executor.shutdown(wait=True)
612613
if not self.is_closed():
613-
self.call_soon_threadsafe(future.set_result, None)
614+
self.call_soon_threadsafe(futures._set_result_unless_cancelled,
615+
future, None)
614616
except Exception as ex:
615-
if not self.is_closed():
617+
if not self.is_closed() and not future.cancelled():
616618
self.call_soon_threadsafe(future.set_exception, ex)
617619

618620
def _check_running(self):

PythonLib/full/asyncio/tasks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ async def wait_for(fut, timeout):
480480
481481
If the wait is cancelled, the task is also cancelled.
482482
483-
If the task supresses the cancellation and returns a value instead,
483+
If the task suppresses the cancellation and returns a value instead,
484484
that value is returned.
485485
486486
This function is a coroutine.

PythonLib/full/asyncio/windows_events.py

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import _overlapped
99
import _winapi
1010
import errno
11+
from functools import partial
1112
import math
1213
import msvcrt
1314
import socket
@@ -323,13 +324,13 @@ def run_forever(self):
323324
if self._self_reading_future is not None:
324325
ov = self._self_reading_future._ov
325326
self._self_reading_future.cancel()
326-
# self_reading_future was just cancelled so if it hasn't been
327-
# finished yet, it never will be (it's possible that it has
328-
# already finished and its callback is waiting in the queue,
329-
# where it could still happen if the event loop is restarted).
330-
# Unregister it otherwise IocpProactor.close will wait for it
331-
# forever
332-
if ov is not None:
327+
# self_reading_future always uses IOCP, so even though it's
328+
# been cancelled, we need to make sure that the IOCP message
329+
# is received so that the kernel is not holding on to the
330+
# memory, possibly causing memory corruption later. Only
331+
# unregister it if IO is complete in all respects. Otherwise
332+
# we need another _poll() later to complete the IO.
333+
if ov is not None and not ov.pending:
333334
self._proactor._unregister(ov)
334335
self._self_reading_future = None
335336

@@ -466,6 +467,18 @@ def finish_socket_func(trans, key, ov):
466467
else:
467468
raise
468469

470+
@classmethod
471+
def _finish_recvfrom(cls, trans, key, ov, *, empty_result):
472+
try:
473+
return cls.finish_socket_func(trans, key, ov)
474+
except OSError as exc:
475+
# WSARecvFrom will report ERROR_PORT_UNREACHABLE when the same
476+
# socket is used to send to an address that is not listening.
477+
if exc.winerror == _overlapped.ERROR_PORT_UNREACHABLE:
478+
return empty_result, None
479+
else:
480+
raise
481+
469482
def recv(self, conn, nbytes, flags=0):
470483
self._register_with_iocp(conn)
471484
ov = _overlapped.Overlapped(NULL)
@@ -500,7 +513,8 @@ def recvfrom(self, conn, nbytes, flags=0):
500513
except BrokenPipeError:
501514
return self._result((b'', None))
502515

503-
return self._register(ov, conn, self.finish_socket_func)
516+
return self._register(ov, conn, partial(self._finish_recvfrom,
517+
empty_result=b''))
504518

505519
def recvfrom_into(self, conn, buf, flags=0):
506520
self._register_with_iocp(conn)
@@ -510,17 +524,8 @@ def recvfrom_into(self, conn, buf, flags=0):
510524
except BrokenPipeError:
511525
return self._result((0, None))
512526

513-
def finish_recv(trans, key, ov):
514-
try:
515-
return ov.getresult()
516-
except OSError as exc:
517-
if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
518-
_overlapped.ERROR_OPERATION_ABORTED):
519-
raise ConnectionResetError(*exc.args)
520-
else:
521-
raise
522-
523-
return self._register(ov, conn, finish_recv)
527+
return self._register(ov, conn, partial(self._finish_recvfrom,
528+
empty_result=0))
524529

525530
def sendto(self, conn, buf, flags=0, addr=None):
526531
self._register_with_iocp(conn)

PythonLib/full/collections/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,8 @@ def elements(self):
638638
>>> sorted(c.elements())
639639
['A', 'A', 'B', 'B', 'C', 'C']
640640
641-
# Knuth's example for prime factors of 1836: 2**2 * 3**3 * 17**1
641+
Knuth's example for prime factors of 1836: 2**2 * 3**3 * 17**1
642+
642643
>>> import math
643644
>>> prime_factors = Counter({2: 2, 3: 3, 17: 1})
644645
>>> math.prod(prime_factors.elements())
@@ -679,7 +680,7 @@ def update(self, iterable=None, /, **kwds):
679680
680681
'''
681682
# The regular dict.update() operation makes no sense here because the
682-
# replace behavior results in the some of original untouched counts
683+
# replace behavior results in some of the original untouched counts
683684
# being mixed-in with all of the other counts for a mismash that
684685
# doesn't have a straight-forward interpretation in most counting
685686
# contexts. Instead, we implement straight-addition. Both the inputs

0 commit comments

Comments
 (0)