GH-109190: Copyedit 3.12 What's New: Release highlights (#109770)

This commit is contained in:
Adam Turner 2023-09-27 15:31:55 +01:00 committed by GitHub
parent 62881a79a8
commit b35f0843fc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -59,36 +59,106 @@ Summary -- Release highlights
.. This section singles out the most important changes in Python 3.12. .. This section singles out the most important changes in Python 3.12.
Brevity is key. Brevity is key.
Python 3.12 is the latest stable release of the Python programming language,
with a mix of changes to the language and the standard library.
The library changes focus on cleaning up deprecated APIs, usability, and correctness.
Of note, the :mod:`!distutils` package has been removed from the standard library.
Filesystem support in :mod:`os` and :mod:`pathlib` has seen a number of improvements,
and several modules have better performance.
The language changes focus on usability,
as :term:`f-strings <f-string>` have had many limitations removed
and 'Did you mean ...' suggestions continue to improve.
The new :ref:`type parameter syntax <whatsnew312-pep695>`
and :keyword:`type` statement improve ergonomics for using :term:`generic types
<generic type>` and :term:`type aliases <type alias>` with static type checkers.
This article doesn't attempt to provide a complete specification of all new features,
but instead gives a convenient overview.
For full details, you should refer to the documentation,
such as the :ref:`Library Reference <library-index>`
and :ref:`Language Reference <reference-index>`.
If you want to understand the complete implementation and design rationale for a change,
refer to the PEP for a particular new feature;
but note that PEPs usually are not kept up-to-date
once a feature has been fully implemented.
--------------
.. PEP-sized items next. .. PEP-sized items next.
New syntax features:
* :ref:`PEP 695 <whatsnew312-pep695>`, type parameter syntax and the :keyword:`type` statement
New grammar features: New grammar features:
* :ref:`whatsnew312-pep701` * :ref:`PEP 701 <whatsnew312-pep701>`, :term:`f-strings <f-string>` in the grammar
Interpreter improvements: Interpreter improvements:
* :ref:`whatsnew312-pep684` * :ref:`PEP 684 <whatsnew312-pep684>`, a unique per-interpreter :term:`GIL
<global interpreter lock>`
* :ref:`PEP 669 <whatsnew312-pep669>`, low impact monitoring
* `Improved 'Did you mean ...' suggestions <improved error messages_>`_
for :exc:`NameError`, :exc:`ImportError`, and :exc:`SyntaxError` exceptions
* :ref:`whatsnew312-pep669` Python data model improvements:
* :ref:`PEP 688 <whatsnew312-pep688>`, using the :ref:`buffer protocol
<bufferobjects>` from Python
Significant improvements in the standard library:
* The :class:`pathlib.Path` class now supports subclassing
* The :mod:`os` module received several improvements for Windows support
* A :ref:`command-line interface <sqlite3-cli>` has been added to the
:mod:`sqlite3` module
* :func:`isinstance` checks against :func:`runtime-checkable protocols
<typing.runtime_checkable>` enjoy a speed up of between two and 20 times
* The :mod:`asyncio` package has had a number of performance improvements,
with some benchmarks showing a 75% speed up.
* A :ref:`command-line interface <uuid-cli>` has been added to the
:mod:`uuid` module
* Due to the changes in :ref:`PEP 701 <whatsnew312-pep701>`,
producing tokens via the :mod:`tokenize` module is up to up to 64% faster.
Security improvements:
* Replace the builtin :mod:`hashlib` implementations of
SHA1, SHA3, SHA2-384, SHA2-512, and MD5 with formally verified code from the
`HACL* <https://github.com/hacl-star/hacl-star/>`__ project.
These builtin implementations remain as fallbacks that are only used when
OpenSSL does not provide them.
C API improvements:
* :ref:`PEP 697 <whatsnew312-pep697>`, unstable C API tier
* :ref:`PEP 683 <whatsnew312-pep683>`, immortal objects
CPython implementation improvements:
* :ref:`PEP 709 <whatsnew312-pep709>`, comprehension inlining
* :ref:`CPython support <perf_profiling>` for the Linux ``perf`` profiler
* Implement stack overflow protection on supported platforms
New typing features: New typing features:
* :ref:`whatsnew312-pep688` * :ref:`PEP 692 <whatsnew312-pep692>`, using :class:`~typing.TypedDict` to
annotate :term:`**kwargs <argument>`
* :ref:`whatsnew312-pep692` * :ref:`PEP 698 <whatsnew312-pep698>`, :func:`typing.override` decorator
* :ref:`whatsnew312-pep695`
* :ref:`whatsnew312-pep698`
Important deprecations, removals or restrictions: Important deprecations, removals or restrictions:
* :pep:`623`: Remove wstr from Unicode * :pep:`623`: Remove ``wstr`` from Unicode objects in Python's C API,
reducing the size of every :class:`str` object by at least 8 bytes.
* :pep:`632`: Remove the ``distutils`` package. See * :pep:`632`: Remove the :mod:`!distutils` package.
`the migration guide <https://peps.python.org/pep-0632/#migration-advice>`_ See `the migration guide <https://peps.python.org/pep-0632/#migration-advice>`_
for advice on its replacement. for advice replacing the APIs it provided.
The third-party `Setuptools <https://setuptools.pypa.io/en/latest/deprecated/distutils-legacy.html>`__
package continues to provide :mod:`!distutils`,
if you still require it in Python 3.12 and beyond.
* :gh:`95299`: Do not pre-install ``setuptools`` in virtual environments * :gh:`95299`: Do not pre-install ``setuptools`` in virtual environments
created with :mod:`venv`. created with :mod:`venv`.
@ -97,61 +167,78 @@ Important deprecations, removals or restrictions:
run ``pip install setuptools`` in the :ref:`activated <venv-explanation>` run ``pip install setuptools`` in the :ref:`activated <venv-explanation>`
virtual environment. virtual environment.
Improved Error Messages * The :mod:`!asynchat`, :mod:`!asyncore`, and :mod:`!imp` modules have been
======================= removed, along with several :class:`unittest.TestCase`
`method aliases <unittest-TestCase-removed-aliases_>`_.
* Modules from the standard library are now potentially suggested as part of
the error messages displayed by the interpreter when a :exc:`NameError` is
raised to the top level. (Contributed by Pablo Galindo in :gh:`98254`.)
>>> sys.version_info
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'sys' is not defined. Did you forget to import 'sys'?
* Improve the error suggestion for :exc:`NameError` exceptions for instances.
Now if a :exc:`NameError` is raised in a method and the instance has an
attribute that's exactly equal to the name in the exception, the suggestion
will include ``self.<NAME>`` instead of the closest match in the method
scope. (Contributed by Pablo Galindo in :gh:`99139`.)
>>> class A:
... def __init__(self):
... self.blech = 1
...
... def foo(self):
... somethin = blech
...
>>> A().foo()
Traceback (most recent call last):
File "<stdin>", line 1
somethin = blech
^^^^^
NameError: name 'blech' is not defined. Did you mean: 'self.blech'?
* Improve the :exc:`SyntaxError` error message when the user types ``import x
from y`` instead of ``from y import x``. (Contributed by Pablo Galindo in :gh:`98931`.)
>>> import a.y.z from b.y.z
Traceback (most recent call last):
File "<stdin>", line 1
import a.y.z from b.y.z
^^^^^^^^^^^^^^^^^^^^^^^
SyntaxError: Did you mean to use 'from ... import ...' instead?
* :exc:`ImportError` exceptions raised from failed ``from <module> import
<name>`` statements now include suggestions for the value of ``<name>`` based on the
available names in ``<module>``. (Contributed by Pablo Galindo in :gh:`91058`.)
>>> from collections import chainmap
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: cannot import name 'chainmap' from 'collections'. Did you mean: 'ChainMap'?
New Features New Features
============ ============
.. _whatsnew312-pep695:
PEP 695: Type Parameter Syntax
------------------------------
Generic classes and functions under :pep:`484` were declared using a verbose syntax
that left the scope of type parameters unclear and required explicit declarations of
variance.
:pep:`695` introduces a new, more compact and explicit way to create
:ref:`generic classes <generic-classes>` and :ref:`functions <generic-functions>`::
def max[T](args: Iterable[T]) -> T:
...
class list[T]:
def __getitem__(self, index: int, /) -> T:
...
def append(self, element: T) -> None:
...
In addition, the PEP introduces a new way to declare :ref:`type aliases <type-aliases>`
using the :keyword:`type` statement, which creates an instance of
:class:`~typing.TypeAliasType`::
type Point = tuple[float, float]
Type aliases can also be :ref:`generic <generic-type-aliases>`::
type Point[T] = tuple[T, T]
The new syntax allows declaring :class:`~typing.TypeVarTuple`
and :class:`~typing.ParamSpec` parameters, as well as :class:`~typing.TypeVar`
parameters with bounds or constraints::
type IntFunc[**P] = Callable[P, int] # ParamSpec
type LabeledTuple[*Ts] = tuple[str, *Ts] # TypeVarTuple
type HashableSequence[T: Hashable] = Sequence[T] # TypeVar with bound
type IntOrStrSequence[T: (int, str)] = Sequence[T] # TypeVar with constraints
The value of type aliases and the bound and constraints of type variables
created through this syntax are evaluated only on demand (see
:ref:`lazy evaluation <lazy-evaluation>`). This means type aliases are able to
refer to other types defined later in the file.
Type parameters declared through a type parameter list are visible within the
scope of the declaration and any nested scopes, but not in the outer scope. For
example, they can be used in the type annotations for the methods of a generic
class or in the class body. However, they cannot be used in the module scope after
the class is defined. See :ref:`type-params` for a detailed description of the
runtime semantics of type parameters.
In order to support these scoping semantics, a new kind of scope is introduced,
the :ref:`annotation scope <annotation-scopes>`. Annotation scopes behave for the
most part like function scopes, but interact differently with enclosing class scopes.
In Python 3.13, :term:`annotations <annotation>` will also be evaluated in
annotation scopes.
See :pep:`695` for more details.
(PEP written by Eric Traut. Implementation by Jelle Zijlstra, Eric Traut,
and others in :gh:`103764`.)
.. _whatsnew312-pep701: .. _whatsnew312-pep701:
PEP 701: Syntactic formalization of f-strings PEP 701: Syntactic formalization of f-strings
@ -244,52 +331,6 @@ are parsed with the PEG parser, error messages can be more precise and show the
Maureira-Fredes and Marta Gómez in :gh:`102856`. PEP written by Pablo Galindo, Maureira-Fredes and Marta Gómez in :gh:`102856`. PEP written by Pablo Galindo,
Batuhan Taskaya, Lysandros Nikolaou and Marta Gómez). Batuhan Taskaya, Lysandros Nikolaou and Marta Gómez).
.. _whatsnew312-pep709:
PEP 709: Comprehension inlining
-------------------------------
Dictionary, list, and set comprehensions are now inlined, rather than creating a
new single-use function object for each execution of the comprehension. This
speeds up execution of a comprehension by up to two times.
See :pep:`709` for further details.
Comprehension iteration variables remain isolated and don't overwrite a
variable of the same name in the outer scope, nor are they visible after the
comprehension. Inlining does result in a few visible behavior changes:
* There is no longer a separate frame for the comprehension in tracebacks,
and tracing/profiling no longer shows the comprehension as a function call.
* The :mod:`symtable` module will no longer produce child symbol tables for each
comprehension; instead, the comprehension's locals will be included in the
parent function's symbol table.
* Calling :func:`locals` inside a comprehension now includes variables
from outside the comprehension, and no longer includes the synthetic ``.0``
variable for the comprehension "argument".
* A comprehension iterating directly over ``locals()`` (e.g. ``[k for k in
locals()]``) may see "RuntimeError: dictionary changed size during iteration"
when run under tracing (e.g. code coverage measurement). This is the same
behavior already seen in e.g. ``for k in locals():``. To avoid the error, first
create a list of keys to iterate over: ``keys = list(locals()); [k for k in
keys]``.
(Contributed by Carl Meyer and Vladimir Matveev in :pep:`709`.)
.. _whatsnew312-pep688:
PEP 688: Making the buffer protocol accessible in Python
--------------------------------------------------------
:pep:`688` introduces a way to use the :ref:`buffer protocol <bufferobjects>`
from Python code. Classes that implement the :meth:`~object.__buffer__` method
are now usable as buffer types.
The new :class:`collections.abc.Buffer` ABC provides a standard
way to represent buffer objects, for example in type annotations.
The new :class:`inspect.BufferFlags` enum represents the flags that
can be used to customize buffer creation.
(Contributed by Jelle Zijlstra in :gh:`102500`.)
.. _whatsnew312-pep684: .. _whatsnew312-pep684:
PEP 684: A Per-Interpreter GIL PEP 684: A Per-Interpreter GIL
@ -333,7 +374,105 @@ This means that you only pay for what you use, providing support
for near-zero overhead debuggers and coverage tools. for near-zero overhead debuggers and coverage tools.
See :mod:`sys.monitoring` for details. See :mod:`sys.monitoring` for details.
(Contributed by Mark Shannon in :gh:`103083`.) (Contributed by Mark Shannon in :gh:`103082`.)
.. _whatsnew312-pep688:
PEP 688: Making the buffer protocol accessible in Python
--------------------------------------------------------
:pep:`688` introduces a way to use the :ref:`buffer protocol <bufferobjects>`
from Python code. Classes that implement the :meth:`~object.__buffer__` method
are now usable as buffer types.
The new :class:`collections.abc.Buffer` ABC provides a standard
way to represent buffer objects, for example in type annotations.
The new :class:`inspect.BufferFlags` enum represents the flags that
can be used to customize buffer creation.
(Contributed by Jelle Zijlstra in :gh:`102500`.)
.. _whatsnew312-pep709:
PEP 709: Comprehension inlining
-------------------------------
Dictionary, list, and set comprehensions are now inlined, rather than creating a
new single-use function object for each execution of the comprehension. This
speeds up execution of a comprehension by up to two times.
See :pep:`709` for further details.
Comprehension iteration variables remain isolated and don't overwrite a
variable of the same name in the outer scope, nor are they visible after the
comprehension. Inlining does result in a few visible behavior changes:
* There is no longer a separate frame for the comprehension in tracebacks,
and tracing/profiling no longer shows the comprehension as a function call.
* The :mod:`symtable` module will no longer produce child symbol tables for each
comprehension; instead, the comprehension's locals will be included in the
parent function's symbol table.
* Calling :func:`locals` inside a comprehension now includes variables
from outside the comprehension, and no longer includes the synthetic ``.0``
variable for the comprehension "argument".
* A comprehension iterating directly over ``locals()`` (e.g. ``[k for k in
locals()]``) may see "RuntimeError: dictionary changed size during iteration"
when run under tracing (e.g. code coverage measurement). This is the same
behavior already seen in e.g. ``for k in locals():``. To avoid the error, first
create a list of keys to iterate over: ``keys = list(locals()); [k for k in
keys]``.
(Contributed by Carl Meyer and Vladimir Matveev in :pep:`709`.)
Improved Error Messages
-----------------------
* Modules from the standard library are now potentially suggested as part of
the error messages displayed by the interpreter when a :exc:`NameError` is
raised to the top level. (Contributed by Pablo Galindo in :gh:`98254`.)
>>> sys.version_info
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'sys' is not defined. Did you forget to import 'sys'?
* Improve the error suggestion for :exc:`NameError` exceptions for instances.
Now if a :exc:`NameError` is raised in a method and the instance has an
attribute that's exactly equal to the name in the exception, the suggestion
will include ``self.<NAME>`` instead of the closest match in the method
scope. (Contributed by Pablo Galindo in :gh:`99139`.)
>>> class A:
... def __init__(self):
... self.blech = 1
...
... def foo(self):
... somethin = blech
...
>>> A().foo()
Traceback (most recent call last):
File "<stdin>", line 1
somethin = blech
^^^^^
NameError: name 'blech' is not defined. Did you mean: 'self.blech'?
* Improve the :exc:`SyntaxError` error message when the user types ``import x
from y`` instead of ``from y import x``. (Contributed by Pablo Galindo in :gh:`98931`.)
>>> import a.y.z from b.y.z
Traceback (most recent call last):
File "<stdin>", line 1
import a.y.z from b.y.z
^^^^^^^^^^^^^^^^^^^^^^^
SyntaxError: Did you mean to use 'from ... import ...' instead?
* :exc:`ImportError` exceptions raised from failed ``from <module> import
<name>`` statements now include suggestions for the value of ``<name>`` based on the
available names in ``<module>``. (Contributed by Pablo Galindo in :gh:`91058`.)
>>> from collections import chainmap
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: cannot import name 'chainmap' from 'collections'. Did you mean: 'ChainMap'?
New Features Related to Type Hints New Features Related to Type Hints
================================== ==================================
@ -398,70 +537,6 @@ See :pep:`698` for more details.
(Contributed by Steven Troxler in :gh:`101561`.) (Contributed by Steven Troxler in :gh:`101561`.)
.. _whatsnew312-pep695:
PEP 695: Type Parameter Syntax
------------------------------
Generic classes and functions under :pep:`484` were declared using a verbose syntax
that left the scope of type parameters unclear and required explicit declarations of
variance.
:pep:`695` introduces a new, more compact and explicit way to create
:ref:`generic classes <generic-classes>` and :ref:`functions <generic-functions>`::
def max[T](args: Iterable[T]) -> T:
...
class list[T]:
def __getitem__(self, index: int, /) -> T:
...
def append(self, element: T) -> None:
...
In addition, the PEP introduces a new way to declare :ref:`type aliases <type-aliases>`
using the :keyword:`type` statement, which creates an instance of
:class:`~typing.TypeAliasType`::
type Point = tuple[float, float]
Type aliases can also be :ref:`generic <generic-type-aliases>`::
type Point[T] = tuple[T, T]
The new syntax allows declaring :class:`~typing.TypeVarTuple`
and :class:`~typing.ParamSpec` parameters, as well as :class:`~typing.TypeVar`
parameters with bounds or constraints::
type IntFunc[**P] = Callable[P, int] # ParamSpec
type LabeledTuple[*Ts] = tuple[str, *Ts] # TypeVarTuple
type HashableSequence[T: Hashable] = Sequence[T] # TypeVar with bound
type IntOrStrSequence[T: (int, str)] = Sequence[T] # TypeVar with constraints
The value of type aliases and the bound and constraints of type variables
created through this syntax are evaluated only on demand (see
:ref:`lazy evaluation <lazy-evaluation>`). This means type aliases are able to
refer to other types defined later in the file.
Type parameters declared through a type parameter list are visible within the
scope of the declaration and any nested scopes, but not in the outer scope. For
example, they can be used in the type annotations for the methods of a generic
class or in the class body. However, they cannot be used in the module scope after
the class is defined. See :ref:`type-params` for a detailed description of the
runtime semantics of type parameters.
In order to support these scoping semantics, a new kind of scope is introduced,
the :ref:`annotation scope <annotation-scopes>`. Annotation scopes behave for the
most part like function scopes, but interact differently with enclosing class scopes.
In Python 3.13, :term:`annotations <annotation>` will also be evaluated in
annotation scopes.
See :pep:`695` for more details.
(PEP written by Eric Traut. Implementation by Jelle Zijlstra, Eric Traut,
and others in :gh:`103764`.)
Other Language Changes Other Language Changes
====================== ======================
@ -1020,6 +1095,13 @@ CPython bytecode changes
* Add the :opcode:`LOAD_SUPER_ATTR` instruction. (Contributed by Carl Meyer and * Add the :opcode:`LOAD_SUPER_ATTR` instruction. (Contributed by Carl Meyer and
Vladimir Matveev in :gh:`103497`.) Vladimir Matveev in :gh:`103497`.)
FOR_ITER new behavior is not mentioned
The fact that POP_JUMP_IF_* family of instructions are now real instructions is not mentioned
YIELD_VALUE need for an argument is not mentioned
Demos and Tools Demos and Tools
=============== ===============
@ -1578,6 +1660,8 @@ unittest
* Remove many long-deprecated :mod:`unittest` features: * Remove many long-deprecated :mod:`unittest` features:
.. _unittest-TestCase-removed-aliases:
* A number of :class:`~unittest.TestCase` method aliases: * A number of :class:`~unittest.TestCase` method aliases:
============================ =============================== =============== ============================ =============================== ===============
@ -1811,6 +1895,7 @@ C API Changes
New Features New Features
------------ ------------
.. _whatsnew312-pep697:
* :pep:`697`: Introduce the :ref:`Unstable C API tier <unstable-c-api>`, * :pep:`697`: Introduce the :ref:`Unstable C API tier <unstable-c-api>`,
intended for low-level tools like debuggers and JIT compilers. intended for low-level tools like debuggers and JIT compilers.
@ -1938,6 +2023,8 @@ New Features
to replace the legacy-api :c:func:`!PyErr_Display`. (Contributed by to replace the legacy-api :c:func:`!PyErr_Display`. (Contributed by
Irit Katriel in :gh:`102755`). Irit Katriel in :gh:`102755`).
.. _whatsnew312-pep683:
* :pep:`683`: Introduce *Immortal Objects*, which allows objects * :pep:`683`: Introduce *Immortal Objects*, which allows objects
to bypass reference counts, and related changes to the C-API: to bypass reference counts, and related changes to the C-API: