From 0906a8d6d75b6cb05aa8cd25f888609cdd19a352 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Sat, 7 Feb 2026 18:36:08 +0200 Subject: [PATCH 1/4] Add colour to pprint output --- Doc/library/pprint.rst | 26 ++++++++++++++--- Doc/whatsnew/3.15.rst | 10 +++++++ Lib/pprint.py | 63 +++++++++++++++++++++++++++++++++++------ Lib/test/test_pickle.py | 1 + Lib/test/test_pprint.py | 48 +++++++++++++++++++++++++++++++ 5 files changed, 136 insertions(+), 12 deletions(-) diff --git a/Doc/library/pprint.rst b/Doc/library/pprint.rst index 350831d6ad3c1b..c99dc343d4fd8a 100644 --- a/Doc/library/pprint.rst +++ b/Doc/library/pprint.rst @@ -31,7 +31,8 @@ Functions --------- .. function:: pp(object, stream=None, indent=1, width=80, depth=None, *, \ - compact=False, sort_dicts=False, underscore_numbers=False) + color=True, compact=False, sort_dicts=False, \ + underscore_numbers=False) Prints the formatted representation of *object*, followed by a newline. This function may be used in the interactive interpreter @@ -63,6 +64,12 @@ Functions on the depth of the objects being formatted. :type depth: int | None + :param bool color: + If ``True`` (the default), output will be syntax highlighted using ANSI + escape sequences, if the *stream* and :ref:`environment variables + ` permit. + If ``False``, colored output is always disabled. + :param bool compact: Control the way long :term:`sequences ` are formatted. If ``False`` (the default), @@ -93,14 +100,21 @@ Functions .. versionadded:: 3.8 + .. versionchanged:: next + Added the *color* parameter. + .. function:: pprint(object, stream=None, indent=1, width=80, depth=None, *, \ - compact=False, sort_dicts=True, underscore_numbers=False) + color=True, compact=False, sort_dicts=True, \ + underscore_numbers=False) Alias for :func:`~pprint.pp` with *sort_dicts* set to ``True`` by default, which would automatically sort the dictionaries' keys, you might want to use :func:`~pprint.pp` instead where it is ``False`` by default. + .. versionchanged:: next + Added the *color* parameter. + .. function:: pformat(object, indent=1, width=80, depth=None, *, \ compact=False, sort_dicts=True, underscore_numbers=False) @@ -144,13 +158,14 @@ Functions .. _prettyprinter-objects: -PrettyPrinter Objects +PrettyPrinter objects --------------------- .. index:: single: ...; placeholder .. class:: PrettyPrinter(indent=1, width=80, depth=None, stream=None, *, \ - compact=False, sort_dicts=True, underscore_numbers=False) + color=True, compact=False, sort_dicts=True, \ + underscore_numbers=False) Construct a :class:`PrettyPrinter` instance. @@ -193,6 +208,9 @@ PrettyPrinter Objects .. versionchanged:: 3.11 No longer attempts to write to :data:`!sys.stdout` if it is ``None``. + .. versionchanged:: next + Added the *color* parameter. + :class:`PrettyPrinter` instances have the following methods: diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 37ebdfee7915fe..19e05f76a04dd3 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -864,6 +864,16 @@ pickle (Contributed by Zackery Spytz and Serhiy Storchaka in :gh:`77188`.) +pprint +------ + +* Add *color* parameter to :func:`~pprint.pp` and :func:`~pprint.pprint`. + If ``True`` (the default), output is highlighted in color, when the stream + and :ref:`environment variables ` permit. + If ``False``, colored output is always disabled. + (Contributed by Hugo van Kemenade in :gh:`123456`.) + + re -- diff --git a/Lib/pprint.py b/Lib/pprint.py index e111bd59d4152c..e0d170963cfae1 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -39,17 +39,36 @@ import types as _types from io import StringIO as _StringIO +lazy import _colorize +lazy from _pyrepl.utils import disp_str, gen_colors + __all__ = ["pprint","pformat","isreadable","isrecursive","saferepr", "PrettyPrinter", "pp"] -def pprint(object, stream=None, indent=1, width=80, depth=None, *, - compact=False, sort_dicts=True, underscore_numbers=False): +def pprint( + object, + stream=None, + indent=1, + width=80, + depth=None, + *, + color=True, + compact=False, + sort_dicts=True, + underscore_numbers=False, +): """Pretty-print a Python object to a stream [default is sys.stdout].""" printer = PrettyPrinter( - stream=stream, indent=indent, width=width, depth=depth, - compact=compact, sort_dicts=sort_dicts, - underscore_numbers=underscore_numbers) + stream=stream, + indent=indent, + width=width, + depth=depth, + color=color, + compact=compact, + sort_dicts=sort_dicts, + underscore_numbers=underscore_numbers, + ) printer.pprint(object) @@ -109,9 +128,26 @@ def _safe_tuple(t): return _safe_key(t[0]), _safe_key(t[1]) +def _colorize_output(text): + """Apply syntax highlighting.""" + colors = list(gen_colors(text)) + chars, _ = disp_str(text, colors=colors, force_color=True) + return "".join(chars) + + class PrettyPrinter: - def __init__(self, indent=1, width=80, depth=None, stream=None, *, - compact=False, sort_dicts=True, underscore_numbers=False): + def __init__( + self, + indent=1, + width=80, + depth=None, + stream=None, + *, + color=True, + compact=False, + sort_dicts=True, + underscore_numbers=False, + ): """Handle pretty printing operations onto a stream using a set of configured parameters. @@ -128,6 +164,11 @@ def __init__(self, indent=1, width=80, depth=None, stream=None, *, The desired output stream. If omitted (or false), the standard output stream available at construction will be used. + color + If true (the default), syntax highlighting is enabled for pprint + when the stream and environment variables permit. + If false, colored output is always disabled. + compact If true, several items will be combined in one line. @@ -156,10 +197,16 @@ def __init__(self, indent=1, width=80, depth=None, stream=None, *, self._compact = bool(compact) self._sort_dicts = sort_dicts self._underscore_numbers = underscore_numbers + self._color = color def pprint(self, object): if self._stream is not None: - self._format(object, self._stream, 0, 0, {}, 0) + if self._color and _colorize.can_colorize(file=self._stream): + sio = _StringIO() + self._format(object, sio, 0, 0, {}, 0) + self._stream.write(_colorize_output(sio.getvalue())) + else: + self._format(object, self._stream, 0, 0, {}, 0) self._stream.write("\n") def pformat(self, object): diff --git a/Lib/test/test_pickle.py b/Lib/test/test_pickle.py index 48375cf459ea0b..9ad1ab7f4e1b75 100644 --- a/Lib/test/test_pickle.py +++ b/Lib/test/test_pickle.py @@ -779,6 +779,7 @@ def invoke_pickle(self, *flags): pickle._main(args=[*flags, self.filename]) return self.text_normalize(output.getvalue()) + @support.force_not_colorized def test_invocation(self): # test 'python -m pickle pickle_file' data = { diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py index f3860a5d511989..03e443cf85b6a4 100644 --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -10,6 +10,7 @@ import re import types import unittest +import unittest.mock from collections.abc import ItemsView, KeysView, Mapping, MappingView, ValuesView from test.support import cpython_only @@ -165,6 +166,53 @@ def test_init(self): self.assertRaises(ValueError, pprint.PrettyPrinter, depth=-1) self.assertRaises(ValueError, pprint.PrettyPrinter, width=0) + def test_color_pprint(self): + """Test pprint color parameter.""" + obj = {"key": "value"} + stream = io.StringIO() + + # color=False should produce no ANSI codes + pprint.pprint(obj, stream=stream, color=False) + result = stream.getvalue() + self.assertNotIn("\x1b[", result) + + # Explicit color=False should override FORCE_COLOR + stream = io.StringIO() + with unittest.mock.patch.dict( + "os.environ", {"FORCE_COLOR": "1", "NO_COLOR": ""} + ): + pprint.pprint(obj, stream=stream, color=False) + result = stream.getvalue() + self.assertNotIn("\x1b[", result) + + def test_color_prettyprinter(self): + """Test PrettyPrinter color parameter.""" + obj = {"key": "value"} + + # color=False should produce no ANSI codes in pprint + stream = io.StringIO() + pp = pprint.PrettyPrinter(stream=stream, color=False) + pp.pprint(obj) + self.assertNotIn("\x1b[", stream.getvalue()) + + # color=True with FORCE_COLOR should produce ANSI codes in pprint + with unittest.mock.patch.dict( + "os.environ", {"FORCE_COLOR": "1", "NO_COLOR": ""} + ): + stream = io.StringIO() + pp = pprint.PrettyPrinter(stream=stream, color=True) + pp.pprint(obj) + self.assertIn("\x1b[", stream.getvalue()) + + # Explicit color=False should override FORCE_COLOR + with unittest.mock.patch.dict( + "os.environ", {"FORCE_COLOR": "1", "NO_COLOR": ""} + ): + stream = io.StringIO() + pp = pprint.PrettyPrinter(stream=stream, color=False) + pp.pprint(obj) + self.assertNotIn("\x1b[", stream.getvalue()) + def test_basic(self): # Verify .isrecursive() and .isreadable() w/o recursion pp = pprint.PrettyPrinter() From 71739fe9e205535ea24618fe444135d86307621b Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Wed, 25 Feb 2026 16:19:40 +0200 Subject: [PATCH 2/4] Add blurb --- Doc/whatsnew/3.15.rst | 2 +- .../next/Library/2026-02-25-16-19-21.gh-issue-145217.QQBY0-.rst | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2026-02-25-16-19-21.gh-issue-145217.QQBY0-.rst diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 19e05f76a04dd3..2de79cc901ba1e 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -871,7 +871,7 @@ pprint If ``True`` (the default), output is highlighted in color, when the stream and :ref:`environment variables ` permit. If ``False``, colored output is always disabled. - (Contributed by Hugo van Kemenade in :gh:`123456`.) + (Contributed by Hugo van Kemenade in :gh:`145217`.) re diff --git a/Misc/NEWS.d/next/Library/2026-02-25-16-19-21.gh-issue-145217.QQBY0-.rst b/Misc/NEWS.d/next/Library/2026-02-25-16-19-21.gh-issue-145217.QQBY0-.rst new file mode 100644 index 00000000000000..ee4cd9a86eeb43 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-25-16-19-21.gh-issue-145217.QQBY0-.rst @@ -0,0 +1 @@ +Add colour to :mod:`pprint` output. Patch by Hugo van Kemenade. From e11465be1f26981907caa6656cf42a316b2d5e01 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Thu, 9 Apr 2026 16:48:53 +0300 Subject: [PATCH 3/4] Pass escape=False for pprint to keep real control chars --- Lib/_pyrepl/utils.py | 16 ++++++++++++++-- Lib/pprint.py | 2 +- Lib/test/test_pprint.py | 21 +++++++++++++++++++++ Lib/test/test_pyrepl/test_utils.py | 17 ++++++++++++++++- 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/Lib/_pyrepl/utils.py b/Lib/_pyrepl/utils.py index b50426c31ead53..e1bd41183eb699 100644 --- a/Lib/_pyrepl/utils.py +++ b/Lib/_pyrepl/utils.py @@ -307,9 +307,14 @@ def iter_display_chars( buffer: str, colors: list[ColorSpan] | None = None, start_index: int = 0, + *, + escape: bool = True, ) -> Iterator[StyledChar]: """Yield visible display characters with widths and semantic color tags. + With ``escape=True`` (default) ASCII control chars are rewritten to caret + notation (``\\n`` -> ``^J``); pass ``escape=False`` to keep them verbatim. + Note: ``colors`` is consumed in place as spans are processed -- callers that split a buffer across multiple calls rely on this mutation to track which spans have already been handled. @@ -331,7 +336,7 @@ def iter_display_chars( if colors and color_idx < len(colors) and colors[color_idx].span.start == i: active_tag = colors[color_idx].tag - if control := _ascii_control_repr(c): + if escape and (control := _ascii_control_repr(c)): text = control width = len(control) elif ord(c) < 128: @@ -363,6 +368,8 @@ def disp_str( colors: list[ColorSpan] | None = None, start_index: int = 0, force_color: bool = False, + *, + escape: bool = True, ) -> tuple[CharBuffer, CharWidths]: r"""Decompose the input buffer into a printable variant with applied colors. @@ -374,6 +381,9 @@ def disp_str( - the second list is the visible width of each character in the input buffer. + With ``escape=True`` (default) ASCII control chars are rewritten to caret + notation (``\\n`` -> ``^J``); pass ``escape=False`` to keep them verbatim. + Note on colors: - The `colors` list, if provided, is partially consumed within. We're using a list and not a generator since we need to hold onto the current @@ -393,7 +403,9 @@ def disp_str( (['\x1b[1;34mw', 'h', 'i', 'l', 'e\x1b[0m', ' ', '1', ':'], [1, 1, 1, 1, 1, 1, 1, 1]) """ - styled_chars = list(iter_display_chars(buffer, colors, start_index)) + styled_chars = list( + iter_display_chars(buffer, colors, start_index, escape=escape) + ) chars: CharBuffer = [] char_widths: CharWidths = [] theme = THEME(force_color=force_color) diff --git a/Lib/pprint.py b/Lib/pprint.py index c53c7881ec91ad..dc42b257bb3f45 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -134,7 +134,7 @@ def _safe_tuple(t): def _colorize_output(text): """Apply syntax highlighting.""" colors = list(gen_colors(text)) - chars, _ = disp_str(text, colors=colors, force_color=True) + chars, _ = disp_str(text, colors=colors, force_color=True, escape=False) return "".join(chars) diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py index a18cc2b34cd759..7973cc9501842b 100644 --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -214,6 +214,27 @@ def test_color_prettyprinter(self): pp.pprint(obj) self.assertNotIn("\x1b[", stream.getvalue()) + def test_color_preserves_newlines(self): + """Color multiline output must use real newlines, not '^J'.""" + obj = {"a": 1, "b": 2, "c": 3, "d": [10, 20, 30, 40, 50, 60, 70, 80]} + + plain_stream = io.StringIO() + pprint.pprint(obj, stream=plain_stream, width=20, color=False) + plain = plain_stream.getvalue() + self.assertIn("\n", plain) + + with unittest.mock.patch.dict( + "os.environ", {"FORCE_COLOR": "1", "NO_COLOR": ""} + ): + color_stream = io.StringIO() + pprint.pprint(obj, stream=color_stream, width=20, color=True) + color = color_stream.getvalue() + + self.assertIn("\x1b[", color) # has color + self.assertNotIn("^J", color) + stripped = re.sub(r"\x1b\[[0-9;]*m", "", color) + self.assertEqual(stripped, plain) + def test_basic(self): # Verify .isrecursive() and .isreadable() w/o recursion pp = pprint.PrettyPrinter() diff --git a/Lib/test/test_pyrepl/test_utils.py b/Lib/test/test_pyrepl/test_utils.py index 3c55b6bdaeee9e..da141c2b9b5ae3 100644 --- a/Lib/test/test_pyrepl/test_utils.py +++ b/Lib/test/test_pyrepl/test_utils.py @@ -1,6 +1,12 @@ from unittest import TestCase -from _pyrepl.utils import str_width, wlen, prev_next_window, gen_colors +from _pyrepl.utils import ( + disp_str, + gen_colors, + prev_next_window, + str_width, + wlen, +) class TestUtils(TestCase): @@ -135,3 +141,12 @@ def test_gen_colors_keyword_highlighting(self): span_text = code[color.span.start:color.span.end + 1] actual_highlights.append((span_text, color.tag)) self.assertEqual(actual_highlights, expected_highlights) + + def test_disp_str_escape(self): + # default: control chars become caret notation + chars, _ = disp_str("a\nb\tc\x1bd") + self.assertEqual("".join(chars), "a^Jb^Ic^[d") + + # escape=False: control chars pass through verbatim + chars, _ = disp_str("a\nb\tc\x1bd", escape=False) + self.assertEqual("".join(chars), "a\nb\tc\x1bd") From fede255c72a50b4fd8513ccdce5c5605f57068ad Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Sat, 18 Apr 2026 23:07:50 +0300 Subject: [PATCH 4/4] Change back line endings to LF --- Doc/whatsnew/3.15.rst | 4362 ++++++++++++++++++++--------------------- 1 file changed, 2181 insertions(+), 2181 deletions(-) diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 7e6cac0191d7b7..7dde4e11472a6d 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1,2181 +1,2181 @@ - -**************************** - What's new in Python 3.15 -**************************** - -:Editor: Hugo van Kemenade - -.. Rules for maintenance: - - * Anyone can add text to this document. Do not spend very much time - on the wording of your changes, because your text will probably - get rewritten to some degree. - - * The maintainer will go through Misc/NEWS periodically and add - changes; it's therefore more important to add your changes to - Misc/NEWS than to this file. - - * This is not a complete list of every single change; completeness - is the purpose of Misc/NEWS. Some changes I consider too small - or esoteric to include. If such a change is added to the text, - I'll just remove it. (This is another reason you shouldn't spend - too much time on writing your addition.) - - * If you want to draw your new text to the attention of the - maintainer, add 'XXX' to the beginning of the paragraph or - section. - - * It's OK to just add a fragmentary note about a change. For - example: "XXX Describe the transmogrify() function added to the - socket module." The maintainer will research the change and - write the necessary text. - - * You can comment out your additions if you like, but it's not - necessary (especially when a final release is some months away). - - * Credit the author of a patch or bugfix. Just the name is - sufficient; the e-mail address isn't necessary. - - * It's helpful to add the issue number as a comment: - - XXX Describe the transmogrify() function added to the socket - module. - (Contributed by P.Y. Developer in :gh:`12345`.) - - This saves the maintainer the effort of going through the VCS log - when researching a change. - -This article explains the new features in Python 3.15, compared to 3.14. - -For full details, see the :ref:`changelog `. - -.. note:: - - Prerelease users should be aware that this document is currently in draft - form. It will be updated substantially as Python 3.15 moves towards release, - so it's worth checking back even after reading earlier versions. - - -Summary -- Release highlights -============================= - -.. This section singles out the most important changes in Python 3.15. - Brevity is key. - - -.. PEP-sized items next. - -* :pep:`810`: :ref:`Explicit lazy imports for faster startup times - ` -* :pep:`814`: :ref:`Add frozendict built-in type - ` -* :pep:`799`: :ref:`A dedicated profiling package for organizing Python - profiling tools ` -* :pep:`799`: :ref:`Tachyon: High frequency statistical sampling profiler - ` -* :pep:`798`: :ref:`Unpacking in comprehensions - ` -* :pep:`686`: :ref:`Python now uses UTF-8 as the default encoding - ` -* :pep:`728`: ``TypedDict`` with typed extra items -* :pep:`747`: :ref:`Annotating type forms with TypeForm - ` -* :pep:`800`: Disjoint bases in the type system -* :pep:`782`: :ref:`A new PyBytesWriter C API to create a Python bytes object - ` -* :pep:`803`: :ref:`Stable ABI for Free-Threaded Builds ` -* :ref:`The JIT compiler has been significantly upgraded ` -* :ref:`Improved error messages ` -* :ref:`The official Windows 64-bit binaries now use the tail-calling interpreter - ` - -New features -============ - -.. _whatsnew315-lazy-imports: - -:pep:`810`: Explicit lazy imports ---------------------------------- - -Large Python applications often suffer from slow startup times. A -significant contributor to this problem is the import system: when a module -is imported, Python must locate the file, read it from disk, compile it to -bytecode, and execute all top-level code. For applications with deep -dependency trees, this process can take seconds, even when most of the -imported code is never actually used during a particular run. - -Developers have worked around this by moving imports inside functions, using -:mod:`importlib` to load modules on demand, or restructuring code to avoid -unnecessary dependencies. These approaches work but make code harder to read -and maintain, scatter import statements throughout the codebase, and require -discipline to apply consistently. - -Python now provides a cleaner solution through explicit :keyword:`lazy` -imports using the new ``lazy`` soft keyword. When you mark an import as -lazy, Python defers the actual module loading until the imported name is -first used. This gives you the organizational benefits of declaring all -imports at the top of the file while only paying the loading cost for -modules you actually use. - -The ``lazy`` keyword works with both ``import`` and ``from ... import`` -statements. When you write ``lazy import heavy_module``, Python does not -immediately load the module. Instead, it creates a lightweight proxy object. -The actual module loading happens transparently when you first access the -name: - -.. code-block:: python - - lazy import json - lazy from pathlib import Path - - print("Starting up...") # json and pathlib not loaded yet - - data = json.loads('{"key": "value"}') # json loads here - p = Path(".") # pathlib loads here - -This mechanism is particularly useful for applications that import many -modules at the top level but may only use a subset of them in any given run. -The deferred loading reduces startup latency without requiring code -restructuring or conditional imports scattered throughout the codebase. - -In the case where loading a lazily imported module fails (for example, if -the module does not exist), Python raises the exception at the point of -first use rather than at import time. The associated traceback includes both -the location where the name was accessed and the original import statement, -making it straightforward to diagnose & debug the failure. - -For cases where you want to enable lazy loading globally without modifying -source code, Python provides the :option:`-X lazy_imports <-X>` command-line -option and the :envvar:`PYTHON_LAZY_IMPORTS` environment variable. Both -accept three values: ``all`` makes all imports lazy by default, ``none`` -disables lazy imports entirely (even explicit ``lazy`` statements become -eager), and ``normal`` (the default) respects the ``lazy`` keyword in source -code. The :func:`sys.set_lazy_imports` and :func:`sys.get_lazy_imports` -functions allow changing and querying this mode at runtime. - -For more selective control, :func:`sys.set_lazy_imports_filter` accepts a -callable that determines whether a specific module should be loaded lazily. -The filter receives three arguments: the importing module's name (or -``None``), the imported module's name, and the fromlist (or ``None`` for -regular imports). It should return ``True`` to allow the import to be lazy, -or ``False`` to force eager loading. This allows patterns like making only -your own application's modules lazy while keeping third-party dependencies -eager: - -.. code-block:: python - - import sys - - def myapp_filter(importing, imported, fromlist): - return imported.startswith("myapp.") - sys.set_lazy_imports_filter(myapp_filter) - sys.set_lazy_imports("all") - - import myapp.slow_module # lazy (matches filter) - import json # eager (does not match filter) - -The proxy type itself is available as :data:`types.LazyImportType` for code -that needs to detect lazy imports programmatically. - -There are some restrictions on where the ``lazy`` keyword can be used. Lazy -imports are only permitted at module scope; using ``lazy`` inside a -function, class body, or ``try``/``except``/``finally`` block raises a -:exc:`SyntaxError`. Neither star imports nor future imports can be lazy -(``lazy from module import *`` and ``lazy from __future__ import ...`` both -raise :exc:`SyntaxError`). - -.. seealso:: :pep:`810` for the full specification and rationale. - -(Contributed by Pablo Galindo Salgado and Dino Viehland in :gh:`142349`.) - - -.. _whatsnew315-frozendict: - -:pep:`814`: Add frozendict built-in type ----------------------------------------- - -A new :term:`immutable` type, :class:`frozendict`, is added to the :mod:`builtins` module. -It does not allow modification after creation. A :class:`!frozendict` is not a subclass of ``dict``; -it inherits directly from ``object``. A :class:`!frozendict` is :term:`hashable` -as long as all of its keys and values are hashable. A :class:`!frozendict` preserves -insertion order, but comparison does not take order into account. - -For example:: - - >>> a = frozendict(x=1, y=2) - >>> a - frozendict({'x': 1, 'y': 2}) - >>> a['z'] = 3 - Traceback (most recent call last): - File "", line 1, in - a['z'] = 3 - ~^^^^^ - TypeError: 'frozendict' object does not support item assignment - >>> b = frozendict(y=2, x=1) - >>> hash(a) == hash(b) - True - >>> a == b - True - -The following standard library modules have been updated to accept -:class:`!frozendict`: :mod:`copy`, :mod:`decimal`, :mod:`json`, :mod:`marshal`, -:mod:`plistlib` (only for serialization), :mod:`pickle`, :mod:`pprint` and -:mod:`xml.etree.ElementTree`. - -:func:`eval` and :func:`exec` accept :class:`!frozendict` for *globals*, and -:func:`type` and :meth:`str.maketrans` accept :class:`!frozendict` for *dict*. - -Code checking for :class:`dict` type using ``isinstance(arg, dict)`` can be -updated to ``isinstance(arg, (dict, frozendict))`` to accept also the -:class:`!frozendict` type, or to ``isinstance(arg, collections.abc.Mapping)`` -to accept also other mapping types such as :class:`~types.MappingProxyType`. - -.. seealso:: :pep:`814` for the full specification and rationale. - -(Contributed by Victor Stinner and Donghee Na in :gh:`141510`.) - - -.. _whatsnew315-profiling-package: - -:pep:`799`: A dedicated profiling package ------------------------------------------ - -A new :mod:`profiling` module has been added to organize Python's built-in -profiling tools under a single, coherent namespace. This module contains: - -* :mod:`profiling.tracing`: deterministic function-call tracing (relocated from - ``cProfile``). -* :mod:`profiling.sampling`: a new statistical sampling profiler (named Tachyon). - -The ``cProfile`` module remains as an alias for backwards compatibility. -The :mod:`profile` module is deprecated and will be removed in Python 3.17. - -.. seealso:: :pep:`799` for further details. - -(Contributed by Pablo Galindo and László Kiss Kollár in :gh:`138122`.) - - -.. _whatsnew315-sampling-profiler: - -Tachyon: High frequency statistical sampling profiler ------------------------------------------------------ - -.. image:: ../library/tachyon-logo.png - :alt: Tachyon profiler logo - :align: center - :width: 200px - -A new statistical sampling profiler (Tachyon) has been added as -:mod:`profiling.sampling`. This profiler enables low-overhead performance analysis of -running Python processes without requiring code modification or process restart. - -Unlike deterministic profilers (such as :mod:`profiling.tracing`) that instrument -every function call, the sampling profiler periodically captures stack traces from -running processes. This approach provides virtually zero overhead while achieving -sampling rates of **up to 1,000,000 Hz**, making it the fastest sampling profiler -available for Python (at the time of its contribution) and ideal for debugging -performance issues in production environments. This capability is particularly -valuable for debugging performance issues in production systems where traditional -profiling approaches would be too intrusive. - -Key features include: - -* **Zero-overhead profiling**: Attach to any running Python process without - affecting its performance. Ideal for production debugging where you can't afford - to restart or slow down your application. - -* **No code modification required**: Profile existing applications without restart. - Simply point the profiler at a running process by PID and start collecting data. - -* **Flexible target modes**: - - * Profile running processes by PID (``attach``) - attach to already-running applications - * Run and profile scripts directly (``run``) - profile from the very start of execution - * Execute and profile modules (``run -m``) - profile packages run as ``python -m module`` - -* **Multiple profiling modes**: Choose what to measure based on your performance investigation: - - * **Wall-clock time** (``--mode wall``, default): Measures real elapsed time including I/O, - network waits, and blocking operations. Use this to understand where your program spends - calendar time, including when waiting for external resources. - * **CPU time** (``--mode cpu``): Measures only active CPU execution time, excluding I/O waits - and blocking. Use this to identify CPU-bound bottlenecks and optimize computational work. - * **GIL-holding time** (``--mode gil``): Measures time spent holding Python's Global Interpreter - Lock. Use this to identify which threads dominate GIL usage in multi-threaded applications. - * **Exception handling time** (``--mode exception``): Captures samples only from threads with - an active exception. Use this to analyze exception handling overhead. - -* **Thread-aware profiling**: Option to profile all threads (``-a``) or just the main thread, - essential for understanding multi-threaded application behavior. - -* **Multiple output formats**: Choose the visualization that best fits your workflow: - - * ``--pstats``: Detailed tabular statistics compatible with :mod:`pstats`. Shows function-level - timing with direct and cumulative samples. Best for detailed analysis and integration with - existing Python profiling tools. - * ``--collapsed``: Generates collapsed stack traces (one line per stack). This format is - specifically designed for creating flame graphs with external tools like Brendan Gregg's - FlameGraph scripts or speedscope. - * ``--flamegraph``: Generates a self-contained interactive HTML flame graph using D3.js. - Opens directly in your browser for immediate visual analysis. Flame graphs show the call - hierarchy where width represents time spent, making it easy to spot bottlenecks at a glance. - * ``--gecko``: Generates Gecko Profiler format compatible with `Firefox Profiler - `__. Upload the output to Firefox Profiler for advanced - timeline-based analysis with features like stack charts, markers, and network activity. - * ``--heatmap``: Generates an interactive HTML heatmap visualization with line-level sample - counts. Creates a directory with per-file heatmaps showing exactly where time is spent - at the source code level. - -* **Live interactive mode**: Real-time TUI profiler with a top-like interface (``--live``). - Monitor performance as your application runs with interactive sorting and filtering. - -* **Async-aware profiling**: Profile async/await code with task-based stack reconstruction - (``--async-aware``). See which coroutines are consuming time, with options to show only - running tasks or all tasks including those waiting. - -* **Opcode-level profiling**: Gather bytecode opcode information for instruction-level - profiling (``--opcodes``). Shows which bytecode instructions are executing, including - specializations from the adaptive interpreter. - -See :mod:`profiling.sampling` for the complete documentation, including all -available output formats, profiling modes, and configuration options. - -(Contributed by Pablo Galindo and László Kiss Kollár in :gh:`135953` and :gh:`138122`.) - - -.. _whatsnew315-unpacking-in-comprehensions: - -:pep:`798`: Unpacking in Comprehensions ---------------------------------------- - -List, set, and dictionary comprehensions, as well as generator expressions, now -support unpacking with ``*`` and ``**``. This extends the unpacking syntax -from :pep:`448` to comprehensions, providing a new syntax for combining an -arbitrary number of iterables or dictionaries into a single flat structure. -This new syntax is a direct alternative to nested comprehensions, -:func:`itertools.chain`, and :meth:`itertools.chain.from_iterable`. For -example:: - - >>> lists = [[1, 2], [3, 4], [5]] - >>> [*L for L in lists] # equivalent to [x for L in lists for x in L] - [1, 2, 3, 4, 5] - - >>> sets = [{1, 2}, {2, 3}, {3, 4}] - >>> {*s for s in sets} # equivalent to {x for s in sets for x in s} - {1, 2, 3, 4} - - >>> dicts = [{'a': 1}, {'b': 2}, {'a': 3}] - >>> {**d for d in dicts} # equivalent to {k: v for d in dicts for k,v in d.items()} - {'a': 3, 'b': 2} - -Generator expressions can similarly use unpacking to yield values from multiple -iterables:: - - >>> gen = (*L for L in lists) # equivalent to (x for L in lists for x in L) - >>> list(gen) - [1, 2, 3, 4, 5] - -This change also extends to asynchronous generator expressions, such that, for -example, ``(*a async for a in agen())`` is equivalent to ``(x async for a in -agen() for x in a)``. - -.. seealso:: :pep:`798` for further details. - -(Contributed by Adam Hartz in :gh:`143055`.) - -.. _whatsnew315-abi3t: - -:pep:`803`: ``abi3t`` -- Stable ABI for Free-Threaded Builds ------------------------------------------------------------- - -C extensions that target the :ref:`Stable ABI ` can now be -compiled for the new *Stable ABI for Free-Threaded Builds* (also known -as ``abi3t``), which makes them compatible with -:term:`free-threaded builds ` of CPython. -This usually requires some non-trivial changes to the source code; -specifically: - -- Switching to API introduced in :pep:`697` (Python 3.12), such as - negative :c:member:`~PyType_Spec.basicsize` and - :c:func:`PyObject_GetTypeData`, rather than making :c:type:`PyObject` - part of the instance struct; and -- Switching from a ``PyInit_`` function to a new export hook, - :c:func:`PyModExport_* `, introduced for this - purpose in :pep:`793`. - -Note that Stable ABI does not offer all the functionality that CPython -has to offer. -Extensions that cannot switch to ``abi3t`` should continue to build for -the existing Stable ABI (``abi3``) and the version-specific ABI for -free-threading (``cp315t``) separately. - -Stable ABI for Free-Threaded Builds should typically -be selected in a build tool (such as, for example, Setuptools, meson-python, -scikit-build-core, or Maturin). -At the time of writing, these tools did **not** support ``abi3t``. -If this is the case for your tool, compile for ``cp315t`` separately. -If not using a build tool -- or when writing such a tool -- you can select -``abi3t`` by setting the macro :c:macro:`!Py_TARGET_ABI3T` as discussed -in :ref:`abi3-compiling`. - - -.. _whatsnew315-improved-error-messages: - -Improved error messages ------------------------ - -* The interpreter now provides more helpful suggestions in :exc:`AttributeError` - exceptions when accessing an attribute on an object that does not exist, but - a similar attribute is available through one of its members. - - For example, if the object has an attribute that itself exposes the requested - name, the error message will suggest accessing it via that inner attribute: - - .. code-block:: python - - @dataclass - class Circle: - radius: float - - @property - def area(self) -> float: - return pi * self.radius**2 - - class Container: - def __init__(self, inner: Circle) -> None: - self.inner = inner - - circle = Circle(radius=4.0) - container = Container(circle) - print(container.area) - - Running this code now produces a clearer suggestion: - - .. code-block:: pycon - - Traceback (most recent call last): - File "/home/pablogsal/github/python/main/lel.py", line 42, in - print(container.area) - ^^^^^^^^^^^^^^ - AttributeError: 'Container' object has no attribute 'area'. Did you mean '.inner.area' instead of '.area'? - - -Other language changes -====================== - -.. _whatsnew315-utf8-default: - -* Python now uses UTF-8_ as the default encoding, independent of the system's - environment. This means that I/O operations without an explicit encoding, - for example, ``open('flying-circus.txt')``, will use UTF-8. - UTF-8 is a widely-supported Unicode_ character encoding that has become a - *de facto* standard for representing text, including nearly every webpage - on the internet, many common file formats, programming languages, and more. - - This only applies when no ``encoding`` argument is given. For best - compatibility between versions of Python, ensure that an explicit ``encoding`` - argument is always provided. The :ref:`opt-in encoding warning ` - can be used to identify code that may be affected by this change. - The special ``encoding='locale'`` argument uses the current locale - encoding, and has been supported since Python 3.10. - - To retain the previous behaviour, Python's UTF-8 mode may be disabled with - the :envvar:`PYTHONUTF8=0 ` environment variable or the - :option:`-X utf8=0 <-X>` command-line option. - - .. seealso:: :pep:`686` for further details. - - .. _UTF-8: https://en.wikipedia.org/wiki/UTF-8 - .. _Unicode: https://home.unicode.org/ - - (Contributed by Adam Turner in :gh:`133711`; PEP 686 written by Inada Naoki.) - -* Several error messages incorrectly using the term "argument" have been corrected. - (Contributed by Stan Ulbrych in :gh:`133382`.) - -* The interpreter now tries to provide a suggestion when - :func:`delattr` fails due to a missing attribute. - When an attribute name that closely resembles an existing attribute is used, - the interpreter will suggest the correct attribute name in the error message. - For example: - - .. doctest:: - - >>> class A: - ... pass - >>> a = A() - >>> a.abcde = 1 - >>> del a.abcdf # doctest: +ELLIPSIS - Traceback (most recent call last): - ... - AttributeError: 'A' object has no attribute 'abcdf'. Did you mean: 'abcde'? - - (Contributed by Nikita Sobolev and Pranjal Prajapati in :gh:`136588`.) - -* Unraisable exceptions are now highlighted with color by default. This can be - controlled by :ref:`environment variables `. - (Contributed by Peter Bierma in :gh:`134170`.) - -* The :meth:`~object.__repr__` of :class:`ImportError` and :class:`ModuleNotFoundError` - now shows "name" and "path" as ``name=`` and ``path=`` if they were given - as keyword arguments at construction time. - (Contributed by Serhiy Storchaka, Oleg Iarygin, and Yoav Nir in :gh:`74185`.) - -* The :attr:`~object.__dict__` and :attr:`!__weakref__` descriptors now use a - single descriptor instance per interpreter, shared across all types that - need them. - This speeds up class creation, and helps avoid reference cycles. - (Contributed by Petr Viktorin in :gh:`135228`.) - -* The :option:`-W` option and the :envvar:`PYTHONWARNINGS` environment variable - can now specify regular expressions instead of literal strings to match - the warning message and the module name, if the corresponding field starts - and ends with a forward slash (``/``). - (Contributed by Serhiy Storchaka in :gh:`134716`.) - -* Functions that take timestamp or timeout arguments now accept any real - numbers (such as :class:`~decimal.Decimal` and :class:`~fractions.Fraction`), - not only integers or floats, although this does not improve precision. - (Contributed by Serhiy Storchaka in :gh:`67795`.) - -.. _whatsnew315-bytearray-take-bytes: - -* Added :meth:`bytearray.take_bytes(n=None, /) ` to take - bytes out of a :class:`bytearray` without copying. This enables optimizing code - which must return :class:`bytes` after working with a mutable buffer of bytes - such as data buffering, network protocol parsing, encoding, decoding, - and compression. Common code patterns which can be optimized with - :func:`~bytearray.take_bytes` are listed below. - - .. list-table:: Suggested optimizing refactors - :header-rows: 1 - - * - Description - - Old - - New - - * - Return :class:`bytes` after working with :class:`bytearray` - - .. code:: python - - def read() -> bytes: - buffer = bytearray(1024) - ... - return bytes(buffer) - - - .. code:: python - - def read() -> bytes: - buffer = bytearray(1024) - ... - return buffer.take_bytes() - - * - Empty a buffer getting the bytes - - .. code:: python - - buffer = bytearray(1024) - ... - data = bytes(buffer) - buffer.clear() - - - .. code:: python - - buffer = bytearray(1024) - ... - data = buffer.take_bytes() - - * - Split a buffer at a specific separator - - .. code:: python - - buffer = bytearray(b'abc\ndef') - n = buffer.find(b'\n') - data = bytes(buffer[:n + 1]) - del buffer[:n + 1] - assert data == b'abc' - assert buffer == bytearray(b'def') - - - .. code:: python - - buffer = bytearray(b'abc\ndef') - n = buffer.find(b'\n') - data = buffer.take_bytes(n + 1) - - * - Split a buffer at a specific separator; discard after the separator - - .. code:: python - - buffer = bytearray(b'abc\ndef') - n = buffer.find(b'\n') - data = bytes(buffer[:n]) - buffer.clear() - assert data == b'abc' - assert len(buffer) == 0 - - - .. code:: python - - buffer = bytearray(b'abc\ndef') - n = buffer.find(b'\n') - buffer.resize(n) - data = buffer.take_bytes() - - (Contributed by Cody Maloney in :gh:`139871`.) - -* Many functions related to compiling or parsing Python code, such as - :func:`compile`, :func:`ast.parse`, :func:`symtable.symtable`, - and :func:`importlib.abc.InspectLoader.source_to_code`, now allow the module - name to be passed. It is needed to unambiguously :ref:`filter ` - syntax warnings by module name. - (Contributed by Serhiy Storchaka in :gh:`135801`.) - -* Allowed defining the *__dict__* and *__weakref__* :ref:`__slots__ ` - for any class. - (Contributed by Serhiy Storchaka in :gh:`41779`.) - -* Allowed defining any :ref:`__slots__ ` for a class derived from - :class:`tuple` (including classes created by :func:`collections.namedtuple`). - (Contributed by Serhiy Storchaka in :gh:`41779`.) - -* The :class:`slice` type now supports subscription, - making it a :term:`generic type`. - (Contributed by James Hilton-Balfe in :gh:`128335`.) - -* The class :class:`memoryview` now supports the :c:expr:`float complex` and - :c:expr:`double complex` C types: formatting characters ``'F'`` and ``'D'`` - respectively. - (Contributed by Sergey B Kirpichev in :gh:`146151`.) - -* Allow the *count* argument of :meth:`bytes.replace` to be a keyword. - (Contributed by Stan Ulbrych in :gh:`147856`.) - - -New modules -=========== - -math.integer ------------- - -This module provides access to the mathematical functions for integer -arguments (:pep:`791`). -(Contributed by Serhiy Storchaka in :gh:`81313`.) - - -Improved modules -================ - -argparse --------- - -* The :class:`~argparse.BooleanOptionalAction` action supports now single-dash - long options and alternate prefix characters. - (Contributed by Serhiy Storchaka in :gh:`138525`.) - -* Changed the *suggest_on_error* parameter of :class:`argparse.ArgumentParser` to - default to ``True``. This enables suggestions for mistyped arguments by default. - (Contributed by Jakob Schluse in :gh:`140450`.) - -* Added backtick markup support in description and epilog text to highlight - inline code when color output is enabled. - (Contributed by Savannah Ostrowski in :gh:`142390`.) - - -array ------ - -* Support the :c:expr:`float complex` and :c:expr:`double complex` C types: - formatting characters ``'F'`` and ``'D'`` respectively. - (Contributed by Sergey B Kirpichev in :gh:`146151`.) - -* Support half-floats (16-bit IEEE 754 binary interchange format): formatting - character ``'e'``. - (Contributed by Sergey B Kirpichev in :gh:`146238`.) - - -base64 ------- - -* Added the *pad* parameter in :func:`~base64.z85encode`. - (Contributed by Hauke Dämpfling in :gh:`143103`.) - -* Added the *padded* parameter in - :func:`~base64.b32encode`, :func:`~base64.b32decode`, - :func:`~base64.b32hexencode`, :func:`~base64.b32hexdecode`, - :func:`~base64.b64encode`, :func:`~base64.b64decode`, - :func:`~base64.urlsafe_b64encode`, and :func:`~base64.urlsafe_b64decode`. - (Contributed by Serhiy Storchaka in :gh:`73613`.) - -* Added the *wrapcol* parameter in :func:`~base64.b16encode`, - :func:`~base64.b32encode`, :func:`~base64.b32hexencode`, - :func:`~base64.b64encode`, :func:`~base64.b85encode`, and - :func:`~base64.z85encode`. - (Contributed by Serhiy Storchaka in :gh:`143214` and :gh:`146431`.) - -* Added the *ignorechars* parameter in :func:`~base64.b16decode`, - :func:`~base64.b32decode`, :func:`~base64.b32hexdecode`, - :func:`~base64.b64decode`, :func:`~base64.b85decode`, and - :func:`~base64.z85decode`. - (Contributed by Serhiy Storchaka in :gh:`144001` and :gh:`146431`.) - - -binascii --------- - -* Added functions for Base32 encoding: - - - :func:`~binascii.b2a_base32` and :func:`~binascii.a2b_base32` - - (Contributed by James Seo in :gh:`146192`.) - -* Added functions for Ascii85, Base85, and Z85 encoding: - - - :func:`~binascii.b2a_ascii85` and :func:`~binascii.a2b_ascii85` - - :func:`~binascii.b2a_base85` and :func:`~binascii.a2b_base85` - - (Contributed by James Seo and Serhiy Storchaka in :gh:`101178`.) - -* Added the *padded* parameter in - :func:`~binascii.b2a_base32`, :func:`~binascii.a2b_base32`, - :func:`~binascii.b2a_base64`, and :func:`~binascii.a2b_base64`. - (Contributed by Serhiy Storchaka in :gh:`73613`.) - -* Added the *wrapcol* parameter in :func:`~binascii.b2a_base64`. - (Contributed by Serhiy Storchaka in :gh:`143214`.) - -* Added the *alphabet* parameter in :func:`~binascii.b2a_base64` and - :func:`~binascii.a2b_base64`. - (Contributed by Serhiy Storchaka in :gh:`145980`.) - -* Added the *ignorechars* parameter in :func:`~binascii.a2b_hex`, - :func:`~binascii.unhexlify`, and :func:`~binascii.a2b_base64`. - (Contributed by Serhiy Storchaka in :gh:`144001` and :gh:`146431`.) - - -calendar --------- - -* Calendar pages generated by the :class:`calendar.HTMLCalendar` class now support - dark mode and have been migrated to the HTML5 standard for improved accessibility. - (Contributed by Jiahao Li and Hugo van Kemenade in :gh:`137634`.) - -* The :mod:`calendar`'s :ref:`command-line ` HTML output now - accepts the year-month option: ``python -m calendar -t html 2009 06``. - (Contributed by Pål Grønås Drange in :gh:`140212`.) - - -collections ------------ - -* Added :meth:`!collections.Counter.__xor__` and - :meth:`!collections.Counter.__ixor__` to compute the symmetric difference - between :class:`~collections.Counter` objects. - (Contributed by Raymond Hettinger in :gh:`138682`.) - - -concurrent.futures ------------------- - -* Improved error reporting when a child process in a - :class:`concurrent.futures.ProcessPoolExecutor` terminates abruptly. - The resulting traceback will now tell you the PID and exit code of the - terminated process. - (Contributed by Jonathan Berg in :gh:`139486`.) - - -contextlib ----------- - -* Added support for arbitrary descriptors :meth:`!__enter__`, - :meth:`!__exit__`, :meth:`!__aenter__`, and :meth:`!__aexit__` in - :class:`~contextlib.ExitStack` and :class:`contextlib.AsyncExitStack`, for - consistency with the :keyword:`with` and :keyword:`async with` statements. - (Contributed by Serhiy Storchaka in :gh:`144386`.) - - -dataclasses ------------ - -* Annotations for generated ``__init__`` methods no longer include internal - type names. - - -dbm ---- - -* Added new :meth:`!reorganize` methods to :mod:`dbm.dumb` and :mod:`dbm.sqlite3` - which allow to recover unused free space previously occupied by deleted entries. - (Contributed by Andrea Oliveri in :gh:`134004`.) - - -difflib -------- - - .. _whatsnew315-color-difflib: - -* Introduced the optional *color* parameter to :func:`difflib.unified_diff`, - enabling color output similar to :program:`git diff`. - This can be controlled by :ref:`environment variables - `. - (Contributed by Douglas Thor in :gh:`133725`.) - -* Improved the styling of HTML diff pages generated by the :class:`difflib.HtmlDiff` - class, and migrated the output to the HTML5 standard. - (Contributed by Jiahao Li in :gh:`134580`.) - - -functools ---------- - -* :func:`~functools.singledispatchmethod` now supports non-:term:`descriptor` - callables. - (Contributed by Serhiy Storchaka in :gh:`140873`.) - -* :func:`~functools.singledispatchmethod` now dispatches on the second argument - if it wraps a regular method and is called as a class attribute. - (Contributed by Bartosz Sławecki in :gh:`143535`.) - - -hashlib -------- - -* Ensure that hash functions guaranteed to be always *available* exist as - attributes of :mod:`hashlib` even if they will not work at runtime due to - missing backend implementations. For instance, ``hashlib.md5`` will no - longer raise :exc:`AttributeError` if OpenSSL is not available and Python - has been built without MD5 support. - (Contributed by Bénédikt Tran in :gh:`136929`.) - - -http.client ------------ - -* A new *max_response_headers* keyword-only parameter has been added to - :class:`~http.client.HTTPConnection` and :class:`~http.client.HTTPSConnection` - constructors. This parameter overrides the default maximum number of allowed - response headers. - (Contributed by Alexander Enrique Urieles Nieto in :gh:`131724`.) - - -http.cookies ------------- - -* Allow '``"``' double quotes in cookie values. - (Contributed by Nick Burns and Senthil Kumaran in :gh:`92936`.) - - -http.server ------------ - -* The logging of :mod:`~http.server.BaseHTTPRequestHandler`, - as used by the :ref:`command-line interface `, - is colored by default. - This can be controlled with :ref:`environment variables - `. - (Contributed by Hugo van Kemenade in :gh:`146292`.) - - -inspect -------- - -* Add parameters *inherit_class_doc* and *fallback_to_class_doc* - for :func:`~inspect.getdoc`. - (Contributed by Serhiy Storchaka in :gh:`132686`.) - -json ----- - -* Add the *array_hook* parameter to :func:`~json.load` and - :func:`~json.loads` functions: - allow a callback for JSON literal array types to customize Python lists in - the resulting decoded object. Passing combined :class:`frozendict` to - *object_pairs_hook* param and :class:`tuple` to ``array_hook`` will yield a - deeply nested immutable Python structure representing the JSON data. - (Contributed by Joao S. O. Bueno in :gh:`146440`) - - -locale ------- - -* :func:`~locale.setlocale` now supports language codes with ``@``-modifiers. - ``@``-modifiers are no longer silently removed in :func:`~locale.getlocale`, - but included in the language code. - (Contributed by Serhiy Storchaka in :gh:`137729`.) - -* Undeprecate the :func:`locale.getdefaultlocale` function. - (Contributed by Victor Stinner in :gh:`130796`.) - - -math ----- - -* Add :func:`math.isnormal` and :func:`math.issubnormal` functions. - (Contributed by Sergey B Kirpichev in :gh:`132908`.) - -* Add :func:`math.fmax`, :func:`math.fmin` and :func:`math.signbit` functions. - (Contributed by Bénédikt Tran in :gh:`135853`.) - - -mimetypes ---------- - -* Add ``application/dicom`` MIME type for ``.dcm`` extension. - (Contributed by Benedikt Johannes in :gh:`144217`.) -* Add ``application/efi``. (Contributed by Charlie Lin in :gh:`145720`.) -* Add ``application/node`` MIME type for ``.cjs`` extension. - (Contributed by John Franey in :gh:`140937`.) -* Add ``application/toml``. (Contributed by Gil Forcada in :gh:`139959`.) -* Add ``application/sql`` and ``application/vnd.sqlite3``. - (Contributed by Charlie Lin in :gh:`145698`.) -* Add the following MIME types: - - - ``application/vnd.ms-cab-compressed`` for ``.cab`` extension - - ``application/vnd.ms-htmlhelp`` for ``.chm`` extension - - ``application/vnd.ms-officetheme`` for ``.thmx`` extension - - (Contributed by Charlie Lin in :gh:`145718`.) - -* Add ``image/jxl``. (Contributed by Foolbar in :gh:`144213`.) -* Rename ``application/x-texinfo`` to ``application/texinfo``. - (Contributed by Charlie Lin in :gh:`140165`.) -* Changed the MIME type for ``.ai`` files to ``application/pdf``. - (Contributed by Stan Ulbrych in :gh:`141239`.) - - -mmap ----- - -* :class:`mmap.mmap` now has a *trackfd* parameter on Windows; - if it is ``False``, the file handle corresponding to *fileno* will - not be duplicated. - (Contributed by Serhiy Storchaka in :gh:`78502`.) - -* Added the :meth:`mmap.mmap.set_name` method - to annotate an anonymous memory mapping - if Linux kernel supports :manpage:`PR_SET_VMA_ANON_NAME ` (Linux 5.17 or newer). - (Contributed by Donghee Na in :gh:`142419`.) - - -os --- - -* Add :func:`os.statx` on Linux kernel versions 4.11 and later with - glibc versions 2.28 and later. - (Contributed by Jeffrey Bosboom and Victor Stinner in :gh:`83714`.) - - -os.path -------- - -* Add support of the all-but-last mode in :func:`~os.path.realpath`. - (Contributed by Serhiy Storchaka in :gh:`71189`.) - -* The *strict* parameter to :func:`os.path.realpath` accepts a new value, - :data:`os.path.ALLOW_MISSING`. - If used, errors other than :exc:`FileNotFoundError` will be re-raised; - the resulting path can be missing but it will be free of symlinks. - (Contributed by Petr Viktorin for :cve:`2025-4517`.) - - -pickle ------- - -* Add support for pickling private methods and nested classes. - (Contributed by Zackery Spytz and Serhiy Storchaka in :gh:`77188`.) - - -pprint ------- - -* Add an *expand* keyword argument for :func:`pprint.pprint`, - :func:`pprint.pformat`, :func:`pprint.pp`. If true, the output will be - formatted similar to pretty-printed :func:`json.dumps` when - *indent* is supplied. - (Contributed by Stefan Todoran, Semyon Moroz and Hugo van Kemenade in - :gh:`112632`.) - -* Add *color* parameter to :func:`~pprint.pp` and :func:`~pprint.pprint`. - If ``True`` (the default), output is highlighted in color, when the stream - and :ref:`environment variables ` permit. - If ``False``, colored output is always disabled. - (Contributed by Hugo van Kemenade in :gh:`145217`.) - -* Add t-string support to :mod:`pprint`. - (Contributed by Loïc Simon and Hugo van Kemenade in :gh:`134551`.) - - -re --- - -* :func:`re.prefixmatch` and a corresponding :meth:`re.Pattern.prefixmatch` - have been added as alternate, more explicit names for the existing - and now :term:`soft deprecated` - :func:`re.match` and :meth:`re.Pattern.match` APIs. These are intended - to be used to alleviate confusion around what *match* means by following the - Zen of Python's *"Explicit is better than implicit"* mantra. Most other - language regular expression libraries use an API named *match* to mean what - Python has always called *search*. - (Contributed by Gregory P. Smith in :gh:`86519`.) - - -resource --------- - -* Add new constants: :data:`~resource.RLIMIT_NTHR`, - :data:`~resource.RLIMIT_UMTXP`, :data:`~resource.RLIMIT_THREADS`, - :data:`~resource.RLIM_SAVED_CUR`, and :data:`~resource.RLIM_SAVED_MAX`. - (Contributed by Serhiy Storchaka in :gh:`137512`.) - - -shelve ------- - -* Added new :meth:`!reorganize` method to :mod:`shelve` used to recover unused free - space previously occupied by deleted entries. - (Contributed by Andrea Oliveri in :gh:`134004`.) -* Add support for custom serialization and deserialization functions - in the :mod:`shelve` module. - (Contributed by Furkan Onder in :gh:`99631`.) - - -socket ------- - -* Add constants for the ISO-TP CAN protocol. - (Contributed by Patrick Menschel and Stefan Tatschner in :gh:`86819`.) - - -sqlite3 -------- - -* The :ref:`command-line interface ` has several new features: - - * SQL keyword completion on . - (Contributed by Long Tan in :gh:`133393`.) - - * Prompts, error messages, and help text are now colored. - This is enabled by default, see :ref:`using-on-controlling-color` for - details. - (Contributed by Stan Ulbrych and Łukasz Langa in :gh:`133461`.) - - * Table, index, trigger, view, column, function, and schema completion on . - (Contributed by Long Tan in :gh:`136101`.) - - -ssl ---- - -* Indicate through :data:`ssl.HAS_PSK_TLS13` whether the :mod:`ssl` module - supports "External PSKs" in TLSv1.3, as described in :rfc:`9258`. - (Contributed by Will Childs-Klein in :gh:`133624`.) - -* Added new methods for managing groups used for SSL key agreement - - * :meth:`ssl.SSLContext.set_groups` sets the groups allowed for doing - key agreement, extending the previous - :meth:`ssl.SSLContext.set_ecdh_curve` method. - This new API provides the ability to list multiple groups and - supports fixed-field and post-quantum groups in addition to ECDH - curves. This method can also be used to control what key shares - are sent in the TLS handshake. - * :meth:`ssl.SSLSocket.group` returns the group selected for doing key - agreement on the current connection after the TLS handshake completes. - This call requires OpenSSL 3.2 or later. - * :meth:`ssl.SSLContext.get_groups` returns a list of all available key - agreement groups compatible with the minimum and maximum TLS versions - currently set in the context. This call requires OpenSSL 3.5 or later. - - (Contributed by Ron Frederick in :gh:`136306`.) - -* Added a new method :meth:`ssl.SSLContext.set_ciphersuites` for setting TLS 1.3 - ciphers. For TLS 1.2 or earlier, :meth:`ssl.SSLContext.set_ciphers` should - continue to be used. Both calls can be made on the same context and the - selected cipher suite will depend on the TLS version negotiated when a - connection is made. - (Contributed by Ron Frederick in :gh:`137197`.) - -* Added new methods for managing signature algorithms: - - * :func:`ssl.get_sigalgs` returns a list of all available TLS signature - algorithms. This call requires OpenSSL 3.4 or later. - * :meth:`ssl.SSLContext.set_client_sigalgs` sets the signature algorithms - allowed for certificate-based client authentication. - * :meth:`ssl.SSLContext.set_server_sigalgs` sets the signature algorithms - allowed for the server to complete the TLS handshake. - * :meth:`ssl.SSLSocket.client_sigalg` returns the signature algorithm - selected for client authentication on the current connection. This call - requires OpenSSL 3.5 or later. - * :meth:`ssl.SSLSocket.server_sigalg` returns the signature algorithm - selected for the server to complete the TLS handshake on the current - connection. This call requires OpenSSL 3.5 or later. - - (Contributed by Ron Frederick in :gh:`138252`.) - - -subprocess ----------- - -* :meth:`subprocess.Popen.wait`: when ``timeout`` is not ``None`` and the - platform supports it, an efficient event-driven mechanism is used to wait for - process termination: - - - Linux >= 5.3 uses :func:`os.pidfd_open` + :func:`select.poll`. - - macOS and other BSD variants use :func:`select.kqueue` + ``KQ_FILTER_PROC`` + ``KQ_NOTE_EXIT``. - - Windows keeps using ``WaitForSingleObject`` (unchanged). - - If none of these mechanisms are available, the function falls back to the - traditional busy loop (non-blocking call and short sleeps). - (Contributed by Giampaolo Rodola in :gh:`83069`). - - -symtable --------- - -* Add :meth:`symtable.Function.get_cells` and :meth:`symtable.Symbol.is_cell` methods. - (Contributed by Yashp002 in :gh:`143504`.) - - -sys ---- - -* Add :data:`sys.abi_info` namespace to improve access to ABI information. - (Contributed by Klaus Zimmermann in :gh:`137476`.) - - -tarfile -------- - -* :func:`~tarfile.data_filter` now normalizes symbolic link targets in order to - avoid path traversal attacks. - (Contributed by Petr Viktorin in :gh:`127987` and :cve:`2025-4138`.) -* :func:`~tarfile.TarFile.extractall` now skips fixing up directory attributes - when a directory was removed or replaced by another kind of file. - (Contributed by Petr Viktorin in :gh:`127987` and :cve:`2024-12718`.) -* :func:`~tarfile.TarFile.extract` and :func:`~tarfile.TarFile.extractall` - now (re-)apply the extraction filter when substituting a link (hard or - symbolic) with a copy of another archive member, and when fixing up - directory attributes. - The former raises a new exception, :exc:`~tarfile.LinkFallbackError`. - (Contributed by Petr Viktorin for :cve:`2025-4330` and :cve:`2024-12718`.) -* :func:`~tarfile.TarFile.extract` and :func:`~tarfile.TarFile.extractall` - no longer extract rejected members when - :func:`~tarfile.TarFile.errorlevel` is zero. - (Contributed by Matt Prodani and Petr Viktorin in :gh:`112887` - and :cve:`2025-4435`.) -* :func:`~tarfile.TarFile.extract` and :func:`~tarfile.TarFile.extractall` - now replace slashes by backslashes in symlink targets on Windows to prevent - creation of corrupted links. - (Contributed by Christoph Walcher in :gh:`57911`.) - - -timeit ------- - -* The output of the :mod:`timeit` command-line interface is colored by default. - This can be controlled with - :ref:`environment variables `. - (Contributed by Hugo van Kemenade in :gh:`146609`.) -* The command-line interface now colorizes error tracebacks - by default. This can be controlled with - :ref:`environment variables `. - (Contributed by Yi Hong in :gh:`139374`.) - -* Make the target time of :meth:`timeit.Timer.autorange` configurable - and add ``--target-time`` option to the command-line interface. - (Contributed by Alessandro Cucci and Miikka Koskinen in :gh:`140283`.) - - -tkinter -------- - -* The :meth:`!tkinter.Text.search` method now supports two additional - arguments: *nolinestop* which allows the search to - continue across line boundaries; - and *strictlimits* which restricts the search to within the specified range. - (Contributed by Rihaan Meher in :gh:`130848`.) - -* A new method :meth:`!tkinter.Text.search_all` has been introduced. - This method allows for searching for all matches of a pattern - using Tcl's ``-all`` and ``-overlap`` options. - (Contributed by Rihaan Meher in :gh:`130848`.) - -* Added new methods :meth:`!pack_content`, :meth:`!place_content` and - :meth:`!grid_content` which use Tk commands with new names (introduced - in Tk 8.6) instead of :meth:`!*_slaves` methods which use Tk commands - with outdated names. - (Contributed by Serhiy Storchaka in :gh:`143754`.) - -* Added :class:`!Event` attributes :attr:`!user_data` for Tk virtual events - and :attr:`!detail` for ``Enter``, ``Leave``, ``FocusIn``, ``FocusOut``, - and ``ConfigureRequest`` events. - (Contributed by Matthias Kievernagel and Serhiy Storchaka in :gh:`47655`.) - - -.. _whatsnew315-tomllib-1-1-0: - -tomllib -------- - -* The :mod:`tomllib` module now supports TOML 1.1.0. - This is a backwards compatible update, meaning that all valid TOML 1.0.0 - documents are parsed the same way. - - The changes, according to the `official TOML changelog`_, are: - - - Allow newlines and trailing commas in inline tables. - - Previously an inline table had to be on a single line and couldn't end - with a trailing comma. This is now relaxed so that the following is valid: - - .. syntax highlighting needs TOML 1.1.0 support in Pygments, - see https://github.com/pygments/pygments/issues/3026 - - .. code-block:: text - - tbl = { - key = "a string", - moar-tbl = { - key = 1, - }, - } - - - Add ``\xHH`` notation to basic strings for codepoints under 255, - and the ``\e`` escape for the escape character: - - .. code-block:: text - - null = "null byte: \x00; letter a: \x61" - csi = "\e[" - - - Seconds in datetime and time values are now optional. - The following are now valid: - - .. code-block:: text - - dt = 2010-02-03 14:15 - t = 14:15 - - (Contributed by Taneli Hukkinen in :gh:`142956`.) - -.. _official TOML changelog: https://github.com/toml-lang/toml/blob/main/CHANGELOG.md - - -types ------ - -* Expose the write-through :func:`locals` proxy type - as :data:`types.FrameLocalsProxyType`. - This represents the type of the :attr:`frame.f_locals` attribute, - as described in :pep:`667`. - - -typing ------- - -.. _whatsnew315-typeform: - -* :pep:`747`: Add :data:`~typing.TypeForm`, a new special form for annotating - values that are themselves type expressions. - ``TypeForm[T]`` means "a type form object describing ``T`` (or a type - assignable to ``T``)". At runtime, ``TypeForm(x)`` simply returns ``x``, - which allows explicit annotation of type-form values without changing - behavior. - - This helps libraries that accept user-provided type expressions - (for example ``int``, ``str | None``, :class:`~typing.TypedDict` - classes, or ``list[int]``) expose precise signatures: - - .. code-block:: python - - from typing import Any, TypeForm - - def cast[T](typ: TypeForm[T], value: Any) -> T: ... - - (Contributed by Jelle Zijlstra in :gh:`145033`.) - -* Code like ``class ExtraTypeVars(P1[S], Protocol[T, T2]): ...`` now raises - a :exc:`TypeError`, because ``S`` is not listed in ``Protocol`` parameters. - (Contributed by Nikita Sobolev in :gh:`137191`.) - -* Code like ``class B2(A[T2], Protocol[T1, T2]): ...`` now correctly handles - type parameters order: it is ``(T1, T2)``, not ``(T2, T1)`` - as it was incorrectly inferred in runtime before. - (Contributed by Nikita Sobolev in :gh:`137191`.) - -* :pep:`800`: Add :deco:`typing.disjoint_base`, a new decorator marking a class - as a disjoint base. This is an advanced feature primarily intended to allow - type checkers to faithfully reflect the runtime semantics of types defined - as builtins or in compiled extensions. If a class ``C`` is a disjoint base, then - child classes of that class cannot inherit from other disjoint bases that are - not parent or child classes of ``C``. (Contributed by Jelle Zijlstra in :gh:`148639`.) - - -unicodedata ------------ - -* The Unicode database has been updated to Unicode 17.0.0. - -* Add :func:`unicodedata.isxidstart` and :func:`unicodedata.isxidcontinue` - functions to check whether a character can start or continue a - `Unicode Standard Annex #31 `_ identifier. - (Contributed by Stan Ulbrych in :gh:`129117`.) - -* Add the :func:`~unicodedata.iter_graphemes` - function to iterate over grapheme clusters according to rules defined in - `Unicode Standard Annex #29, "Unicode Text Segmentation" - `_. - Add :func:`~unicodedata.grapheme_cluster_break`, - :func:`~unicodedata.indic_conjunct_break` and - :func:`~unicodedata.extended_pictographic` functions to get the properties - of the character which are related to the above algorithm. - (Contributed by Serhiy Storchaka and Guillaume Sanchez in :gh:`74902`.) - -* Add :func:`~unicodedata.block` function to return the `Unicode block - `_ - assigned to a character. - (Contributed by Stan Ulbrych in :gh:`66802`.) - - -unittest --------- - -* :func:`unittest.TestCase.assertLogs` will now accept a formatter - to control how messages are formatted. - (Contributed by Garry Cairns in :gh:`134567`.) - - -urllib.parse ------------- - -* Add the *missing_as_none* parameter to :func:`~urllib.parse.urlsplit`, - :func:`~urllib.parse.urlparse` and :func:`~urllib.parse.urldefrag` functions. - Add the *keep_empty* parameter to :func:`~urllib.parse.urlunsplit` and - :func:`~urllib.parse.urlunparse` functions. - This allows to distinguish between empty and not defined URI components - and preserve empty components. - (Contributed by Serhiy Storchaka in :gh:`67041`.) - - -venv ----- - -* On POSIX platforms, platlib directories will be created if needed when - creating virtual environments, instead of using ``lib64 -> lib`` symlink. - This means purelib and platlib of virtual environments no longer share the - same ``lib`` directory on platforms where :data:`sys.platlibdir` is not - equal to ``lib``. - (Contributed by Rui Xi in :gh:`133951`.) - - -warnings --------- - -* Improve filtering by module in :func:`warnings.warn_explicit` if no *module* - argument is passed. - It now tests the module regular expression in the warnings filter not only - against the filename with ``.py`` stripped, but also against module names - constructed starting from different parent directories of the filename - (with ``/__init__.py``, ``.py`` and, on Windows, ``.pyw`` stripped). - (Contributed by Serhiy Storchaka in :gh:`135801`.) - - -wave ----- - -* Added support for IEEE floating-point WAVE audio - (``WAVE_FORMAT_IEEE_FLOAT``) in :mod:`wave`. - -* Added :meth:`wave.Wave_read.getformat`, :meth:`wave.Wave_write.getformat`, - and :meth:`wave.Wave_write.setformat` for explicit frame format handling. - -* :meth:`wave.Wave_write.setparams` accepts both 7-item tuples including - ``format`` and 6-item tuples for backwards compatibility (defaulting to - ``WAVE_FORMAT_PCM``). - -* ``WAVE_FORMAT_IEEE_FLOAT`` output now includes a ``fact`` chunk, - as required for non-PCM WAVE formats. - -(Contributed by Lionel Koenig and Michiel W. Beijen in :gh:`60729`.) - - -xml.parsers.expat ------------------ - -* Add :meth:`~xml.parsers.expat.xmlparser.SetAllocTrackerActivationThreshold` - and :meth:`~xml.parsers.expat.xmlparser.SetAllocTrackerMaximumAmplification` - to :ref:`xmlparser ` objects to tune protections against - disproportional amounts of dynamic memory usage from within an Expat parser. - (Contributed by Bénédikt Tran in :gh:`90949`.) - -* Add :meth:`~xml.parsers.expat.xmlparser.SetBillionLaughsAttackProtectionActivationThreshold` - and :meth:`~xml.parsers.expat.xmlparser.SetBillionLaughsAttackProtectionMaximumAmplification` - to :ref:`xmlparser ` objects to tune protections against - `billion laughs`_ attacks. - (Contributed by Bénédikt Tran in :gh:`90949`.) - - .. _billion laughs: https://en.wikipedia.org/wiki/Billion_laughs_attack - - -zlib ----- - -* Allow combining two Adler-32 checksums via :func:`~zlib.adler32_combine`. - (Contributed by Callum Attryde and Bénédikt Tran in :gh:`134635`.) - -* Allow combining two CRC-32 checksums via :func:`~zlib.crc32_combine`. - (Contributed by Bénédikt Tran in :gh:`134635`.) - - -.. Add improved modules above alphabetically, not here at the end. - -Optimizations -============= - -* ``mimalloc`` is now used as the default allocator for - for raw memory allocations such as via :c:func:`PyMem_RawMalloc` - for better performance on :term:`free-threaded builds `. - (Contributed by Kumar Aditya in :gh:`144914`.) - - -base64 & binascii ------------------ - -* CPython's underlying base64 implementation now encodes 2x faster and decodes 3x - faster thanks to simple CPU pipelining optimizations. - (Contributed by Gregory P. Smith and Serhiy Storchaka in :gh:`143262`.) - -* Implementation for Ascii85, Base85, and Z85 encoding has been rewritten in C. - Encoding and decoding is now two orders of magnitude faster and consumes - two orders of magnitude less memory. - (Contributed by James Seo and Serhiy Storchaka in :gh:`101178`.) - -* Implementation for Base32 has been rewritten in C. - Encoding and decoding is now two orders of magnitude faster. - (Contributed by James Seo in :gh:`146192`) - - -csv ---- - -* :meth:`csv.Sniffer.sniff` delimiter detection is now up to 1.6x faster. - (Contributed by Maurycy Pawłowski-Wieroński in :gh:`137628`.) - - -.. _whatsnew315-jit: - -Upgraded JIT compiler ---------------------- - -Results from the `pyperformance `__ -benchmark suite report -`6-7% `__ -geometric mean performance improvement for the JIT over the standard CPython -interpreter built with all optimizations enabled on x86-64 Linux. On AArch64 -macOS, the JIT has a -`12-13% `__ -speedup over the :ref:`tail calling interpreter ` -with all optimizations enabled. The speedups for JIT -builds versus no JIT builds range from roughly 15% slowdown to over -100% speedup (ignoring the ``unpack_sequence`` microbenchmark) on -x86-64 Linux and AArch64 macOS systems. - -.. attention:: - These results are not yet final. - -The major upgrades to the JIT are: - -* LLVM 21 build-time dependency -* New tracing frontend -* Basic register allocation in the JIT -* More JIT optimizations -* Better machine code generation - -.. rubric:: LLVM 21 build-time dependency - -The JIT compiler now uses LLVM 21 for build-time stencil generation. As -always, LLVM is only needed when building CPython with the JIT enabled; -end users running Python do not need LLVM installed. Instructions for -installing LLVM can be found in the `JIT compiler documentation -`__ -for all supported platforms. -(Contributed by Savannah Ostrowski in :gh:`140973`.) - -.. rubric:: A new tracing frontend - -The JIT compiler now supports significantly more bytecode operations and -control flow than in Python 3.14, enabling speedups on a wider variety of -code. For example, simple Python object creation is now understood by the -3.15 JIT compiler. Overloaded operations and generators are also partially -supported. This was made possible by an overhauled JIT tracing frontend -that records actual execution paths through code, rather than estimating -them as the previous implementation did. -(Contributed by Ken Jin in :gh:`139109`. Support for Windows added by -Mark Shannon in :gh:`141703`.) - -.. rubric:: Basic register allocation in the JIT - -A basic form of register allocation has been added to the JIT compiler's -optimizer. This allows the JIT compiler to avoid certain stack operations -altogether and instead operate on registers. This allows the JIT to produce -more efficient traces by avoiding reads and writes to memory. -(Contributed by Mark Shannon in :gh:`135379`.) - -.. rubric:: More JIT optimizations - -More `constant-propagation `__ -is now performed. This means when the JIT compiler detects that certain user -code results in constants, the code can be simplified by the JIT. -(Contributed by Ken Jin and Savannah Ostrowski in :gh:`132732`.) - -:term:`Reference count`\ s are avoided whenever it is safe to do so. This generally -reduces the cost of most operations in Python. -(Contributed by Ken Jin, Donghee Na, Zheao Li, Hai Zhu, Savannah Ostrowski, -Reiden Ong, Noam Cohen, Tomas Roun, PuQing, Cajetan Rodrigues, and Sacul in :gh:`134584`.) - -By tracking unique references to objects, the JIT optimizer can now eliminate -reference count updates and perform inplace operations on ints and floats. -(Contributed by Reiden Ong, and Pieter Eendebak in :gh:`143414` and :gh:`146306`.) - -The JIT optimizer now supports significantly more operations than in 3.14. -(Contributed by Kumar Aditya, Ken Jin, Jiahao Li, and Sacul in :gh:`131798`.) - -.. rubric:: Better machine code generation - -The JIT compiler's machine code generator now produces better machine code -for x86-64 and AArch64 macOS and Linux targets. In general, users should -experience lower memory usage for generated machine code and more efficient -machine code versus 3.14. -(Contributed by Brandt Bucher in :gh:`136528` and :gh:`136528`. -Implementation for AArch64 contributed by Mark Shannon in :gh:`139855`. -Additional optimizations for AArch64 contributed by Mark Shannon and -Diego Russo in :gh:`140683` and :gh:`142305`.) - -.. rubric:: Maintainability - -The JIT optimizer's operations have been simplified. -This was made possible by a refactoring of JIT data structures. -(Contributed by Zhongtian Zheng in :gh:`148211` and Hai Zhu in :gh:`143421`.) - - -Removed -======== - -collections.abc ---------------- - -* :class:`collections.abc.ByteString` has been removed from - ``collections.abc.__all__``. :class:`!collections.abc.ByteString` has been - deprecated since Python 3.12, and is scheduled for removal in Python 3.17. - - -datetime --------- - -* :meth:`~datetime.datetime.strptime` now raises :exc:`ValueError` when the - format string contains ``%d`` (day of month) without a year directive. - This has been deprecated since Python 3.13. - (Contributed by Stan Ulbrych and Gregory P. Smith in :gh:`70647`.) - - -ctypes ------- - -* Removed the undocumented function :func:`!ctypes.SetPointerType`, - which has been deprecated since Python 3.13. - (Contributed by Bénédikt Tran in :gh:`133866`.) - - -glob ----- - -* Removed the undocumented :func:`!glob.glob0` and :func:`!glob.glob1` - functions, which have been deprecated since Python 3.13. Use - :func:`glob.glob` and pass a directory to its *root_dir* argument instead. - (Contributed by Barney Gale in :gh:`137466`.) - - -http.server ------------ - -* Removed the :class:`!CGIHTTPRequestHandler` class - and the ``--cgi`` flag from the :program:`python -m http.server` - command-line interface. They were deprecated in Python 3.13. - (Contributed by Bénédikt Tran in :gh:`133810`.) - - -importlib.resources -------------------- - -* Removed deprecated ``package`` parameter - from :func:`importlib.resources.files` function. - (Contributed by Semyon Moroz in :gh:`138044`.) - - -pathlib -------- - -* Removed deprecated :meth:`!pathlib.PurePath.is_reserved`. - Use :func:`os.path.isreserved` to detect reserved paths on Windows. - (Contributed by Nikita Sobolev in :gh:`133875`.) - - -platform --------- - -* Removed the :func:`!platform.java_ver` function, - which was deprecated since Python 3.13. - (Contributed by Alexey Makridenko in :gh:`133604`.) - - -sre_* ------ - -* Removed :mod:`!sre_compile`, :mod:`!sre_constants` and :mod:`!sre_parse` modules. - (Contributed by Stan Ulbrych in :gh:`135994`.) - - -sysconfig ---------- - -* Removed the *check_home* parameter of :func:`sysconfig.is_python_build`. - (Contributed by Filipe Laíns in :gh:`92897`.) - - -threading ---------- - -* Remove support for arbitrary positional or keyword arguments in the C - implementation of :class:`~threading.RLock` objects. This was deprecated - in Python 3.14. - (Contributed by Bénédikt Tran in :gh:`134087`.) - - -typing ------- - -* :class:`typing.ByteString` has been removed from ``typing.__all__``. - :class:`!typing.ByteString` has been deprecated since Python 3.9, and is - scheduled for removal in Python 3.17. - -* The undocumented keyword argument syntax for creating - :class:`~typing.NamedTuple` classes (for example, - ``Point = NamedTuple("Point", x=int, y=int)``) is no longer supported. - Use the class-based syntax or the functional syntax instead. - (Contributed by Bénédikt Tran in :gh:`133817`.) - -* Using ``TD = TypedDict("TD")`` or ``TD = TypedDict("TD", None)`` to - construct a :class:`~typing.TypedDict` type with zero fields is no - longer supported. Use ``class TD(TypedDict): pass`` - or ``TD = TypedDict("TD", {})`` instead. - (Contributed by Bénédikt Tran in :gh:`133823`.) - - -wave ----- - -* Removed the ``getmark()``, ``setmark()`` and ``getmarkers()`` methods - of the :class:`~wave.Wave_read` and :class:`~wave.Wave_write` classes, - which were deprecated since Python 3.13. - (Contributed by Bénédikt Tran in :gh:`133873`.) - - -zipimport ---------- - -* Remove deprecated :meth:`!zipimport.zipimporter.load_module`. - Use :meth:`zipimport.zipimporter.exec_module` instead. - (Contributed by Jiahao Li in :gh:`133656`.) - - -Deprecated -========== - -New deprecations ----------------- - -* :mod:`base64`: - - * Accepting the ``+`` and ``/`` characters with an alternative alphabet in - :func:`~base64.b64decode` and :func:`~base64.urlsafe_b64decode` is now - deprecated. - In future Python versions they will be errors in the strict mode and - discarded in the non-strict mode. - (Contributed by Serhiy Storchaka in :gh:`125346`.) - -* CLI: - - * Deprecate :option:`-b` and :option:`!-bb` command-line options - and schedule them to become no-ops in Python 3.17. - These were primarily helpers for the Python 2 -> 3 transition. - Starting with Python 3.17, no :exc:`BytesWarning` will be raised - for these cases; use a type checker instead. - - (Contributed by Nikita Sobolev in :gh:`136355`.) - -* :mod:`collections.abc` - - * The following statements now cause ``DeprecationWarning``\ s to be emitted - at runtime: - - * ``from collections.abc import ByteString`` - * ``import collections.abc; collections.abc.ByteString``. - - ``DeprecationWarning``\ s were already emitted if - :class:`collections.abc.ByteString` was subclassed or used as the second - argument to :func:`isinstance` or :func:`issubclass`, but warnings were not - previously emitted if it was merely imported or accessed from the - :mod:`!collections.abc` module. - - -* :mod:`hashlib`: - - * In hash function constructors such as :func:`~hashlib.new` or the - direct hash-named constructors such as :func:`~hashlib.md5` and - :func:`~hashlib.sha256`, the optional initial data parameter could - also be passed as a keyword argument named ``data=`` or ``string=`` in - various :mod:`hashlib` implementations. - - Support for the ``string`` keyword argument name is now deprecated and - is slated for removal in Python 3.19. Prefer passing the initial data as - a positional argument for maximum backwards compatibility. - - (Contributed by Bénédikt Tran in :gh:`134978`.) - - -* :mod:`re`: - - * :func:`re.match` and :meth:`re.Pattern.match` are now - :term:`soft deprecated` in favor of the new :func:`re.prefixmatch` and - :meth:`re.Pattern.prefixmatch` APIs, which have been added as alternate, - more explicit names. These are intended to be used to alleviate confusion - around what *match* means by following the Zen of Python's *"Explicit is - better than implicit"* mantra. Most other language regular expression - libraries use an API named *match* to mean what Python has always called - *search*. - - We **do not** plan to remove the older :func:`!match` name, as it has been - used in code for over 30 years. Code supporting older versions of Python - should continue to use :func:`!match`, while new code should prefer - :func:`!prefixmatch`. See :ref:`prefixmatch-vs-match`. - - (Contributed by Gregory P. Smith in :gh:`86519` and - Hugo van Kemenade in :gh:`148100`.) - - -* :mod:`struct`: - - * Calling the ``Struct.__new__()`` without required argument now is - deprecated and will be removed in Python 3.20. Calling - :meth:`~object.__init__` method on initialized :class:`~struct.Struct` - objects is deprecated and will be removed in Python 3.20. - - (Contributed by Sergey B Kirpichev and Serhiy Storchaka in :gh:`143715`.) - -* :mod:`typing`: - - * The following statements now cause ``DeprecationWarning``\ s to be emitted - at runtime: - - * ``from typing import ByteString`` - * ``import typing; typing.ByteString``. - - ``DeprecationWarning``\ s were already emitted if :class:`typing.ByteString` - was subclassed or used as the second argument to :func:`isinstance` or - :func:`issubclass`, but warnings were not previously emitted if it was - merely imported or accessed from the :mod:`!typing` module. - - * Deprecated :func:`!typing.no_type_check_decorator` has been removed. - (Contributed by Nikita Sobolev in :gh:`133601`.) - -* ``__version__`` - - * The ``__version__``, ``version`` and ``VERSION`` attributes have been - deprecated in these standard library modules and will be removed in - Python 3.20. Use :py:data:`sys.version_info` instead. - - - :mod:`argparse` - - :mod:`csv` - - :mod:`ctypes` - - :mod:`!ctypes.macholib` - - :mod:`decimal` (use :data:`decimal.SPEC_VERSION` instead) - - :mod:`http.server` - - :mod:`imaplib` - - :mod:`ipaddress` - - :mod:`json` - - :mod:`logging` (``__date__`` also deprecated) - - :mod:`optparse` - - :mod:`pickle` - - :mod:`platform` - - :mod:`re` - - :mod:`socketserver` - - :mod:`tabnanny` - - :mod:`tarfile` - - :mod:`tkinter.font` - - :mod:`tkinter.ttk` - - :mod:`wsgiref.simple_server` - - :mod:`xml.etree.ElementTree` - - :mod:`!xml.sax.expatreader` - - :mod:`xml.sax.handler` - - :mod:`zlib` - - (Contributed by Hugo van Kemenade and Stan Ulbrych in :gh:`76007`.) - -.. Add deprecations above alphabetically, not here at the end. - -.. include:: ../deprecations/pending-removal-in-3.16.rst - -.. include:: ../deprecations/pending-removal-in-3.17.rst - -.. include:: ../deprecations/pending-removal-in-3.18.rst - -.. include:: ../deprecations/pending-removal-in-3.19.rst - -.. include:: ../deprecations/pending-removal-in-3.20.rst - -.. include:: ../deprecations/pending-removal-in-future.rst - -.. include:: ../deprecations/soft-deprecations.rst - - -C API changes -============= - -New features ------------- - -* Add :c:func:`PyArg_ParseArray` and :c:func:`PyArg_ParseArrayAndKeywords` - functions to parse arguments of functions using the :c:macro:`METH_FASTCALL` - calling convention. - (Contributed by Victor Stinner in :gh:`144175`.) - -* Add the following functions for the new :class:`frozendict` type: - - * :c:func:`PyAnyDict_Check` - * :c:func:`PyAnyDict_CheckExact` - * :c:func:`PyFrozenDict_Check` - * :c:func:`PyFrozenDict_CheckExact` - * :c:func:`PyFrozenDict_New` - - (Contributed by Victor Stinner in :gh:`141510`.) - -* Add :c:func:`PySys_GetAttr`, :c:func:`PySys_GetAttrString`, - :c:func:`PySys_GetOptionalAttr`, and :c:func:`PySys_GetOptionalAttrString` - functions as replacements for :c:func:`PySys_GetObject`. - (Contributed by Serhiy Storchaka in :gh:`108512`.) - -* Add :c:type:`PyUnstable_Unicode_GET_CACHED_HASH` to get the cached hash of - a string. See the documentation for caveats. - (Contributed by Petr Viktorin in :gh:`131510`.) - -* Add API for checking an extension module's ABI compatibility: - :c:data:`Py_mod_abi`, :c:func:`PyABIInfo_Check`, :c:macro:`PyABIInfo_VAR` - and :c:data:`Py_mod_abi`. - (Contributed by Petr Viktorin in :gh:`137210`.) - -.. _whatsnew315-pybyteswriter: - -* Implement :pep:`782`, the :ref:`PyBytesWriter API `. - Add functions: - - * :c:func:`PyBytesWriter_Create` - * :c:func:`PyBytesWriter_Discard` - * :c:func:`PyBytesWriter_FinishWithPointer` - * :c:func:`PyBytesWriter_FinishWithSize` - * :c:func:`PyBytesWriter_Finish` - * :c:func:`PyBytesWriter_Format` - * :c:func:`PyBytesWriter_GetData` - * :c:func:`PyBytesWriter_GetSize` - * :c:func:`PyBytesWriter_GrowAndUpdatePointer` - * :c:func:`PyBytesWriter_Grow` - * :c:func:`PyBytesWriter_Resize` - * :c:func:`PyBytesWriter_WriteBytes` - - (Contributed by Victor Stinner in :gh:`129813`.) - -* Add a new :c:func:`PyImport_CreateModuleFromInitfunc` C-API for creating - a module from a *spec* and *initfunc*. - (Contributed by Itamar Oren in :gh:`116146`.) - -* Add :c:func:`PyTuple_FromArray` to create a :class:`tuple` from an array. - (Contributed by Victor Stinner in :gh:`111489`.) - -* Add functions that are guaranteed to be safe for use in - :c:member:`~PyTypeObject.tp_traverse` handlers: - :c:func:`PyObject_GetTypeData_DuringGC`, - :c:func:`PyObject_GetItemData_DuringGC`, - :c:func:`PyType_GetModuleState_DuringGC`, - :c:func:`PyModule_GetState_DuringGC`, :c:func:`PyModule_GetToken_DuringGC`, - :c:func:`PyType_GetBaseByToken_DuringGC`, - :c:func:`PyType_GetModule_DuringGC`, - :c:func:`PyType_GetModuleByToken_DuringGC`. - (Contributed by Petr Viktorin in :gh:`145925`.) - -* Add :c:func:`PyObject_Dump` to dump an object to ``stderr``. - It should only be used for debugging. - (Contributed by Victor Stinner in :gh:`141070`.) - -* Add :c:func:`PyUnstable_ThreadState_SetStackProtection` and - :c:func:`PyUnstable_ThreadState_ResetStackProtection` functions to set - the stack protection base address and stack protection size of a Python - thread state. - (Contributed by Victor Stinner in :gh:`139653`.) - -* Add :c:func:`PyUnstable_SetImmortal` C-API function to mark objects as :term:`immortal`. - (Contributed by Kumar Aditya in :gh:`143300`.) - -* Restore private provisional ``_Py_InitializeMain()`` function removed in - Python 3.14. - (Contributed by Victor Stinner in :gh:`142417`.) - -Changed C APIs --------------- - -* If the :c:macro:`Py_TPFLAGS_MANAGED_DICT` or :c:macro:`Py_TPFLAGS_MANAGED_WEAKREF` - flag is set then :c:macro:`Py_TPFLAGS_HAVE_GC` must be set too. - (Contributed by Sergey Miryanov in :gh:`134786`.) - -* :c:macro:`PyDateTime_IMPORT` is now thread safe. Code that directly checks ``PyDateTimeAPI`` - for ``NULL`` should be updated to call :c:macro:`PyDateTime_IMPORT` instead. - (Contributed by Kumar Aditya in :gh:`141563`.) - -Porting to Python 3.15 ----------------------- - -* Private functions promoted to public C APIs: - - The |pythoncapi_compat_project| can be used to get most of these new - functions on Python 3.14 and older. - - -Removed C APIs --------------- - -* Remove deprecated ``PyUnicode`` functions: - - * :c:func:`!PyUnicode_AsDecodedObject`: - Use :c:func:`PyCodec_Decode` instead. - * :c:func:`!PyUnicode_AsDecodedUnicode`: - Use :c:func:`PyCodec_Decode` instead; Note that some codecs (for example, "base64") - may return a type other than :class:`str`, such as :class:`bytes`. - * :c:func:`!PyUnicode_AsEncodedObject`: - Use :c:func:`PyCodec_Encode` instead. - * :c:func:`!PyUnicode_AsEncodedUnicode`: - Use :c:func:`PyCodec_Encode` instead; Note that some codecs (for example, "base64") - may return a type other than :class:`bytes`, such as :class:`str`. - - (Contributed by Stan Ulbrych in :gh:`133612`.) - -* :c:func:`!PyImport_ImportModuleNoBlock`: deprecated alias - of :c:func:`PyImport_ImportModule`. - (Contributed by Bénédikt Tran in :gh:`133644`.) - -* :c:func:`!PyWeakref_GetObject` and :c:macro:`!PyWeakref_GET_OBJECT`: - use :c:func:`PyWeakref_GetRef` instead. The |pythoncapi_compat_project| - can be used to get :c:func:`!PyWeakref_GetRef` on Python 3.12 and older. - (Contributed by Bénédikt Tran in :gh:`133644`.) - -* Remove deprecated :c:func:`!PySys_ResetWarnOptions`. - Clear :data:`sys.warnoptions` and :data:`!warnings.filters` instead. - - (Contributed by Nikita Sobolev in :gh:`138886`.) - -The following functions are removed in favor of :c:func:`PyConfig_Get`. -The |pythoncapi_compat_project| can be used to get :c:func:`!PyConfig_Get` -on Python 3.13 and older. - -* Python initialization functions: - - * :c:func:`!Py_GetExecPrefix`: - use :c:func:`PyConfig_Get("base_exec_prefix") ` - (:data:`sys.base_exec_prefix`) instead. - Use :c:func:`PyConfig_Get("exec_prefix") ` - (:data:`sys.exec_prefix`) if :ref:`virtual environments ` - need to be handled. - * :c:func:`!Py_GetPath`: - use :c:func:`PyConfig_Get("module_search_paths") ` - (:data:`sys.path`) instead. - * :c:func:`!Py_GetPrefix`: - use :c:func:`PyConfig_Get("base_prefix") ` - (:data:`sys.base_prefix`) instead. - Use :c:func:`PyConfig_Get("prefix") ` - (:data:`sys.prefix`) if :ref:`virtual environments ` - need to be handled. - * :c:func:`!Py_GetProgramFullPath`: - use :c:func:`PyConfig_Get("executable") ` - (:data:`sys.executable`) instead. - * :c:func:`!Py_GetProgramName`: - use :c:func:`PyConfig_Get("executable") ` - (:data:`sys.executable`) instead. - * :c:func:`!Py_GetPythonHome`: - use :c:func:`PyConfig_Get("home") ` or the - :envvar:`PYTHONHOME` environment variable instead. - - (Contributed by Bénédikt Tran in :gh:`133644`.) - -.. |pythoncapi_compat_project| replace:: |pythoncapi_compat_project_link|_ -.. |pythoncapi_compat_project_link| replace:: pythoncapi-compat project -.. _pythoncapi_compat_project_link: https://github.com/python/pythoncapi-compat - - -Deprecated C APIs ------------------ - -* Deprecate :pep:`456` support for providing an external definition - of the string hashing scheme. Removal is scheduled for Python 3.19. - - Previously, embedders could define :c:macro:`Py_HASH_ALGORITHM` to be - ``Py_HASH_EXTERNAL`` to indicate that the hashing scheme was provided - externally but this feature was undocumented, untested and most likely - unused. - - (Contributed by Bénédikt Tran in :gh:`141226`.) - -* For unsigned integer formats in :c:func:`PyArg_ParseTuple`, - accepting Python integers with value that is larger than the maximal value - for the C type or less than the minimal value for the corresponding - signed integer type of the same size is now deprecated. - (Contributed by Serhiy Storchaka in :gh:`132629`.) - -* :c:func:`PyBytes_FromStringAndSize(NULL, len) ` - and :c:func:`_PyBytes_Resize` are :term:`soft deprecated`, - use the :c:type:`PyBytesWriter` API instead. - (Contributed by Victor Stinner in :gh:`129813`.) - -* :c:func:`!_PyObject_CallMethodId`, :c:func:`!_PyObject_GetAttrId` and - :c:func:`!_PyUnicode_FromId` are deprecated since 3.15 and will be removed in - 3.20. Instead, use :c:func:`PyUnicode_InternFromString()` and cache the result in - the module state, then call :c:func:`PyObject_CallMethod` or - :c:func:`PyObject_GetAttr`. - (Contributed by Victor Stinner in :gh:`141049`.) - -* Deprecate :c:member:`~PyComplexObject.cval` field of the - :c:type:`PyComplexObject` type. - Use :c:func:`PyComplex_AsCComplex` and :c:func:`PyComplex_FromCComplex` - to convert a Python complex number to/from the C :c:type:`Py_complex` - representation. - (Contributed by Sergey B Kirpichev in :gh:`128813`.) - -* Functions :c:func:`_Py_c_sum`, :c:func:`_Py_c_diff`, :c:func:`_Py_c_neg`, - :c:func:`_Py_c_prod`, :c:func:`_Py_c_quot`, :c:func:`_Py_c_pow` and - :c:func:`_Py_c_abs` are :term:`soft deprecated`. - (Contributed by Sergey B Kirpichev in :gh:`128813`.) - -* :c:member:`~PyConfig.bytes_warning` is deprecated - since 3.15 and will be removed in 3.17. - (Contributed by Nikita Sobolev in :gh:`136355`.) - -* :c:macro:`!Py_INFINITY` macro is :term:`soft deprecated`, - use the C11 standard ```` :c:macro:`!INFINITY` instead. - (Contributed by Sergey B Kirpichev in :gh:`141004`.) - -* The following macros are :term:`soft deprecated`: - - - :c:macro:`Py_ALIGNED`: Prefer ``alignas`` instead. - - :c:macro:`PY_FORMAT_SIZE_T`: Use ``"z"`` directly. - - :c:macro:`Py_LL` & :c:macro:`Py_ULL`: - Use standard suffixes, ``LL`` & ``ULL``. - - :c:macro:`PY_LONG_LONG`, :c:macro:`PY_LLONG_MIN`, :c:macro:`PY_LLONG_MAX`, - :c:macro:`PY_ULLONG_MAX`, :c:macro:`PY_INT32_T`, :c:macro:`PY_UINT32_T`, - :c:macro:`PY_INT64_T`, :c:macro:`PY_UINT64_T`, :c:macro:`PY_SIZE_MAX`: - Use C99 types/limits. - - :c:macro:`Py_UNICODE_SIZE`: Use ``sizeof(wchar_t)`` directly. - - :c:macro:`Py_VA_COPY`: Use ``va_copy`` directly. - - The macro :c:macro:`Py_UNICODE_WIDE`, which was scheduled for removal, - is :term:`soft deprecated` instead. - - (Contributed by Petr Viktorin in :gh:`146175`.) - -* :c:macro:`!Py_MATH_El` and :c:macro:`!Py_MATH_PIl` are deprecated - since 3.15 and will be removed in 3.20. - (Contributed by Sergey B Kirpichev in :gh:`141004`.) - - -.. Add C API deprecations above alphabetically, not here at the end. - - -Build changes -============= - -* Removed implicit fallback to the bundled copy of the ``libmpdec`` library. - Now this should be explicitly enabled with :option:`--with-system-libmpdec` - set to ``no`` or with :option:`!--without-system-libmpdec`. - (Contributed by Sergey B Kirpichev in :gh:`115119`.) - -* The new configure option :option:`--with-missing-stdlib-config=FILE` allows - distributors to pass a `JSON `_ - configuration file containing custom error messages for :term:`standard library` - modules that are missing or packaged separately. - (Contributed by Stan Ulbrych and Petr Viktorin in :gh:`139707`.) - -* The new configure option :option:`--with-pymalloc-hugepages` enables huge - page support for :ref:`pymalloc ` arenas. When enabled, arena size - increases to 2 MiB and allocation uses ``MAP_HUGETLB`` (Linux) or - ``MEM_LARGE_PAGES`` (Windows) with automatic fallback to regular pages. - On Windows, use ``build.bat --pymalloc-hugepages``. - At runtime, huge pages must be explicitly enabled by setting the - :envvar:`PYTHON_PYMALLOC_HUGEPAGES` environment variable to ``1``. - -* Annotating anonymous mmap usage is now supported if Linux kernel supports - :manpage:`PR_SET_VMA_ANON_NAME ` (Linux 5.17 or newer). - Annotations are visible in ``/proc//maps`` if the kernel supports the feature - and :option:`-X dev <-X>` is passed to the Python or Python is built in :ref:`debug mode `. - (Contributed by Donghee Na in :gh:`141770`.) - -.. _whatsnew315-windows-tail-calling-interpreter: - -* 64-bit builds using Visual Studio 2026 (MSVC 18) may now use the new - :ref:`tail-calling interpreter `. - Results on Visual Studio 18.1.1 report between - `15-20% `__ - speedup on the geometric mean of pyperformance on Windows x86-64 over - the switch-case interpreter on an AMD Ryzen 7 5800X. We have - observed speedups ranging from 14% for large pure-Python libraries - to 40% for long-running small pure-Python scripts on Windows. - This was made possible by a new feature introduced in MSVC 18, - which the official Windows 64-bit binaries on python.org__ now use. - (Contributed by Chris Eibl, Ken Jin, and Brandt Bucher in :gh:`143068`. - Special thanks to Steve Dower, and the MSVC team including Hulon Jenkins.) - - __ https://www.python.org/downloads/windows/ - - -Porting to Python 3.15 -====================== - -This section lists previously described changes and other bugfixes -that may require changes to your code. - -* :class:`sqlite3.Connection` APIs have been cleaned up. - - * All parameters of :func:`sqlite3.connect` except *database* are now keyword-only. - * The first three parameters of methods :meth:`~sqlite3.Connection.create_function` - and :meth:`~sqlite3.Connection.create_aggregate` are now positional-only. - * The first parameter of methods :meth:`~sqlite3.Connection.set_authorizer`, - :meth:`~sqlite3.Connection.set_progress_handler` and - :meth:`~sqlite3.Connection.set_trace_callback` is now positional-only. - - (Contributed by Serhiy Storchaka in :gh:`133595`.) - -* :data:`resource.RLIM_INFINITY` is now always positive. - Passing a negative integer value that corresponded to its old value - (such as ``-1`` or ``-3``, depending on platform) to - :func:`resource.setrlimit` and :func:`resource.prlimit` is now deprecated. - (Contributed by Serhiy Storchaka in :gh:`137044`.) - -* :meth:`mmap.mmap.resize` has been removed on platforms that don't support the - underlying syscall, instead of raising a :exc:`SystemError`. - -* A resource warning is now emitted for an unclosed - :func:`xml.etree.ElementTree.iterparse` iterator if it opened a file. - Use its :meth:`!close` method or the :func:`contextlib.closing` context - manager to close it. - (Contributed by Osama Abdelkader and Serhiy Storchaka in :gh:`140601`.) - -* If a short option and a single-dash long option are passed to - :meth:`argparse.ArgumentParser.add_argument`, *dest* is now inferred from - the single-dash long option. For example, in ``add_argument('-f', '-foo')``, - *dest* is now ``'foo'`` instead of ``'f'``. - Pass an explicit *dest* argument to preserve the old behavior. - (Contributed by Serhiy Storchaka in :gh:`138697`.) - -* Padding of input no longer required in :func:`base64.urlsafe_b64decode`. - Pass a new argument ``padded=True`` or use :func:`base64.b64decode` - with argument ``altchars=b'-_'`` (this works with older Python versions) - to make padding required. - (Contributed by Serhiy Storchaka in :gh:`73613`.) + +**************************** + What's new in Python 3.15 +**************************** + +:Editor: Hugo van Kemenade + +.. Rules for maintenance: + + * Anyone can add text to this document. Do not spend very much time + on the wording of your changes, because your text will probably + get rewritten to some degree. + + * The maintainer will go through Misc/NEWS periodically and add + changes; it's therefore more important to add your changes to + Misc/NEWS than to this file. + + * This is not a complete list of every single change; completeness + is the purpose of Misc/NEWS. Some changes I consider too small + or esoteric to include. If such a change is added to the text, + I'll just remove it. (This is another reason you shouldn't spend + too much time on writing your addition.) + + * If you want to draw your new text to the attention of the + maintainer, add 'XXX' to the beginning of the paragraph or + section. + + * It's OK to just add a fragmentary note about a change. For + example: "XXX Describe the transmogrify() function added to the + socket module." The maintainer will research the change and + write the necessary text. + + * You can comment out your additions if you like, but it's not + necessary (especially when a final release is some months away). + + * Credit the author of a patch or bugfix. Just the name is + sufficient; the e-mail address isn't necessary. + + * It's helpful to add the issue number as a comment: + + XXX Describe the transmogrify() function added to the socket + module. + (Contributed by P.Y. Developer in :gh:`12345`.) + + This saves the maintainer the effort of going through the VCS log + when researching a change. + +This article explains the new features in Python 3.15, compared to 3.14. + +For full details, see the :ref:`changelog `. + +.. note:: + + Prerelease users should be aware that this document is currently in draft + form. It will be updated substantially as Python 3.15 moves towards release, + so it's worth checking back even after reading earlier versions. + + +Summary -- Release highlights +============================= + +.. This section singles out the most important changes in Python 3.15. + Brevity is key. + + +.. PEP-sized items next. + +* :pep:`810`: :ref:`Explicit lazy imports for faster startup times + ` +* :pep:`814`: :ref:`Add frozendict built-in type + ` +* :pep:`799`: :ref:`A dedicated profiling package for organizing Python + profiling tools ` +* :pep:`799`: :ref:`Tachyon: High frequency statistical sampling profiler + ` +* :pep:`798`: :ref:`Unpacking in comprehensions + ` +* :pep:`686`: :ref:`Python now uses UTF-8 as the default encoding + ` +* :pep:`728`: ``TypedDict`` with typed extra items +* :pep:`747`: :ref:`Annotating type forms with TypeForm + ` +* :pep:`800`: Disjoint bases in the type system +* :pep:`782`: :ref:`A new PyBytesWriter C API to create a Python bytes object + ` +* :pep:`803`: :ref:`Stable ABI for Free-Threaded Builds ` +* :ref:`The JIT compiler has been significantly upgraded ` +* :ref:`Improved error messages ` +* :ref:`The official Windows 64-bit binaries now use the tail-calling interpreter + ` + +New features +============ + +.. _whatsnew315-lazy-imports: + +:pep:`810`: Explicit lazy imports +--------------------------------- + +Large Python applications often suffer from slow startup times. A +significant contributor to this problem is the import system: when a module +is imported, Python must locate the file, read it from disk, compile it to +bytecode, and execute all top-level code. For applications with deep +dependency trees, this process can take seconds, even when most of the +imported code is never actually used during a particular run. + +Developers have worked around this by moving imports inside functions, using +:mod:`importlib` to load modules on demand, or restructuring code to avoid +unnecessary dependencies. These approaches work but make code harder to read +and maintain, scatter import statements throughout the codebase, and require +discipline to apply consistently. + +Python now provides a cleaner solution through explicit :keyword:`lazy` +imports using the new ``lazy`` soft keyword. When you mark an import as +lazy, Python defers the actual module loading until the imported name is +first used. This gives you the organizational benefits of declaring all +imports at the top of the file while only paying the loading cost for +modules you actually use. + +The ``lazy`` keyword works with both ``import`` and ``from ... import`` +statements. When you write ``lazy import heavy_module``, Python does not +immediately load the module. Instead, it creates a lightweight proxy object. +The actual module loading happens transparently when you first access the +name: + +.. code-block:: python + + lazy import json + lazy from pathlib import Path + + print("Starting up...") # json and pathlib not loaded yet + + data = json.loads('{"key": "value"}') # json loads here + p = Path(".") # pathlib loads here + +This mechanism is particularly useful for applications that import many +modules at the top level but may only use a subset of them in any given run. +The deferred loading reduces startup latency without requiring code +restructuring or conditional imports scattered throughout the codebase. + +In the case where loading a lazily imported module fails (for example, if +the module does not exist), Python raises the exception at the point of +first use rather than at import time. The associated traceback includes both +the location where the name was accessed and the original import statement, +making it straightforward to diagnose & debug the failure. + +For cases where you want to enable lazy loading globally without modifying +source code, Python provides the :option:`-X lazy_imports <-X>` command-line +option and the :envvar:`PYTHON_LAZY_IMPORTS` environment variable. Both +accept three values: ``all`` makes all imports lazy by default, ``none`` +disables lazy imports entirely (even explicit ``lazy`` statements become +eager), and ``normal`` (the default) respects the ``lazy`` keyword in source +code. The :func:`sys.set_lazy_imports` and :func:`sys.get_lazy_imports` +functions allow changing and querying this mode at runtime. + +For more selective control, :func:`sys.set_lazy_imports_filter` accepts a +callable that determines whether a specific module should be loaded lazily. +The filter receives three arguments: the importing module's name (or +``None``), the imported module's name, and the fromlist (or ``None`` for +regular imports). It should return ``True`` to allow the import to be lazy, +or ``False`` to force eager loading. This allows patterns like making only +your own application's modules lazy while keeping third-party dependencies +eager: + +.. code-block:: python + + import sys + + def myapp_filter(importing, imported, fromlist): + return imported.startswith("myapp.") + sys.set_lazy_imports_filter(myapp_filter) + sys.set_lazy_imports("all") + + import myapp.slow_module # lazy (matches filter) + import json # eager (does not match filter) + +The proxy type itself is available as :data:`types.LazyImportType` for code +that needs to detect lazy imports programmatically. + +There are some restrictions on where the ``lazy`` keyword can be used. Lazy +imports are only permitted at module scope; using ``lazy`` inside a +function, class body, or ``try``/``except``/``finally`` block raises a +:exc:`SyntaxError`. Neither star imports nor future imports can be lazy +(``lazy from module import *`` and ``lazy from __future__ import ...`` both +raise :exc:`SyntaxError`). + +.. seealso:: :pep:`810` for the full specification and rationale. + +(Contributed by Pablo Galindo Salgado and Dino Viehland in :gh:`142349`.) + + +.. _whatsnew315-frozendict: + +:pep:`814`: Add frozendict built-in type +---------------------------------------- + +A new :term:`immutable` type, :class:`frozendict`, is added to the :mod:`builtins` module. +It does not allow modification after creation. A :class:`!frozendict` is not a subclass of ``dict``; +it inherits directly from ``object``. A :class:`!frozendict` is :term:`hashable` +as long as all of its keys and values are hashable. A :class:`!frozendict` preserves +insertion order, but comparison does not take order into account. + +For example:: + + >>> a = frozendict(x=1, y=2) + >>> a + frozendict({'x': 1, 'y': 2}) + >>> a['z'] = 3 + Traceback (most recent call last): + File "", line 1, in + a['z'] = 3 + ~^^^^^ + TypeError: 'frozendict' object does not support item assignment + >>> b = frozendict(y=2, x=1) + >>> hash(a) == hash(b) + True + >>> a == b + True + +The following standard library modules have been updated to accept +:class:`!frozendict`: :mod:`copy`, :mod:`decimal`, :mod:`json`, :mod:`marshal`, +:mod:`plistlib` (only for serialization), :mod:`pickle`, :mod:`pprint` and +:mod:`xml.etree.ElementTree`. + +:func:`eval` and :func:`exec` accept :class:`!frozendict` for *globals*, and +:func:`type` and :meth:`str.maketrans` accept :class:`!frozendict` for *dict*. + +Code checking for :class:`dict` type using ``isinstance(arg, dict)`` can be +updated to ``isinstance(arg, (dict, frozendict))`` to accept also the +:class:`!frozendict` type, or to ``isinstance(arg, collections.abc.Mapping)`` +to accept also other mapping types such as :class:`~types.MappingProxyType`. + +.. seealso:: :pep:`814` for the full specification and rationale. + +(Contributed by Victor Stinner and Donghee Na in :gh:`141510`.) + + +.. _whatsnew315-profiling-package: + +:pep:`799`: A dedicated profiling package +----------------------------------------- + +A new :mod:`profiling` module has been added to organize Python's built-in +profiling tools under a single, coherent namespace. This module contains: + +* :mod:`profiling.tracing`: deterministic function-call tracing (relocated from + ``cProfile``). +* :mod:`profiling.sampling`: a new statistical sampling profiler (named Tachyon). + +The ``cProfile`` module remains as an alias for backwards compatibility. +The :mod:`profile` module is deprecated and will be removed in Python 3.17. + +.. seealso:: :pep:`799` for further details. + +(Contributed by Pablo Galindo and László Kiss Kollár in :gh:`138122`.) + + +.. _whatsnew315-sampling-profiler: + +Tachyon: High frequency statistical sampling profiler +----------------------------------------------------- + +.. image:: ../library/tachyon-logo.png + :alt: Tachyon profiler logo + :align: center + :width: 200px + +A new statistical sampling profiler (Tachyon) has been added as +:mod:`profiling.sampling`. This profiler enables low-overhead performance analysis of +running Python processes without requiring code modification or process restart. + +Unlike deterministic profilers (such as :mod:`profiling.tracing`) that instrument +every function call, the sampling profiler periodically captures stack traces from +running processes. This approach provides virtually zero overhead while achieving +sampling rates of **up to 1,000,000 Hz**, making it the fastest sampling profiler +available for Python (at the time of its contribution) and ideal for debugging +performance issues in production environments. This capability is particularly +valuable for debugging performance issues in production systems where traditional +profiling approaches would be too intrusive. + +Key features include: + +* **Zero-overhead profiling**: Attach to any running Python process without + affecting its performance. Ideal for production debugging where you can't afford + to restart or slow down your application. + +* **No code modification required**: Profile existing applications without restart. + Simply point the profiler at a running process by PID and start collecting data. + +* **Flexible target modes**: + + * Profile running processes by PID (``attach``) - attach to already-running applications + * Run and profile scripts directly (``run``) - profile from the very start of execution + * Execute and profile modules (``run -m``) - profile packages run as ``python -m module`` + +* **Multiple profiling modes**: Choose what to measure based on your performance investigation: + + * **Wall-clock time** (``--mode wall``, default): Measures real elapsed time including I/O, + network waits, and blocking operations. Use this to understand where your program spends + calendar time, including when waiting for external resources. + * **CPU time** (``--mode cpu``): Measures only active CPU execution time, excluding I/O waits + and blocking. Use this to identify CPU-bound bottlenecks and optimize computational work. + * **GIL-holding time** (``--mode gil``): Measures time spent holding Python's Global Interpreter + Lock. Use this to identify which threads dominate GIL usage in multi-threaded applications. + * **Exception handling time** (``--mode exception``): Captures samples only from threads with + an active exception. Use this to analyze exception handling overhead. + +* **Thread-aware profiling**: Option to profile all threads (``-a``) or just the main thread, + essential for understanding multi-threaded application behavior. + +* **Multiple output formats**: Choose the visualization that best fits your workflow: + + * ``--pstats``: Detailed tabular statistics compatible with :mod:`pstats`. Shows function-level + timing with direct and cumulative samples. Best for detailed analysis and integration with + existing Python profiling tools. + * ``--collapsed``: Generates collapsed stack traces (one line per stack). This format is + specifically designed for creating flame graphs with external tools like Brendan Gregg's + FlameGraph scripts or speedscope. + * ``--flamegraph``: Generates a self-contained interactive HTML flame graph using D3.js. + Opens directly in your browser for immediate visual analysis. Flame graphs show the call + hierarchy where width represents time spent, making it easy to spot bottlenecks at a glance. + * ``--gecko``: Generates Gecko Profiler format compatible with `Firefox Profiler + `__. Upload the output to Firefox Profiler for advanced + timeline-based analysis with features like stack charts, markers, and network activity. + * ``--heatmap``: Generates an interactive HTML heatmap visualization with line-level sample + counts. Creates a directory with per-file heatmaps showing exactly where time is spent + at the source code level. + +* **Live interactive mode**: Real-time TUI profiler with a top-like interface (``--live``). + Monitor performance as your application runs with interactive sorting and filtering. + +* **Async-aware profiling**: Profile async/await code with task-based stack reconstruction + (``--async-aware``). See which coroutines are consuming time, with options to show only + running tasks or all tasks including those waiting. + +* **Opcode-level profiling**: Gather bytecode opcode information for instruction-level + profiling (``--opcodes``). Shows which bytecode instructions are executing, including + specializations from the adaptive interpreter. + +See :mod:`profiling.sampling` for the complete documentation, including all +available output formats, profiling modes, and configuration options. + +(Contributed by Pablo Galindo and László Kiss Kollár in :gh:`135953` and :gh:`138122`.) + + +.. _whatsnew315-unpacking-in-comprehensions: + +:pep:`798`: Unpacking in Comprehensions +--------------------------------------- + +List, set, and dictionary comprehensions, as well as generator expressions, now +support unpacking with ``*`` and ``**``. This extends the unpacking syntax +from :pep:`448` to comprehensions, providing a new syntax for combining an +arbitrary number of iterables or dictionaries into a single flat structure. +This new syntax is a direct alternative to nested comprehensions, +:func:`itertools.chain`, and :meth:`itertools.chain.from_iterable`. For +example:: + + >>> lists = [[1, 2], [3, 4], [5]] + >>> [*L for L in lists] # equivalent to [x for L in lists for x in L] + [1, 2, 3, 4, 5] + + >>> sets = [{1, 2}, {2, 3}, {3, 4}] + >>> {*s for s in sets} # equivalent to {x for s in sets for x in s} + {1, 2, 3, 4} + + >>> dicts = [{'a': 1}, {'b': 2}, {'a': 3}] + >>> {**d for d in dicts} # equivalent to {k: v for d in dicts for k,v in d.items()} + {'a': 3, 'b': 2} + +Generator expressions can similarly use unpacking to yield values from multiple +iterables:: + + >>> gen = (*L for L in lists) # equivalent to (x for L in lists for x in L) + >>> list(gen) + [1, 2, 3, 4, 5] + +This change also extends to asynchronous generator expressions, such that, for +example, ``(*a async for a in agen())`` is equivalent to ``(x async for a in +agen() for x in a)``. + +.. seealso:: :pep:`798` for further details. + +(Contributed by Adam Hartz in :gh:`143055`.) + +.. _whatsnew315-abi3t: + +:pep:`803`: ``abi3t`` -- Stable ABI for Free-Threaded Builds +------------------------------------------------------------ + +C extensions that target the :ref:`Stable ABI ` can now be +compiled for the new *Stable ABI for Free-Threaded Builds* (also known +as ``abi3t``), which makes them compatible with +:term:`free-threaded builds ` of CPython. +This usually requires some non-trivial changes to the source code; +specifically: + +- Switching to API introduced in :pep:`697` (Python 3.12), such as + negative :c:member:`~PyType_Spec.basicsize` and + :c:func:`PyObject_GetTypeData`, rather than making :c:type:`PyObject` + part of the instance struct; and +- Switching from a ``PyInit_`` function to a new export hook, + :c:func:`PyModExport_* `, introduced for this + purpose in :pep:`793`. + +Note that Stable ABI does not offer all the functionality that CPython +has to offer. +Extensions that cannot switch to ``abi3t`` should continue to build for +the existing Stable ABI (``abi3``) and the version-specific ABI for +free-threading (``cp315t``) separately. + +Stable ABI for Free-Threaded Builds should typically +be selected in a build tool (such as, for example, Setuptools, meson-python, +scikit-build-core, or Maturin). +At the time of writing, these tools did **not** support ``abi3t``. +If this is the case for your tool, compile for ``cp315t`` separately. +If not using a build tool -- or when writing such a tool -- you can select +``abi3t`` by setting the macro :c:macro:`!Py_TARGET_ABI3T` as discussed +in :ref:`abi3-compiling`. + + +.. _whatsnew315-improved-error-messages: + +Improved error messages +----------------------- + +* The interpreter now provides more helpful suggestions in :exc:`AttributeError` + exceptions when accessing an attribute on an object that does not exist, but + a similar attribute is available through one of its members. + + For example, if the object has an attribute that itself exposes the requested + name, the error message will suggest accessing it via that inner attribute: + + .. code-block:: python + + @dataclass + class Circle: + radius: float + + @property + def area(self) -> float: + return pi * self.radius**2 + + class Container: + def __init__(self, inner: Circle) -> None: + self.inner = inner + + circle = Circle(radius=4.0) + container = Container(circle) + print(container.area) + + Running this code now produces a clearer suggestion: + + .. code-block:: pycon + + Traceback (most recent call last): + File "/home/pablogsal/github/python/main/lel.py", line 42, in + print(container.area) + ^^^^^^^^^^^^^^ + AttributeError: 'Container' object has no attribute 'area'. Did you mean '.inner.area' instead of '.area'? + + +Other language changes +====================== + +.. _whatsnew315-utf8-default: + +* Python now uses UTF-8_ as the default encoding, independent of the system's + environment. This means that I/O operations without an explicit encoding, + for example, ``open('flying-circus.txt')``, will use UTF-8. + UTF-8 is a widely-supported Unicode_ character encoding that has become a + *de facto* standard for representing text, including nearly every webpage + on the internet, many common file formats, programming languages, and more. + + This only applies when no ``encoding`` argument is given. For best + compatibility between versions of Python, ensure that an explicit ``encoding`` + argument is always provided. The :ref:`opt-in encoding warning ` + can be used to identify code that may be affected by this change. + The special ``encoding='locale'`` argument uses the current locale + encoding, and has been supported since Python 3.10. + + To retain the previous behaviour, Python's UTF-8 mode may be disabled with + the :envvar:`PYTHONUTF8=0 ` environment variable or the + :option:`-X utf8=0 <-X>` command-line option. + + .. seealso:: :pep:`686` for further details. + + .. _UTF-8: https://en.wikipedia.org/wiki/UTF-8 + .. _Unicode: https://home.unicode.org/ + + (Contributed by Adam Turner in :gh:`133711`; PEP 686 written by Inada Naoki.) + +* Several error messages incorrectly using the term "argument" have been corrected. + (Contributed by Stan Ulbrych in :gh:`133382`.) + +* The interpreter now tries to provide a suggestion when + :func:`delattr` fails due to a missing attribute. + When an attribute name that closely resembles an existing attribute is used, + the interpreter will suggest the correct attribute name in the error message. + For example: + + .. doctest:: + + >>> class A: + ... pass + >>> a = A() + >>> a.abcde = 1 + >>> del a.abcdf # doctest: +ELLIPSIS + Traceback (most recent call last): + ... + AttributeError: 'A' object has no attribute 'abcdf'. Did you mean: 'abcde'? + + (Contributed by Nikita Sobolev and Pranjal Prajapati in :gh:`136588`.) + +* Unraisable exceptions are now highlighted with color by default. This can be + controlled by :ref:`environment variables `. + (Contributed by Peter Bierma in :gh:`134170`.) + +* The :meth:`~object.__repr__` of :class:`ImportError` and :class:`ModuleNotFoundError` + now shows "name" and "path" as ``name=`` and ``path=`` if they were given + as keyword arguments at construction time. + (Contributed by Serhiy Storchaka, Oleg Iarygin, and Yoav Nir in :gh:`74185`.) + +* The :attr:`~object.__dict__` and :attr:`!__weakref__` descriptors now use a + single descriptor instance per interpreter, shared across all types that + need them. + This speeds up class creation, and helps avoid reference cycles. + (Contributed by Petr Viktorin in :gh:`135228`.) + +* The :option:`-W` option and the :envvar:`PYTHONWARNINGS` environment variable + can now specify regular expressions instead of literal strings to match + the warning message and the module name, if the corresponding field starts + and ends with a forward slash (``/``). + (Contributed by Serhiy Storchaka in :gh:`134716`.) + +* Functions that take timestamp or timeout arguments now accept any real + numbers (such as :class:`~decimal.Decimal` and :class:`~fractions.Fraction`), + not only integers or floats, although this does not improve precision. + (Contributed by Serhiy Storchaka in :gh:`67795`.) + +.. _whatsnew315-bytearray-take-bytes: + +* Added :meth:`bytearray.take_bytes(n=None, /) ` to take + bytes out of a :class:`bytearray` without copying. This enables optimizing code + which must return :class:`bytes` after working with a mutable buffer of bytes + such as data buffering, network protocol parsing, encoding, decoding, + and compression. Common code patterns which can be optimized with + :func:`~bytearray.take_bytes` are listed below. + + .. list-table:: Suggested optimizing refactors + :header-rows: 1 + + * - Description + - Old + - New + + * - Return :class:`bytes` after working with :class:`bytearray` + - .. code:: python + + def read() -> bytes: + buffer = bytearray(1024) + ... + return bytes(buffer) + + - .. code:: python + + def read() -> bytes: + buffer = bytearray(1024) + ... + return buffer.take_bytes() + + * - Empty a buffer getting the bytes + - .. code:: python + + buffer = bytearray(1024) + ... + data = bytes(buffer) + buffer.clear() + + - .. code:: python + + buffer = bytearray(1024) + ... + data = buffer.take_bytes() + + * - Split a buffer at a specific separator + - .. code:: python + + buffer = bytearray(b'abc\ndef') + n = buffer.find(b'\n') + data = bytes(buffer[:n + 1]) + del buffer[:n + 1] + assert data == b'abc' + assert buffer == bytearray(b'def') + + - .. code:: python + + buffer = bytearray(b'abc\ndef') + n = buffer.find(b'\n') + data = buffer.take_bytes(n + 1) + + * - Split a buffer at a specific separator; discard after the separator + - .. code:: python + + buffer = bytearray(b'abc\ndef') + n = buffer.find(b'\n') + data = bytes(buffer[:n]) + buffer.clear() + assert data == b'abc' + assert len(buffer) == 0 + + - .. code:: python + + buffer = bytearray(b'abc\ndef') + n = buffer.find(b'\n') + buffer.resize(n) + data = buffer.take_bytes() + + (Contributed by Cody Maloney in :gh:`139871`.) + +* Many functions related to compiling or parsing Python code, such as + :func:`compile`, :func:`ast.parse`, :func:`symtable.symtable`, + and :func:`importlib.abc.InspectLoader.source_to_code`, now allow the module + name to be passed. It is needed to unambiguously :ref:`filter ` + syntax warnings by module name. + (Contributed by Serhiy Storchaka in :gh:`135801`.) + +* Allowed defining the *__dict__* and *__weakref__* :ref:`__slots__ ` + for any class. + (Contributed by Serhiy Storchaka in :gh:`41779`.) + +* Allowed defining any :ref:`__slots__ ` for a class derived from + :class:`tuple` (including classes created by :func:`collections.namedtuple`). + (Contributed by Serhiy Storchaka in :gh:`41779`.) + +* The :class:`slice` type now supports subscription, + making it a :term:`generic type`. + (Contributed by James Hilton-Balfe in :gh:`128335`.) + +* The class :class:`memoryview` now supports the :c:expr:`float complex` and + :c:expr:`double complex` C types: formatting characters ``'F'`` and ``'D'`` + respectively. + (Contributed by Sergey B Kirpichev in :gh:`146151`.) + +* Allow the *count* argument of :meth:`bytes.replace` to be a keyword. + (Contributed by Stan Ulbrych in :gh:`147856`.) + + +New modules +=========== + +math.integer +------------ + +This module provides access to the mathematical functions for integer +arguments (:pep:`791`). +(Contributed by Serhiy Storchaka in :gh:`81313`.) + + +Improved modules +================ + +argparse +-------- + +* The :class:`~argparse.BooleanOptionalAction` action supports now single-dash + long options and alternate prefix characters. + (Contributed by Serhiy Storchaka in :gh:`138525`.) + +* Changed the *suggest_on_error* parameter of :class:`argparse.ArgumentParser` to + default to ``True``. This enables suggestions for mistyped arguments by default. + (Contributed by Jakob Schluse in :gh:`140450`.) + +* Added backtick markup support in description and epilog text to highlight + inline code when color output is enabled. + (Contributed by Savannah Ostrowski in :gh:`142390`.) + + +array +----- + +* Support the :c:expr:`float complex` and :c:expr:`double complex` C types: + formatting characters ``'F'`` and ``'D'`` respectively. + (Contributed by Sergey B Kirpichev in :gh:`146151`.) + +* Support half-floats (16-bit IEEE 754 binary interchange format): formatting + character ``'e'``. + (Contributed by Sergey B Kirpichev in :gh:`146238`.) + + +base64 +------ + +* Added the *pad* parameter in :func:`~base64.z85encode`. + (Contributed by Hauke Dämpfling in :gh:`143103`.) + +* Added the *padded* parameter in + :func:`~base64.b32encode`, :func:`~base64.b32decode`, + :func:`~base64.b32hexencode`, :func:`~base64.b32hexdecode`, + :func:`~base64.b64encode`, :func:`~base64.b64decode`, + :func:`~base64.urlsafe_b64encode`, and :func:`~base64.urlsafe_b64decode`. + (Contributed by Serhiy Storchaka in :gh:`73613`.) + +* Added the *wrapcol* parameter in :func:`~base64.b16encode`, + :func:`~base64.b32encode`, :func:`~base64.b32hexencode`, + :func:`~base64.b64encode`, :func:`~base64.b85encode`, and + :func:`~base64.z85encode`. + (Contributed by Serhiy Storchaka in :gh:`143214` and :gh:`146431`.) + +* Added the *ignorechars* parameter in :func:`~base64.b16decode`, + :func:`~base64.b32decode`, :func:`~base64.b32hexdecode`, + :func:`~base64.b64decode`, :func:`~base64.b85decode`, and + :func:`~base64.z85decode`. + (Contributed by Serhiy Storchaka in :gh:`144001` and :gh:`146431`.) + + +binascii +-------- + +* Added functions for Base32 encoding: + + - :func:`~binascii.b2a_base32` and :func:`~binascii.a2b_base32` + + (Contributed by James Seo in :gh:`146192`.) + +* Added functions for Ascii85, Base85, and Z85 encoding: + + - :func:`~binascii.b2a_ascii85` and :func:`~binascii.a2b_ascii85` + - :func:`~binascii.b2a_base85` and :func:`~binascii.a2b_base85` + + (Contributed by James Seo and Serhiy Storchaka in :gh:`101178`.) + +* Added the *padded* parameter in + :func:`~binascii.b2a_base32`, :func:`~binascii.a2b_base32`, + :func:`~binascii.b2a_base64`, and :func:`~binascii.a2b_base64`. + (Contributed by Serhiy Storchaka in :gh:`73613`.) + +* Added the *wrapcol* parameter in :func:`~binascii.b2a_base64`. + (Contributed by Serhiy Storchaka in :gh:`143214`.) + +* Added the *alphabet* parameter in :func:`~binascii.b2a_base64` and + :func:`~binascii.a2b_base64`. + (Contributed by Serhiy Storchaka in :gh:`145980`.) + +* Added the *ignorechars* parameter in :func:`~binascii.a2b_hex`, + :func:`~binascii.unhexlify`, and :func:`~binascii.a2b_base64`. + (Contributed by Serhiy Storchaka in :gh:`144001` and :gh:`146431`.) + + +calendar +-------- + +* Calendar pages generated by the :class:`calendar.HTMLCalendar` class now support + dark mode and have been migrated to the HTML5 standard for improved accessibility. + (Contributed by Jiahao Li and Hugo van Kemenade in :gh:`137634`.) + +* The :mod:`calendar`'s :ref:`command-line ` HTML output now + accepts the year-month option: ``python -m calendar -t html 2009 06``. + (Contributed by Pål Grønås Drange in :gh:`140212`.) + + +collections +----------- + +* Added :meth:`!collections.Counter.__xor__` and + :meth:`!collections.Counter.__ixor__` to compute the symmetric difference + between :class:`~collections.Counter` objects. + (Contributed by Raymond Hettinger in :gh:`138682`.) + + +concurrent.futures +------------------ + +* Improved error reporting when a child process in a + :class:`concurrent.futures.ProcessPoolExecutor` terminates abruptly. + The resulting traceback will now tell you the PID and exit code of the + terminated process. + (Contributed by Jonathan Berg in :gh:`139486`.) + + +contextlib +---------- + +* Added support for arbitrary descriptors :meth:`!__enter__`, + :meth:`!__exit__`, :meth:`!__aenter__`, and :meth:`!__aexit__` in + :class:`~contextlib.ExitStack` and :class:`contextlib.AsyncExitStack`, for + consistency with the :keyword:`with` and :keyword:`async with` statements. + (Contributed by Serhiy Storchaka in :gh:`144386`.) + + +dataclasses +----------- + +* Annotations for generated ``__init__`` methods no longer include internal + type names. + + +dbm +--- + +* Added new :meth:`!reorganize` methods to :mod:`dbm.dumb` and :mod:`dbm.sqlite3` + which allow to recover unused free space previously occupied by deleted entries. + (Contributed by Andrea Oliveri in :gh:`134004`.) + + +difflib +------- + + .. _whatsnew315-color-difflib: + +* Introduced the optional *color* parameter to :func:`difflib.unified_diff`, + enabling color output similar to :program:`git diff`. + This can be controlled by :ref:`environment variables + `. + (Contributed by Douglas Thor in :gh:`133725`.) + +* Improved the styling of HTML diff pages generated by the :class:`difflib.HtmlDiff` + class, and migrated the output to the HTML5 standard. + (Contributed by Jiahao Li in :gh:`134580`.) + + +functools +--------- + +* :func:`~functools.singledispatchmethod` now supports non-:term:`descriptor` + callables. + (Contributed by Serhiy Storchaka in :gh:`140873`.) + +* :func:`~functools.singledispatchmethod` now dispatches on the second argument + if it wraps a regular method and is called as a class attribute. + (Contributed by Bartosz Sławecki in :gh:`143535`.) + + +hashlib +------- + +* Ensure that hash functions guaranteed to be always *available* exist as + attributes of :mod:`hashlib` even if they will not work at runtime due to + missing backend implementations. For instance, ``hashlib.md5`` will no + longer raise :exc:`AttributeError` if OpenSSL is not available and Python + has been built without MD5 support. + (Contributed by Bénédikt Tran in :gh:`136929`.) + + +http.client +----------- + +* A new *max_response_headers* keyword-only parameter has been added to + :class:`~http.client.HTTPConnection` and :class:`~http.client.HTTPSConnection` + constructors. This parameter overrides the default maximum number of allowed + response headers. + (Contributed by Alexander Enrique Urieles Nieto in :gh:`131724`.) + + +http.cookies +------------ + +* Allow '``"``' double quotes in cookie values. + (Contributed by Nick Burns and Senthil Kumaran in :gh:`92936`.) + + +http.server +----------- + +* The logging of :mod:`~http.server.BaseHTTPRequestHandler`, + as used by the :ref:`command-line interface `, + is colored by default. + This can be controlled with :ref:`environment variables + `. + (Contributed by Hugo van Kemenade in :gh:`146292`.) + + +inspect +------- + +* Add parameters *inherit_class_doc* and *fallback_to_class_doc* + for :func:`~inspect.getdoc`. + (Contributed by Serhiy Storchaka in :gh:`132686`.) + +json +---- + +* Add the *array_hook* parameter to :func:`~json.load` and + :func:`~json.loads` functions: + allow a callback for JSON literal array types to customize Python lists in + the resulting decoded object. Passing combined :class:`frozendict` to + *object_pairs_hook* param and :class:`tuple` to ``array_hook`` will yield a + deeply nested immutable Python structure representing the JSON data. + (Contributed by Joao S. O. Bueno in :gh:`146440`) + + +locale +------ + +* :func:`~locale.setlocale` now supports language codes with ``@``-modifiers. + ``@``-modifiers are no longer silently removed in :func:`~locale.getlocale`, + but included in the language code. + (Contributed by Serhiy Storchaka in :gh:`137729`.) + +* Undeprecate the :func:`locale.getdefaultlocale` function. + (Contributed by Victor Stinner in :gh:`130796`.) + + +math +---- + +* Add :func:`math.isnormal` and :func:`math.issubnormal` functions. + (Contributed by Sergey B Kirpichev in :gh:`132908`.) + +* Add :func:`math.fmax`, :func:`math.fmin` and :func:`math.signbit` functions. + (Contributed by Bénédikt Tran in :gh:`135853`.) + + +mimetypes +--------- + +* Add ``application/dicom`` MIME type for ``.dcm`` extension. + (Contributed by Benedikt Johannes in :gh:`144217`.) +* Add ``application/efi``. (Contributed by Charlie Lin in :gh:`145720`.) +* Add ``application/node`` MIME type for ``.cjs`` extension. + (Contributed by John Franey in :gh:`140937`.) +* Add ``application/toml``. (Contributed by Gil Forcada in :gh:`139959`.) +* Add ``application/sql`` and ``application/vnd.sqlite3``. + (Contributed by Charlie Lin in :gh:`145698`.) +* Add the following MIME types: + + - ``application/vnd.ms-cab-compressed`` for ``.cab`` extension + - ``application/vnd.ms-htmlhelp`` for ``.chm`` extension + - ``application/vnd.ms-officetheme`` for ``.thmx`` extension + + (Contributed by Charlie Lin in :gh:`145718`.) + +* Add ``image/jxl``. (Contributed by Foolbar in :gh:`144213`.) +* Rename ``application/x-texinfo`` to ``application/texinfo``. + (Contributed by Charlie Lin in :gh:`140165`.) +* Changed the MIME type for ``.ai`` files to ``application/pdf``. + (Contributed by Stan Ulbrych in :gh:`141239`.) + + +mmap +---- + +* :class:`mmap.mmap` now has a *trackfd* parameter on Windows; + if it is ``False``, the file handle corresponding to *fileno* will + not be duplicated. + (Contributed by Serhiy Storchaka in :gh:`78502`.) + +* Added the :meth:`mmap.mmap.set_name` method + to annotate an anonymous memory mapping + if Linux kernel supports :manpage:`PR_SET_VMA_ANON_NAME ` (Linux 5.17 or newer). + (Contributed by Donghee Na in :gh:`142419`.) + + +os +-- + +* Add :func:`os.statx` on Linux kernel versions 4.11 and later with + glibc versions 2.28 and later. + (Contributed by Jeffrey Bosboom and Victor Stinner in :gh:`83714`.) + + +os.path +------- + +* Add support of the all-but-last mode in :func:`~os.path.realpath`. + (Contributed by Serhiy Storchaka in :gh:`71189`.) + +* The *strict* parameter to :func:`os.path.realpath` accepts a new value, + :data:`os.path.ALLOW_MISSING`. + If used, errors other than :exc:`FileNotFoundError` will be re-raised; + the resulting path can be missing but it will be free of symlinks. + (Contributed by Petr Viktorin for :cve:`2025-4517`.) + + +pickle +------ + +* Add support for pickling private methods and nested classes. + (Contributed by Zackery Spytz and Serhiy Storchaka in :gh:`77188`.) + + +pprint +------ + +* Add an *expand* keyword argument for :func:`pprint.pprint`, + :func:`pprint.pformat`, :func:`pprint.pp`. If true, the output will be + formatted similar to pretty-printed :func:`json.dumps` when + *indent* is supplied. + (Contributed by Stefan Todoran, Semyon Moroz and Hugo van Kemenade in + :gh:`112632`.) + +* Add *color* parameter to :func:`~pprint.pp` and :func:`~pprint.pprint`. + If ``True`` (the default), output is highlighted in color, when the stream + and :ref:`environment variables ` permit. + If ``False``, colored output is always disabled. + (Contributed by Hugo van Kemenade in :gh:`145217`.) + +* Add t-string support to :mod:`pprint`. + (Contributed by Loïc Simon and Hugo van Kemenade in :gh:`134551`.) + + +re +-- + +* :func:`re.prefixmatch` and a corresponding :meth:`re.Pattern.prefixmatch` + have been added as alternate, more explicit names for the existing + and now :term:`soft deprecated` + :func:`re.match` and :meth:`re.Pattern.match` APIs. These are intended + to be used to alleviate confusion around what *match* means by following the + Zen of Python's *"Explicit is better than implicit"* mantra. Most other + language regular expression libraries use an API named *match* to mean what + Python has always called *search*. + (Contributed by Gregory P. Smith in :gh:`86519`.) + + +resource +-------- + +* Add new constants: :data:`~resource.RLIMIT_NTHR`, + :data:`~resource.RLIMIT_UMTXP`, :data:`~resource.RLIMIT_THREADS`, + :data:`~resource.RLIM_SAVED_CUR`, and :data:`~resource.RLIM_SAVED_MAX`. + (Contributed by Serhiy Storchaka in :gh:`137512`.) + + +shelve +------ + +* Added new :meth:`!reorganize` method to :mod:`shelve` used to recover unused free + space previously occupied by deleted entries. + (Contributed by Andrea Oliveri in :gh:`134004`.) +* Add support for custom serialization and deserialization functions + in the :mod:`shelve` module. + (Contributed by Furkan Onder in :gh:`99631`.) + + +socket +------ + +* Add constants for the ISO-TP CAN protocol. + (Contributed by Patrick Menschel and Stefan Tatschner in :gh:`86819`.) + + +sqlite3 +------- + +* The :ref:`command-line interface ` has several new features: + + * SQL keyword completion on . + (Contributed by Long Tan in :gh:`133393`.) + + * Prompts, error messages, and help text are now colored. + This is enabled by default, see :ref:`using-on-controlling-color` for + details. + (Contributed by Stan Ulbrych and Łukasz Langa in :gh:`133461`.) + + * Table, index, trigger, view, column, function, and schema completion on . + (Contributed by Long Tan in :gh:`136101`.) + + +ssl +--- + +* Indicate through :data:`ssl.HAS_PSK_TLS13` whether the :mod:`ssl` module + supports "External PSKs" in TLSv1.3, as described in :rfc:`9258`. + (Contributed by Will Childs-Klein in :gh:`133624`.) + +* Added new methods for managing groups used for SSL key agreement + + * :meth:`ssl.SSLContext.set_groups` sets the groups allowed for doing + key agreement, extending the previous + :meth:`ssl.SSLContext.set_ecdh_curve` method. + This new API provides the ability to list multiple groups and + supports fixed-field and post-quantum groups in addition to ECDH + curves. This method can also be used to control what key shares + are sent in the TLS handshake. + * :meth:`ssl.SSLSocket.group` returns the group selected for doing key + agreement on the current connection after the TLS handshake completes. + This call requires OpenSSL 3.2 or later. + * :meth:`ssl.SSLContext.get_groups` returns a list of all available key + agreement groups compatible with the minimum and maximum TLS versions + currently set in the context. This call requires OpenSSL 3.5 or later. + + (Contributed by Ron Frederick in :gh:`136306`.) + +* Added a new method :meth:`ssl.SSLContext.set_ciphersuites` for setting TLS 1.3 + ciphers. For TLS 1.2 or earlier, :meth:`ssl.SSLContext.set_ciphers` should + continue to be used. Both calls can be made on the same context and the + selected cipher suite will depend on the TLS version negotiated when a + connection is made. + (Contributed by Ron Frederick in :gh:`137197`.) + +* Added new methods for managing signature algorithms: + + * :func:`ssl.get_sigalgs` returns a list of all available TLS signature + algorithms. This call requires OpenSSL 3.4 or later. + * :meth:`ssl.SSLContext.set_client_sigalgs` sets the signature algorithms + allowed for certificate-based client authentication. + * :meth:`ssl.SSLContext.set_server_sigalgs` sets the signature algorithms + allowed for the server to complete the TLS handshake. + * :meth:`ssl.SSLSocket.client_sigalg` returns the signature algorithm + selected for client authentication on the current connection. This call + requires OpenSSL 3.5 or later. + * :meth:`ssl.SSLSocket.server_sigalg` returns the signature algorithm + selected for the server to complete the TLS handshake on the current + connection. This call requires OpenSSL 3.5 or later. + + (Contributed by Ron Frederick in :gh:`138252`.) + + +subprocess +---------- + +* :meth:`subprocess.Popen.wait`: when ``timeout`` is not ``None`` and the + platform supports it, an efficient event-driven mechanism is used to wait for + process termination: + + - Linux >= 5.3 uses :func:`os.pidfd_open` + :func:`select.poll`. + - macOS and other BSD variants use :func:`select.kqueue` + ``KQ_FILTER_PROC`` + ``KQ_NOTE_EXIT``. + - Windows keeps using ``WaitForSingleObject`` (unchanged). + + If none of these mechanisms are available, the function falls back to the + traditional busy loop (non-blocking call and short sleeps). + (Contributed by Giampaolo Rodola in :gh:`83069`). + + +symtable +-------- + +* Add :meth:`symtable.Function.get_cells` and :meth:`symtable.Symbol.is_cell` methods. + (Contributed by Yashp002 in :gh:`143504`.) + + +sys +--- + +* Add :data:`sys.abi_info` namespace to improve access to ABI information. + (Contributed by Klaus Zimmermann in :gh:`137476`.) + + +tarfile +------- + +* :func:`~tarfile.data_filter` now normalizes symbolic link targets in order to + avoid path traversal attacks. + (Contributed by Petr Viktorin in :gh:`127987` and :cve:`2025-4138`.) +* :func:`~tarfile.TarFile.extractall` now skips fixing up directory attributes + when a directory was removed or replaced by another kind of file. + (Contributed by Petr Viktorin in :gh:`127987` and :cve:`2024-12718`.) +* :func:`~tarfile.TarFile.extract` and :func:`~tarfile.TarFile.extractall` + now (re-)apply the extraction filter when substituting a link (hard or + symbolic) with a copy of another archive member, and when fixing up + directory attributes. + The former raises a new exception, :exc:`~tarfile.LinkFallbackError`. + (Contributed by Petr Viktorin for :cve:`2025-4330` and :cve:`2024-12718`.) +* :func:`~tarfile.TarFile.extract` and :func:`~tarfile.TarFile.extractall` + no longer extract rejected members when + :func:`~tarfile.TarFile.errorlevel` is zero. + (Contributed by Matt Prodani and Petr Viktorin in :gh:`112887` + and :cve:`2025-4435`.) +* :func:`~tarfile.TarFile.extract` and :func:`~tarfile.TarFile.extractall` + now replace slashes by backslashes in symlink targets on Windows to prevent + creation of corrupted links. + (Contributed by Christoph Walcher in :gh:`57911`.) + + +timeit +------ + +* The output of the :mod:`timeit` command-line interface is colored by default. + This can be controlled with + :ref:`environment variables `. + (Contributed by Hugo van Kemenade in :gh:`146609`.) +* The command-line interface now colorizes error tracebacks + by default. This can be controlled with + :ref:`environment variables `. + (Contributed by Yi Hong in :gh:`139374`.) + +* Make the target time of :meth:`timeit.Timer.autorange` configurable + and add ``--target-time`` option to the command-line interface. + (Contributed by Alessandro Cucci and Miikka Koskinen in :gh:`140283`.) + + +tkinter +------- + +* The :meth:`!tkinter.Text.search` method now supports two additional + arguments: *nolinestop* which allows the search to + continue across line boundaries; + and *strictlimits* which restricts the search to within the specified range. + (Contributed by Rihaan Meher in :gh:`130848`.) + +* A new method :meth:`!tkinter.Text.search_all` has been introduced. + This method allows for searching for all matches of a pattern + using Tcl's ``-all`` and ``-overlap`` options. + (Contributed by Rihaan Meher in :gh:`130848`.) + +* Added new methods :meth:`!pack_content`, :meth:`!place_content` and + :meth:`!grid_content` which use Tk commands with new names (introduced + in Tk 8.6) instead of :meth:`!*_slaves` methods which use Tk commands + with outdated names. + (Contributed by Serhiy Storchaka in :gh:`143754`.) + +* Added :class:`!Event` attributes :attr:`!user_data` for Tk virtual events + and :attr:`!detail` for ``Enter``, ``Leave``, ``FocusIn``, ``FocusOut``, + and ``ConfigureRequest`` events. + (Contributed by Matthias Kievernagel and Serhiy Storchaka in :gh:`47655`.) + + +.. _whatsnew315-tomllib-1-1-0: + +tomllib +------- + +* The :mod:`tomllib` module now supports TOML 1.1.0. + This is a backwards compatible update, meaning that all valid TOML 1.0.0 + documents are parsed the same way. + + The changes, according to the `official TOML changelog`_, are: + + - Allow newlines and trailing commas in inline tables. + + Previously an inline table had to be on a single line and couldn't end + with a trailing comma. This is now relaxed so that the following is valid: + + .. syntax highlighting needs TOML 1.1.0 support in Pygments, + see https://github.com/pygments/pygments/issues/3026 + + .. code-block:: text + + tbl = { + key = "a string", + moar-tbl = { + key = 1, + }, + } + + - Add ``\xHH`` notation to basic strings for codepoints under 255, + and the ``\e`` escape for the escape character: + + .. code-block:: text + + null = "null byte: \x00; letter a: \x61" + csi = "\e[" + + - Seconds in datetime and time values are now optional. + The following are now valid: + + .. code-block:: text + + dt = 2010-02-03 14:15 + t = 14:15 + + (Contributed by Taneli Hukkinen in :gh:`142956`.) + +.. _official TOML changelog: https://github.com/toml-lang/toml/blob/main/CHANGELOG.md + + +types +----- + +* Expose the write-through :func:`locals` proxy type + as :data:`types.FrameLocalsProxyType`. + This represents the type of the :attr:`frame.f_locals` attribute, + as described in :pep:`667`. + + +typing +------ + +.. _whatsnew315-typeform: + +* :pep:`747`: Add :data:`~typing.TypeForm`, a new special form for annotating + values that are themselves type expressions. + ``TypeForm[T]`` means "a type form object describing ``T`` (or a type + assignable to ``T``)". At runtime, ``TypeForm(x)`` simply returns ``x``, + which allows explicit annotation of type-form values without changing + behavior. + + This helps libraries that accept user-provided type expressions + (for example ``int``, ``str | None``, :class:`~typing.TypedDict` + classes, or ``list[int]``) expose precise signatures: + + .. code-block:: python + + from typing import Any, TypeForm + + def cast[T](typ: TypeForm[T], value: Any) -> T: ... + + (Contributed by Jelle Zijlstra in :gh:`145033`.) + +* Code like ``class ExtraTypeVars(P1[S], Protocol[T, T2]): ...`` now raises + a :exc:`TypeError`, because ``S`` is not listed in ``Protocol`` parameters. + (Contributed by Nikita Sobolev in :gh:`137191`.) + +* Code like ``class B2(A[T2], Protocol[T1, T2]): ...`` now correctly handles + type parameters order: it is ``(T1, T2)``, not ``(T2, T1)`` + as it was incorrectly inferred in runtime before. + (Contributed by Nikita Sobolev in :gh:`137191`.) + +* :pep:`800`: Add :deco:`typing.disjoint_base`, a new decorator marking a class + as a disjoint base. This is an advanced feature primarily intended to allow + type checkers to faithfully reflect the runtime semantics of types defined + as builtins or in compiled extensions. If a class ``C`` is a disjoint base, then + child classes of that class cannot inherit from other disjoint bases that are + not parent or child classes of ``C``. (Contributed by Jelle Zijlstra in :gh:`148639`.) + + +unicodedata +----------- + +* The Unicode database has been updated to Unicode 17.0.0. + +* Add :func:`unicodedata.isxidstart` and :func:`unicodedata.isxidcontinue` + functions to check whether a character can start or continue a + `Unicode Standard Annex #31 `_ identifier. + (Contributed by Stan Ulbrych in :gh:`129117`.) + +* Add the :func:`~unicodedata.iter_graphemes` + function to iterate over grapheme clusters according to rules defined in + `Unicode Standard Annex #29, "Unicode Text Segmentation" + `_. + Add :func:`~unicodedata.grapheme_cluster_break`, + :func:`~unicodedata.indic_conjunct_break` and + :func:`~unicodedata.extended_pictographic` functions to get the properties + of the character which are related to the above algorithm. + (Contributed by Serhiy Storchaka and Guillaume Sanchez in :gh:`74902`.) + +* Add :func:`~unicodedata.block` function to return the `Unicode block + `_ + assigned to a character. + (Contributed by Stan Ulbrych in :gh:`66802`.) + + +unittest +-------- + +* :func:`unittest.TestCase.assertLogs` will now accept a formatter + to control how messages are formatted. + (Contributed by Garry Cairns in :gh:`134567`.) + + +urllib.parse +------------ + +* Add the *missing_as_none* parameter to :func:`~urllib.parse.urlsplit`, + :func:`~urllib.parse.urlparse` and :func:`~urllib.parse.urldefrag` functions. + Add the *keep_empty* parameter to :func:`~urllib.parse.urlunsplit` and + :func:`~urllib.parse.urlunparse` functions. + This allows to distinguish between empty and not defined URI components + and preserve empty components. + (Contributed by Serhiy Storchaka in :gh:`67041`.) + + +venv +---- + +* On POSIX platforms, platlib directories will be created if needed when + creating virtual environments, instead of using ``lib64 -> lib`` symlink. + This means purelib and platlib of virtual environments no longer share the + same ``lib`` directory on platforms where :data:`sys.platlibdir` is not + equal to ``lib``. + (Contributed by Rui Xi in :gh:`133951`.) + + +warnings +-------- + +* Improve filtering by module in :func:`warnings.warn_explicit` if no *module* + argument is passed. + It now tests the module regular expression in the warnings filter not only + against the filename with ``.py`` stripped, but also against module names + constructed starting from different parent directories of the filename + (with ``/__init__.py``, ``.py`` and, on Windows, ``.pyw`` stripped). + (Contributed by Serhiy Storchaka in :gh:`135801`.) + + +wave +---- + +* Added support for IEEE floating-point WAVE audio + (``WAVE_FORMAT_IEEE_FLOAT``) in :mod:`wave`. + +* Added :meth:`wave.Wave_read.getformat`, :meth:`wave.Wave_write.getformat`, + and :meth:`wave.Wave_write.setformat` for explicit frame format handling. + +* :meth:`wave.Wave_write.setparams` accepts both 7-item tuples including + ``format`` and 6-item tuples for backwards compatibility (defaulting to + ``WAVE_FORMAT_PCM``). + +* ``WAVE_FORMAT_IEEE_FLOAT`` output now includes a ``fact`` chunk, + as required for non-PCM WAVE formats. + +(Contributed by Lionel Koenig and Michiel W. Beijen in :gh:`60729`.) + + +xml.parsers.expat +----------------- + +* Add :meth:`~xml.parsers.expat.xmlparser.SetAllocTrackerActivationThreshold` + and :meth:`~xml.parsers.expat.xmlparser.SetAllocTrackerMaximumAmplification` + to :ref:`xmlparser ` objects to tune protections against + disproportional amounts of dynamic memory usage from within an Expat parser. + (Contributed by Bénédikt Tran in :gh:`90949`.) + +* Add :meth:`~xml.parsers.expat.xmlparser.SetBillionLaughsAttackProtectionActivationThreshold` + and :meth:`~xml.parsers.expat.xmlparser.SetBillionLaughsAttackProtectionMaximumAmplification` + to :ref:`xmlparser ` objects to tune protections against + `billion laughs`_ attacks. + (Contributed by Bénédikt Tran in :gh:`90949`.) + + .. _billion laughs: https://en.wikipedia.org/wiki/Billion_laughs_attack + + +zlib +---- + +* Allow combining two Adler-32 checksums via :func:`~zlib.adler32_combine`. + (Contributed by Callum Attryde and Bénédikt Tran in :gh:`134635`.) + +* Allow combining two CRC-32 checksums via :func:`~zlib.crc32_combine`. + (Contributed by Bénédikt Tran in :gh:`134635`.) + + +.. Add improved modules above alphabetically, not here at the end. + +Optimizations +============= + +* ``mimalloc`` is now used as the default allocator for + for raw memory allocations such as via :c:func:`PyMem_RawMalloc` + for better performance on :term:`free-threaded builds `. + (Contributed by Kumar Aditya in :gh:`144914`.) + + +base64 & binascii +----------------- + +* CPython's underlying base64 implementation now encodes 2x faster and decodes 3x + faster thanks to simple CPU pipelining optimizations. + (Contributed by Gregory P. Smith and Serhiy Storchaka in :gh:`143262`.) + +* Implementation for Ascii85, Base85, and Z85 encoding has been rewritten in C. + Encoding and decoding is now two orders of magnitude faster and consumes + two orders of magnitude less memory. + (Contributed by James Seo and Serhiy Storchaka in :gh:`101178`.) + +* Implementation for Base32 has been rewritten in C. + Encoding and decoding is now two orders of magnitude faster. + (Contributed by James Seo in :gh:`146192`) + + +csv +--- + +* :meth:`csv.Sniffer.sniff` delimiter detection is now up to 1.6x faster. + (Contributed by Maurycy Pawłowski-Wieroński in :gh:`137628`.) + + +.. _whatsnew315-jit: + +Upgraded JIT compiler +--------------------- + +Results from the `pyperformance `__ +benchmark suite report +`6-7% `__ +geometric mean performance improvement for the JIT over the standard CPython +interpreter built with all optimizations enabled on x86-64 Linux. On AArch64 +macOS, the JIT has a +`12-13% `__ +speedup over the :ref:`tail calling interpreter ` +with all optimizations enabled. The speedups for JIT +builds versus no JIT builds range from roughly 15% slowdown to over +100% speedup (ignoring the ``unpack_sequence`` microbenchmark) on +x86-64 Linux and AArch64 macOS systems. + +.. attention:: + These results are not yet final. + +The major upgrades to the JIT are: + +* LLVM 21 build-time dependency +* New tracing frontend +* Basic register allocation in the JIT +* More JIT optimizations +* Better machine code generation + +.. rubric:: LLVM 21 build-time dependency + +The JIT compiler now uses LLVM 21 for build-time stencil generation. As +always, LLVM is only needed when building CPython with the JIT enabled; +end users running Python do not need LLVM installed. Instructions for +installing LLVM can be found in the `JIT compiler documentation +`__ +for all supported platforms. +(Contributed by Savannah Ostrowski in :gh:`140973`.) + +.. rubric:: A new tracing frontend + +The JIT compiler now supports significantly more bytecode operations and +control flow than in Python 3.14, enabling speedups on a wider variety of +code. For example, simple Python object creation is now understood by the +3.15 JIT compiler. Overloaded operations and generators are also partially +supported. This was made possible by an overhauled JIT tracing frontend +that records actual execution paths through code, rather than estimating +them as the previous implementation did. +(Contributed by Ken Jin in :gh:`139109`. Support for Windows added by +Mark Shannon in :gh:`141703`.) + +.. rubric:: Basic register allocation in the JIT + +A basic form of register allocation has been added to the JIT compiler's +optimizer. This allows the JIT compiler to avoid certain stack operations +altogether and instead operate on registers. This allows the JIT to produce +more efficient traces by avoiding reads and writes to memory. +(Contributed by Mark Shannon in :gh:`135379`.) + +.. rubric:: More JIT optimizations + +More `constant-propagation `__ +is now performed. This means when the JIT compiler detects that certain user +code results in constants, the code can be simplified by the JIT. +(Contributed by Ken Jin and Savannah Ostrowski in :gh:`132732`.) + +:term:`Reference count`\ s are avoided whenever it is safe to do so. This generally +reduces the cost of most operations in Python. +(Contributed by Ken Jin, Donghee Na, Zheao Li, Hai Zhu, Savannah Ostrowski, +Reiden Ong, Noam Cohen, Tomas Roun, PuQing, Cajetan Rodrigues, and Sacul in :gh:`134584`.) + +By tracking unique references to objects, the JIT optimizer can now eliminate +reference count updates and perform inplace operations on ints and floats. +(Contributed by Reiden Ong, and Pieter Eendebak in :gh:`143414` and :gh:`146306`.) + +The JIT optimizer now supports significantly more operations than in 3.14. +(Contributed by Kumar Aditya, Ken Jin, Jiahao Li, and Sacul in :gh:`131798`.) + +.. rubric:: Better machine code generation + +The JIT compiler's machine code generator now produces better machine code +for x86-64 and AArch64 macOS and Linux targets. In general, users should +experience lower memory usage for generated machine code and more efficient +machine code versus 3.14. +(Contributed by Brandt Bucher in :gh:`136528` and :gh:`136528`. +Implementation for AArch64 contributed by Mark Shannon in :gh:`139855`. +Additional optimizations for AArch64 contributed by Mark Shannon and +Diego Russo in :gh:`140683` and :gh:`142305`.) + +.. rubric:: Maintainability + +The JIT optimizer's operations have been simplified. +This was made possible by a refactoring of JIT data structures. +(Contributed by Zhongtian Zheng in :gh:`148211` and Hai Zhu in :gh:`143421`.) + + +Removed +======== + +collections.abc +--------------- + +* :class:`collections.abc.ByteString` has been removed from + ``collections.abc.__all__``. :class:`!collections.abc.ByteString` has been + deprecated since Python 3.12, and is scheduled for removal in Python 3.17. + + +datetime +-------- + +* :meth:`~datetime.datetime.strptime` now raises :exc:`ValueError` when the + format string contains ``%d`` (day of month) without a year directive. + This has been deprecated since Python 3.13. + (Contributed by Stan Ulbrych and Gregory P. Smith in :gh:`70647`.) + + +ctypes +------ + +* Removed the undocumented function :func:`!ctypes.SetPointerType`, + which has been deprecated since Python 3.13. + (Contributed by Bénédikt Tran in :gh:`133866`.) + + +glob +---- + +* Removed the undocumented :func:`!glob.glob0` and :func:`!glob.glob1` + functions, which have been deprecated since Python 3.13. Use + :func:`glob.glob` and pass a directory to its *root_dir* argument instead. + (Contributed by Barney Gale in :gh:`137466`.) + + +http.server +----------- + +* Removed the :class:`!CGIHTTPRequestHandler` class + and the ``--cgi`` flag from the :program:`python -m http.server` + command-line interface. They were deprecated in Python 3.13. + (Contributed by Bénédikt Tran in :gh:`133810`.) + + +importlib.resources +------------------- + +* Removed deprecated ``package`` parameter + from :func:`importlib.resources.files` function. + (Contributed by Semyon Moroz in :gh:`138044`.) + + +pathlib +------- + +* Removed deprecated :meth:`!pathlib.PurePath.is_reserved`. + Use :func:`os.path.isreserved` to detect reserved paths on Windows. + (Contributed by Nikita Sobolev in :gh:`133875`.) + + +platform +-------- + +* Removed the :func:`!platform.java_ver` function, + which was deprecated since Python 3.13. + (Contributed by Alexey Makridenko in :gh:`133604`.) + + +sre_* +----- + +* Removed :mod:`!sre_compile`, :mod:`!sre_constants` and :mod:`!sre_parse` modules. + (Contributed by Stan Ulbrych in :gh:`135994`.) + + +sysconfig +--------- + +* Removed the *check_home* parameter of :func:`sysconfig.is_python_build`. + (Contributed by Filipe Laíns in :gh:`92897`.) + + +threading +--------- + +* Remove support for arbitrary positional or keyword arguments in the C + implementation of :class:`~threading.RLock` objects. This was deprecated + in Python 3.14. + (Contributed by Bénédikt Tran in :gh:`134087`.) + + +typing +------ + +* :class:`typing.ByteString` has been removed from ``typing.__all__``. + :class:`!typing.ByteString` has been deprecated since Python 3.9, and is + scheduled for removal in Python 3.17. + +* The undocumented keyword argument syntax for creating + :class:`~typing.NamedTuple` classes (for example, + ``Point = NamedTuple("Point", x=int, y=int)``) is no longer supported. + Use the class-based syntax or the functional syntax instead. + (Contributed by Bénédikt Tran in :gh:`133817`.) + +* Using ``TD = TypedDict("TD")`` or ``TD = TypedDict("TD", None)`` to + construct a :class:`~typing.TypedDict` type with zero fields is no + longer supported. Use ``class TD(TypedDict): pass`` + or ``TD = TypedDict("TD", {})`` instead. + (Contributed by Bénédikt Tran in :gh:`133823`.) + + +wave +---- + +* Removed the ``getmark()``, ``setmark()`` and ``getmarkers()`` methods + of the :class:`~wave.Wave_read` and :class:`~wave.Wave_write` classes, + which were deprecated since Python 3.13. + (Contributed by Bénédikt Tran in :gh:`133873`.) + + +zipimport +--------- + +* Remove deprecated :meth:`!zipimport.zipimporter.load_module`. + Use :meth:`zipimport.zipimporter.exec_module` instead. + (Contributed by Jiahao Li in :gh:`133656`.) + + +Deprecated +========== + +New deprecations +---------------- + +* :mod:`base64`: + + * Accepting the ``+`` and ``/`` characters with an alternative alphabet in + :func:`~base64.b64decode` and :func:`~base64.urlsafe_b64decode` is now + deprecated. + In future Python versions they will be errors in the strict mode and + discarded in the non-strict mode. + (Contributed by Serhiy Storchaka in :gh:`125346`.) + +* CLI: + + * Deprecate :option:`-b` and :option:`!-bb` command-line options + and schedule them to become no-ops in Python 3.17. + These were primarily helpers for the Python 2 -> 3 transition. + Starting with Python 3.17, no :exc:`BytesWarning` will be raised + for these cases; use a type checker instead. + + (Contributed by Nikita Sobolev in :gh:`136355`.) + +* :mod:`collections.abc` + + * The following statements now cause ``DeprecationWarning``\ s to be emitted + at runtime: + + * ``from collections.abc import ByteString`` + * ``import collections.abc; collections.abc.ByteString``. + + ``DeprecationWarning``\ s were already emitted if + :class:`collections.abc.ByteString` was subclassed or used as the second + argument to :func:`isinstance` or :func:`issubclass`, but warnings were not + previously emitted if it was merely imported or accessed from the + :mod:`!collections.abc` module. + + +* :mod:`hashlib`: + + * In hash function constructors such as :func:`~hashlib.new` or the + direct hash-named constructors such as :func:`~hashlib.md5` and + :func:`~hashlib.sha256`, the optional initial data parameter could + also be passed as a keyword argument named ``data=`` or ``string=`` in + various :mod:`hashlib` implementations. + + Support for the ``string`` keyword argument name is now deprecated and + is slated for removal in Python 3.19. Prefer passing the initial data as + a positional argument for maximum backwards compatibility. + + (Contributed by Bénédikt Tran in :gh:`134978`.) + + +* :mod:`re`: + + * :func:`re.match` and :meth:`re.Pattern.match` are now + :term:`soft deprecated` in favor of the new :func:`re.prefixmatch` and + :meth:`re.Pattern.prefixmatch` APIs, which have been added as alternate, + more explicit names. These are intended to be used to alleviate confusion + around what *match* means by following the Zen of Python's *"Explicit is + better than implicit"* mantra. Most other language regular expression + libraries use an API named *match* to mean what Python has always called + *search*. + + We **do not** plan to remove the older :func:`!match` name, as it has been + used in code for over 30 years. Code supporting older versions of Python + should continue to use :func:`!match`, while new code should prefer + :func:`!prefixmatch`. See :ref:`prefixmatch-vs-match`. + + (Contributed by Gregory P. Smith in :gh:`86519` and + Hugo van Kemenade in :gh:`148100`.) + + +* :mod:`struct`: + + * Calling the ``Struct.__new__()`` without required argument now is + deprecated and will be removed in Python 3.20. Calling + :meth:`~object.__init__` method on initialized :class:`~struct.Struct` + objects is deprecated and will be removed in Python 3.20. + + (Contributed by Sergey B Kirpichev and Serhiy Storchaka in :gh:`143715`.) + +* :mod:`typing`: + + * The following statements now cause ``DeprecationWarning``\ s to be emitted + at runtime: + + * ``from typing import ByteString`` + * ``import typing; typing.ByteString``. + + ``DeprecationWarning``\ s were already emitted if :class:`typing.ByteString` + was subclassed or used as the second argument to :func:`isinstance` or + :func:`issubclass`, but warnings were not previously emitted if it was + merely imported or accessed from the :mod:`!typing` module. + + * Deprecated :func:`!typing.no_type_check_decorator` has been removed. + (Contributed by Nikita Sobolev in :gh:`133601`.) + +* ``__version__`` + + * The ``__version__``, ``version`` and ``VERSION`` attributes have been + deprecated in these standard library modules and will be removed in + Python 3.20. Use :py:data:`sys.version_info` instead. + + - :mod:`argparse` + - :mod:`csv` + - :mod:`ctypes` + - :mod:`!ctypes.macholib` + - :mod:`decimal` (use :data:`decimal.SPEC_VERSION` instead) + - :mod:`http.server` + - :mod:`imaplib` + - :mod:`ipaddress` + - :mod:`json` + - :mod:`logging` (``__date__`` also deprecated) + - :mod:`optparse` + - :mod:`pickle` + - :mod:`platform` + - :mod:`re` + - :mod:`socketserver` + - :mod:`tabnanny` + - :mod:`tarfile` + - :mod:`tkinter.font` + - :mod:`tkinter.ttk` + - :mod:`wsgiref.simple_server` + - :mod:`xml.etree.ElementTree` + - :mod:`!xml.sax.expatreader` + - :mod:`xml.sax.handler` + - :mod:`zlib` + + (Contributed by Hugo van Kemenade and Stan Ulbrych in :gh:`76007`.) + +.. Add deprecations above alphabetically, not here at the end. + +.. include:: ../deprecations/pending-removal-in-3.16.rst + +.. include:: ../deprecations/pending-removal-in-3.17.rst + +.. include:: ../deprecations/pending-removal-in-3.18.rst + +.. include:: ../deprecations/pending-removal-in-3.19.rst + +.. include:: ../deprecations/pending-removal-in-3.20.rst + +.. include:: ../deprecations/pending-removal-in-future.rst + +.. include:: ../deprecations/soft-deprecations.rst + + +C API changes +============= + +New features +------------ + +* Add :c:func:`PyArg_ParseArray` and :c:func:`PyArg_ParseArrayAndKeywords` + functions to parse arguments of functions using the :c:macro:`METH_FASTCALL` + calling convention. + (Contributed by Victor Stinner in :gh:`144175`.) + +* Add the following functions for the new :class:`frozendict` type: + + * :c:func:`PyAnyDict_Check` + * :c:func:`PyAnyDict_CheckExact` + * :c:func:`PyFrozenDict_Check` + * :c:func:`PyFrozenDict_CheckExact` + * :c:func:`PyFrozenDict_New` + + (Contributed by Victor Stinner in :gh:`141510`.) + +* Add :c:func:`PySys_GetAttr`, :c:func:`PySys_GetAttrString`, + :c:func:`PySys_GetOptionalAttr`, and :c:func:`PySys_GetOptionalAttrString` + functions as replacements for :c:func:`PySys_GetObject`. + (Contributed by Serhiy Storchaka in :gh:`108512`.) + +* Add :c:type:`PyUnstable_Unicode_GET_CACHED_HASH` to get the cached hash of + a string. See the documentation for caveats. + (Contributed by Petr Viktorin in :gh:`131510`.) + +* Add API for checking an extension module's ABI compatibility: + :c:data:`Py_mod_abi`, :c:func:`PyABIInfo_Check`, :c:macro:`PyABIInfo_VAR` + and :c:data:`Py_mod_abi`. + (Contributed by Petr Viktorin in :gh:`137210`.) + +.. _whatsnew315-pybyteswriter: + +* Implement :pep:`782`, the :ref:`PyBytesWriter API `. + Add functions: + + * :c:func:`PyBytesWriter_Create` + * :c:func:`PyBytesWriter_Discard` + * :c:func:`PyBytesWriter_FinishWithPointer` + * :c:func:`PyBytesWriter_FinishWithSize` + * :c:func:`PyBytesWriter_Finish` + * :c:func:`PyBytesWriter_Format` + * :c:func:`PyBytesWriter_GetData` + * :c:func:`PyBytesWriter_GetSize` + * :c:func:`PyBytesWriter_GrowAndUpdatePointer` + * :c:func:`PyBytesWriter_Grow` + * :c:func:`PyBytesWriter_Resize` + * :c:func:`PyBytesWriter_WriteBytes` + + (Contributed by Victor Stinner in :gh:`129813`.) + +* Add a new :c:func:`PyImport_CreateModuleFromInitfunc` C-API for creating + a module from a *spec* and *initfunc*. + (Contributed by Itamar Oren in :gh:`116146`.) + +* Add :c:func:`PyTuple_FromArray` to create a :class:`tuple` from an array. + (Contributed by Victor Stinner in :gh:`111489`.) + +* Add functions that are guaranteed to be safe for use in + :c:member:`~PyTypeObject.tp_traverse` handlers: + :c:func:`PyObject_GetTypeData_DuringGC`, + :c:func:`PyObject_GetItemData_DuringGC`, + :c:func:`PyType_GetModuleState_DuringGC`, + :c:func:`PyModule_GetState_DuringGC`, :c:func:`PyModule_GetToken_DuringGC`, + :c:func:`PyType_GetBaseByToken_DuringGC`, + :c:func:`PyType_GetModule_DuringGC`, + :c:func:`PyType_GetModuleByToken_DuringGC`. + (Contributed by Petr Viktorin in :gh:`145925`.) + +* Add :c:func:`PyObject_Dump` to dump an object to ``stderr``. + It should only be used for debugging. + (Contributed by Victor Stinner in :gh:`141070`.) + +* Add :c:func:`PyUnstable_ThreadState_SetStackProtection` and + :c:func:`PyUnstable_ThreadState_ResetStackProtection` functions to set + the stack protection base address and stack protection size of a Python + thread state. + (Contributed by Victor Stinner in :gh:`139653`.) + +* Add :c:func:`PyUnstable_SetImmortal` C-API function to mark objects as :term:`immortal`. + (Contributed by Kumar Aditya in :gh:`143300`.) + +* Restore private provisional ``_Py_InitializeMain()`` function removed in + Python 3.14. + (Contributed by Victor Stinner in :gh:`142417`.) + +Changed C APIs +-------------- + +* If the :c:macro:`Py_TPFLAGS_MANAGED_DICT` or :c:macro:`Py_TPFLAGS_MANAGED_WEAKREF` + flag is set then :c:macro:`Py_TPFLAGS_HAVE_GC` must be set too. + (Contributed by Sergey Miryanov in :gh:`134786`.) + +* :c:macro:`PyDateTime_IMPORT` is now thread safe. Code that directly checks ``PyDateTimeAPI`` + for ``NULL`` should be updated to call :c:macro:`PyDateTime_IMPORT` instead. + (Contributed by Kumar Aditya in :gh:`141563`.) + +Porting to Python 3.15 +---------------------- + +* Private functions promoted to public C APIs: + + The |pythoncapi_compat_project| can be used to get most of these new + functions on Python 3.14 and older. + + +Removed C APIs +-------------- + +* Remove deprecated ``PyUnicode`` functions: + + * :c:func:`!PyUnicode_AsDecodedObject`: + Use :c:func:`PyCodec_Decode` instead. + * :c:func:`!PyUnicode_AsDecodedUnicode`: + Use :c:func:`PyCodec_Decode` instead; Note that some codecs (for example, "base64") + may return a type other than :class:`str`, such as :class:`bytes`. + * :c:func:`!PyUnicode_AsEncodedObject`: + Use :c:func:`PyCodec_Encode` instead. + * :c:func:`!PyUnicode_AsEncodedUnicode`: + Use :c:func:`PyCodec_Encode` instead; Note that some codecs (for example, "base64") + may return a type other than :class:`bytes`, such as :class:`str`. + + (Contributed by Stan Ulbrych in :gh:`133612`.) + +* :c:func:`!PyImport_ImportModuleNoBlock`: deprecated alias + of :c:func:`PyImport_ImportModule`. + (Contributed by Bénédikt Tran in :gh:`133644`.) + +* :c:func:`!PyWeakref_GetObject` and :c:macro:`!PyWeakref_GET_OBJECT`: + use :c:func:`PyWeakref_GetRef` instead. The |pythoncapi_compat_project| + can be used to get :c:func:`!PyWeakref_GetRef` on Python 3.12 and older. + (Contributed by Bénédikt Tran in :gh:`133644`.) + +* Remove deprecated :c:func:`!PySys_ResetWarnOptions`. + Clear :data:`sys.warnoptions` and :data:`!warnings.filters` instead. + + (Contributed by Nikita Sobolev in :gh:`138886`.) + +The following functions are removed in favor of :c:func:`PyConfig_Get`. +The |pythoncapi_compat_project| can be used to get :c:func:`!PyConfig_Get` +on Python 3.13 and older. + +* Python initialization functions: + + * :c:func:`!Py_GetExecPrefix`: + use :c:func:`PyConfig_Get("base_exec_prefix") ` + (:data:`sys.base_exec_prefix`) instead. + Use :c:func:`PyConfig_Get("exec_prefix") ` + (:data:`sys.exec_prefix`) if :ref:`virtual environments ` + need to be handled. + * :c:func:`!Py_GetPath`: + use :c:func:`PyConfig_Get("module_search_paths") ` + (:data:`sys.path`) instead. + * :c:func:`!Py_GetPrefix`: + use :c:func:`PyConfig_Get("base_prefix") ` + (:data:`sys.base_prefix`) instead. + Use :c:func:`PyConfig_Get("prefix") ` + (:data:`sys.prefix`) if :ref:`virtual environments ` + need to be handled. + * :c:func:`!Py_GetProgramFullPath`: + use :c:func:`PyConfig_Get("executable") ` + (:data:`sys.executable`) instead. + * :c:func:`!Py_GetProgramName`: + use :c:func:`PyConfig_Get("executable") ` + (:data:`sys.executable`) instead. + * :c:func:`!Py_GetPythonHome`: + use :c:func:`PyConfig_Get("home") ` or the + :envvar:`PYTHONHOME` environment variable instead. + + (Contributed by Bénédikt Tran in :gh:`133644`.) + +.. |pythoncapi_compat_project| replace:: |pythoncapi_compat_project_link|_ +.. |pythoncapi_compat_project_link| replace:: pythoncapi-compat project +.. _pythoncapi_compat_project_link: https://github.com/python/pythoncapi-compat + + +Deprecated C APIs +----------------- + +* Deprecate :pep:`456` support for providing an external definition + of the string hashing scheme. Removal is scheduled for Python 3.19. + + Previously, embedders could define :c:macro:`Py_HASH_ALGORITHM` to be + ``Py_HASH_EXTERNAL`` to indicate that the hashing scheme was provided + externally but this feature was undocumented, untested and most likely + unused. + + (Contributed by Bénédikt Tran in :gh:`141226`.) + +* For unsigned integer formats in :c:func:`PyArg_ParseTuple`, + accepting Python integers with value that is larger than the maximal value + for the C type or less than the minimal value for the corresponding + signed integer type of the same size is now deprecated. + (Contributed by Serhiy Storchaka in :gh:`132629`.) + +* :c:func:`PyBytes_FromStringAndSize(NULL, len) ` + and :c:func:`_PyBytes_Resize` are :term:`soft deprecated`, + use the :c:type:`PyBytesWriter` API instead. + (Contributed by Victor Stinner in :gh:`129813`.) + +* :c:func:`!_PyObject_CallMethodId`, :c:func:`!_PyObject_GetAttrId` and + :c:func:`!_PyUnicode_FromId` are deprecated since 3.15 and will be removed in + 3.20. Instead, use :c:func:`PyUnicode_InternFromString()` and cache the result in + the module state, then call :c:func:`PyObject_CallMethod` or + :c:func:`PyObject_GetAttr`. + (Contributed by Victor Stinner in :gh:`141049`.) + +* Deprecate :c:member:`~PyComplexObject.cval` field of the + :c:type:`PyComplexObject` type. + Use :c:func:`PyComplex_AsCComplex` and :c:func:`PyComplex_FromCComplex` + to convert a Python complex number to/from the C :c:type:`Py_complex` + representation. + (Contributed by Sergey B Kirpichev in :gh:`128813`.) + +* Functions :c:func:`_Py_c_sum`, :c:func:`_Py_c_diff`, :c:func:`_Py_c_neg`, + :c:func:`_Py_c_prod`, :c:func:`_Py_c_quot`, :c:func:`_Py_c_pow` and + :c:func:`_Py_c_abs` are :term:`soft deprecated`. + (Contributed by Sergey B Kirpichev in :gh:`128813`.) + +* :c:member:`~PyConfig.bytes_warning` is deprecated + since 3.15 and will be removed in 3.17. + (Contributed by Nikita Sobolev in :gh:`136355`.) + +* :c:macro:`!Py_INFINITY` macro is :term:`soft deprecated`, + use the C11 standard ```` :c:macro:`!INFINITY` instead. + (Contributed by Sergey B Kirpichev in :gh:`141004`.) + +* The following macros are :term:`soft deprecated`: + + - :c:macro:`Py_ALIGNED`: Prefer ``alignas`` instead. + - :c:macro:`PY_FORMAT_SIZE_T`: Use ``"z"`` directly. + - :c:macro:`Py_LL` & :c:macro:`Py_ULL`: + Use standard suffixes, ``LL`` & ``ULL``. + - :c:macro:`PY_LONG_LONG`, :c:macro:`PY_LLONG_MIN`, :c:macro:`PY_LLONG_MAX`, + :c:macro:`PY_ULLONG_MAX`, :c:macro:`PY_INT32_T`, :c:macro:`PY_UINT32_T`, + :c:macro:`PY_INT64_T`, :c:macro:`PY_UINT64_T`, :c:macro:`PY_SIZE_MAX`: + Use C99 types/limits. + - :c:macro:`Py_UNICODE_SIZE`: Use ``sizeof(wchar_t)`` directly. + - :c:macro:`Py_VA_COPY`: Use ``va_copy`` directly. + + The macro :c:macro:`Py_UNICODE_WIDE`, which was scheduled for removal, + is :term:`soft deprecated` instead. + + (Contributed by Petr Viktorin in :gh:`146175`.) + +* :c:macro:`!Py_MATH_El` and :c:macro:`!Py_MATH_PIl` are deprecated + since 3.15 and will be removed in 3.20. + (Contributed by Sergey B Kirpichev in :gh:`141004`.) + + +.. Add C API deprecations above alphabetically, not here at the end. + + +Build changes +============= + +* Removed implicit fallback to the bundled copy of the ``libmpdec`` library. + Now this should be explicitly enabled with :option:`--with-system-libmpdec` + set to ``no`` or with :option:`!--without-system-libmpdec`. + (Contributed by Sergey B Kirpichev in :gh:`115119`.) + +* The new configure option :option:`--with-missing-stdlib-config=FILE` allows + distributors to pass a `JSON `_ + configuration file containing custom error messages for :term:`standard library` + modules that are missing or packaged separately. + (Contributed by Stan Ulbrych and Petr Viktorin in :gh:`139707`.) + +* The new configure option :option:`--with-pymalloc-hugepages` enables huge + page support for :ref:`pymalloc ` arenas. When enabled, arena size + increases to 2 MiB and allocation uses ``MAP_HUGETLB`` (Linux) or + ``MEM_LARGE_PAGES`` (Windows) with automatic fallback to regular pages. + On Windows, use ``build.bat --pymalloc-hugepages``. + At runtime, huge pages must be explicitly enabled by setting the + :envvar:`PYTHON_PYMALLOC_HUGEPAGES` environment variable to ``1``. + +* Annotating anonymous mmap usage is now supported if Linux kernel supports + :manpage:`PR_SET_VMA_ANON_NAME ` (Linux 5.17 or newer). + Annotations are visible in ``/proc//maps`` if the kernel supports the feature + and :option:`-X dev <-X>` is passed to the Python or Python is built in :ref:`debug mode `. + (Contributed by Donghee Na in :gh:`141770`.) + +.. _whatsnew315-windows-tail-calling-interpreter: + +* 64-bit builds using Visual Studio 2026 (MSVC 18) may now use the new + :ref:`tail-calling interpreter `. + Results on Visual Studio 18.1.1 report between + `15-20% `__ + speedup on the geometric mean of pyperformance on Windows x86-64 over + the switch-case interpreter on an AMD Ryzen 7 5800X. We have + observed speedups ranging from 14% for large pure-Python libraries + to 40% for long-running small pure-Python scripts on Windows. + This was made possible by a new feature introduced in MSVC 18, + which the official Windows 64-bit binaries on python.org__ now use. + (Contributed by Chris Eibl, Ken Jin, and Brandt Bucher in :gh:`143068`. + Special thanks to Steve Dower, and the MSVC team including Hulon Jenkins.) + + __ https://www.python.org/downloads/windows/ + + +Porting to Python 3.15 +====================== + +This section lists previously described changes and other bugfixes +that may require changes to your code. + +* :class:`sqlite3.Connection` APIs have been cleaned up. + + * All parameters of :func:`sqlite3.connect` except *database* are now keyword-only. + * The first three parameters of methods :meth:`~sqlite3.Connection.create_function` + and :meth:`~sqlite3.Connection.create_aggregate` are now positional-only. + * The first parameter of methods :meth:`~sqlite3.Connection.set_authorizer`, + :meth:`~sqlite3.Connection.set_progress_handler` and + :meth:`~sqlite3.Connection.set_trace_callback` is now positional-only. + + (Contributed by Serhiy Storchaka in :gh:`133595`.) + +* :data:`resource.RLIM_INFINITY` is now always positive. + Passing a negative integer value that corresponded to its old value + (such as ``-1`` or ``-3``, depending on platform) to + :func:`resource.setrlimit` and :func:`resource.prlimit` is now deprecated. + (Contributed by Serhiy Storchaka in :gh:`137044`.) + +* :meth:`mmap.mmap.resize` has been removed on platforms that don't support the + underlying syscall, instead of raising a :exc:`SystemError`. + +* A resource warning is now emitted for an unclosed + :func:`xml.etree.ElementTree.iterparse` iterator if it opened a file. + Use its :meth:`!close` method or the :func:`contextlib.closing` context + manager to close it. + (Contributed by Osama Abdelkader and Serhiy Storchaka in :gh:`140601`.) + +* If a short option and a single-dash long option are passed to + :meth:`argparse.ArgumentParser.add_argument`, *dest* is now inferred from + the single-dash long option. For example, in ``add_argument('-f', '-foo')``, + *dest* is now ``'foo'`` instead of ``'f'``. + Pass an explicit *dest* argument to preserve the old behavior. + (Contributed by Serhiy Storchaka in :gh:`138697`.) + +* Padding of input no longer required in :func:`base64.urlsafe_b64decode`. + Pass a new argument ``padded=True`` or use :func:`base64.b64decode` + with argument ``altchars=b'-_'`` (this works with older Python versions) + to make padding required. + (Contributed by Serhiy Storchaka in :gh:`73613`.)