Skip to content

Commit 49c7e40

Browse files
authored
python 3.14.4 (#414)
1 parent cf5d34b commit 49c7e40

File tree

136 files changed

+1403
-596
lines changed

Some content is hidden

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

136 files changed

+1403
-596
lines changed

.github/workflows/CI_build.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ jobs:
4444
if: matrix.build_configuration == 'Release'
4545
working-directory: installer
4646
run: |
47-
$env:PYTHONBUILDDIR_ARM64='${{ github.workspace }}\packages\pythonarm64.3.14.3\tools'
48-
$env:PYTHONBUILDDIR_X64='${{ github.workspace }}\packages\python.3.14.3\tools'
49-
$env:PYTHONBUILDDIR='${{ github.workspace }}\packages\pythonx86.3.14.3\tools'
47+
$env:PYTHONBUILDDIR_ARM64='${{ github.workspace }}\packages\pythonarm64.3.14.4\tools'
48+
$env:PYTHONBUILDDIR_X64='${{ github.workspace }}\packages\python.3.14.4\tools'
49+
$env:PYTHONBUILDDIR='${{ github.workspace }}\packages\pythonx86.3.14.4\tools'
5050
Rename-Item -Path ".\buildPaths.bat.orig" -NewName "buildPaths.bat"
51-
dotnet tool install --global wix --version 6.0.2
51+
dotnet tool install --global wix --version 7.0.0
5252
.\buildAll.bat ${{ matrix.build_platform }}

PythonLib/full/_py_warnings.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -647,18 +647,18 @@ def __enter__(self):
647647
context = None
648648
self._filters = self._module.filters
649649
self._module.filters = self._filters[:]
650-
self._showwarning = self._module.showwarning
651650
self._showwarnmsg_impl = self._module._showwarnmsg_impl
651+
self._showwarning = self._module.showwarning
652652
self._module._filters_mutated_lock_held()
653653
if self._record:
654654
if _use_context:
655655
context.log = log = []
656656
else:
657657
log = []
658658
self._module._showwarnmsg_impl = log.append
659-
# Reset showwarning() to the default implementation to make sure
660-
# that _showwarnmsg() calls _showwarnmsg_impl()
661-
self._module.showwarning = self._module._showwarning_orig
659+
# Reset showwarning() to the default implementation to make sure
660+
# that _showwarnmsg() calls _showwarnmsg_impl()
661+
self._module.showwarning = self._module._showwarning_orig
662662
else:
663663
log = None
664664
if self._filter is not None:
@@ -673,8 +673,8 @@ def __exit__(self, *exc_info):
673673
self._module._warnings_context.set(self._saved_context)
674674
else:
675675
self._module.filters = self._filters
676-
self._module.showwarning = self._showwarning
677676
self._module._showwarnmsg_impl = self._showwarnmsg_impl
677+
self._module.showwarning = self._showwarning
678678
self._module._filters_mutated_lock_held()
679679

680680

PythonLib/full/_pyrepl/windows_console.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -283,18 +283,13 @@ def __write_changed_line(
283283
self._erase_to_end()
284284

285285
self.__write(newline[x_pos:])
286-
if wlen(newline) == self.width:
287-
# If we wrapped we want to start at the next line
288-
self._move_relative(0, y + 1)
289-
self.posxy = 0, y + 1
290-
else:
291-
self.posxy = wlen(newline), y
286+
self.posxy = min(wlen(newline), self.width - 1), y
292287

293-
if "\x1b" in newline or y != self.posxy[1] or '\x1a' in newline:
294-
# ANSI escape characters are present, so we can't assume
295-
# anything about the position of the cursor. Moving the cursor
296-
# to the left margin should work to get to a known position.
297-
self.move_cursor(0, y)
288+
if "\x1b" in newline or y != self.posxy[1] or '\x1a' in newline:
289+
# ANSI escape characters are present, so we can't assume
290+
# anything about the position of the cursor. Moving the cursor
291+
# to the left margin should work to get to a known position.
292+
self.move_cursor(0, y)
298293

299294
def _scroll(
300295
self, top: int, bottom: int, left: int | None = None, right: int | None = None

PythonLib/full/annotationlib.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,7 @@ def get_annotations(
919919
does not exist, the __annotate__ function is called. The
920920
FORWARDREF format uses __annotations__ if it exists and can be
921921
evaluated, and otherwise falls back to calling the __annotate__ function.
922-
The SOURCE format tries __annotate__ first, and falls back to
922+
The STRING format tries __annotate__ first, and falls back to
923923
using __annotations__, stringified using annotations_to_string().
924924
925925
This function handles several details for you:
@@ -1037,13 +1037,26 @@ def get_annotations(
10371037
obj_globals = obj_locals = unwrap = None
10381038

10391039
if unwrap is not None:
1040+
# Use an id-based visited set to detect cycles in the __wrapped__
1041+
# and functools.partial.func chain (e.g. f.__wrapped__ = f).
1042+
# On cycle detection we stop and use whatever __globals__ we have
1043+
# found so far, mirroring the approach of inspect.unwrap().
1044+
_seen_ids = {id(unwrap)}
10401045
while True:
10411046
if hasattr(unwrap, "__wrapped__"):
1042-
unwrap = unwrap.__wrapped__
1047+
candidate = unwrap.__wrapped__
1048+
if id(candidate) in _seen_ids:
1049+
break
1050+
_seen_ids.add(id(candidate))
1051+
unwrap = candidate
10431052
continue
10441053
if functools := sys.modules.get("functools"):
10451054
if isinstance(unwrap, functools.partial):
1046-
unwrap = unwrap.func
1055+
candidate = unwrap.func
1056+
if id(candidate) in _seen_ids:
1057+
break
1058+
_seen_ids.add(id(candidate))
1059+
unwrap = candidate
10471060
continue
10481061
break
10491062
if hasattr(unwrap, "__globals__"):

PythonLib/full/argparse.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ def _copy_items(items):
149149
return copy.copy(items)
150150

151151

152+
def _identity(value):
153+
return value
154+
155+
152156
# ===============
153157
# Formatting Help
154158
# ===============
@@ -200,7 +204,7 @@ def _set_color(self, color):
200204
self._decolor = decolor
201205
else:
202206
self._theme = get_theme(force_no_color=True).argparse
203-
self._decolor = lambda text: text
207+
self._decolor = _identity
204208

205209
# ===============================
206210
# Section and indentation methods
@@ -1903,9 +1907,7 @@ def __init__(self,
19031907
self._subparsers = None
19041908

19051909
# register types
1906-
def identity(string):
1907-
return string
1908-
self.register('type', None, identity)
1910+
self.register('type', None, _identity)
19091911

19101912
# add help argument if necessary
19111913
# (using explicit default to override global argument_default)

PythonLib/full/asyncio/base_events.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,6 +1345,17 @@ async def start_tls(self, transport, protocol, sslcontext, *,
13451345
# have a chance to get called before "ssl_protocol.connection_made()".
13461346
transport.pause_reading()
13471347

1348+
# gh-142352: move buffered StreamReader data to SSLProtocol
1349+
if server_side:
1350+
from .streams import StreamReaderProtocol
1351+
if isinstance(protocol, StreamReaderProtocol):
1352+
stream_reader = getattr(protocol, '_stream_reader', None)
1353+
if stream_reader is not None:
1354+
buffer = stream_reader._buffer
1355+
if buffer:
1356+
ssl_protocol._incoming.write(buffer)
1357+
buffer.clear()
1358+
13481359
transport.set_protocol(ssl_protocol)
13491360
conmade_cb = self.call_soon(ssl_protocol.connection_made, transport)
13501361
resume_cb = self.call_soon(transport.resume_reading)

PythonLib/full/asyncio/base_subprocess.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ def _try_finish(self):
265265
# to avoid hanging forever in self._wait as otherwise _exit_waiters
266266
# would never be woken up, we wake them up here.
267267
for waiter in self._exit_waiters:
268-
if not waiter.cancelled():
268+
if not waiter.done():
269269
waiter.set_result(self._returncode)
270270
if all(p is not None and p.disconnected
271271
for p in self._pipes.values()):
@@ -278,7 +278,7 @@ def _call_connection_lost(self, exc):
278278
finally:
279279
# wake up futures waiting for wait()
280280
for waiter in self._exit_waiters:
281-
if not waiter.cancelled():
281+
if not waiter.done():
282282
waiter.set_result(self._returncode)
283283
self._exit_waiters = None
284284
self._loop = None

PythonLib/full/asyncio/queues.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class Queue(mixins._LoopBoundMixin):
3737
is an integer greater than 0, then "await put()" will block when the
3838
queue reaches maxsize, until an item is removed by get().
3939
40-
Unlike the standard library Queue, you can reliably know this Queue's size
40+
Unlike queue.Queue, you can reliably know this Queue's size
4141
with qsize(), since your single-threaded asyncio application won't be
4242
interrupted between calling qsize() and doing an operation on the Queue.
4343
"""

PythonLib/full/asyncio/windows_utils.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import msvcrt
1111
import os
1212
import subprocess
13-
import tempfile
1413
import warnings
1514

1615

@@ -24,17 +23,14 @@
2423
PIPE = subprocess.PIPE
2524
STDOUT = subprocess.STDOUT
2625
_mmap_counter = itertools.count()
26+
_MAX_PIPE_ATTEMPTS = 20
2727

2828

2929
# Replacement for os.pipe() using handles instead of fds
3030

3131

3232
def pipe(*, duplex=False, overlapped=(True, True), bufsize=BUFSIZE):
3333
"""Like os.pipe() but with overlapped support and using handles not fds."""
34-
address = tempfile.mktemp(
35-
prefix=r'\\.\pipe\python-pipe-{:d}-{:d}-'.format(
36-
os.getpid(), next(_mmap_counter)))
37-
3834
if duplex:
3935
openmode = _winapi.PIPE_ACCESS_DUPLEX
4036
access = _winapi.GENERIC_READ | _winapi.GENERIC_WRITE
@@ -56,9 +52,20 @@ def pipe(*, duplex=False, overlapped=(True, True), bufsize=BUFSIZE):
5652

5753
h1 = h2 = None
5854
try:
59-
h1 = _winapi.CreateNamedPipe(
60-
address, openmode, _winapi.PIPE_WAIT,
61-
1, obsize, ibsize, _winapi.NMPWAIT_WAIT_FOREVER, _winapi.NULL)
55+
for attempts in itertools.count():
56+
address = r'\\.\pipe\python-pipe-{:d}-{:d}-{}'.format(
57+
os.getpid(), next(_mmap_counter), os.urandom(8).hex())
58+
try:
59+
h1 = _winapi.CreateNamedPipe(
60+
address, openmode, _winapi.PIPE_WAIT,
61+
1, obsize, ibsize, _winapi.NMPWAIT_WAIT_FOREVER, _winapi.NULL)
62+
break
63+
except OSError as e:
64+
if attempts >= _MAX_PIPE_ATTEMPTS:
65+
raise
66+
if e.winerror not in (_winapi.ERROR_PIPE_BUSY,
67+
_winapi.ERROR_ACCESS_DENIED):
68+
raise
6269

6370
h2 = _winapi.CreateFile(
6471
address, access, 0, _winapi.NULL, _winapi.OPEN_EXISTING,

PythonLib/full/ctypes/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,8 @@ def _load_library(self, name, mode, handle, winmode):
470470
if name and name.endswith(")") and ".a(" in name:
471471
mode |= _os.RTLD_MEMBER | _os.RTLD_NOW
472472
self._name = name
473+
if handle is not None:
474+
return handle
473475
return _dlopen(name, mode)
474476

475477
def __repr__(self):

0 commit comments

Comments
 (0)