diff --git a/Doc/Makefile b/Doc/Makefile index 8020884447983c..09fcd0d8291daf 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -217,7 +217,7 @@ dist: # as otherwise the full latexmk process is run twice. # ($$ is needed to escape the $; https://www.gnu.org/software/make/manual/make.html#Basics-of-Variable-References) -sed -i 's/: all-$$(FMT)/:/' build/latex/Makefile - (cd build/latex; $(MAKE) clean && $(MAKE) --jobs=$((`nproc`+1)) --output-sync LATEXMKOPTS='-quiet' all-pdf && $(MAKE) FMT=pdf zip bz2) + (cd build/latex; $(MAKE) clean && $(MAKE) --jobs=$$((`nproc`+1)) --output-sync LATEXMKOPTS='-quiet' all-pdf && $(MAKE) FMT=pdf zip bz2) cp build/latex/docs-pdf.zip dist/python-$(DISTVERSION)-docs-pdf-a4.zip cp build/latex/docs-pdf.tar.bz2 dist/python-$(DISTVERSION)-docs-pdf-a4.tar.bz2 @echo "Build finished and archived!" @@ -227,7 +227,7 @@ dist: rm -rf build/latex $(MAKE) latex PAPER=letter -sed -i 's/: all-$$(FMT)/:/' build/latex/Makefile - (cd build/latex; $(MAKE) clean && $(MAKE) --jobs=$((`nproc`+1)) --output-sync LATEXMKOPTS='-quiet' all-pdf && $(MAKE) FMT=pdf zip bz2) + (cd build/latex; $(MAKE) clean && $(MAKE) --jobs=$$((`nproc`+1)) --output-sync LATEXMKOPTS='-quiet' all-pdf && $(MAKE) FMT=pdf zip bz2) cp build/latex/docs-pdf.zip dist/python-$(DISTVERSION)-docs-pdf-letter.zip cp build/latex/docs-pdf.tar.bz2 dist/python-$(DISTVERSION)-docs-pdf-letter.tar.bz2 @echo "Build finished and archived!" diff --git a/Doc/library/os.rst b/Doc/library/os.rst index b0ff81141db77d..4793717d0e5c87 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -3892,6 +3892,8 @@ features: .. versionadded:: 3.10 +.. _os-timerfd: + Timer File Descriptors ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index c5e11458733508..476ae39e453b87 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -138,13 +138,13 @@ Significant improvements in the standard library: * The :mod:`argparse` module now supports deprecating command-line options, positional arguments, and subcommands. * The new functions :func:`base64.z85encode` and :func:`base64.z85decode` - support encoding and decoding `Z85 data `_. + support encoding and decoding `Z85 data`_. * The :mod:`copy` module now has a :func:`copy.replace` function, with support for many builtin types and any class defining the :func:`~object.__replace__` method. * The :mod:`dbm.sqlite3` module is now the default :mod:`dbm` backend. -* The :mod:`os` module has a suite of new functions for working with Linux's - timer notification file descriptors. +* The :mod:`os` module has a :ref:`suite of new functions ` + for working with Linux's timer notification file descriptors. * The :mod:`random` module now has a :ref:`command-line interface `. Security improvements: @@ -190,7 +190,7 @@ Important removals: * Remove the :program:`2to3` tool and :mod:`!lib2to3` module (deprecated in Python 3.11). * Remove the :mod:`!tkinter.tix` module (deprecated in Python 3.6). -* Remove :func:`!locale.resetlocale()`. +* Remove :func:`!locale.resetlocale`. * Remove :mod:`!typing.io` and :mod:`!typing.re`. * Remove chained :class:`classmethod` descriptors. @@ -535,7 +535,7 @@ Other Language Changes * :ref:`Future statements ` are no longer triggered by relative imports of the :mod:`__future__` module, - meaning that statements of the form ``from .__future__ import ...`` + meaning that statements of the form ``from .__future__ import ...`` are now simply standard relative imports, with no special features activated. (Contributed by Jeremiah Gabriel Pascual in :gh:`118216`.) @@ -616,129 +616,140 @@ New Modules Improved Modules ================ + argparse -------- -* Add parameter *deprecated* in methods - :meth:`~argparse.ArgumentParser.add_argument` and :meth:`!add_parser` - which allows to deprecate command-line options, positional arguments and - subcommands. +* Add the *deprecated* parameter to the + :meth:`~argparse.ArgumentParser.add_argument` + and :meth:`!add_parser` methods, to enable deprecating + command-line options, positional arguments, and subcommands. (Contributed by Serhiy Storchaka in :gh:`83648`.) + array ----- -* Add ``'w'`` type code (``Py_UCS4``) that can be used for Unicode strings. - It can be used instead of ``'u'`` type code, which is deprecated. +* Add the ``'w'`` type code (``Py_UCS4``) for Unicode characters. + It should be used instead of the deprecated ``'u'`` type code. (Contributed by Inada Naoki in :gh:`80480`.) -* Add ``clear()`` method in order to implement :class:`~collections.abc.MutableSequence`. +* Register :class:`array.array` as a :class:`~collections.abc.MutableSequence` + by implementing the :meth:`~array.array.clear` method. (Contributed by Mike Zimin in :gh:`114894`.) + ast --- -* The constructors of node types in the :mod:`ast` module are now stricter - in the arguments they accept, and have more intuitive behaviour when - arguments are omitted. +* The constructors of node types in the :mod:`ast` module are now + stricter in the arguments they accept, + with more intuitive behaviour when arguments are omitted. If an optional field on an AST node is not included as an argument when constructing an instance, the field will now be set to ``None``. Similarly, if a list field is omitted, that field will now be set to an empty list, - and if a :class:`!ast.expr_context` field is omitted, it defaults to + and if an :class:`!expr_context` field is omitted, it defaults to :class:`Load() `. (Previously, in all cases, the attribute would be missing on the newly constructed AST node instance.) - If other arguments are omitted, a :exc:`DeprecationWarning` is emitted. - This will cause an exception in Python 3.15. Similarly, passing a keyword - argument that does not map to a field on the AST node is now deprecated, + In all other cases, where a required argument is omitted, + the node constructor will emit a :exc:`DeprecationWarning`. + This will raise an exception in Python 3.15. + Similarly, passing a keyword argument to the constructor + that does not map to a field on the AST node is now deprecated, and will raise an exception in Python 3.15. - These changes do not apply to user-defined subclasses of :class:`ast.AST`, - unless the class opts in to the new behavior by setting the attribute - :attr:`ast.AST._field_types`. + These changes do not apply to user-defined subclasses of :class:`ast.AST` + unless the class opts in to the new behavior + by defining the :attr:`.AST._field_types` mapping. (Contributed by Jelle Zijlstra in :gh:`105858`, :gh:`117486`, and :gh:`118851`.) * :func:`ast.parse` now accepts an optional argument *optimize* - which is passed on to the :func:`compile` built-in. This makes it - possible to obtain an optimized AST. + which is passed on to :func:`compile`. + This makes it possible to obtain an optimized AST. (Contributed by Irit Katriel in :gh:`108113`.) + asyncio ------- +* :func:`asyncio.as_completed` now returns an object that is both an + :term:`asynchronous iterator` and a plain :term:`iterator` + of :term:`awaitables `. + The awaitables yielded by asynchronous iteration include original task + or future objects that were passed in, + making it easier to associate results with the tasks being completed. + (Contributed by Justin Arthur in :gh:`77714`.) + * :meth:`asyncio.loop.create_unix_server` will now automatically remove the Unix socket when the server is closed. (Contributed by Pierre Ossman in :gh:`111246`.) -* :meth:`asyncio.DatagramTransport.sendto` will now send zero-length - datagrams if called with an empty bytes object. The transport flow - control also now accounts for the datagram header when calculating - the buffer size. +* :meth:`.DatagramTransport.sendto` will now send zero-length + datagrams if called with an empty bytes object. + The transport flow control also now accounts for the datagram header + when calculating the buffer size. (Contributed by Jamie Phan in :gh:`115199`.) -* Add :meth:`asyncio.Server.close_clients` and - :meth:`asyncio.Server.abort_clients` methods which allow to more - forcefully close an asyncio server. - (Contributed by Pierre Ossman in :gh:`113538`.) +* Add :meth:`Queue.shutdown ` + and :exc:`~asyncio.QueueShutDown` to manage queue termination. + (Contributed by Laurie Opperman and Yves Duprat in :gh:`104228`.) -* :func:`asyncio.as_completed` now returns an object that is both an - :term:`asynchronous iterator` and a plain :term:`iterator` of awaitables. - The awaitables yielded by asynchronous iteration include original task or - future objects that were passed in, making it easier to associate results - with the tasks being completed. - (Contributed by Justin Arthur in :gh:`77714`.) +* Add the :meth:`.Server.close_clients` and :meth:`.Server.abort_clients` + methods, which more forcefully close an asyncio server. + (Contributed by Pierre Ossman in :gh:`113538`.) -* When :func:`asyncio.TaskGroup.create_task` is called on an inactive - :class:`asyncio.TaskGroup`, the given coroutine will be closed (which - prevents a :exc:`RuntimeWarning` about the given coroutine being - never awaited). - (Contributed by Arthur Tacca and Jason Zhang in :gh:`115957`.) +* Accept a tuple of separators in :meth:`.StreamReader.readuntil`, + stopping when any one of them is encountered. + (Contributed by Bruce Merry in :gh:`81322`.) -* Improved behavior of :class:`asyncio.TaskGroup` when an external cancellation - collides with an internal cancellation. For example, when two task groups - are nested and both experience an exception in a child task simultaneously, - it was possible that the outer task group would hang, because its internal - cancellation was swallowed by the inner task group. +* Improve the behavior of :class:`~asyncio.TaskGroup` when + an external cancellation collides with an internal cancellation. + For example, when two task groups are nested + and both experience an exception in a child task simultaneously, + it was possible that the outer task group would hang, + because its internal cancellation was swallowed by the inner task group. - In the case where a task group is cancelled externally and also must - raise an :exc:`ExceptionGroup`, it will now call the parent task's - :meth:`~asyncio.Task.cancel` method. This ensures that a - :exc:`asyncio.CancelledError` will be raised at the next - :keyword:`await`, so the cancellation is not lost. + In the case where a task group is cancelled externally + and also must raise an :exc:`ExceptionGroup`, + it will now call the parent task's :meth:`~asyncio.Task.cancel` method. + This ensures that a :exc:`~asyncio.CancelledError` will be raised + at the next :keyword:`await`, so the cancellation is not lost. - An added benefit of these changes is that task groups now preserve the - cancellation count (:meth:`asyncio.Task.cancelling`). + An added benefit of these changes is that task groups now preserve + the cancellation count (:meth:`~asyncio.Task.cancelling`). - In order to handle some corner cases, :meth:`asyncio.Task.uncancel` may now - reset the undocumented ``_must_cancel`` flag when the cancellation count - reaches zero. + In order to handle some corner cases, :meth:`~asyncio.Task.uncancel` may now + reset the undocumented ``_must_cancel`` flag + when the cancellation count reaches zero. (Inspired by an issue reported by Arthur Tacca in :gh:`116720`.) -* Add :meth:`asyncio.Queue.shutdown` (along with - :exc:`asyncio.QueueShutDown`) for queue termination. - (Contributed by Laurie Opperman and Yves Duprat in :gh:`104228`.) +* When :meth:`.TaskGroup.create_task` is called on an inactive + :class:`~asyncio.TaskGroup`, the given coroutine will be closed (which + prevents a :exc:`RuntimeWarning` about the given coroutine being + never awaited). + (Contributed by Arthur Tacca and Jason Zhang in :gh:`115957`.) -* Accept a tuple of separators in :meth:`asyncio.StreamReader.readuntil`, - stopping when one of them is encountered. - (Contributed by Bruce Merry in :gh:`81322`.) base64 ------ -* Add :func:`base64.z85encode` and :func:`base64.z85decode` functions which allow encoding - and decoding Z85 data. - See the `Z85 specification `_ for more information. +* Add :func:`~base64.z85encode` and :func:`~base64.z85decode` functions + for encoding :class:`bytes` as `Z85 data`_ + and decoding Z85-encoded data to :class:`!bytes`. (Contributed by Matan Perelman in :gh:`75299`.) + .. _Z85 data: https://rfc.zeromq.org/spec/32/ + compileall ---------- -* Select the default number of worker threads and processes using +* The default number of worker threads and processes is now selected using :func:`os.process_cpu_count` instead of :func:`os.cpu_count`. (Contributed by Victor Stinner in :gh:`109649`.) @@ -746,82 +757,107 @@ compileall concurrent.futures ------------------ -* Select the default number of worker threads and processes using +* The default number of worker threads and processes is now selected using :func:`os.process_cpu_count` instead of :func:`os.cpu_count`. (Contributed by Victor Stinner in :gh:`109649`.) +configparser +------------ + +* :class:`~configparser.ConfigParser` now has support for unnamed sections, + which allows for top-level key-value pairs. + This can be enabled with the new *allow_unnamed_section* parameter. + (Contributed by Pedro Sousa Lacerda in :gh:`66449`.) + + copy ---- -* Add :func:`copy.replace` function which allows to create a modified copy of - an object, which is especially useful for immutable objects. - It supports named tuples created with the factory function - :func:`collections.namedtuple`, :class:`~dataclasses.dataclass` instances, - various :mod:`datetime` objects, :class:`~inspect.Signature` objects, - :class:`~inspect.Parameter` objects, :ref:`code object `, and - any user classes which define the :meth:`!__replace__` method. +* The new :func:`~copy.replace` function and the :meth:`replace protocol + ` make creating modified copies of objects much simpler. + This is especially useful when working with immutable objects. + The following types support the :func:`~copy.replace` function + and implement the replace protocol: + + * :func:`collections.namedtuple` + * :class:`dataclasses.dataclass` + * :class:`datetime.datetime`, :class:`datetime.date`, :class:`datetime.time` + * :class:`inspect.Signature`, :class:`inspect.Parameter` + * :class:`types.SimpleNamespace` + * :ref:`code objects ` + + Any user-defined class can also support :func:`copy.replace` by defining + the :meth:`~object.__replace__` method. (Contributed by Serhiy Storchaka in :gh:`108751`.) + ctypes ------ -* The layout of :ref:`bit fields ` in - :class:`~ctypes.Structure` and :class:`~ctypes.Union` was improved to better - match platform defaults (GCC/Clang or MSC). In particular, fields no longer - overlap. +* The layout of :ref:`bit fields ` + in :class:`~ctypes.Structure` and :class:`~ctypes.Union` + now matches platform defaults (GCC/Clang or MVSC) more closely. + In particular, fields no longer overlap. (Contributed by Matthias Görgens in :gh:`97702`.) -* A :attr:`ctypes.Structure._layout_` class attribute can be set + +* The :attr:`.Structure._layout_` class attribute can now be set to help match a non-default ABI. (Contributed by Petr Viktorin in :gh:`97702`.) + dbm --- -* Add :meth:`dbm.gnu.gdbm.clear` and :meth:`dbm.ndbm.ndbm.clear` methods that remove all items - from the database. +* Add :mod:`dbm.sqlite3`, a new module which implements an SQLite backend, + and make it the default :mod:`!dbm` backend. + (Contributed by Raymond Hettinger and Erlend E. Aasland in :gh:`100414`.) + +* Allow removing all items from the database through + the new :meth:`.gdbm.clear` and :meth:`.ndbm.clear` methods. (Contributed by Donghee Na in :gh:`107122`.) -* Add new :mod:`dbm.sqlite3` backend, and make it the default :mod:`!dbm` backend. - (Contributed by Raymond Hettinger and Erlend E. Aasland in :gh:`100414`.) dis --- * Change the output of :mod:`dis` module functions to show logical labels for jump targets and exception handlers, rather than offsets. - The offsets can be added with the new ``-O`` command line option or - the ``show_offsets`` parameter. + The offsets can be added with the new + :option:`-O ` command-line option + or the *show_offsets* argument. (Contributed by Irit Katriel in :gh:`112137`.) -* :meth:`~dis.get_instructions` no longer represents cache entries as - separate instructions. Instead, it returns them as part of the - :class:`~dis.Instruction`, in the new *cache_info* field. The - *show_caches* argument to :meth:`~dis.get_instructions` is - deprecated and no longer has any effect. +* :meth:`~dis.get_instructions` no longer represents cache entries + as separate instructions. + Instead, it returns them as part of the :class:`~dis.Instruction`, + in the new *cache_info* field. + The *show_caches* argument to :meth:`~dis.get_instructions` is deprecated + and no longer has any effect. (Contributed by Irit Katriel in :gh:`112962`.) + .. _whatsnew313-doctest: doctest ------- -* Color is added to the output by default. +* :mod:`doctest` output is now colored by default. This can be controlled via the new :envvar:`PYTHON_COLORS` environment - variable as well as the canonical |NO_COLOR|_ and |FORCE_COLOR|_ environment - variables. See also :ref:`using-on-controlling-color`. + variable as well as the canonical |NO_COLOR|_ + and |FORCE_COLOR|_ environment variables. + See also :ref:`using-on-controlling-color`. (Contributed by Hugo van Kemenade in :gh:`117225`.) -* The :meth:`doctest.DocTestRunner.run` method now counts the number of skipped - tests. Add :attr:`doctest.DocTestRunner.skips` and - :attr:`doctest.TestResults.skipped` attributes. +* The :meth:`.DocTestRunner.run` method now counts the number of skipped tests. + Add the :attr:`.DocTestRunner.skips` and :attr:`.TestResults.skipped` attributes. (Contributed by Victor Stinner in :gh:`108794`.) + email ----- * Headers with embedded newlines are now quoted on output. - The :mod:`~email.generator` will now refuse to serialize (write) headers that are improperly folded or delimited, such that they would be parsed as multiple headers or joined with adjacent data. @@ -829,323 +865,353 @@ email set :attr:`~email.policy.Policy.verify_generated_headers`. (Contributed by Bas Bloemsaat and Petr Viktorin in :gh:`121650`.) -* :func:`email.utils.getaddresses` and :func:`email.utils.parseaddr` now return - ``('', '')`` 2-tuples in more situations where invalid email addresses are - encountered instead of potentially inaccurate values. Add optional *strict* - parameter to these two functions: use ``strict=False`` to get the old - behavior, accept malformed inputs. - ``getattr(email.utils, 'supports_strict_parsing', False)`` can be used to - check if the *strict* parameter is available. +* :func:`~email.utils.getaddresses` and :func:`~email.utils.parseaddr` now + return ``('', '')`` pairs in more situations where invalid email addresses + are encountered instead of potentially inaccurate values. + The two functions have a new optional *strict* parameter (default ``True``). + To get the old behaviour (accepting malformed input), use ``strict=False``. + ``getattr(email.utils, 'supports_strict_parsing', False)`` can be used + to check if the *strict* parameter is available. (Contributed by Thomas Dwyer and Victor Stinner for :gh:`102988` to improve the :cve:`2023-27043` fix.) + fractions --------- -* Formatting for objects of type :class:`fractions.Fraction` now supports - the standard format specification mini-language rules for fill, alignment, - sign handling, minimum width and grouping. (Contributed by Mark Dickinson - in :gh:`111320`.) +* :class:`~fractions.Fraction` objects now support the standard + :ref:`format specification mini-language ` rules + for fill, alignment, sign handling, minimum width, and grouping. + (Contributed by Mark Dickinson in :gh:`111320`.) + gc -- -* The cyclic garbage collector is now incremental, which changes the meanings - of the results of :meth:`gc.get_threshold` and :meth:`gc.set_threshold` as - well as :meth:`gc.get_count` and :meth:`gc.get_stats`. - - * :meth:`gc.get_threshold` returns a three-item tuple for backwards compatibility. - The first value is the threshold for young collections, as before; the second - value determines the rate at which the old collection is scanned (the - default is 10, and higher values mean that the old collection is scanned more slowly). - The third value is meaningless and is always zero. - * :meth:`gc.set_threshold` ignores any items after the second. - * :meth:`gc.get_count` and :meth:`gc.get_stats` - return the same format of results as before. - The only difference is that instead of the results referring to - the young, aging and old generations, the results refer to the - young generation and the aging and collecting spaces of the old generation. - - In summary, code that attempted to manipulate the behavior of the cycle GC may - not work exactly as intended, but it is very unlikely to be harmful. - All other code will work just fine. +The cyclic garbage collector is now incremental, +which changes the meaning of the results of +:meth:`~gc.get_threshold` and :meth:`~gc.set_threshold` +as well as :meth:`~gc.get_count` and :meth:`~gc.get_stats`. + +* For backwards compatibility, :meth:`~gc.get_threshold` continues to return + a three-item tuple. + The first value is the threshold for young collections, as before; + the second value determines the rate at which the old collection is scanned + (the default is 10, and higher values mean that the old collection + is scanned more slowly). + The third value is meaningless and is always zero. + +* :meth:`~gc.set_threshold` ignores any items after the second. + +* :meth:`~gc.get_count` and :meth:`~gc.get_stats` continue to return + the same format of results. + The only difference is that instead of the results referring to + the young, aging and old generations, + the results refer to the young generation + and the aging and collecting spaces of the old generation. + +In summary, code that attempted to manipulate the behavior of the cycle GC +may not work exactly as intended, but it is very unlikely to be harmful. +All other code will work just fine. + glob ---- -* Add :func:`glob.translate` function that converts a path specification with - shell-style wildcards to a regular expression. +* Add :func:`~glob.translate`, a function to convert a path specification + with shell-style wildcards to a regular expression. (Contributed by Barney Gale in :gh:`72904`.) + importlib --------- -* Previously deprecated :mod:`importlib.resources` functions are un-deprecated: - - * :func:`~importlib.resources.is_resource()` - * :func:`~importlib.resources.open_binary()` - * :func:`~importlib.resources.open_text()` - * :func:`~importlib.resources.path()` - * :func:`~importlib.resources.read_binary()` - * :func:`~importlib.resources.read_text()` +* The following functions in :mod:`importlib.resources` now allow accessing + a directory (or tree) of resources, using multiple positional arguments + (the *encoding* and *errors* arguments in the text-reading functions + are now keyword-only): - All now allow for a directory (or tree) of resources, using multiple positional - arguments. + * :func:`~importlib.resources.is_resource` + * :func:`~importlib.resources.open_binary` + * :func:`~importlib.resources.open_text` + * :func:`~importlib.resources.path` + * :func:`~importlib.resources.read_binary` + * :func:`~importlib.resources.read_text` - For text-reading functions, the *encoding* and *errors* must now be given as - keyword arguments. + These functions are no longer deprecated and are not scheduled for removal. + (Contributed by Petr Viktorin in :gh:`106532`.) - The :func:`~importlib.resources.contents()` remains deprecated in favor of - the full-featured :class:`~importlib.resources.abc.Traversable` API. +* :func:`~importlib.resources.contents` remains deprecated in favor of + the fully-featured :class:`~importlib.resources.abc.Traversable` API. However, there is now no plan to remove it. - (Contributed by Petr Viktorin in :gh:`106532`.) + io -- -* The :class:`io.IOBase` finalizer now logs errors raised by the ``close()`` method with - :data:`sys.unraisablehook`. Previously, errors were ignored silently by default, - and only logged in :ref:`Python Development Mode ` or on :ref:`Python - built on debug mode `. +* The :class:`~io.IOBase` finalizer now logs any errors raised by + the :meth:`~io.IOBase.close` method with :data:`sys.unraisablehook`. + Previously, errors were ignored silently by default, + and only logged in :ref:`Python Development Mode ` + or when using a :ref:``. (Contributed by Victor Stinner in :gh:`62948`.) + ipaddress --------- -* Add the :attr:`ipaddress.IPv4Address.ipv6_mapped` property, which returns the IPv4-mapped IPv6 address. +* Add the :attr:`.IPv4Address.ipv6_mapped` property, + which returns the IPv4-mapped IPv6 address. (Contributed by Charles Machalow in :gh:`109466`.) + * Fix ``is_global`` and ``is_private`` behavior in - :class:`~ipaddress.IPv4Address`, - :class:`~ipaddress.IPv6Address`, - :class:`~ipaddress.IPv4Network` and - :class:`~ipaddress.IPv6Network`. + :class:`~ipaddress.IPv4Address`, :class:`~ipaddress.IPv6Address`, + :class:`~ipaddress.IPv4Network`, and :class:`~ipaddress.IPv6Network`. + (Contributed by Jakub Stasiak in :gh:`113171`.) + itertools --------- -* Added a ``strict`` option to :func:`itertools.batched`. - This raises a :exc:`ValueError` if the final batch is shorter +* :func:`~itertools.batched` has a new *strict* parameter, + which raises a :exc:`ValueError` if the final batch is shorter than the specified batch size. (Contributed by Raymond Hettinger in :gh:`113202`.) + marshal ------- * Add the *allow_code* parameter in module functions. - Passing ``allow_code=False`` prevents serialization and de-serialization of - code objects which are incompatible between Python versions. + Passing ``allow_code=False`` prevents serialization and de-serialization + of code objects which are incompatible between Python versions. (Contributed by Serhiy Storchaka in :gh:`113626`.) + math ---- -* A new function :func:`~math.fma` for fused multiply-add operations has been - added. This function computes ``x * y + z`` with only a single round, and so - avoids any intermediate loss of precision. It wraps the ``fma()`` function - provided by C99, and follows the specification of the IEEE 754 - "fusedMultiplyAdd" operation for special cases. +* The new function :func:`~math.fma` performs fused multiply-add operations. + This computes ``x * y + z`` with only a single round, + and so avoids any intermediate loss of precision. + It wraps the ``fma()`` function provided by C99, + and follows the specification of the IEEE 754 "fusedMultiplyAdd" operation + for special cases. (Contributed by Mark Dickinson and Victor Stinner in :gh:`73468`.) + mimetypes --------- -* Add the :func:`~mimetypes.guess_file_type` function which works with file path. - Passing file path instead of URL in :func:`~mimetypes.guess_type` is :term:`soft deprecated`. +* Add the :func:`~mimetypes.guess_file_type` function to guess a MIME type + from a filesystem path. + Using paths with :func:`~mimetypes.guess_type` is now :term:`soft deprecated`. (Contributed by Serhiy Storchaka in :gh:`66543`.) + mmap ---- -* The :class:`mmap.mmap` class now has a :meth:`~mmap.mmap.seekable` method +* :class:`~mmap.mmap` is now protected from crashing on Windows when the + mapped memory is inaccessible due to file system errors or access violations. + (Contributed by Jannis Weigend in :gh:`118209`.) + +* :class:`~mmap.mmap` has a new :meth:`~mmap.mmap.seekable` method that can be used when a seekable file-like object is required. The :meth:`~mmap.mmap.seek` method now returns the new absolute position. (Contributed by Donghee Na and Sylvie Liberman in :gh:`111835`.) -* :class:`mmap.mmap` now has a *trackfd* parameter on Unix; if it is ``False``, - the file descriptor specified by *fileno* will not be duplicated. + +* The new UNIX-only *trackfd* parameter for :class:`~mmap.mmap` controls + file descriptor duplication; + if false, the file descriptor specified by *fileno* will not be duplicated. (Contributed by Zackery Spytz and Petr Viktorin in :gh:`78502`.) -* :class:`mmap.mmap` is now protected from crashing on Windows when the mapped memory - is inaccessible due to file system errors or access violations. - (Contributed by Jannis Weigend in :gh:`118209`.) multiprocessing --------------- -* Select the default number of worker threads and processes using +* The default number of worker threads and processes is now selected using :func:`os.process_cpu_count` instead of :func:`os.cpu_count`. (Contributed by Victor Stinner in :gh:`109649`.) -opcode ------- - -* Move ``opcode.ENABLE_SPECIALIZATION`` to ``_opcode.ENABLE_SPECIALIZATION``. - This field was added in 3.12, it was never documented and is not intended for - external usage. (Contributed by Irit Katriel in :gh:`105481`.) - -* Removed ``opcode.is_pseudo``, ``opcode.MIN_PSEUDO_OPCODE`` and - ``opcode.MAX_PSEUDO_OPCODE``, which were added in 3.12, were never - documented or exposed through ``dis``, and were not intended to be - used externally. - os -- -* Add :func:`os.process_cpu_count` function to get the number of logical CPUs - usable by the calling thread of the current process. +* Add :func:`~os.process_cpu_count` function to get the number + of logical CPU cores usable by the calling thread of the current process. (Contributed by Victor Stinner in :gh:`109649`.) -* Add a low level interface for Linux's timer notification file descriptors - via :func:`os.timerfd_create`, - :func:`os.timerfd_settime`, :func:`os.timerfd_settime_ns`, - :func:`os.timerfd_gettime`, and :func:`os.timerfd_gettime_ns`, - :const:`os.TFD_NONBLOCK`, :const:`os.TFD_CLOEXEC`, - :const:`os.TFD_TIMER_ABSTIME`, and :const:`os.TFD_TIMER_CANCEL_ON_SET` - (Contributed by Masaru Tsuchiyama in :gh:`108277`.) - -* :func:`os.cpu_count` and :func:`os.process_cpu_count` can be overridden through - the new environment variable :envvar:`PYTHON_CPU_COUNT` or the new command-line option - :option:`-X cpu_count <-X>`. This option is useful for users who need to limit - CPU resources of a container system without having to modify the container (application code). +* :func:`~os.cpu_count` and :func:`~os.process_cpu_count` can be overridden + through the new environment variable :envvar:`PYTHON_CPU_COUNT` + or the new command-line option :option:`-X cpu_count <-X>`. + This option is useful for users who need to limit CPU resources + of a container system without having to modify application code + or the container itself. (Contributed by Donghee Na in :gh:`109595`.) -* Add support of :func:`os.lchmod` and the *follow_symlinks* argument - in :func:`os.chmod` on Windows. - Note that the default value of *follow_symlinks* in :func:`!os.lchmod` is - ``False`` on Windows. +* Add a :ref:`low level interface ` to Linux's + :manpage:`timer file descriptors ` + via :func:`~os.timerfd_create`, + :func:`~os.timerfd_settime`, :func:`~os.timerfd_settime_ns`, + :func:`~os.timerfd_gettime`, :func:`~os.timerfd_gettime_ns`, + :const:`~os.TFD_NONBLOCK`, :const:`~os.TFD_CLOEXEC`, + :const:`~os.TFD_TIMER_ABSTIME`, and :const:`~os.TFD_TIMER_CANCEL_ON_SET` + (Contributed by Masaru Tsuchiyama in :gh:`108277`.) + +* :func:`~os.lchmod` and the *follow_symlinks* argument of :func:`~os.chmod` + are both now available on Windows. + Note that the default value of *follow_symlinks* + in :func:`!lchmod` is ``False`` on Windows. (Contributed by Serhiy Storchaka in :gh:`59616`.) -* Add support of :func:`os.fchmod` and a file descriptor - in :func:`os.chmod` on Windows. +* :func:`~os.fchmod` and support for file descriptors in :func:`~os.chmod` + are both now available on Windows. (Contributed by Serhiy Storchaka in :gh:`113191`.) -* :func:`os.posix_spawn` now accepts ``env=None``, which makes the newly spawned - process use the current process environment. +* On Windows, :func:`~os.mkdir` and :func:`~os.makedirs` now support passing + a *mode* value of ``0o700`` to apply access control to the new directory. + This implicitly affects :func:`tempfile.mkdtemp` + and is a mitigation for :cve:`2024-4030`. + Other values for *mode* continue to be ignored. + (Contributed by Steve Dower in :gh:`118486`.) + +* :func:`~os.posix_spawn` now accepts ``None`` for the *env* argument, + which makes the newly spawned process use the current process environment. (Contributed by Jakub Kulik in :gh:`113119`.) -* :func:`os.posix_spawn` gains an :attr:`os.POSIX_SPAWN_CLOSEFROM` attribute for - use in ``file_actions=`` on platforms that support +* :func:`~os.posix_spawn` can now use the :attr:`~os.POSIX_SPAWN_CLOSEFROM` + attribute in the *file_actions* parameter on platforms that support :c:func:`!posix_spawn_file_actions_addclosefrom_np`. (Contributed by Jakub Kulik in :gh:`113117`.) -* :func:`os.mkdir` and :func:`os.makedirs` on Windows now support passing a - *mode* value of ``0o700`` to apply access control to the new directory. This - implicitly affects :func:`tempfile.mkdtemp` and is a mitigation for - :cve:`2024-4030`. Other values for *mode* continue to be ignored. - (Contributed by Steve Dower in :gh:`118486`.) os.path ------- -* Add :func:`os.path.isreserved` to check if a path is reserved on the current - system. This function is only available on Windows. +* Add :func:`~os.path.isreserved` to check if a path is reserved + on the current system. + This function is only available on Windows. (Contributed by Barney Gale in :gh:`88569`.) -* On Windows, :func:`os.path.isabs` no longer considers paths starting with - exactly one (back)slash to be absolute. +* On Windows, :func:`~os.path.isabs` no longer considers paths + starting with exactly one slash (``\`` or ``/``) to be absolute. (Contributed by Barney Gale and Jon Foster in :gh:`44626`.) -* :func:`os.path.realpath` now resolves MS-DOS style file names even if - the file is not accessible. +* :func:`~os.path.realpath` now resolves MS-DOS style file names + even if the file is not accessible. (Contributed by Moonsik Park in :gh:`82367`.) -* Add support of *dir_fd* and *follow_symlinks* keyword arguments in - :func:`shutil.chown`. - (Contributed by Berker Peksag and Tahia K in :gh:`62308`) pathlib ------- -* Add :exc:`pathlib.UnsupportedOperation`, which is raised instead of +* Add :exc:`~pathlib.UnsupportedOperation`, which is raised instead of :exc:`NotImplementedError` when a path operation isn't supported. (Contributed by Barney Gale in :gh:`89812`.) -* Add :meth:`pathlib.Path.from_uri`, a new constructor to create a :class:`pathlib.Path` - object from a 'file' URI (``file://``). +* Add a new constructor for creating :class:`~pathlib.Path` objects + from 'file' URIs (``file:///``), :meth:`.Path.from_uri`. (Contributed by Barney Gale in :gh:`107465`.) -* Add :meth:`pathlib.PurePath.full_match` for matching paths with +* Add :meth:`.PurePath.full_match` for matching paths with shell-style wildcards, including the recursive wildcard "``**``". (Contributed by Barney Gale in :gh:`73435`.) -* Add :attr:`pathlib.PurePath.parser` class attribute that stores the - implementation of :mod:`os.path` used for low-level path parsing and - joining: either ``posixpath`` or ``ntpath``. +* Add the :attr:`.PurePath.parser` class attribute to store the + implementation of :mod:`os.path` used + for low-level path parsing and joining. + This will be either :mod:`!posixpath` or :mod:`!ntpath`. -* Add *recurse_symlinks* keyword-only argument to :meth:`pathlib.Path.glob` - and :meth:`~pathlib.Path.rglob`. +* Add *recurse_symlinks* keyword-only argument to + :meth:`.Path.glob` and :meth:`~pathlib.Path.rglob`. (Contributed by Barney Gale in :gh:`77609`.) -* Add *follow_symlinks* keyword-only argument to :meth:`~pathlib.Path.is_file`, - :meth:`~pathlib.Path.is_dir`, :meth:`~pathlib.Path.owner`, - :meth:`~pathlib.Path.group`. - (Contributed by Barney Gale in :gh:`105793`, and Kamil Turek in - :gh:`107962`.) - -* Return files and directories from :meth:`pathlib.Path.glob` and - :meth:`~pathlib.Path.rglob` when given a pattern that ends with "``**``". In - earlier versions, only directories were returned. +* :meth:`.Path.glob` and :meth:`~pathlib.Path.rglob` + now return files and directories when given a pattern that ends with "``**``". + Previously, only directories were returned. (Contributed by Barney Gale in :gh:`70303`.) +* Add the *follow_symlinks* keyword-only argument to + :meth:`Path.is_file `, + :meth:`Path.is_dir `, + :meth:`.Path.owner`, and :meth:`.Path.group`. + (Contributed by Barney Gale in :gh:`105793` and Kamil Turek in :gh:`107962`.) + + pdb --- -* Add ability to move between chained exceptions during post-mortem debugging in :func:`~pdb.pm` using - the new ``exceptions [exc_number]`` command for Pdb. (Contributed by Matthias - Bussonnier in :gh:`106676`.) - -* Expressions/statements whose prefix is a pdb command are now correctly - identified and executed. - (Contributed by Tian Gao in :gh:`108464`.) +* :func:`breakpoint` and :func:`~pdb.set_trace` now enter the debugger immediately + rather than on the next line of code to be executed. This change prevents the + debugger from breaking outside of the context when :func:`!breakpoint` is positioned + at the end of the context. + (Contributed by Tian Gao in :gh:`118579`.) -* ``sys.path[0]`` will no longer be replaced by the directory of the script - being debugged when ``sys.flags.safe_path`` is set (via the :option:`-P` - command line option or :envvar:`PYTHONSAFEPATH` environment variable). +* ``sys.path[0]`` is no longer replaced by the directory of the script + being debugged when :attr:`sys.flags.safe_path` is set. (Contributed by Tian Gao and Christian Walther in :gh:`111762`.) -* :mod:`zipapp` is supported as a debugging target. +* :mod:`zipapp` is now supported as a debugging target. (Contributed by Tian Gao in :gh:`118501`.) -* ``breakpoint()`` and ``pdb.set_trace()`` now enter the debugger immediately - rather than on the next line of code to be executed. This change prevents the - debugger from breaking outside of the context when ``breakpoint()`` is positioned - at the end of the context. - (Contributed by Tian Gao in :gh:`118579`.) +* Add ability to move between chained exceptions during + post-mortem debugging in :func:`~pdb.pm` using + the new :pdbcmd:`exceptions [exc_number] ` command for Pdb. + (Contributed by Matthias Bussonnier in :gh:`106676`.) + +* Expressions and statements whose prefix is a pdb command are now correctly + identified and executed. + (Contributed by Tian Gao in :gh:`108464`.) + queue ----- -* Add :meth:`queue.Queue.shutdown` (along with :exc:`queue.ShutDown`) for queue - termination. +* Add :meth:`Queue.shutdown ` and :exc:`~queue.ShutDown` + to manage queue termination. (Contributed by Laurie Opperman and Yves Duprat in :gh:`104750`.) + random ------ * Add a :ref:`command-line interface `. (Contributed by Hugo van Kemenade in :gh:`118131`.) + re -- -* Rename :exc:`!re.error` to :exc:`re.PatternError` for improved clarity. + +* Rename :exc:`!re.error` to :exc:`~re.PatternError` for improved clarity. :exc:`!re.error` is kept for backward compatibility. + +shutil +------ + +* Support the *dir_fd* and *follow_symlinks* keyword arguments + in :func:`~shutil.chown`. + (Contributed by Berker Peksag and Tahia K in :gh:`62308`) + + site ---- -* :file:`.pth` files are now decoded by UTF-8 first, and then by the - :term:`locale encoding` if the UTF-8 decoding fails. +* :file:`.pth` files are now decoded using UTF-8 first, + and then with the :term:`locale encoding` if UTF-8 decoding fails. (Contributed by Inada Naoki in :gh:`117802`.) + sqlite3 ------- -* A :exc:`ResourceWarning` is now emitted if a :class:`sqlite3.Connection` +* A :exc:`ResourceWarning` is now emitted if a :class:`~sqlite3.Connection` object is not :meth:`closed ` explicitly. (Contributed by Erlend E. Aasland in :gh:`105539`.) -* Add *filter* keyword-only parameter to :meth:`sqlite3.Connection.iterdump` +* Add the *filter* keyword-only parameter to :meth:`.Connection.iterdump` for filtering database objects to dump. (Contributed by Mariusz Felisiak in :gh:`91602`.) @@ -1153,18 +1219,23 @@ sqlite3 ssl --- -* The :func:`ssl.create_default_context` API now includes - :data:`ssl.VERIFY_X509_PARTIAL_CHAIN` and :data:`ssl.VERIFY_X509_STRICT` +* The :func:`~ssl.create_default_context` API now includes + :data:`~ssl.VERIFY_X509_PARTIAL_CHAIN` and :data:`~ssl.VERIFY_X509_STRICT` in its default flags. .. note:: - :data:`ssl.VERIFY_X509_STRICT` may reject pre-:rfc:`5280` or malformed - certificates that the underlying OpenSSL implementation otherwise would - accept. While disabling this is not recommended, you can do so using:: + :data:`~ssl.VERIFY_X509_STRICT` may reject pre-:rfc:`5280` + or malformed certificates that the underlying OpenSSL implementation + might otherwise accept. + Whilst disabling this is not recommended, you can do so using: - ctx = ssl.create_default_context() - ctx.verify_flags &= ~ssl.VERIFY_X509_STRICT + .. code-block:: python + + import ssl + + ctx = ssl.create_default_context() + ctx.verify_flags &= ~ssl.VERIFY_X509_STRICT (Contributed by William Woodruff in :gh:`112389`.) @@ -1172,56 +1243,70 @@ ssl statistics ---------- -* Add :func:`statistics.kde` for kernel density estimation. +* Add :func:`~statistics.kde` for kernel density estimation. This makes it possible to estimate a continuous probability density function - from a fixed number of discrete samples. Also added :func:`statistics.kde_random` - for sampling from the estimated probability density function. + from a fixed number of discrete samples. + (Contributed by Raymond Hettinger in :gh:`115863`.) + +* Add :func:`~statistics.kde_random` for sampling from an + estimated probability density function created by :func:`~statistics.kde`. (Contributed by Raymond Hettinger in :gh:`115863`.) + .. _whatsnew313-subprocess: subprocess ---------- -* The :mod:`subprocess` module now uses the :func:`os.posix_spawn` function in - more situations. Notably in the default case of ``close_fds=True`` on more - recent versions of platforms including Linux, FreeBSD, and Solaris where the - C library provides :c:func:`!posix_spawn_file_actions_addclosefrom_np`. - On Linux this should perform similarly to the existing Linux :c:func:`!vfork` - based code. A private control knob :attr:`!subprocess._USE_POSIX_SPAWN` can - be set to ``False`` if you need to force :mod:`subprocess` not to ever use - :func:`os.posix_spawn`. Please report your reason and platform details in - the CPython issue tracker if you set this so that we can improve our API - selection logic for everyone. +* The :mod:`subprocess` module now uses the :func:`~os.posix_spawn` function in + more situations. + + Notably, when *close_fds* is ``True`` (the default), + :func:`~os.posix_spawn` will be used when the C library provides + :c:func:`!posix_spawn_file_actions_addclosefrom_np`, + which includes recent versions of Linux, FreeBSD, and Solaris. + On Linux, this should perform similarly to the existing + Linux :c:func:`!vfork` based code. + + A private control knob :attr:`!subprocess._USE_POSIX_SPAWN` can + be set to ``False`` if you need to force :mod:`subprocess` + to never use :func:`~os.posix_spawn`. + Please report your reason and platform details in + the :ref:`issue tracker ` if you set this + so that we can improve our API selection logic for everyone. (Contributed by Jakub Kulik in :gh:`113117`.) + sys --- -* Add the :func:`sys._is_interned` function to test if a string was interned. +* Add the :func:`~sys._is_interned` function to test if a string was interned. This function is not guaranteed to exist in all implementations of Python. (Contributed by Serhiy Storchaka in :gh:`78573`.) + tempfile -------- * On Windows, the default mode ``0o700`` used by :func:`tempfile.mkdtemp` now - limits access to the new directory due to changes to :func:`os.mkdir`. This - is a mitigation for :cve:`2024-4030`. + limits access to the new directory due to changes to :func:`os.mkdir`. + This is a mitigation for :cve:`2024-4030`. (Contributed by Steve Dower in :gh:`118486`.) + time ---- -* On Windows, :func:`time.monotonic()` now uses the - ``QueryPerformanceCounter()`` clock to have a resolution better than 1 μs, - instead of the ``GetTickCount64()`` clock which has a resolution of 15.6 ms. +* On Windows, :func:`~time.monotonic` now uses the + ``QueryPerformanceCounter()`` clock for a resolution of 1 microsecond, + instead of the ``GetTickCount64()`` clock which has + a resolution of 15.6 milliseconds. (Contributed by Victor Stinner in :gh:`88494`.) -* On Windows, :func:`time.time()` now uses the - ``GetSystemTimePreciseAsFileTime()`` clock to have a resolution better - than 1 μs, instead of the ``GetSystemTimeAsFileTime()`` clock which has a - resolution of 15.6 ms. +* On Windows, :func:`~time.time` now uses the + ``GetSystemTimePreciseAsFileTime()`` clock for a resolution of 1 microsecond, + instead of the ``GetSystemTimeAsFileTime()`` clock which has + a resolution of 15.6 milliseconds. (Contributed by Victor Stinner in :gh:`63207`.) @@ -1236,20 +1321,21 @@ tkinter * The :mod:`tkinter` widget method :meth:`!wm_attributes` now accepts the attribute name without the minus prefix to get window attributes, - e.g. ``w.wm_attributes('alpha')`` and allows to specify attributes and - values to set as keyword arguments, e.g. ``w.wm_attributes(alpha=0.5)``. - Add new optional keyword-only parameter *return_python_dict*: calling - ``w.wm_attributes(return_python_dict=True)`` returns the attributes as - a dict instead of a tuple. + for example ``w.wm_attributes('alpha')`` + and allows specifying attributes and values to set as keyword arguments, + for example ``w.wm_attributes(alpha=0.5)``. (Contributed by Serhiy Storchaka in :gh:`43457`.) -* Add new optional keyword-only parameter *return_ints* in - the :meth:`!Text.count` method. - Passing ``return_ints=True`` makes it always return the single count - as an integer instead of a 1-tuple or ``None``. +* :meth:`!wm_attributes` can now return attributes as a :class:`dict`, + by using the new optional keyword-only parameter *return_python_dict*. + (Contributed by Serhiy Storchaka in :gh:`43457`.) + +* :meth:`!Text.count` can now return a simple :class:`int` + when the new optional keyword-only parameter *return_ints* is used. + Otherwise, the single count is returned as a 1-tuple or ``None``. (Contributed by Serhiy Storchaka in :gh:`97928`.) -* Add support of the "vsapi" element type in +* Support the "vsapi" element type in the :meth:`~tkinter.ttk.Style.element_create` method of :class:`tkinter.ttk.Style`. (Contributed by Serhiy Storchaka in :gh:`68166`.) @@ -1257,82 +1343,108 @@ tkinter * Add the :meth:`!after_info` method for Tkinter widgets. (Contributed by Cheryl Sabella in :gh:`77020`.) -* Add the :class:`!PhotoImage` method :meth:`!copy_replace` to copy a region - from one image to other image, possibly with pixel zooming and/or - subsampling. - Add *from_coords* parameter to :class:`!PhotoImage` methods :meth:`!copy()`, - :meth:`!zoom()` and :meth:`!subsample()`. - Add *zoom* and *subsample* parameters to :class:`!PhotoImage` method - :meth:`!copy()`. +* Add a new :meth:`!copy_replace` method to :class:`!PhotoImage` + to copy a region from one image to another, + possibly with pixel zooming, subsampling, or both. + (Contributed by Serhiy Storchaka in :gh:`118225`.) + +* Add *from_coords* parameter to the :class:`!PhotoImage` methods + :meth:`!copy`, :meth:`!zoom` and :meth:`!subsample`. + Add *zoom* and *subsample* parameters to the :class:`!PhotoImage` method + :meth:`!copy`. (Contributed by Serhiy Storchaka in :gh:`118225`.) -* Add the :class:`!PhotoImage` methods :meth:`!read` to read - an image from a file and :meth:`!data` to get the image data. - Add *background* and *grayscale* parameters to :class:`!PhotoImage` method - :meth:`!write`. +* Add the :class:`!PhotoImage` methods + :meth:`!read` to read an image from a file + and :meth:`!data` to get the image data. + Add *background* and *grayscale* parameters to the :meth:`!write` method. (Contributed by Serhiy Storchaka in :gh:`118271`.) + traceback --------- -* Add *show_group* parameter to :func:`traceback.TracebackException.format_exception_only` - to format the nested exceptions of a :exc:`BaseExceptionGroup` instance, recursively. +* Add the :attr:`~traceback.TracebackException.exc_type_str` attribute + to :class:`~traceback.TracebackException`, + which holds a string display of the *exc_type*. + Deprecate the :attr:`~traceback.TracebackException.exc_type` attribute, + which holds the type object itself. + Add parameter *save_exc_type* (default ``True``) + to indicate whether ``exc_type`` should be saved. + (Contributed by Irit Katriel in :gh:`112332`.) + +* Add a new *show_group* keyword-only parameter to + :meth:`.TracebackException.format_exception_only` to (recursively) format + the nested exceptions of a :exc:`BaseExceptionGroup` instance. (Contributed by Irit Katriel in :gh:`105292`.) -* Add the field *exc_type_str* to :class:`~traceback.TracebackException`, which - holds a string display of the *exc_type*. Deprecate the field *exc_type* - which holds the type object itself. Add parameter *save_exc_type* (default - ``True``) to indicate whether ``exc_type`` should be saved. - (Contributed by Irit Katriel in :gh:`112332`.) types ----- -* The :class:`~types.SimpleNamespace` constructor now allows specifying initial - values of attributes as a positional argument, which must be a mapping or - an iterable of key-value pairs. +* :class:`~types.SimpleNamespace` can now take a single positional argument + to initialise the namespace's arguments. + This argument must either be a mapping or an iterable of key-value pairs. (Contributed by Serhiy Storchaka in :gh:`108191`.) + typing ------ -* Add :func:`typing.get_protocol_members` to return the set of members - defining a :class:`typing.Protocol`. Add :func:`typing.is_protocol` to - check whether a class is a :class:`typing.Protocol`. (Contributed by Jelle Zijlstra in - :gh:`104873`.) +* :pep:`705`: Add :data:`~typing.ReadOnly`, a special typing construct + to mark a :class:`~typing.TypedDict` item as read-only for type checkers. + +* :pep:`742`: Add :data:`~typing.TypeIs`, a typing construct + that can be used to instruct a type checker how to narrow a type. + +* Add :data:`~typing.NoDefault`, a sentinel object used to represent + the defaults of some parameters in the :mod:`typing` module. + (Contributed by Jelle Zijlstra in :gh:`116126`.) + +* Add :func:`~typing.get_protocol_members` to return the set of members + defining a :class:`typing.Protocol`. + (Contributed by Jelle Zijlstra in :gh:`104873`.) -* Add :data:`typing.ReadOnly`, a special typing construct to mark - an item of a :class:`typing.TypedDict` as read-only for type checkers. - See :pep:`705` for more details. +* Add :func:`~typing.is_protocol` to check whether a class + is a :class:`~typing.Protocol`. + (Contributed by Jelle Zijlstra in :gh:`104873`.) + +* :data:`~typing.ClassVar` can now be nested in :data:`~typing.Final`, + and vice versa. + (Contributed by Mehdi Drissi in :gh:`89547`.) -* Add :data:`typing.NoDefault`, a sentinel object used to represent the defaults - of some parameters in the :mod:`typing` module. (Contributed by Jelle Zijlstra in - :gh:`116126`.) unicodedata ----------- -* The Unicode database has been updated to version 15.1.0. (Contributed by - James Gerity in :gh:`109559`.) +* Update the Unicode database to `version 15.1.0`__. + (Contributed by James Gerity in :gh:`109559`.) + + __ https://www.unicode.org/versions/Unicode15.1.0/ + venv ---- -* Add support for adding source control management (SCM) ignore files to a - virtual environment's directory. By default, Git is supported. This is - implemented as opt-in via the API which can be extended to support other SCMs - (:class:`venv.EnvBuilder` and :func:`venv.create`), and opt-out via the CLI - (using ``--without-scm-ignore-files``). (Contributed by Brett Cannon in - :gh:`108125`.) +* Add support for creating source control management (SCM) ignore files + in a virtual environment's directory. + By default, Git is supported. + This is implemented as opt-in via the API, + which can be extended to support other SCMs + (:class:`~venv.EnvBuilder` and :func:`~venv.create`), + and opt-out via the CLI, using :option:`!--without-scm-ignore-files`. + (Contributed by Brett Cannon in :gh:`108125`.) + warnings -------- -* The new :func:`warnings.deprecated` decorator provides a way to communicate - deprecations to :term:`static type checkers ` and - to warn on usage of deprecated classes and functions. A runtime deprecation - warning may also be emitted when a decorated function or class is used at runtime. - See :pep:`702`. (Contributed by Jelle Zijlstra in :gh:`104003`.) +* :pep:`702`: The new :func:`warnings.deprecated` decorator provides a way to + communicate deprecations to a :term:`static type checker` + and to warn on usage of deprecated classes and functions. + A :exc:`DeprecationWarning` may also be emitted when + a decorated function or class is used at runtime. + (Contributed by Jelle Zijlstra in :gh:`104003`.) xml @@ -1350,17 +1462,19 @@ xml (Contributed by Sebastian Pipping in :gh:`115623`.) * Add the :meth:`!close` method for the iterator returned by - :func:`~xml.etree.ElementTree.iterparse` for explicit cleaning up. + :func:`~xml.etree.ElementTree.iterparse` for explicit cleanup. (Contributed by Serhiy Storchaka in :gh:`69893`.) zipimport --------- -* Gains support for ZIP64 format files. Everybody loves huge code right? +* Add support for ZIP64_ format files. + Everybody loves huge data, right? (Contributed by Tim Hatch in :gh:`94146`.) -.. Add improved modules above alphabetically, not here at the end. + .. _ZIP64: https://en.wikipedia.org/wiki/Zip_(file_format)#ZIP64 + Optimizations ============= @@ -1509,10 +1623,6 @@ PEP 594: dead batteries (and other module removals) configparser ------------ -* The :class:`configparser.ConfigParser` now accepts unnamed sections - before named ones if configured to do so. - (Contributed by Pedro Sousa Lacerda in :gh:`66449`.) - * Remove the undocumented :class:`!configparser.LegacyInterpolation` class, deprecated in the docstring since Python 3.2, and with a deprecation warning since Python 3.11. @@ -1532,6 +1642,19 @@ locale use ``locale.setlocale(locale.LC_ALL, "")`` instead. (Contributed by Victor Stinner in :gh:`104783`.) +opcode +------ + +* Move :attr:`!opcode.ENABLE_SPECIALIZATION` to :attr:`!_opcode.ENABLE_SPECIALIZATION`. + This field was added in 3.12, it was never documented, + and is not intended for external use. + (Contributed by Irit Katriel in :gh:`105481`.) + +* Removed :func:`!opcode.is_pseudo`, :attr:`!opcode.MIN_PSEUDO_OPCODE`, + and :attr:`!opcode.MAX_PSEUDO_OPCODE`, which were added in 3.12, + but were neither documented nor exposed through ``dis``, + and were not intended to be used externally. + pathlib ------- diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index 8c9bb1ae8c4908..7c106577671b5f 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -190,18 +190,15 @@ PyStackRef_FromPyObjectImmortal(PyObject *obj) } while (0) #ifdef Py_GIL_DISABLED -static inline void -PyStackRef_CLOSE(_PyStackRef stackref) -{ - if (PyStackRef_IsDeferred(stackref)) { - // No assert for being immortal or deferred here. - // The GC unsets deferred objects right before clearing. - return; - } - Py_DECREF(PyStackRef_AsPyObjectBorrow(stackref)); -} +# define PyStackRef_CLOSE(REF) \ + do { \ + _PyStackRef _close_tmp = (REF); \ + if (!PyStackRef_IsDeferred(_close_tmp)) { \ + Py_DECREF(PyStackRef_AsPyObjectBorrow(_close_tmp)); \ + } \ + } while (0) #else -# define PyStackRef_CLOSE(stackref) Py_DECREF(PyStackRef_AsPyObjectBorrow(stackref)); +# define PyStackRef_CLOSE(stackref) Py_DECREF(PyStackRef_AsPyObjectBorrow(stackref)) #endif #define PyStackRef_XCLOSE(stackref) \ @@ -227,7 +224,7 @@ PyStackRef_DUP(_PyStackRef stackref) return stackref; } #else -# define PyStackRef_DUP(stackref) PyStackRef_FromPyObjectSteal(Py_NewRef(PyStackRef_AsPyObjectBorrow(stackref))); +# define PyStackRef_DUP(stackref) PyStackRef_FromPyObjectSteal(Py_NewRef(PyStackRef_AsPyObjectBorrow(stackref))) #endif static inline void diff --git a/Lib/pathlib/_os.py b/Lib/pathlib/_os.py index 63dbe131baea51..642b3a57c59a1d 100644 --- a/Lib/pathlib/_os.py +++ b/Lib/pathlib/_os.py @@ -20,7 +20,7 @@ _winapi = None -def get_copy_blocksize(infd): +def _get_copy_blocksize(infd): """Determine blocksize for fastcopying on Linux. Hopefully the whole file will be copied in a single call. The copying itself should be performed in a loop 'till EOF is @@ -40,7 +40,7 @@ def get_copy_blocksize(infd): if fcntl and hasattr(fcntl, 'FICLONE'): - def clonefd(source_fd, target_fd): + def _ficlone(source_fd, target_fd): """ Perform a lightweight copy of two files, where the data blocks are copied only when modified. This is known as Copy on Write (CoW), @@ -48,18 +48,22 @@ def clonefd(source_fd, target_fd): """ fcntl.ioctl(target_fd, fcntl.FICLONE, source_fd) else: - clonefd = None + _ficlone = None if posix and hasattr(posix, '_fcopyfile'): - def copyfd(source_fd, target_fd): + def _fcopyfile(source_fd, target_fd): """ Copy a regular file content using high-performance fcopyfile(3) syscall (macOS). """ posix._fcopyfile(source_fd, target_fd, posix._COPYFILE_DATA) -elif hasattr(os, 'copy_file_range'): - def copyfd(source_fd, target_fd): +else: + _fcopyfile = None + + +if hasattr(os, 'copy_file_range'): + def _copy_file_range(source_fd, target_fd): """ Copy data from one regular mmap-like fd to another by using a high-performance copy_file_range(2) syscall that gives filesystems @@ -67,7 +71,7 @@ def copyfd(source_fd, target_fd): copy. This should work on Linux >= 4.5 only. """ - blocksize = get_copy_blocksize(source_fd) + blocksize = _get_copy_blocksize(source_fd) offset = 0 while True: sent = os.copy_file_range(source_fd, target_fd, blocksize, @@ -75,13 +79,17 @@ def copyfd(source_fd, target_fd): if sent == 0: break # EOF offset += sent -elif hasattr(os, 'sendfile'): - def copyfd(source_fd, target_fd): +else: + _copy_file_range = None + + +if hasattr(os, 'sendfile'): + def _sendfile(source_fd, target_fd): """Copy data from one regular mmap-like fd to another by using high-performance sendfile(2) syscall. This should work on Linux >= 2.6.33 only. """ - blocksize = get_copy_blocksize(source_fd) + blocksize = _get_copy_blocksize(source_fd) offset = 0 while True: sent = os.sendfile(target_fd, source_fd, offset, blocksize) @@ -89,7 +97,7 @@ def copyfd(source_fd, target_fd): break # EOF offset += sent else: - copyfd = None + _sendfile = None if _winapi and hasattr(_winapi, 'CopyFile2'): @@ -114,18 +122,36 @@ def copyfileobj(source_f, target_f): else: try: # Use OS copy-on-write where available. - if clonefd: + if _ficlone: try: - clonefd(source_fd, target_fd) + _ficlone(source_fd, target_fd) return except OSError as err: if err.errno not in (EBADF, EOPNOTSUPP, ETXTBSY, EXDEV): raise err # Use OS copy where available. - if copyfd: - copyfd(source_fd, target_fd) - return + if _fcopyfile: + try: + _fcopyfile(source_fd, target_fd) + return + except OSError as err: + if err.errno not in (EINVAL, ENOTSUP): + raise err + if _copy_file_range: + try: + _copy_file_range(source_fd, target_fd) + return + except OSError as err: + if err.errno not in (ETXTBSY, EXDEV): + raise err + if _sendfile: + try: + _sendfile(source_fd, target_fd) + return + except OSError as err: + if err.errno != ENOTSOCK: + raise err except OSError as err: # Produce more useful error messages. err.filename = source_f.name diff --git a/Lib/test/test_pathlib/test_pathlib.py b/Lib/test/test_pathlib/test_pathlib.py index 0a3c9aac221f22..4d38246dbb3853 100644 --- a/Lib/test/test_pathlib/test_pathlib.py +++ b/Lib/test/test_pathlib/test_pathlib.py @@ -1,3 +1,4 @@ +import contextlib import io import os import sys @@ -22,10 +23,18 @@ from test.test_pathlib import test_pathlib_abc from test.test_pathlib.test_pathlib_abc import needs_posix, needs_windows, needs_symlinks +try: + import fcntl +except ImportError: + fcntl = None try: import grp, pwd except ImportError: grp = pwd = None +try: + import posix +except ImportError: + posix = None root_in_posix = False @@ -720,6 +729,45 @@ def test_copy_link_preserve_metadata(self): if hasattr(source_st, 'st_flags'): self.assertEqual(source_st.st_flags, target_st.st_flags) + def test_copy_error_handling(self): + def make_raiser(err): + def raiser(*args, **kwargs): + raise OSError(err, os.strerror(err)) + return raiser + + base = self.cls(self.base) + source = base / 'fileA' + target = base / 'copyA' + + # Raise non-fatal OSError from all available fast copy functions. + with contextlib.ExitStack() as ctx: + if fcntl and hasattr(fcntl, 'FICLONE'): + ctx.enter_context(mock.patch('fcntl.ioctl', make_raiser(errno.EXDEV))) + if posix and hasattr(posix, '_fcopyfile'): + ctx.enter_context(mock.patch('posix._fcopyfile', make_raiser(errno.ENOTSUP))) + if hasattr(os, 'copy_file_range'): + ctx.enter_context(mock.patch('os.copy_file_range', make_raiser(errno.EXDEV))) + if hasattr(os, 'sendfile'): + ctx.enter_context(mock.patch('os.sendfile', make_raiser(errno.ENOTSOCK))) + + source.copy(target) + self.assertTrue(target.exists()) + self.assertEqual(source.read_text(), target.read_text()) + + # Raise fatal OSError from first available fast copy function. + if fcntl and hasattr(fcntl, 'FICLONE'): + patchpoint = 'fcntl.ioctl' + elif posix and hasattr(posix, '_fcopyfile'): + patchpoint = 'posix._fcopyfile' + elif hasattr(os, 'copy_file_range'): + patchpoint = 'os.copy_file_range' + elif hasattr(os, 'sendfile'): + patchpoint = 'os.sendfile' + else: + return + with mock.patch(patchpoint, make_raiser(errno.ENOENT)): + self.assertRaises(FileNotFoundError, source.copy, target) + @unittest.skipIf(sys.platform == "win32" or sys.platform == "wasi", "directories are always readable on Windows and WASI") @unittest.skipIf(root_in_posix, "test fails with root privilege") def test_copy_dir_no_read_permission(self): diff --git a/Misc/NEWS.d/next/Library/2024-08-22-20-10-13.gh-issue-123243.Kifj1L.rst b/Misc/NEWS.d/next/Library/2024-08-22-20-10-13.gh-issue-123243.Kifj1L.rst new file mode 100644 index 00000000000000..cf52585020111f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-08-22-20-10-13.gh-issue-123243.Kifj1L.rst @@ -0,0 +1 @@ +Fix memory leak in :mod:`!_decimal`. diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 15855e2cf1bb32..0e743a609d33d6 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -1390,6 +1390,10 @@ context_new(PyTypeObject *type, PyObject *args UNUSED, PyObject *kwds UNUSED) CtxCaps(self) = 1; self->tstate = NULL; + if (type == state->PyDecContext_Type) { + PyObject_GC_Track(self); + } + assert(PyObject_GC_IsTracked((PyObject *)self)); return (PyObject *)self; } @@ -2038,6 +2042,10 @@ PyDecType_New(PyTypeObject *type) MPD(dec)->alloc = _Py_DEC_MINALLOC; MPD(dec)->data = dec->data; + if (type == state->PyDec_Type) { + PyObject_GC_Track(dec); + } + assert(PyObject_GC_IsTracked((PyObject *)dec)); return (PyObject *)dec; } #define dec_alloc(st) PyDecType_New((st)->PyDec_Type) @@ -6143,8 +6151,22 @@ decimal_clear(PyObject *module) Py_CLEAR(state->SignalTuple); Py_CLEAR(state->PyDecimal); - PyMem_Free(state->signal_map); - PyMem_Free(state->cond_map); + if (state->signal_map != NULL) { + for (DecCondMap *cm = state->signal_map; cm->name != NULL; cm++) { + Py_DECREF(cm->ex); + } + PyMem_Free(state->signal_map); + state->signal_map = NULL; + } + + if (state->cond_map != NULL) { + // cond_map[0].ex has borrowed a reference from signal_map[0].ex + for (DecCondMap *cm = state->cond_map + 1; cm->name != NULL; cm++) { + Py_DECREF(cm->ex); + } + PyMem_Free(state->cond_map); + state->cond_map = NULL; + } return 0; } diff --git a/Python/bytecodes.c b/Python/bytecodes.c index fefa3af37a16b0..ad30fb3db0360a 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2215,7 +2215,7 @@ dummy_func( *value_ptr = PyStackRef_AsPyObjectSteal(value); if (old_value == NULL) { PyDictValues *values = _PyObject_InlineValues(owner_o); - int index = value_ptr - values->values; + Py_ssize_t index = value_ptr - values->values; _PyDictValues_AddToInsertionOrder(values, index); } else { diff --git a/Python/ceval.c b/Python/ceval.c index b615deec3c4242..2a5c16aa101985 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -52,13 +52,27 @@ # error "ceval.c must be build with Py_BUILD_CORE define for best performance" #endif -#if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_GIL_DISABLED) +#if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) // GH-89279: The MSVC compiler does not inline these static inline functions // in PGO build in _PyEval_EvalFrameDefault(), because this function is over // the limit of PGO, and that limit cannot be configured. // Define them as macros to make sure that they are always inlined by the // preprocessor. -// TODO: implement Py_DECREF macro for Py_GIL_DISABLED + +#undef Py_IS_TYPE +#define Py_IS_TYPE(ob, type) \ + (_PyObject_CAST(ob)->ob_type == (type)) + +#undef Py_XDECREF +#define Py_XDECREF(arg) \ + do { \ + PyObject *xop = _PyObject_CAST(arg); \ + if (xop != NULL) { \ + Py_DECREF(xop); \ + } \ + } while (0) + +#ifndef Py_GIL_DISABLED #undef Py_DECREF #define Py_DECREF(arg) \ @@ -74,19 +88,6 @@ } \ } while (0) -#undef Py_XDECREF -#define Py_XDECREF(arg) \ - do { \ - PyObject *xop = _PyObject_CAST(arg); \ - if (xop != NULL) { \ - Py_DECREF(xop); \ - } \ - } while (0) - -#undef Py_IS_TYPE -#define Py_IS_TYPE(ob, type) \ - (_PyObject_CAST(ob)->ob_type == (type)) - #undef _Py_DECREF_SPECIALIZED #define _Py_DECREF_SPECIALIZED(arg, dealloc) \ do { \ @@ -100,6 +101,34 @@ d(op); \ } \ } while (0) + +#else // Py_GIL_DISABLED + +#undef Py_DECREF +#define Py_DECREF(arg) \ + do { \ + PyObject *op = _PyObject_CAST(arg); \ + uint32_t local = _Py_atomic_load_uint32_relaxed(&op->ob_ref_local); \ + if (local == _Py_IMMORTAL_REFCNT_LOCAL) { \ + break; \ + } \ + _Py_DECREF_STAT_INC(); \ + if (_Py_IsOwnedByCurrentThread(op)) { \ + local--; \ + _Py_atomic_store_uint32_relaxed(&op->ob_ref_local, local); \ + if (local == 0) { \ + _Py_MergeZeroLocalRefcount(op); \ + } \ + } \ + else { \ + _Py_DecRefShared(op); \ + } \ + } while (0) + +#undef _Py_DECREF_SPECIALIZED +#define _Py_DECREF_SPECIALIZED(arg, dealloc) Py_DECREF(arg) + +#endif #endif diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 8726adeeeadc10..3d0f3b36a40ed2 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -2596,7 +2596,7 @@ *value_ptr = PyStackRef_AsPyObjectSteal(value); if (old_value == NULL) { PyDictValues *values = _PyObject_InlineValues(owner_o); - int index = value_ptr - values->values; + Py_ssize_t index = value_ptr - values->values; _PyDictValues_AddToInsertionOrder(values, index); } else { diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 69f5dc5a54378f..bf75cb901bc46d 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -6881,7 +6881,7 @@ *value_ptr = PyStackRef_AsPyObjectSteal(value); if (old_value == NULL) { PyDictValues *values = _PyObject_InlineValues(owner_o); - int index = value_ptr - values->values; + Py_ssize_t index = value_ptr - values->values; _PyDictValues_AddToInsertionOrder(values, index); } else {