Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c05a60c
Update _elementtree.c
clin1234 May 17, 2026
2f9d79d
📜🤖 Added by blurb_it.
blurb-it[bot] May 17, 2026
648be0a
Modify critical section assertion in _elementtree.c
clin1234 May 17, 2026
d8e3e88
Update Misc/NEWS.d/next/Library/2026-05-17-22-42-54.gh-issue-149965.O…
clin1234 May 18, 2026
a865654
gh-149966: deduplicate ptr_wise_atomic_memmove into a shared internal…
Jun 9, 2026
1bfa4fd
GH-54732: Tweak wording around empty lines in argument files (#150980)
savannahostrowski Jun 9, 2026
0bf42e2
GH-61082: Clarify nargs='*' positional default behavior (#150989)
savannahostrowski Jun 9, 2026
42e2817
gh-150285: Fix too long docstrings in the asyncio package (GH-151074)
serhiy-storchaka Jun 9, 2026
ace91ac
gh-150285: Fix too long docstrings in the concurrent package (GH-151076)
serhiy-storchaka Jun 9, 2026
7853e5b
gh-151126: Add missing `PyErr_NoMemory` in `_winapi` module (#151154)
sobolevn Jun 9, 2026
aa1a8c5
GH-59633: Clarify dest collisions in argparse docs (#150987)
savannahostrowski Jun 9, 2026
208fe27
gh-151159: Update Windows builds to use OpenSSL 3.5.7 (GH-151183)
zware Jun 9, 2026
b403a41
gh-151159: Update macOS installer to use OpenSSL 3.5.7. (#151171)
ByteFlowing1337 Jun 9, 2026
1a7e057
gh-151159: Bump OpenSSL versions for iOS and Android (GH-151164)
zware Jun 9, 2026
371a716
gh-151159: Update CI to use latest SSL library versions (#151176)
zware Jun 9, 2026
864de8d
gh-139819: rlcompleter – avoid suggesting attributes not accessible o…
ttw225 Jun 9, 2026
f506aa2
gh-151163: Update Android, macOS installer, and Windows builds to SQL…
zware Jun 9, 2026
92008d3
Use _Py_ptr_wise_atomic_memmove everywhere in listobject.c
clin1234 Jun 9, 2026
ca1d432
Keep _testlimitedcapi/weakref.c in Setup.stdlib.in
clin1234 Jun 9, 2026
19c93f3
Cast 1st arg of all calls to _Py_ptr_wise_atomic_memmove to PyObject*
clin1234 Jun 9, 2026
7ed7148
Make test shut up check-c-globals.py
clin1234 Jun 9, 2026
56d4198
Drop const in test_objs
clin1234 Jun 9, 2026
6d506b6
Revert previous changes
clin1234 Jun 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -278,14 +278,13 @@ jobs:
# unsupported as it most resembles other 1.1.1-work-a-like ssl APIs
# supported by important vendors such as AWS-LC.
- { name: openssl, version: 1.1.1w }
- { name: openssl, version: 3.0.20 }
- { name: openssl, version: 3.3.7 }
- { name: openssl, version: 3.4.5 }
- { name: openssl, version: 3.5.6 }
- { name: openssl, version: 3.6.2 }
- { name: openssl, version: 4.0.0 }
- { name: openssl, version: 3.0.21 }
- { name: openssl, version: 3.4.6 }
- { name: openssl, version: 3.5.7 }
- { name: openssl, version: 3.6.3 }
- { name: openssl, version: 4.0.1 }
## AWS-LC
- { name: aws-lc, version: 1.72.1 }
- { name: aws-lc, version: 5.0.0 }
env:
SSLLIB_VER: ${{ matrix.ssllib.version }}
MULTISSL_DIR: ${{ github.workspace }}/multissl
Expand Down Expand Up @@ -399,7 +398,7 @@ jobs:
needs: build-context
if: needs.build-context.outputs.run-ubuntu == 'true'
env:
OPENSSL_VER: 3.5.6
OPENSSL_VER: 3.5.7
PYTHONSTRICTEXTENSIONBUILD: 1
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand Down Expand Up @@ -507,7 +506,7 @@ jobs:
matrix:
os: [ubuntu-24.04]
env:
OPENSSL_VER: 3.5.6
OPENSSL_VER: 3.5.7
PYTHONSTRICTEXTENSIONBUILD: 1
ASAN_OPTIONS: detect_leaks=0:allocator_may_return_null=1:handle_segv=0
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/reusable-ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
runs-on: ${{ inputs.os }}
timeout-minutes: 60
env:
OPENSSL_VER: 3.5.6
OPENSSL_VER: 3.5.7
PYTHONSTRICTEXTENSIONBUILD: 1
TERM: linux
steps:
Expand Down
22 changes: 19 additions & 3 deletions Doc/library/argparse.rst
Original file line number Diff line number Diff line change
Expand Up @@ -442,9 +442,8 @@ is considered equivalent to the expression ``['-f', 'foo', '-f', 'bar']``.

.. note::

Empty lines are treated as empty strings (``''``), which are allowed as values but
not as arguments. Empty lines that are read as arguments will result in an
"unrecognized arguments" error.
Each line is treated as a single argument, so an empty line is read as an
empty string (``''``).

:class:`ArgumentParser` uses :term:`filesystem encoding and error handler`
to read the file containing arguments.
Expand Down Expand Up @@ -1052,6 +1051,10 @@ is used when no command-line argument was present::
>>> parser.parse_args([])
Namespace(foo=42)

Because ``nargs='*'`` gathers any supplied values into a list, an absent
positional argument yields an empty list (``[]``). Only a non-``None``
*default* overrides this (so ``default=None`` still gives ``[]``).

For required_ arguments, the ``default`` value is ignored. For example, this
applies to positional arguments with nargs_ values other than ``?`` or ``*``,
or optional arguments marked as ``required=True``.
Expand Down Expand Up @@ -1369,6 +1372,11 @@ behavior::
>>> parser.parse_args('--foo XXX'.split())
Namespace(bar='XXX')

Multiple arguments may share the same ``dest``. By default, the value from the
last such argument given on the command line wins. Use ``action='append'`` to
collect values from all of them into a list instead. For conflicting *option
strings* rather than ``dest`` names, see conflict_handler_.

.. versionchanged:: 3.15
Single-dash long option now takes precedence over short options.

Expand Down Expand Up @@ -1777,6 +1785,11 @@ Subcommands
present, and when the ``b`` command is specified, only the ``foo`` and
``baz`` attributes are present.

If a subparser defines an argument with the same ``dest`` as the parent
parser, the two share a single namespace attribute, so the parent's value
won't be retained. Users should give them distinct ``dest`` values to
keep both.

Similarly, when a help message is requested from a subparser, only the help
for that particular parser will be printed. The help message will not
include parent parser or sibling parser messages. (A help message for each
Expand Down Expand Up @@ -2232,6 +2245,9 @@ Customizing file parsing
def convert_arg_line_to_args(self, arg_line):
return arg_line.split()

Note that with this override an argument can no longer contain spaces, since
each space-separated word becomes a separate argument.


Exiting methods
^^^^^^^^^^^^^^^
Expand Down
29 changes: 29 additions & 0 deletions Include/internal/pycore_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,35 @@ static inline Py_ALWAYS_INLINE void _Py_INCREF_MORTAL(PyObject *op)
* references. */
PyAPI_FUNC(int) _PyObject_VisitType(PyObject *op, visitproc visit, void *arg);

// Pointer-by-pointer memmove for PyObject** arrays that is safe for shared
// objects in Py_GIL_DISABLED builds. Locking is the caller's responsibility.
static inline void
_Py_ptr_wise_atomic_memmove(PyObject *a, PyObject **dest, PyObject **src,
Py_ssize_t n)
{
#ifndef Py_GIL_DISABLED
(void)a;
memmove(dest, src, n * sizeof(PyObject *));
#else
if (_Py_IsOwnedByCurrentThread(a) && !_PyObject_GC_IS_SHARED(a)) {
// No other threads can read this object's array concurrently
memmove(dest, src, n * sizeof(PyObject *));
return;
}
if (dest < src) {
for (Py_ssize_t i = 0; i != n; i++) {
_Py_atomic_store_ptr_release(&dest[i], src[i]);
}
}
else {
// copy backwards to avoid overwriting src before it's read
for (Py_ssize_t i = n; i != 0; i--) {
_Py_atomic_store_ptr_release(&dest[i - 1], src[i - 1]);
}
}
#endif
}

#ifdef __cplusplus
}
#endif
Expand Down
32 changes: 16 additions & 16 deletions Lib/asyncio/base_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,10 +488,10 @@ def set_task_factory(self, factory):
If factory is None the default task factory will be set.

If factory is a callable, it should have a signature matching
'(loop, coro, **kwargs)', where 'loop' will be a reference to the active
event loop, 'coro' will be a coroutine object, and **kwargs will be
arbitrary keyword arguments that should be passed on to Task.
The callable must return a Task.
'(loop, coro, **kwargs)', where 'loop' will be a reference to the
active event loop, 'coro' will be a coroutine object, and **kwargs
will be arbitrary keyword arguments that should be passed on to
Task. The callable must return a Task.
"""
if factory is not None and not callable(factory):
raise TypeError('task factory must be a callable or None')
Expand Down Expand Up @@ -727,8 +727,8 @@ def run_until_complete(self, future):
def stop(self):
"""Stop running the event loop.

Every callback already scheduled will still run. This simply informs
run_forever to stop looping after a complete iteration.
Every callback already scheduled will still run. This simply
informs run_forever to stop looping after a complete iteration.
"""
self._stopping = True

Expand Down Expand Up @@ -1076,12 +1076,12 @@ async def create_connection(

Create a streaming transport connection to a given internet host and
port: socket family AF_INET or socket.AF_INET6 depending on host (or
family if specified), socket type SOCK_STREAM. protocol_factory must be
a callable returning a protocol instance.
family if specified), socket type SOCK_STREAM. protocol_factory must
be a callable returning a protocol instance.

This method is a coroutine which will try to establish the connection
in the background. When successful, the coroutine returns a
(transport, protocol) pair.
This method is a coroutine which will try to establish the
connection in the background. When successful, the coroutine
returns a (transport, protocol) pair.
"""
if server_hostname is not None and not ssl:
raise ValueError('server_hostname is only meaningful with ssl')
Expand Down Expand Up @@ -1550,11 +1550,11 @@ async def create_server(
The host parameter can be a string, in that case the TCP server is
bound to host and port.

The host parameter can also be a sequence of strings and in that case
the TCP server is bound to all hosts of the sequence. If a host
appears multiple times (possibly indirectly e.g. when hostnames
resolve to the same IP address), the server is only bound once to that
host.
The host parameter can also be a sequence of strings and in that
case the TCP server is bound to all hosts of the sequence. If
a host appears multiple times (possibly indirectly e.g. when
hostnames resolve to the same IP address), the server is only bound
once to that host.

Return a Server object which can be used to stop the service.

Expand Down
21 changes: 12 additions & 9 deletions Lib/asyncio/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,8 @@ async def create_server(

If host is an empty string or None all interfaces are assumed
and a list of multiple sockets will be returned (most likely
one for IPv4 and another one for IPv6). The host parameter can also be
a sequence (e.g. list) of hosts to bind to.
one for IPv4 and another one for IPv6). The host parameter can also
be a sequence (e.g. list) of hosts to bind to.

family can be set to either AF_INET or AF_INET6 to force the
socket to use IPv4 or IPv6. If not set it will be determined
Expand Down Expand Up @@ -415,8 +415,9 @@ async def create_server(

start_serving set to True (default) causes the created server
to start accepting connections immediately. When set to False,
the user should await Server.start_serving() or Server.serve_forever()
to make the server to start accepting connections.
the user should await Server.start_serving() or
Server.serve_forever() to make the server to start accepting
connections.
"""
raise NotImplementedError

Expand Down Expand Up @@ -479,8 +480,9 @@ async def create_unix_server(

start_serving set to True (default) causes the created server
to start accepting connections immediately. When set to False,
the user should await Server.start_serving() or Server.serve_forever()
to make the server to start accepting connections.
the user should await Server.start_serving() or
Server.serve_forever() to make the server to start accepting
connections.
"""
raise NotImplementedError

Expand Down Expand Up @@ -511,8 +513,8 @@ async def create_datagram_endpoint(self, protocol_factory,

protocol_factory must be a callable returning a protocol instance.

socket family AF_INET, socket.AF_INET6 or socket.AF_UNIX depending on
host (or family if specified), socket type SOCK_DGRAM.
socket family AF_INET, socket.AF_INET6 or socket.AF_UNIX depending
on host (or family if specified), socket type SOCK_DGRAM.

reuse_address tells the kernel to reuse a local socket in
TIME_WAIT state, without waiting for its natural timeout to
Expand Down Expand Up @@ -552,7 +554,8 @@ async def connect_read_pipe(self, protocol_factory, pipe):
async def connect_write_pipe(self, protocol_factory, pipe):
"""Register write pipe in event loop.

protocol_factory should instantiate object with BaseProtocol interface.
protocol_factory should instantiate object with BaseProtocol
interface.
Pipe is file-like object already switched to nonblocking.
Return pair (transport, protocol), where transport support
WriteTransport interface."""
Expand Down
14 changes: 7 additions & 7 deletions Lib/asyncio/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,13 @@ def capture_call_graph(
optional keyword-only 'depth' argument can be used to skip the specified
number of frames from top of the stack.

If the optional keyword-only 'limit' argument is provided, each call stack
in the resulting graph is truncated to include at most ``abs(limit)``
entries. If 'limit' is positive, the entries left are the closest to
the invocation point. If 'limit' is negative, the topmost entries are
left. If 'limit' is omitted or None, all entries are present.
If 'limit' is 0, the call stack is not captured at all, only
"awaited by" information is present.
If the optional keyword-only 'limit' argument is provided, each call
stack in the resulting graph is truncated to include at most
``abs(limit)`` entries. If 'limit' is positive, the entries left are
the closest to the invocation point. If 'limit' is negative, the
topmost entries are left. If 'limit' is omitted or None, all entries
are present. If 'limit' is 0, the call stack is not captured at all,
only "awaited by" information is present.
"""

loop = events._get_running_loop()
Expand Down
18 changes: 9 additions & 9 deletions Lib/asyncio/locks.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,10 @@ def _wake_up_first(self):
class Event(mixins._LoopBoundMixin):
"""Asynchronous equivalent to threading.Event.

Class implementing event objects. An event manages a flag that can be set
to true with the set() method and reset to false with the clear() method.
The wait() method blocks until the flag is true. The flag is initially
false.
Class implementing event objects. An event manages a flag that can be
set to true with the set() method and reset to false with the clear()
method. The wait() method blocks until the flag is true. The flag is
initially false.
"""

def __init__(self):
Expand Down Expand Up @@ -350,9 +350,9 @@ class Semaphore(_ContextManagerMixin, mixins._LoopBoundMixin):
"""A Semaphore implementation.

A semaphore manages an internal counter which is decremented by each
acquire() call and incremented by each release() call. The counter
can never go below zero; when acquire() finds that it is zero, it blocks,
waiting until some other thread calls release().
acquire() call and incremented by each release() call. The counter
can never go below zero; when acquire() finds that it is zero, it
blocks, waiting until some other thread calls release().

Semaphores also support the context management protocol.

Expand Down Expand Up @@ -508,8 +508,8 @@ async def __aexit__(self, *args):
async def wait(self):
"""Wait for the barrier.

When the specified number of tasks have started waiting, they are all
simultaneously awoken.
When the specified number of tasks have started waiting, they are
all simultaneously awoken.
Returns an unique and individual index number from 0 to 'parties-1'.
"""
async with self._cond:
Expand Down
36 changes: 19 additions & 17 deletions Lib/asyncio/queues.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ class QueueShutDown(Exception):
class Queue(mixins._LoopBoundMixin):
"""A queue, useful for coordinating producer and consumer coroutines.

If maxsize is less than or equal to zero, the queue size is infinite. If it
is an integer greater than 0, then "await put()" will block when the
queue reaches maxsize, until an item is removed by get().
If maxsize is less than or equal to zero, the queue size is infinite.
If it is an integer greater than 0, then "await put()" will block when
the queue reaches maxsize, until an item is removed by get().

Unlike queue.Queue, you can reliably know this Queue's size
with qsize(), since your single-threaded asyncio application won't be
Expand Down Expand Up @@ -174,8 +174,8 @@ async def get(self):

If queue is empty, wait until an item is available.

Raises QueueShutDown if the queue has been shut down and is empty, or
if the queue has been shut down immediately.
Raises QueueShutDown if the queue has been shut down and is empty,
or if the queue has been shut down immediately.
"""
while self.empty():
if self._is_shutdown and self.empty():
Expand Down Expand Up @@ -203,10 +203,11 @@ async def get(self):
def get_nowait(self):
"""Remove and return an item from the queue.

Return an item if one is immediately available, else raise QueueEmpty.
Return an item if one is immediately available, else raise
QueueEmpty.

Raises QueueShutDown if the queue has been shut down and is empty, or
if the queue has been shut down immediately.
Raises QueueShutDown if the queue has been shut down and is empty,
or if the queue has been shut down immediately.
"""
if self.empty():
if self._is_shutdown:
Expand All @@ -223,12 +224,12 @@ def task_done(self):
a subsequent call to task_done() tells the queue that the processing
on the task is complete.

If a join() is currently blocking, it will resume when all items have
been processed (meaning that a task_done() call was received for every
item that had been put() into the queue).
If a join() is currently blocking, it will resume when all items
have been processed (meaning that a task_done() call was received
for every item that had been put() into the queue).

Raises ValueError if called more times than there were items placed in
the queue.
Raises ValueError if called more times than there were items placed
in the queue.
"""
if self._unfinished_tasks <= 0:
raise ValueError('task_done() called too many times')
Expand All @@ -239,10 +240,11 @@ def task_done(self):
async def join(self):
"""Block until all items in the queue have been gotten and processed.

The count of unfinished tasks goes up whenever an item is added to the
queue. The count goes down whenever a consumer calls task_done() to
indicate that the item was retrieved and all work on it is complete.
When the count of unfinished tasks drops to zero, join() unblocks.
The count of unfinished tasks goes up whenever an item is added to
the queue. The count goes down whenever a consumer calls
task_done() to indicate that the item was retrieved and all work on
it is complete. When the count of unfinished tasks drops to zero,
join() unblocks.
"""
if self._unfinished_tasks > 0:
await self._finished.wait()
Expand Down
Loading
Loading