Skip to content

Commit 3384bb5

Browse files
generatedunixname1734921407115435meta-codesync[bot]
authored andcommitted
Sync pre-release CPython 3.15 branch from GitHub (2026-07-25)
Summary: Imported python/cpython `3.15.0b4+dev` from upstream rev [`1667a6c`](https://www.github.com/python/cpython/commit/1667a6c2acb022ecca37d3dc68b3d67ef186215e) (committed 2026-07-25 15:17:11+00:00). # Commit Info - Base: (`3.15.0b4+dev`) - [`b4d0b26`](https://www.github.com/python/cpython/commit/b4d0b2621a97f8433e25bb88cbd9c815fff7abe0) (commit date: 2026-07-25 03:36:48+00:00) - Imported: (`3.15.0b4+dev`) - [`1667a6c`](https://www.github.com/python/cpython/commit/1667a6c2acb022ecca37d3dc68b3d67ef186215e) (commit date: 2026-07-25 15:17:11+00:00) # Noteworthy file changes - Low-signal files (3 added) (NEWS.d, docs, .github) Complete list of added/removed files: https://www.internalfb.com/intern/everpaste/?color=0&handle=GIaiuCQuFzf_u90DAIt02g83aewabr0LAAAz Differential Revision: D113686228 fbshipit-source-id: 567d957526eb988090a7eb7f80fe18abb7341426
1 parent e1e319c commit 3384bb5

12 files changed

Lines changed: 166 additions & 7 deletions

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,14 @@ PCbuild/*-pgo
124124
PCbuild/*.VC.db
125125
PCbuild/*.VC.opendb
126126
PCbuild/amd64/
127+
PCbuild/amd64t/
127128
PCbuild/arm32/
129+
PCbuild/arm32t/
128130
PCbuild/arm64/
131+
PCbuild/arm64t/
129132
PCbuild/obj/
130133
PCbuild/win32/
134+
PCbuild/win32t/
131135
Tools/unicode/data/
132136
/autom4te.cache
133137
/build/

Doc/library/asyncio-eventloop.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1884,6 +1884,12 @@ Do not instantiate the :class:`Server` class directly.
18841884
Wait until the :meth:`close` method completes and all active
18851885
connections have finished.
18861886

1887+
.. versionchanged:: 3.12
1888+
``wait_closed()`` now waits until the server is closed and
1889+
all active connections have finished. Previously, it returned
1890+
immediately if the server was already closed, even if
1891+
connections were still active.
1892+
18871893
.. attribute:: sockets
18881894

18891895
List of socket-like objects, ``asyncio.trsock.TransportSocket``, which

Doc/license.rst

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,3 +1216,52 @@ license::
12161216
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12171217
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
12181218
DAMAGE.
1219+
1220+
1221+
Unicode Character Database
1222+
--------------------------
1223+
1224+
An extract of the `Unicode Character Database <https://www.unicode.org/ucd/>`__,
1225+
converted to an internal format, is used by the :mod:`unicodedata` module and
1226+
for the Unicode support of the :class:`str` type. The original Unicode data
1227+
files are distributed under the `Unicode License <https://www.unicode.org/license.txt>`__::
1228+
1229+
UNICODE LICENSE V3
1230+
1231+
COPYRIGHT AND PERMISSION NOTICE
1232+
1233+
Copyright © 1991-2026 Unicode, Inc.
1234+
1235+
NOTICE TO USER: Carefully read the following legal agreement. BY
1236+
DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
1237+
SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
1238+
TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
1239+
DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
1240+
1241+
Permission is hereby granted, free of charge, to any person obtaining a
1242+
copy of data files and any associated documentation (the "Data Files") or
1243+
software and any associated documentation (the "Software") to deal in the
1244+
Data Files or Software without restriction, including without limitation
1245+
the rights to use, copy, modify, merge, publish, distribute, and/or sell
1246+
copies of the Data Files or Software, and to permit persons to whom the
1247+
Data Files or Software are furnished to do so, provided that either (a)
1248+
this copyright and permission notice appear with all copies of the Data
1249+
Files or Software, or (b) this copyright and permission notice appear in
1250+
associated Documentation.
1251+
1252+
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
1253+
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1254+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
1255+
THIRD PARTY RIGHTS.
1256+
1257+
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
1258+
BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
1259+
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1260+
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1261+
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
1262+
FILES OR SOFTWARE.
1263+
1264+
Except as contained in this notice, the name of a copyright holder shall
1265+
not be used in advertising or otherwise to promote the sale, use or other
1266+
dealings in these Data Files or Software without prior written
1267+
authorization of the copyright holder.

Lib/asyncio/streams.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ def _stream_reader(self):
216216
def _replace_transport(self, transport):
217217
self._transport = transport
218218
self._over_ssl = transport.get_extra_info('sslcontext') is not None
219+
reader = self._stream_reader
220+
if reader is not None:
221+
reader._replace_transport(transport)
219222

220223
def connection_made(self, transport):
221224
if self._reject_connection:
@@ -475,6 +478,10 @@ def set_transport(self, transport):
475478
assert self._transport is None, 'Transport already set'
476479
self._transport = transport
477480

481+
def _replace_transport(self, transport):
482+
assert self._transport is not None, 'Transport not set'
483+
self._transport = transport
484+
478485
def _maybe_resume_transport(self):
479486
if self._paused and len(self._buffer) <= self._limit:
480487
self._paused = False

Lib/asyncio/unix_events.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,8 @@ def __init__(self, loop, pipe, protocol, waiter=None, extra=None):
639639
self._conn_lost = 0
640640
self._closing = False # Set when close() or write_eof() called.
641641

642-
mode = os.fstat(self._fileno).st_mode
642+
pipe_stat = os.fstat(self._fileno)
643+
mode = pipe_stat.st_mode
643644
is_char = stat.S_ISCHR(mode)
644645
is_fifo = stat.S_ISFIFO(mode)
645646
is_socket = stat.S_ISSOCK(mode)
@@ -656,7 +657,19 @@ def __init__(self, loop, pipe, protocol, waiter=None, extra=None):
656657
# On AIX, the reader trick (to be notified when the read end of the
657658
# socket is closed) only works for sockets. On other platforms it
658659
# works for pipes and sockets. (Exception: OS X 10.4? Issue #19294.)
659-
if is_socket or (is_fifo and not sys.platform.startswith("aix")):
660+
# On macOS, the trick misfires for named FIFOs (but not for pipes
661+
# created with os.pipe(), which have st_nlink == 0): the write end
662+
# polls as readable whenever unread data sits in the FIFO, and no
663+
# event is delivered when the read end is closed, so it can only
664+
# ever report a false disconnection (gh-145030). The same xnu
665+
# behaviour applies on iOS/tvOS/watchOS (sys.platform is not
666+
# "darwin" there).
667+
is_named_fifo_on_apple = (
668+
sys.platform in {"darwin", "ios", "tvos", "watchos"}
669+
and is_fifo and pipe_stat.st_nlink > 0)
670+
if is_socket or (is_fifo
671+
and not sys.platform.startswith("aix")
672+
and not is_named_fifo_on_apple):
660673
# only start reading when connection_made() has been called
661674
self._loop.call_soon(self._loop._add_reader,
662675
self._fileno, self._read_ready)

Lib/test/test_asyncio/test_events.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1725,6 +1725,48 @@ def reader(data):
17251725
self.loop.run_until_complete(proto.done)
17261726
self.assertEqual('CLOSED', proto.state)
17271727

1728+
@unittest.skipUnless(sys.platform != 'win32',
1729+
"Don't support pipes for Windows")
1730+
@unittest.skipUnless(hasattr(os, 'mkfifo'), 'requires os.mkfifo()')
1731+
def test_write_named_fifo_unread_data(self):
1732+
# gh-145030: on macOS, the write end of a named FIFO polls as
1733+
# readable while unread data sits in the FIFO, which made the
1734+
# transport misinterpret the event as the reader hanging up
1735+
# and close itself.
1736+
path = os_helper.TESTFN
1737+
os.mkfifo(path)
1738+
self.assertNotEqual(os.stat(path).st_nlink, 0)
1739+
self.addCleanup(os_helper.unlink, path)
1740+
rfd = os.open(path, os.O_RDONLY | os.O_NONBLOCK)
1741+
self.addCleanup(os.close, rfd)
1742+
wfd = os.open(path, os.O_WRONLY | os.O_NONBLOCK)
1743+
pipeobj = io.open(wfd, 'wb', 1024)
1744+
1745+
proto = MyWritePipeProto(loop=self.loop)
1746+
connect = self.loop.connect_write_pipe(lambda: proto, pipeobj)
1747+
transport, p = self.loop.run_until_complete(connect)
1748+
self.assertIs(p, proto)
1749+
self.assertEqual('CONNECTED', proto.state)
1750+
1751+
transport.write(b'1')
1752+
# Iterate the event loop while the data stays unread in the FIFO;
1753+
# the transport must not detect a false disconnection.
1754+
for _ in range(10):
1755+
test_utils.run_briefly(self.loop)
1756+
self.assertEqual('CONNECTED', proto.state)
1757+
self.assertFalse(transport.is_closing())
1758+
self.assertEqual(b'1', os.read(rfd, 1024))
1759+
1760+
transport.write(b'2345')
1761+
for _ in range(10):
1762+
test_utils.run_briefly(self.loop)
1763+
self.assertEqual('CONNECTED', proto.state)
1764+
self.assertEqual(b'2345', os.read(rfd, 1024))
1765+
1766+
transport.close()
1767+
self.loop.run_until_complete(proto.done)
1768+
self.assertEqual('CLOSED', proto.state)
1769+
17281770
@unittest.skipUnless(sys.platform != 'win32',
17291771
"Don't support pipes for Windows")
17301772
def test_write_pipe_disconnect_on_close(self):

Lib/test/test_asyncio/test_streams.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,34 @@ async def run_test():
861861
self.loop.run_until_complete(run_test())
862862
self.assertEqual(messages, [])
863863

864+
def test_streamwriter_start_tls_updates_reader_transport(self):
865+
reader = asyncio.StreamReader(loop=self.loop)
866+
protocol = asyncio.StreamReaderProtocol(reader, loop=self.loop)
867+
old_transport = mock.Mock()
868+
old_transport.get_extra_info.return_value = None
869+
old_transport.is_closing.return_value = False
870+
protocol.connection_made(old_transport)
871+
872+
writer = asyncio.StreamWriter(old_transport, protocol, reader, self.loop)
873+
874+
ssl_context = mock.sentinel.ssl_context
875+
new_transport = mock.Mock()
876+
new_transport.get_extra_info.return_value = ssl_context
877+
self.loop.start_tls = mock.AsyncMock(return_value=new_transport)
878+
879+
self.loop.run_until_complete(writer.start_tls(ssl_context))
880+
881+
self.loop.start_tls.assert_awaited_once_with(
882+
old_transport, protocol, ssl_context,
883+
server_side=False, server_hostname=None,
884+
ssl_handshake_timeout=None,
885+
ssl_shutdown_timeout=None,
886+
)
887+
self.assertIs(writer.transport, new_transport)
888+
self.assertIs(protocol._transport, new_transport)
889+
self.assertIs(reader._transport, new_transport)
890+
self.assertTrue(protocol._over_ssl)
891+
864892
def test_streamreader_constructor_without_loop(self):
865893
with self.assertRaisesRegex(RuntimeError, 'no current event loop'):
866894
asyncio.StreamReader()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix interpreter crash while deallocating objects of :class:`asyncio.Task` on
2+
free-threaded builds. Contributed by Sergey Miryanov.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix ``asyncio.StreamWriter.start_tls()`` to keep the linked
2+
``StreamReader`` transport in sync with the upgraded transport.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix :mod:`asyncio` write pipe transports for named FIFOs on macOS. Unread
2+
data sitting in the FIFO made the transport misinterpret a poll event as
3+
the reader disconnecting, wrongly closing the transport.

0 commit comments

Comments
 (0)