Skip to content

Commit f4cb658

Browse files
authored
Merge branch 'main' into 62-Concurrent-kwargs-growth-ft
2 parents e29aaa4 + 1617cbe commit f4cb658

42 files changed

Lines changed: 511 additions & 94 deletions

Some content is hidden

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

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ jobs:
338338
with:
339339
persist-credentials: false
340340
- name: Build and test
341-
run: JAVA_HOME="${JAVA_HOME_21_X64:-$JAVA_HOME_21_arm64}" python3 Platforms/Android ci --fast-ci ${{ matrix.arch }}-linux-android
341+
run: python3 Platforms/Android ci --fast-ci ${{ matrix.arch }}-linux-android
342342

343343
build-ios:
344344
name: iOS

Doc/library/asyncio-eventloop.rst

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,7 @@ Creating network servers
838838
*, sock=None, backlog=100, ssl=None, \
839839
ssl_handshake_timeout=None, \
840840
ssl_shutdown_timeout=None, \
841-
start_serving=True, cleanup_socket=True)
841+
start_serving=True, cleanup_socket=True, mode=None)
842842
:async:
843843
844844
Similar to :meth:`loop.create_server` but works with the
@@ -853,6 +853,13 @@ Creating network servers
853853
be removed from the filesystem when the server is closed, unless the
854854
socket has been replaced after the server has been created.
855855

856+
If *mode* is not ``None``, the permissions of the socket file created
857+
for *path* are changed to *mode* (as accepted by :func:`os.chmod`)
858+
right after binding, before the server starts accepting connections,
859+
so a connection can never be accepted while the default,
860+
umask-derived permissions are still in effect. *mode* cannot be
861+
combined with *sock* and is not supported for abstract Unix sockets.
862+
856863
See the documentation of the :meth:`loop.create_server` method
857864
for information about arguments to this method.
858865

@@ -871,6 +878,10 @@ Creating network servers
871878

872879
Added the *cleanup_socket* parameter.
873880

881+
.. versionchanged:: 3.16
882+
883+
Added the *mode* parameter.
884+
874885

875886
.. method:: loop.connect_accepted_socket(protocol_factory, \
876887
sock, *, ssl=None, ssl_handshake_timeout=None, \

Doc/library/asyncio-stream.rst

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ and work with streams:
171171
.. function:: start_unix_server(client_connected_cb, path=None, \
172172
*, limit=None, sock=None, backlog=100, ssl=None, \
173173
ssl_handshake_timeout=None, \
174-
ssl_shutdown_timeout=None, start_serving=True, cleanup_socket=True)
174+
ssl_shutdown_timeout=None, start_serving=True, \
175+
cleanup_socket=True, mode=None)
175176
:async:
176177
177178
Start a Unix socket server.
@@ -182,6 +183,9 @@ and work with streams:
182183
be removed from the filesystem when the server is closed, unless the
183184
socket has been replaced after the server has been created.
184185

186+
If *mode* is not ``None``, the permissions of the Unix socket file
187+
are set to *mode* before the server starts accepting connections.
188+
185189
See also the documentation of :meth:`loop.create_unix_server`.
186190

187191
.. note::
@@ -205,6 +209,9 @@ and work with streams:
205209
.. versionchanged:: 3.13
206210
Added the *cleanup_socket* parameter.
207211

212+
.. versionchanged:: 3.16
213+
Added the *mode* parameter.
214+
208215

209216
StreamReader
210217
============

Doc/library/decimal.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,14 @@ In addition to the three supplied contexts, new contexts can be created with the
11821182

11831183
Return a duplicate of the context.
11841184

1185+
:class:`!Context` objects also support :func:`copy.replace`,
1186+
which returns a duplicate with the specified fields replaced.
1187+
Fields which are not specified keep the values
1188+
they have in the original context.
1189+
1190+
.. versionchanged:: next
1191+
Added support for :func:`copy.replace`.
1192+
11851193
.. method:: copy_decimal(num, /)
11861194

11871195
Return a copy of the Decimal instance num.

Doc/library/functools.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -386,9 +386,9 @@ The :mod:`!functools` module defines the following functions:
386386
only one positional argument is provided, but there are two placeholders
387387
that must be filled in.
388388

389-
If :func:`!partial` is applied to an existing :func:`!partial` object,
390-
:data:`!Placeholder` sentinels of the input object are filled in with
391-
new positional arguments.
389+
If :func:`!partial` is applied to an existing
390+
:ref:`partial object <partial-objects>`, :data:`!Placeholder` sentinels of the
391+
input object are filled in with new positional arguments.
392392
A placeholder can be retained by inserting a new
393393
:data:`!Placeholder` sentinel to the place held by a previous :data:`!Placeholder`:
394394

Doc/whatsnew/3.16.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,15 @@ New modules
9595
Improved modules
9696
================
9797

98+
asyncio
99+
-------
100+
101+
* Add the *mode* parameter to :meth:`asyncio.loop.create_unix_server` and
102+
:func:`asyncio.start_unix_server` to set the permissions of the Unix
103+
socket file created for *path*.
104+
(Contributed by Sam Bull in :gh:`94984`.)
105+
106+
98107
codecs
99108
------
100109

Lib/_pydecimal.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4005,6 +4005,20 @@ def copy(self):
40054005
return nc
40064006
__copy__ = copy
40074007

4008+
def __replace__(self, /, **changes):
4009+
"""Returns a copy of self with the specified attributes replaced."""
4010+
unexpected = changes.keys() - _context_attributes
4011+
if unexpected:
4012+
raise TypeError(f'__replace__() got an unexpected keyword '
4013+
f'argument {min(unexpected)!r}')
4014+
nc = self.copy()
4015+
for name, value in changes.items():
4016+
if name in ('flags', 'traps') and isinstance(value, list):
4017+
# As in the constructor, accept a list of signals.
4018+
value = dict((s, int(s in value)) for s in _signals + value)
4019+
setattr(nc, name, value)
4020+
return nc
4021+
40084022
def _raise_error(self, condition, explanation = None, *args):
40094023
"""Handles an error
40104024

Lib/asyncio/events.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ async def create_unix_server(
451451
sock=None, backlog=100, ssl=None,
452452
ssl_handshake_timeout=None,
453453
ssl_shutdown_timeout=None,
454-
start_serving=True):
454+
start_serving=True, mode=None):
455455
"""A coroutine which creates a UNIX Domain Socket server.
456456
457457
The return value is a Server object, which can be used to stop
@@ -480,6 +480,10 @@ async def create_unix_server(
480480
the user should await Server.start_serving() or
481481
Server.serve_forever() to make the server to start accepting
482482
connections.
483+
484+
mode, if not None, is applied to the socket file created for
485+
path with os.chmod() after binding and before the server
486+
starts accepting connections.
483487
"""
484488
raise NotImplementedError
485489

Lib/asyncio/unix_events.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ async def create_unix_server(
276276
sock=None, backlog=100, ssl=None,
277277
ssl_handshake_timeout=None,
278278
ssl_shutdown_timeout=None,
279-
start_serving=True, cleanup_socket=True):
279+
start_serving=True, cleanup_socket=True, mode=None):
280280
if isinstance(ssl, bool):
281281
raise TypeError('ssl argument must be an SSLContext or None')
282282

@@ -294,6 +294,9 @@ async def create_unix_server(
294294
'path and sock can not be specified at the same time')
295295

296296
path = os.fspath(path)
297+
if mode is not None and path and path[0] in (0, '\x00'):
298+
raise ValueError(
299+
'mode is not supported for abstract sockets')
297300
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
298301

299302
# Check for abstract socket. `str` and `bytes` paths are supported.
@@ -322,11 +325,26 @@ async def create_unix_server(
322325
except:
323326
sock.close()
324327
raise
328+
329+
if mode is not None:
330+
# The socket cannot accept connections until listen() is
331+
# called, which happens later in Server._start_serving(),
332+
# so no connection can be accepted while the socket still
333+
# has the default permissions.
334+
try:
335+
os.chmod(path, mode)
336+
except:
337+
sock.close()
338+
raise
325339
else:
326340
if sock is None:
327341
raise ValueError(
328342
'path was not specified, and no sock specified')
329343

344+
if mode is not None:
345+
raise ValueError(
346+
'mode is only meaningful with path')
347+
330348
if (sock.family != socket.AF_UNIX or
331349
sock.type != socket.SOCK_STREAM):
332350
raise ValueError(
@@ -658,19 +676,19 @@ def __init__(self, loop, pipe, protocol, waiter=None, extra=None):
658676
# On AIX, the reader trick (to be notified when the read end of the
659677
# socket is closed) only works for sockets. On other platforms it
660678
# works for pipes and sockets. (Exception: OS X 10.4? Issue #19294.)
661-
# On macOS, the trick misfires for named FIFOs (but not for pipes
662-
# created with os.pipe(), which have st_nlink == 0): the write end
663-
# polls as readable whenever unread data sits in the FIFO, and no
679+
# On macOS and Solaris, the trick misfires for named FIFOs (but not for
680+
# pipes created with os.pipe(), which have st_nlink == 0): the write
681+
# end polls as readable whenever unread data sits in the FIFO, and no
664682
# event is delivered when the read end is closed, so it can only
665-
# ever report a false disconnection (gh-145030). The same xnu
683+
# ever report a false disconnection (gh-145030). The same XNU
666684
# behaviour applies on iOS/tvOS/watchOS (sys.platform is not
667685
# "darwin" there).
668-
is_named_fifo_on_apple = (
669-
sys.platform in {"darwin", "ios", "tvos", "watchos"}
686+
is_named_fifo_without_close_event = (
687+
sys.platform in {"darwin", "ios", "tvos", "watchos", "sunos5"}
670688
and is_fifo and pipe_stat.st_nlink > 0)
671689
if is_socket or (is_fifo
672690
and not sys.platform.startswith("aix")
673-
and not is_named_fifo_on_apple):
691+
and not is_named_fifo_without_close_event):
674692
# only start reading when connection_made() has been called
675693
self._loop.call_soon(self._loop._add_reader,
676694
self._fileno, self._read_ready)

Lib/logging/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1709,7 +1709,11 @@ def removeHandler(self, hdlr):
17091709
"""
17101710
with _lock:
17111711
if hdlr in self.handlers:
1712-
self.handlers.remove(hdlr)
1712+
# Replace the list instead of mutating it in place, so that
1713+
# callHandlers() can iterate it without a lock (gh-79366).
1714+
handlers = self.handlers.copy()
1715+
handlers.remove(hdlr)
1716+
self.handlers = handlers
17131717

17141718
def hasHandlers(self):
17151719
"""

0 commit comments

Comments
 (0)