Skip to content

Commit cf3613c

Browse files
committed
Catch up with main
2 parents b80bdf8 + c8f233c commit cf3613c

File tree

237 files changed

+11560
-2233
lines changed

Some content is hidden

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

237 files changed

+11560
-2233
lines changed

.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

.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/c-api/object.rst

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,38 @@ Object Protocol
613613
614614
.. versionadded:: 3.14
615615
616+
.. c:function:: int PyUnstable_Object_IsUniqueReferencedTemporary(PyObject *obj)
617+
618+
Check if *obj* is a unique temporary object.
619+
Returns ``1`` if *obj* is known to be a unique temporary object,
620+
and ``0`` otherwise. This function cannot fail, but the check is
621+
conservative, and may return ``0`` in some cases even if *obj* is a unique
622+
temporary object.
623+
624+
If an object is a unique temporary, it is guaranteed that the current code
625+
has the only reference to the object. For arguments to C functions, this
626+
should be used instead of checking if the reference count is ``1``. Starting
627+
with Python 3.14, the interpreter internally avoids some reference count
628+
modifications when loading objects onto the operands stack by
629+
:term:`borrowing <borrowed reference>` references when possible, which means
630+
that a reference count of ``1`` by itself does not guarantee that a function
631+
argument uniquely referenced.
632+
633+
In the example below, ``my_func`` is called with a unique temporary object
634+
as its argument::
635+
636+
my_func([1, 2, 3])
637+
638+
In the example below, ``my_func`` is **not** called with a unique temporary
639+
object as its argument, even if its refcount is ``1``::
640+
641+
my_list = [1, 2, 3]
642+
my_func(my_list)
643+
644+
See also the function :c:func:`Py_REFCNT`.
645+
646+
.. versionadded:: 3.14
647+
616648
.. c:function:: int PyUnstable_IsImmortal(PyObject *obj)
617649
618650
This function returns non-zero if *obj* is :term:`immortal`, and zero

Doc/c-api/refcounting.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ of Python objects.
2323
2424
Use the :c:func:`Py_SET_REFCNT()` function to set an object reference count.
2525
26+
See also the function :c:func:`PyUnstable_Object_IsUniqueReferencedTemporary()`.
27+
2628
.. versionchanged:: 3.10
2729
:c:func:`Py_REFCNT()` is changed to the inline static function.
2830

Doc/deprecations/index.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@ Deprecations
55

66
.. include:: pending-removal-in-3.16.rst
77

8+
.. include:: pending-removal-in-3.17.rst
9+
810
.. include:: pending-removal-in-future.rst
911

1012
C API deprecations
1113
------------------
1214

1315
.. include:: c-api-pending-removal-in-3.15.rst
1416

17+
.. include:: c-api-pending-removal-in-3.18.rst
18+
1519
.. include:: c-api-pending-removal-in-future.rst

Doc/deprecations/pending-removal-in-3.16.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ Pending removal in Python 3.16
6161
* Calling the Python implementation of :func:`functools.reduce` with *function*
6262
or *sequence* as keyword arguments has been deprecated since Python 3.14.
6363

64+
* :mod:`logging`:
65+
66+
Support for custom logging handlers with the *strm* argument is deprecated
67+
and scheduled for removal in Python 3.16. Define handlers with the *stream*
68+
argument instead. (Contributed by Mariusz Felisiak in :gh:`115032`.)
69+
6470
* :mod:`mimetypes`:
6571

6672
* Valid extensions start with a '.' or are empty for
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Pending removal in Python 3.17
2+
------------------------------
3+
4+
* :mod:`typing`:
5+
6+
- Before Python 3.14, old-style unions were implemented using the private class
7+
``typing._UnionGenericAlias``. This class is no longer needed for the implementation,
8+
but it has been retained for backward compatibility, with removal scheduled for Python
9+
3.17. Users should use documented introspection helpers like :func:`typing.get_origin`
10+
and :func:`typing.get_args` instead of relying on private implementation details.

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: 80 additions & 9 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>`.
@@ -300,15 +300,13 @@ Functions
300300

301301
.. versionadded:: 3.14
302302

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

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.
305+
Retrieve the :term:`annotate function` from a class namespace dictionary *namespace*.
306+
Return :const:`!None` if the namespace does not contain an annotate function.
307+
This is primarily useful before the class has been fully created (e.g., in a metaclass);
308+
after the class exists, the annotate function can be retrieved with ``cls.__annotate__``.
309+
See :ref:`below <annotationlib-metaclass>` for an example using this function in a metaclass.
312310

313311
.. versionadded:: 3.14
314312

@@ -407,3 +405,76 @@ Functions
407405

408406
.. versionadded:: 3.14
409407

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

Doc/library/argparse.rst

Lines changed: 35 additions & 3 deletions
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)
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
@@ -111,14 +111,15 @@ ArgumentParser objects
111111
* add_help_ - Add a ``-h/--help`` option to the parser (default: ``True``)
112112

113113
* allow_abbrev_ - Allows long options to be abbreviated if the
114-
abbreviation is unambiguous. (default: ``True``)
114+
abbreviation is unambiguous (default: ``True``)
115115

116116
* exit_on_error_ - Determines whether or not :class:`!ArgumentParser` exits with
117117
error info when an error occurs. (default: ``True``)
118118

119119
* suggest_on_error_ - Enables suggestions for mistyped argument choices
120120
and subparser names (default: ``False``)
121121

122+
* color_ - Allow color output (default: ``False``)
122123

123124
.. versionchanged:: 3.5
124125
*allow_abbrev* parameter was added.
@@ -130,6 +131,9 @@ ArgumentParser objects
130131
.. versionchanged:: 3.9
131132
*exit_on_error* parameter was added.
132133

134+
.. versionchanged:: 3.14
135+
*suggest_on_error* and *color* parameters were added.
136+
133137
The following sections describe how each of these are used.
134138

135139

@@ -594,7 +598,8 @@ subparser names, the feature can be enabled by setting ``suggest_on_error`` to
594598
``True``. Note that this only applies for arguments when the choices specified
595599
are strings::
596600

597-
>>> parser = argparse.ArgumentParser(description='Process some integers.', suggest_on_error=True)
601+
>>> parser = argparse.ArgumentParser(description='Process some integers.',
602+
suggest_on_error=True)
598603
>>> parser.add_argument('--action', choices=['sum', 'max'])
599604
>>> parser.add_argument('integers', metavar='N', type=int, nargs='+',
600605
... help='an integer for the accumulator')
@@ -612,6 +617,33 @@ keyword argument::
612617
.. versionadded:: 3.14
613618

614619

620+
color
621+
^^^^^
622+
623+
By default, the help message is printed in plain text. If you want to allow
624+
color in help messages, you can enable it by setting ``color`` to ``True``::
625+
626+
>>> parser = argparse.ArgumentParser(description='Process some integers.',
627+
... color=True)
628+
>>> parser.add_argument('--action', choices=['sum', 'max'])
629+
>>> parser.add_argument('integers', metavar='N', type=int, nargs='+',
630+
... help='an integer for the accumulator')
631+
>>> parser.parse_args(['--help'])
632+
633+
Even if a CLI author has enabled color, it can be
634+
:ref:`controlled using environment variables <using-on-controlling-color>`.
635+
636+
If you're writing code that needs to be compatible with older Python versions
637+
and want to opportunistically use ``color`` when it's available, you
638+
can set it as an attribute after initializing the parser instead of using the
639+
keyword argument::
640+
641+
>>> parser = argparse.ArgumentParser(description='Process some integers.')
642+
>>> parser.color = True
643+
644+
.. versionadded:: next
645+
646+
615647
The add_argument() method
616648
-------------------------
617649

0 commit comments

Comments
 (0)