Skip to content

Commit 6e099fa

Browse files
authored
Merge branch 'main' into SSL_sendfile
2 parents 028067a + 59f78d7 commit 6e099fa

File tree

261 files changed

+11381
-2103
lines changed

Some content is hidden

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

261 files changed

+11381
-2103
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ Include/internal/pycore_time.h @pganssle @abalkin
188188

189189
# AST
190190
Python/ast.c @isidentical @JelleZijlstra @eclips4
191-
Python/ast_opt.c @isidentical @eclips4
191+
Python/ast_preprocess.c @isidentical @eclips4
192192
Parser/asdl.py @isidentical @JelleZijlstra @eclips4
193193
Parser/asdl_c.py @isidentical @JelleZijlstra @eclips4
194194
Lib/ast.py @isidentical @JelleZijlstra @eclips4

.github/workflows/jit.yml

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,10 @@ jobs:
9595
with:
9696
python-version: '3.11'
9797

98+
# PCbuild downloads LLVM automatically:
9899
- name: Windows
99100
if: runner.os == 'Windows'
100101
run: |
101-
choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }}.1.0
102102
./PCbuild/build.bat --experimental-jit ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }}
103103
./PCbuild/rt.bat ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3
104104
@@ -126,29 +126,30 @@ jobs:
126126
make all --jobs 4
127127
./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
128128
129-
jit-with-disabled-gil:
130-
name: Free-Threaded (Debug)
131-
needs: interpreter
132-
runs-on: ubuntu-24.04
133-
timeout-minutes: 90
134-
strategy:
135-
fail-fast: false
136-
matrix:
137-
llvm:
138-
- 19
139-
steps:
140-
- uses: actions/checkout@v4
141-
with:
142-
persist-credentials: false
143-
- uses: actions/setup-python@v5
144-
with:
145-
python-version: '3.11'
146-
- name: Build with JIT enabled and GIL disabled
147-
run: |
148-
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }}
149-
export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH"
150-
./configure --enable-experimental-jit --with-pydebug --disable-gil
151-
make all --jobs 4
152-
- name: Run tests
153-
run: |
154-
./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
129+
# XXX: GH-133171
130+
# jit-with-disabled-gil:
131+
# name: Free-Threaded (Debug)
132+
# needs: interpreter
133+
# runs-on: ubuntu-24.04
134+
# timeout-minutes: 90
135+
# strategy:
136+
# fail-fast: false
137+
# matrix:
138+
# llvm:
139+
# - 19
140+
# steps:
141+
# - uses: actions/checkout@v4
142+
# with:
143+
# persist-credentials: false
144+
# - uses: actions/setup-python@v5
145+
# with:
146+
# python-version: '3.11'
147+
# - name: Build with JIT enabled and GIL disabled
148+
# run: |
149+
# sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }}
150+
# export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH"
151+
# ./configure --enable-experimental-jit --with-pydebug --disable-gil
152+
# make all --jobs 4
153+
# - name: Run tests
154+
# run: |
155+
# ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3

.github/workflows/reusable-context.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ jobs:
9797
run: python Tools/build/compute-changes.py
9898
env:
9999
GITHUB_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
100+
CCF_TARGET_REF: ${{ github.base_ref || github.event.repository.default_branch }}
101+
CCF_HEAD_REF: ${{ github.event.pull_request.head.sha || github.sha }}
100102

101103
- name: Compute hash for config cache key
102104
id: config-hash

.pre-commit-config.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/astral-sh/ruff-pre-commit
3-
rev: v0.11.6
3+
rev: v0.11.8
44
hooks:
55
- id: ruff
66
name: Run Ruff (lint) on Doc/
@@ -22,14 +22,14 @@ repos:
2222
name: Run Ruff (format) on Doc/
2323
args: [--check]
2424
files: ^Doc/
25+
- id: ruff-format
26+
name: Run Ruff (format) on Tools/build/check_warnings.py
27+
args: [--check, --config=Tools/build/.ruff.toml]
28+
files: ^Tools/build/check_warnings.py
2529

2630
- repo: https://github.com/psf/black-pre-commit-mirror
2731
rev: 25.1.0
2832
hooks:
29-
- id: black
30-
name: Run Black on Tools/build/check_warnings.py
31-
files: ^Tools/build/check_warnings.py
32-
args: [--line-length=79]
3333
- id: black
3434
name: Run Black on Tools/jit/
3535
files: ^Tools/jit/

Doc/deprecations/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Deprecations
77

88
.. include:: pending-removal-in-3.17.rst
99

10+
.. include:: pending-removal-in-3.19.rst
11+
1012
.. include:: pending-removal-in-future.rst
1113

1214
C API deprecations
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Pending removal in Python 3.19
2+
------------------------------
3+
4+
* :mod:`ctypes`:
5+
6+
* Implicitly switching to the MSVC-compatible struct layout by setting
7+
:attr:`~ctypes.Structure._pack_` but not :attr:`~ctypes.Structure._layout_`
8+
on non-Windows platforms.

Doc/howto/regex.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,9 +738,12 @@ given location, they can obviously be matched an infinite number of times.
738738
different: ``\A`` still matches only at the beginning of the string, but ``^``
739739
may match at any location inside the string that follows a newline character.
740740

741-
``\Z``
741+
``\z``
742742
Matches only at the end of the string.
743743

744+
``\Z``
745+
The same as ``\z``. For compatibility with old Python versions.
746+
744747
``\b``
745748
Word boundary. This is a zero-width assertion that matches only at the
746749
beginning or end of a word. A word is defined as a sequence of alphanumeric

Doc/library/annotationlib.rst

Lines changed: 91 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ The :func:`get_annotations` function is the main entry point for
4040
retrieving annotations. Given a function, class, or module, it returns
4141
an annotations dictionary in the requested format. This module also provides
4242
functionality for working directly with the :term:`annotate function`
43-
that is used to evaluate annotations, such as :func:`get_annotate_function`
43+
that is used to evaluate annotations, such as :func:`get_annotate_from_class_namespace`
4444
and :func:`call_annotate_function`, as well as the
4545
:func:`call_evaluate_function` function for working with
4646
:term:`evaluate functions <evaluate function>`.
@@ -132,7 +132,7 @@ Classes
132132

133133
Values are real annotation values (as per :attr:`Format.VALUE` format)
134134
for defined values, and :class:`ForwardRef` proxies for undefined
135-
values. Real objects may contain references to, :class:`ForwardRef`
135+
values. Real objects may contain references to :class:`ForwardRef`
136136
proxy objects.
137137

138138
.. attribute:: STRING
@@ -172,14 +172,21 @@ Classes
172172
:class:`~ForwardRef`. The string may not be exactly equivalent
173173
to the original source.
174174

175-
.. method:: evaluate(*, owner=None, globals=None, locals=None, type_params=None)
175+
.. method:: evaluate(*, owner=None, globals=None, locals=None, type_params=None, format=Format.VALUE)
176176

177177
Evaluate the forward reference, returning its value.
178178

179-
This may throw an exception, such as :exc:`NameError`, if the forward
179+
If the *format* argument is :attr:`~Format.VALUE` (the default),
180+
this method may throw an exception, such as :exc:`NameError`, if the forward
180181
reference refers to a name that cannot be resolved. The arguments to this
181182
method can be used to provide bindings for names that would otherwise
182-
be undefined.
183+
be undefined. If the *format* argument is :attr:`~Format.FORWARDREF`,
184+
the method will never throw an exception, but may return a :class:`~ForwardRef`
185+
instance. For example, if the forward reference object contains the code
186+
``list[undefined]``, where ``undefined`` is a name that is not defined,
187+
evaluating it with the :attr:`~Format.FORWARDREF` format will return
188+
``list[ForwardRef('undefined')]``. If the *format* argument is
189+
:attr:`~Format.STRING`, the method will return :attr:`~ForwardRef.__forward_arg__`.
183190

184191
The *owner* parameter provides the preferred mechanism for passing scope
185192
information to this method. The owner of a :class:`~ForwardRef` is the
@@ -300,15 +307,13 @@ Functions
300307

301308
.. versionadded:: 3.14
302309

303-
.. function:: get_annotate_function(obj)
310+
.. function:: get_annotate_from_class_namespace(namespace)
304311

305-
Retrieve the :term:`annotate function` for *obj*. Return :const:`!None`
306-
if *obj* does not have an annotate function. *obj* may be a class, function,
307-
module, or a namespace dictionary for a class. The last case is useful during
308-
class creation, e.g. in the ``__new__`` method of a metaclass.
309-
310-
This is usually equivalent to accessing the :attr:`~object.__annotate__`
311-
attribute of *obj*, but access through this public function is preferred.
312+
Retrieve the :term:`annotate function` from a class namespace dictionary *namespace*.
313+
Return :const:`!None` if the namespace does not contain an annotate function.
314+
This is primarily useful before the class has been fully created (e.g., in a metaclass);
315+
after the class exists, the annotate function can be retrieved with ``cls.__annotate__``.
316+
See :ref:`below <annotationlib-metaclass>` for an example using this function in a metaclass.
312317

313318
.. versionadded:: 3.14
314319

@@ -407,3 +412,76 @@ Functions
407412

408413
.. versionadded:: 3.14
409414

415+
416+
Recipes
417+
-------
418+
419+
.. _annotationlib-metaclass:
420+
421+
Using annotations in a metaclass
422+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
423+
424+
A :ref:`metaclass <metaclasses>` may want to inspect or even modify the annotations
425+
in a class body during class creation. Doing so requires retrieving annotations
426+
from the class namespace dictionary. For classes created with
427+
``from __future__ import annotations``, the annotations will be in the ``__annotations__``
428+
key of the dictionary. For other classes with annotations,
429+
:func:`get_annotate_from_class_namespace` can be used to get the
430+
annotate function, and :func:`call_annotate_function` can be used to call it and
431+
retrieve the annotations. Using the :attr:`~Format.FORWARDREF` format will usually
432+
be best, because this allows the annotations to refer to names that cannot yet be
433+
resolved when the class is created.
434+
435+
To modify the annotations, it is best to create a wrapper annotate function
436+
that calls the original annotate function, makes any necessary adjustments, and
437+
returns the result.
438+
439+
Below is an example of a metaclass that filters out all :class:`typing.ClassVar`
440+
annotations from the class and puts them in a separate attribute:
441+
442+
.. code-block:: python
443+
444+
import annotationlib
445+
import typing
446+
447+
class ClassVarSeparator(type):
448+
def __new__(mcls, name, bases, ns):
449+
if "__annotations__" in ns: # from __future__ import annotations
450+
annotations = ns["__annotations__"]
451+
classvar_keys = {
452+
key for key, value in annotations.items()
453+
# Use string comparison for simplicity; a more robust solution
454+
# could use annotationlib.ForwardRef.evaluate
455+
if value.startswith("ClassVar")
456+
}
457+
classvars = {key: annotations[key] for key in classvar_keys}
458+
ns["__annotations__"] = {
459+
key: value for key, value in annotations.items()
460+
if key not in classvar_keys
461+
}
462+
wrapped_annotate = None
463+
elif annotate := annotationlib.get_annotate_from_class_namespace(ns):
464+
annotations = annotationlib.call_annotate_function(
465+
annotate, format=annotationlib.Format.FORWARDREF
466+
)
467+
classvar_keys = {
468+
key for key, value in annotations.items()
469+
if typing.get_origin(value) is typing.ClassVar
470+
}
471+
classvars = {key: annotations[key] for key in classvar_keys}
472+
473+
def wrapped_annotate(format):
474+
annos = annotationlib.call_annotate_function(annotate, format, owner=typ)
475+
return {key: value for key, value in annos.items() if key not in classvar_keys}
476+
477+
else: # no annotations
478+
classvars = {}
479+
wrapped_annotate = None
480+
typ = super().__new__(mcls, name, bases, ns)
481+
482+
if wrapped_annotate is not None:
483+
# Wrap the original __annotate__ with a wrapper that removes ClassVars
484+
typ.__annotate__ = wrapped_annotate
485+
typ.classvars = classvars # Store the ClassVars in a separate attribute
486+
return typ
487+

Doc/library/argparse.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ ArgumentParser objects
7474
prefix_chars='-', fromfile_prefix_chars=None, \
7575
argument_default=None, conflict_handler='error', \
7676
add_help=True, allow_abbrev=True, exit_on_error=True, \
77-
suggest_on_error=False, color=False)
77+
*, suggest_on_error=False, color=False)
7878
7979
Create a new :class:`ArgumentParser` object. All parameters should be passed
8080
as keyword arguments. Each parameter has its own more detailed description

Doc/library/asyncio-eventloop.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ Creating Futures and Tasks
361361

362362
.. versionadded:: 3.5.2
363363

364-
.. method:: loop.create_task(coro, *, name=None, context=None)
364+
.. method:: loop.create_task(coro, *, name=None, context=None, eager_start=None)
365365

366366
Schedule the execution of :ref:`coroutine <coroutine>` *coro*.
367367
Return a :class:`Task` object.
@@ -377,12 +377,20 @@ Creating Futures and Tasks
377377
custom :class:`contextvars.Context` for the *coro* to run in.
378378
The current context copy is created when no *context* is provided.
379379

380+
An optional keyword-only *eager_start* argument allows specifying
381+
if the task should execute eagerly during the call to create_task,
382+
or be scheduled later. If *eager_start* is not passed the mode set
383+
by :meth:`loop.set_task_factory` will be used.
384+
380385
.. versionchanged:: 3.8
381386
Added the *name* parameter.
382387

383388
.. versionchanged:: 3.11
384389
Added the *context* parameter.
385390

391+
.. versionchanged:: next
392+
Added the *eager_start* parameter.
393+
386394
.. method:: loop.set_task_factory(factory)
387395

388396
Set a task factory that will be used by

0 commit comments

Comments
 (0)