From 49b351e83281b76abb3258a6cc66c230707801ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 8 Sep 2025 21:12:03 +0200 Subject: [PATCH 1/6] gh-133879: Improve consistency of full stops and whitespace in What's New (#138635) --- Doc/whatsnew/3.15.rst | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 01f1f31647f5e3..56ef80c068634a 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -295,6 +295,7 @@ dbm This may harm performance, but improve crash tolerance. (Contributed by Serhiy Storchaka in :gh:`66234`.) + difflib ------- @@ -379,6 +380,7 @@ os.path the resulting path can be missing but it will be free of symlinks. (Contributed by Petr Viktorin for :cve:`2025-4517`.) + resource -------- @@ -407,7 +409,7 @@ sqlite3 * 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`) + (Contributed by Stan Ulbrych and Łukasz Langa in :gh:`133461`.) ssl @@ -433,7 +435,7 @@ ssl 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`) + (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 @@ -692,12 +694,12 @@ New features * 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`) + (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`) + (Contributed by Petr Viktorin in :gh:`137210`.) Porting to Python 3.15 @@ -750,6 +752,7 @@ Deprecated C APIs :c:func:`_Py_c_abs` are :term:`soft deprecated`. (Contributed by Sergey B Kirpichev in :gh:`128813`.) + .. Add C API deprecations above alphabetically, not here at the end. Removed C APIs @@ -768,7 +771,7 @@ Removed C APIs 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`) + (Contributed by Stan Ulbrych in :gh:`133612`.) * :c:func:`!PyImport_ImportModuleNoBlock`: deprecated alias of :c:func:`PyImport_ImportModule`. From 5443b9e52febb43420622566b7569ef21078baa0 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 8 Sep 2025 20:21:28 +0100 Subject: [PATCH 2/6] gh-133143: Condense the implementation for ``sys.abi_info`` (#138672) --- .../pycore_global_objects_fini_generated.h | 2 + Include/internal/pycore_global_strings.h | 2 + .../internal/pycore_runtime_init_generated.h | 2 + .../internal/pycore_unicodeobject_generated.h | 8 ++++ Lib/test/test_sys.py | 14 +++---- ...-08-06-16-55-44.gh-issue-133143.l7CI9v.rst | 2 +- Python/sysmodule.c | 39 ++++++++----------- 7 files changed, 37 insertions(+), 32 deletions(-) diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 2078c201b4558d..ad65d1fda18e3b 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -984,6 +984,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(format)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(format_spec)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(frame_buffer)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(free_threaded)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(from_param)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(fromlist)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(fromtimestamp)); @@ -1182,6 +1183,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(person)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pi_factory)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pid)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pointer_bits)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(policy)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pos)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pos1)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index a7ebaf76c908c8..88283fa625706f 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -475,6 +475,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(format) STRUCT_FOR_ID(format_spec) STRUCT_FOR_ID(frame_buffer) + STRUCT_FOR_ID(free_threaded) STRUCT_FOR_ID(from_param) STRUCT_FOR_ID(fromlist) STRUCT_FOR_ID(fromtimestamp) @@ -673,6 +674,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(person) STRUCT_FOR_ID(pi_factory) STRUCT_FOR_ID(pid) + STRUCT_FOR_ID(pointer_bits) STRUCT_FOR_ID(policy) STRUCT_FOR_ID(pos) STRUCT_FOR_ID(pos1) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 27669c50cd6101..a08d77ab0a06b9 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -982,6 +982,7 @@ extern "C" { INIT_ID(format), \ INIT_ID(format_spec), \ INIT_ID(frame_buffer), \ + INIT_ID(free_threaded), \ INIT_ID(from_param), \ INIT_ID(fromlist), \ INIT_ID(fromtimestamp), \ @@ -1180,6 +1181,7 @@ extern "C" { INIT_ID(person), \ INIT_ID(pi_factory), \ INIT_ID(pid), \ + INIT_ID(pointer_bits), \ INIT_ID(policy), \ INIT_ID(pos), \ INIT_ID(pos1), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index c9b8a8b50510a2..57c0a7d51f89f3 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -1688,6 +1688,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(free_threaded); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(from_param); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2480,6 +2484,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(pointer_bits); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(policy); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 42672eb7912eba..1198c6d35113c8 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -741,17 +741,15 @@ def test_thread_info(self): def test_abi_info(self): info = sys.abi_info - self.assertEqual(len(info.__dict__), 4) + info_keys = {'pointer_bits', 'free_threaded', 'debug', 'byteorder'} + self.assertEqual(set(vars(info)), info_keys) pointer_bits = 64 if sys.maxsize > 2**32 else 32 self.assertEqual(info.pointer_bits, pointer_bits) + self.assertEqual(info.free_threaded, + bool(sysconfig.get_config_var('Py_GIL_DISABLED'))) + self.assertEqual(info.debug, + bool(sysconfig.get_config_var('Py_DEBUG'))) self.assertEqual(info.byteorder, sys.byteorder) - for attr, flag in [ - ("free_threaded", "Py_GIL_DISABLED"), - ("debug", "Py_DEBUG"), - ]: - self.assertEqual(getattr(info, attr, None), - bool(sysconfig.get_config_var(flag)), - f"for {attr}") @unittest.skipUnless(support.is_emscripten, "only available on Emscripten") def test_emscripten_info(self): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-08-06-16-55-44.gh-issue-133143.l7CI9v.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-08-06-16-55-44.gh-issue-133143.l7CI9v.rst index eaffb4022c6770..b357fbcdb9fbd0 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-08-06-16-55-44.gh-issue-133143.l7CI9v.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-08-06-16-55-44.gh-issue-133143.l7CI9v.rst @@ -1 +1 @@ -Add ``sys.abi_info`` object to make ABI information more easily accessible. +Add :data:`sys.abi_info` object to make ABI information more easily accessible. diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 95ab87589718ce..a5b42d48e432d7 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -3643,33 +3643,30 @@ make_impl_info(PyObject *version_info) static PyObject * make_abi_info(void) { - // New entries should be added when needed for a supported platform, or (for - // enabling an unsupported one) by core dev consensus. Entries should be removed - // following PEP 387. - int res; - PyObject *abi_info, *value, *ns; - abi_info = PyDict_New(); + // New entries should be added when needed for a supported platform, + // or by core dev consensus for enabling an unsupported one. + + PyObject *value; + PyObject *abi_info = PyDict_New(); if (abi_info == NULL) { - goto error; + return NULL; } value = PyLong_FromLong(sizeof(void *) * 8); if (value == NULL) { goto error; } - res = PyDict_SetItemString(abi_info, "pointer_bits", value); - Py_DECREF(value); - if (res < 0) { + if (PyDict_SetItem(abi_info, &_Py_ID(pointer_bits), value) < 0) { goto error; } + Py_DECREF(value); #ifdef Py_GIL_DISABLED value = Py_True; #else value = Py_False; #endif - res = PyDict_SetItemString(abi_info, "free_threaded", value); - if (res < 0) { + if (PyDict_SetItem(abi_info, &_Py_ID(free_threaded), value) < 0) { goto error; } @@ -3678,34 +3675,30 @@ make_abi_info(void) #else value = Py_False; #endif - res = PyDict_SetItemString(abi_info, "debug", value); - if (res < 0) { + if (PyDict_SetItem(abi_info, &_Py_ID(debug), value) < 0) { goto error; } #if PY_BIG_ENDIAN - value = PyUnicode_FromString("big"); + value = &_Py_ID(big); #else - value = PyUnicode_FromString("little"); + value = &_Py_ID(little); #endif - if (value == NULL) { - goto error; - } - res = PyDict_SetItemString(abi_info, "byteorder", value); - Py_DECREF(value); - if (res < 0) { + if (PyDict_SetItem(abi_info, &_Py_ID(byteorder), value) < 0) { goto error; } - ns = _PyNamespace_New(abi_info); + PyObject *ns = _PyNamespace_New(abi_info); Py_DECREF(abi_info); return ns; error: Py_DECREF(abi_info); + Py_XDECREF(value); return NULL; } + #ifdef __EMSCRIPTEN__ PyDoc_STRVAR(emscripten_info__doc__, From 6831634eb71360b0bd1b266d42fe24a930f38078 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 8 Sep 2025 20:31:24 +0100 Subject: [PATCH 3/6] gh-101100: Resolve reference warnings in reference/ (#138418) --- Doc/reference/compound_stmts.rst | 12 ++++++------ Doc/reference/datamodel.rst | 14 +++++++------- Doc/tools/.nitignore | 2 -- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index 05f05bc41a217f..9dca276e4a0001 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -610,9 +610,9 @@ The match statement is used for pattern matching. Syntax: .. productionlist:: python-grammar match_stmt: 'match' `subject_expr` ":" NEWLINE INDENT `case_block`+ DEDENT - subject_expr: `star_named_expression` "," `star_named_expressions`? - : | `named_expression` - case_block: 'case' `patterns` [`guard`] ":" `block` + subject_expr: `!star_named_expression` "," `!star_named_expressions`? + : | `!named_expression` + case_block: 'case' `patterns` [`guard`] ":" `!block` .. note:: This section uses single quotes to denote @@ -701,7 +701,7 @@ Guards .. index:: ! guard .. productionlist:: python-grammar - guard: "if" `named_expression` + guard: "if" `!named_expression` A ``guard`` (which is part of the ``case``) must succeed for code inside the ``case`` block to execute. It takes the form: :keyword:`if` followed by an @@ -1015,8 +1015,8 @@ subject value: items, as for a fixed-length sequence. .. note:: The length of the subject sequence is obtained via - :func:`len` (i.e. via the :meth:`__len__` protocol). This length may be - cached by the interpreter in a similar manner as + :func:`len` (i.e. via the :meth:`~object.__len__` protocol). + This length may be cached by the interpreter in a similar manner as :ref:`value patterns `. diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index ba0071631adfc0..68645d1da3d351 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -453,7 +453,7 @@ Sets These represent a mutable set. They are created by the built-in :func:`set` constructor and can be modified afterwards by several methods, such as - :meth:`~set.add`. + :meth:`add `. Frozen sets @@ -1272,7 +1272,7 @@ Special attributes * - .. attribute:: type.__firstlineno__ - The line number of the first line of the class definition, including decorators. - Setting the :attr:`__module__` attribute removes the + Setting the :attr:`~type.__module__` attribute removes the :attr:`!__firstlineno__` item from the type's dictionary. .. versionadded:: 3.13 @@ -1903,9 +1903,9 @@ falling back to :meth:`~object.__getitem__`). [#]_ When implementing a class that emulates any built-in type, it is important that the emulation only be implemented to the degree that it makes sense for the object being modelled. For example, some sequences may work well with retrieval -of individual elements, but extracting a slice may not make sense. (One example -of this is the :class:`~xml.dom.NodeList` interface in the W3C's Document -Object Model.) +of individual elements, but extracting a slice may not make sense. +(One example of this is the :ref:`NodeList ` interface +in the W3C's Document Object Model.) .. _customization: @@ -2697,7 +2697,7 @@ class defining the method. .. versionadded:: 3.6 -When a class is created, :meth:`type.__new__` scans the class variables +When a class is created, :meth:`!type.__new__` scans the class variables and makes callbacks to those with a :meth:`~object.__set_name__` hook. .. method:: object.__set_name__(self, owner, name) @@ -3145,7 +3145,7 @@ objects. The :mod:`collections.abc` module provides a Mutable sequences should provide methods :meth:`~sequence.append`, :meth:`~sequence.count`, :meth:`~sequence.index`, :meth:`~sequence.extend`, :meth:`~sequence.insert`, :meth:`~sequence.pop`, :meth:`~sequence.remove`, -:meth:`~sequence.reverse` and :meth:`~sequence.sort`, +:meth:`~sequence.reverse` and :meth:`!sort`, like Python standard :class:`list` objects. Finally, sequence types should implement addition (meaning concatenation) and multiplication (meaning repetition) by defining the methods diff --git a/Doc/tools/.nitignore b/Doc/tools/.nitignore index ad521f98162938..0ee92dce43790b 100644 --- a/Doc/tools/.nitignore +++ b/Doc/tools/.nitignore @@ -54,8 +54,6 @@ Doc/library/xml.sax.rst Doc/library/xmlrpc.client.rst Doc/library/xmlrpc.server.rst Doc/library/zlib.rst -Doc/reference/compound_stmts.rst -Doc/reference/datamodel.rst Doc/whatsnew/2.4.rst Doc/whatsnew/2.5.rst Doc/whatsnew/2.6.rst From 1561385863adb3dca0d554633090bc1d13aab415 Mon Sep 17 00:00:00 2001 From: Dino Viehland Date: Mon, 8 Sep 2025 13:53:12 -0700 Subject: [PATCH 4/6] =?UTF-8?q?gh-138679:=20Opcodes=20which=20consume=20no?= =?UTF-8?q?=20inputs=20should=20indicate=20they=20produced=20the=20val?= =?UTF-8?q?=E2=80=A6=20(#138678)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Opcodes which consume no inputs should indicate they produced the value, not an arbitrary local --- Lib/test/test_peepholer.py | 7 +++++++ Python/flowgraph.c | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index 98629df457460e..1caf6de4a14e39 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -1116,6 +1116,13 @@ def trace(frame, event, arg): self.assertInBytecode(f, "LOAD_FAST_BORROW") self.assertNotInBytecode(f, "LOAD_FAST_CHECK") + def test_import_from_doesnt_clobber_load_fast_borrow(self): + def f(self): + if x: pass + self.x + from shutil import ExecError + print(ExecError) + self.assertInBytecode(f, "LOAD_FAST_BORROW", "self") class DirectCfgOptimizerTests(CfgOptimizationTestCase): diff --git a/Python/flowgraph.c b/Python/flowgraph.c index 3a29845db9f7f8..18594ca2f44c0f 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -2891,7 +2891,7 @@ optimize_load_fast(cfg_builder *g) int num_pushed = _PyOpcode_num_pushed(opcode, oparg); int net_pushed = num_pushed - num_popped; assert(net_pushed >= 0); - for (int i = 0; i < net_pushed; i++) { + for (int j = 0; j < net_pushed; j++) { PUSH_REF(i, NOT_LOCAL); } break; From 22cb9ba8f90bfbc0b8831365b6864f41b19d0b6e Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 8 Sep 2025 23:10:26 +0100 Subject: [PATCH 5/6] GH-101100: Remove some entries from ``nitpick_ignore`` (#138464) --- Doc/conf.py | 9 --------- Doc/library/collections.rst | 6 +++--- Doc/library/dataclasses.rst | 2 +- Doc/library/dis.rst | 5 +++++ Doc/library/inspect.rst | 2 +- Doc/library/os.path.rst | 4 ++-- Doc/library/pathlib.rst | 2 +- Doc/library/stdtypes.rst | 11 ++++++----- Doc/reference/compound_stmts.rst | 4 ++-- Doc/tools/check-warnings.py | 2 +- Doc/tutorial/controlflow.rst | 2 +- Doc/whatsnew/3.2.rst | 2 +- Doc/whatsnew/3.4.rst | 2 +- Doc/whatsnew/3.5.rst | 2 +- Doc/whatsnew/3.6.rst | 2 +- Misc/NEWS.d/3.12.0a1.rst | 2 +- Misc/NEWS.d/3.13.0a6.rst | 6 ++++-- Misc/NEWS.d/3.14.0a7.rst | 2 +- 18 files changed, 33 insertions(+), 34 deletions(-) diff --git a/Doc/conf.py b/Doc/conf.py index bdc3ad13617948..c1b07df08b1782 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -221,13 +221,6 @@ ('envvar', 'USER'), ('envvar', 'USERNAME'), ('envvar', 'USERPROFILE'), - # Deprecated function that was never documented: - ('py:func', 'getargspec'), - ('py:func', 'inspect.getargspec'), - # Undocumented modules that users shouldn't have to worry about - # (implementation details of `os.path`): - ('py:mod', 'ntpath'), - ('py:mod', 'posixpath'), ] # Temporary undocumented names. @@ -242,8 +235,6 @@ ('py:meth', '_SubParsersAction.add_parser'), # Attributes/methods/etc. that definitely should be documented better, # but are deferred for now: - ('py:attr', '__annotations__'), - ('py:meth', '__missing__'), ('py:attr', '__wrapped__'), ] diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 17ca8b99db0235..fdd31799bd90d3 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -758,9 +758,9 @@ stack manipulations such as ``dup``, ``drop``, ``swap``, ``over``, ``pick``, .. attribute:: default_factory - This attribute is used by the :meth:`__missing__` method; it is - initialized from the first argument to the constructor, if present, or to - ``None``, if absent. + This attribute is used by the :meth:`~defaultdict.__missing__` method; + it is initialized from the first argument to the constructor, if present, + or to ``None``, if absent. .. versionchanged:: 3.9 Added merge (``|``) and update (``|=``) operators, specified in diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index 2e4520c823bf3e..ca432f2768a127 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -439,7 +439,7 @@ Module contents function is used. This function is not strictly required, because any Python - mechanism for creating a new class with :attr:`!__annotations__` can + mechanism for creating a new class with :attr:`~object.__annotations__` can then apply the :func:`@dataclass ` function to convert that class to a dataclass. This function is provided as a convenience. For example:: diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 7360f4aa804724..21bd1db5f338de 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -1086,6 +1086,11 @@ iterations of the loop. Pushes ``co_consts[consti]`` onto the stack. +.. opcode:: LOAD_CONST_IMMORTAL (consti) + + Works as :opcode:`LOAD_CONST`, but is more efficient for immortal objects. + + .. opcode:: LOAD_SMALL_INT (i) Pushes the integer ``i`` onto the stack. diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 1061ae8849f48f..7f2930ccd5523a 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -1179,7 +1179,7 @@ Classes and functions :func:`signature` in Python 3.5, but that decision has been reversed in order to restore a clearly supported standard interface for single-source Python 2/3 code migrating away from the legacy - :func:`getargspec` API. + :func:`!getargspec` API. .. versionchanged:: 3.7 Python only explicitly guaranteed that it preserved the declaration diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst index cb021be4543e75..bb9a7c86464050 100644 --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -42,8 +42,8 @@ the :mod:`glob` module.) a path that is *always* in one of the different formats. They all have the same interface: - * :mod:`posixpath` for UNIX-style paths - * :mod:`ntpath` for Windows paths + * :mod:`!posixpath` for UNIX-style paths + * :mod:`!ntpath` for Windows paths .. versionchanged:: 3.8 diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index ebf5756146df92..79e0b7f09eaa77 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -311,7 +311,7 @@ Pure paths provide the following methods and properties: .. attribute:: PurePath.parser The implementation of the :mod:`os.path` module used for low-level path - parsing and joining: either :mod:`posixpath` or :mod:`ntpath`. + parsing and joining: either :mod:`!posixpath` or :mod:`!ntpath`. .. versionadded:: 3.13 diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 3ea4edacf3d0cc..b30b7fef9089f1 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -5014,13 +5014,13 @@ can be used interchangeably to index the same dictionary entry. .. index:: __missing__() - If a subclass of dict defines a method :meth:`__missing__` and *key* + If a subclass of dict defines a method :meth:`~object.__missing__` and *key* is not present, the ``d[key]`` operation calls that method with the key *key* as argument. The ``d[key]`` operation then returns or raises whatever is returned or raised by the ``__missing__(key)`` call. - No other operations or methods invoke :meth:`__missing__`. If - :meth:`__missing__` is not defined, :exc:`KeyError` is raised. - :meth:`__missing__` must be a method; it cannot be an instance variable:: + No other operations or methods invoke :meth:`~object.__missing__`. If + :meth:`~object.__missing__` is not defined, :exc:`KeyError` is raised. + :meth:`~object.__missing__` must be a method; it cannot be an instance variable:: >>> class Counter(dict): ... def __missing__(self, key): @@ -5034,7 +5034,8 @@ can be used interchangeably to index the same dictionary entry. 1 The example above shows part of the implementation of - :class:`collections.Counter`. A different ``__missing__`` method is used + :class:`collections.Counter`. + A different :meth:`!__missing__` method is used by :class:`collections.defaultdict`. .. describe:: d[key] = value diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index 9dca276e4a0001..283b3b1bc6d86e 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -1067,8 +1067,8 @@ subject value: .. note:: Key-value pairs are matched using the two-argument form of the mapping subject's ``get()`` method. Matched key-value pairs must already be present - in the mapping, and not created on-the-fly via :meth:`__missing__` or - :meth:`~object.__getitem__`. + in the mapping, and not created on-the-fly via :meth:`~object.__missing__` + or :meth:`~object.__getitem__`. In simple terms ``{KEY1: P1, KEY2: P2, ... }`` matches only if all the following happens: diff --git a/Doc/tools/check-warnings.py b/Doc/tools/check-warnings.py index c686eecf8d9271..2f2bb9e2dcb7ef 100644 --- a/Doc/tools/check-warnings.py +++ b/Doc/tools/check-warnings.py @@ -15,7 +15,7 @@ from typing import TextIO # Fail if NEWS nit found before this line number -NEWS_NIT_THRESHOLD = 1700 +NEWS_NIT_THRESHOLD = 8550 # Exclude these whether they're dirty or clean, # because they trigger a rebuild of dirty files. diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst index b4b9d36cef1754..5ec8789f98c701 100644 --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -1081,7 +1081,7 @@ Function Annotations information about the types used by user-defined functions (see :pep:`3107` and :pep:`484` for more information). -:term:`Annotations ` are stored in the :attr:`!__annotations__` +:term:`Annotations ` are stored in the :attr:`~object.__annotations__` attribute of the function as a dictionary and have no effect on any other part of the function. Parameter annotations are defined by a colon after the parameter name, followed by an expression evaluating to the value of the annotation. Return annotations are diff --git a/Doc/whatsnew/3.2.rst b/Doc/whatsnew/3.2.rst index 7104904c956a7a..47c4d9acbc870e 100644 --- a/Doc/whatsnew/3.2.rst +++ b/Doc/whatsnew/3.2.rst @@ -458,7 +458,7 @@ Some smaller changes made to the core Python language are: :class:`~collections.defaultdict`, :class:`~shelve.Shelf`, :class:`~configparser.ConfigParser`, or :mod:`dbm`. It is also useful with custom :class:`dict` subclasses that normalize keys before look-up or that - supply a :meth:`__missing__` method for unknown keys:: + supply a :meth:`~object.__missing__` method for unknown keys:: >>> import shelve >>> d = shelve.open('tmp.shl') diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst index 5ad4f1c4a5e494..59afd6520c418f 100644 --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1039,7 +1039,7 @@ As part of the implementation of the new :mod:`enum` module, the metaclasses. (Contributed by Ethan Furman in :issue:`18929` and :issue:`19030`.) -:func:`~inspect.getfullargspec` and :func:`~inspect.getargspec` +:func:`~inspect.getfullargspec` and :func:`!getargspec` now use the :func:`~inspect.signature` API. This allows them to support a much broader range of callables, including those with ``__signature__`` attributes, those with metadata provided by argument diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst index d7af63497a0256..59e8ecebb10444 100644 --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -2324,7 +2324,7 @@ The previously undocumented ``from_function`` and ``from_builtin`` methods of :meth:`Signature.from_callable() ` method instead. (Contributed by Yury Selivanov in :issue:`24248`.) -The :func:`inspect.getargspec` function is deprecated and scheduled to be +The :func:`!inspect.getargspec` function is deprecated and scheduled to be removed in Python 3.6. (See :issue:`20438` for details.) The :mod:`inspect` :func:`~inspect.getfullargspec`, diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index 308596498b071a..b1e3269239d629 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -1224,7 +1224,7 @@ generator expression scopes as if they were positional-only parameters called ``implicit0``. (Contributed by Jelle Zijlstra in :issue:`19611`.) To reduce code churn when upgrading from Python 2.7 and the legacy -:func:`inspect.getargspec` API, the previously documented deprecation of +:func:`!inspect.getargspec` API, the previously documented deprecation of :func:`inspect.getfullargspec` has been reversed. While this function is convenient for single/source Python 2/3 code bases, the richer :func:`inspect.signature` interface remains the recommended approach for new diff --git a/Misc/NEWS.d/3.12.0a1.rst b/Misc/NEWS.d/3.12.0a1.rst index f2668e99a6299b..0da7cdde1b2535 100644 --- a/Misc/NEWS.d/3.12.0a1.rst +++ b/Misc/NEWS.d/3.12.0a1.rst @@ -4330,7 +4330,7 @@ and ``sendfile`` inside ``IocpProactor``. .. nonce: GsBL9- .. section: Library -Fixed :meth:`collections.UserDict.get` to not call :meth:`__missing__` when +Fixed :meth:`collections.UserDict.get` to not call :meth:`~object.__missing__` when a value is not found. This matches the behavior of :class:`dict`. Patch by Bar Harel. diff --git a/Misc/NEWS.d/3.13.0a6.rst b/Misc/NEWS.d/3.13.0a6.rst index 2740b4f0d967ba..ad6622d23bf36b 100644 --- a/Misc/NEWS.d/3.13.0a6.rst +++ b/Misc/NEWS.d/3.13.0a6.rst @@ -264,7 +264,8 @@ Improve performance of :func:`os.path.join` and :func:`os.path.expanduser`. .. nonce: hqk9Hn .. section: Library -Raise :exc:`TypeError` for non-paths in :func:`posixpath.relpath`. +Raise :exc:`TypeError` for non-paths in :func:`posixpath.relpath +`. .. @@ -273,7 +274,8 @@ Raise :exc:`TypeError` for non-paths in :func:`posixpath.relpath`. .. nonce: l6rWlj .. section: Library -Preserve mailbox ownership when rewriting in :func:`mailbox.mbox.flush`. +Preserve mailbox ownership when rewriting in :func:`mailbox.mbox.flush +`. Patch by Tony Mountifield. .. diff --git a/Misc/NEWS.d/3.14.0a7.rst b/Misc/NEWS.d/3.14.0a7.rst index ab64bdbb319027..946ca27046a745 100644 --- a/Misc/NEWS.d/3.14.0a7.rst +++ b/Misc/NEWS.d/3.14.0a7.rst @@ -192,7 +192,7 @@ The :class:`ctypes.py_object` type now supports subscription, making it a .. nonce: cX4yTn .. section: Library -Add the :attr:`zipfile.ZipFile.data_offset` attribute, which stores the +Add the :attr:`!zipfile.ZipFile.data_offset` attribute, which stores the offset to the beginning of ZIP data in a file when available. When the :class:`zipfile.ZipFile` is opened in either mode ``'w'`` or ``'x'`` and the underlying file does not support ``tell()``, the value will be ``None`` From 01895d233b4370e0c99f16c01a57cfd73c434b28 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 9 Sep 2025 00:45:42 +0200 Subject: [PATCH 6/6] gh-137242: Add a --no-randomize option, and use it in Android CI (#138649) Adds a --no-randomize option to the CI runner, so that randomisation can be easily disabled for --fast-ci and --slow-ci configurations on single-threaded testing platforms like Android, iOS, and Emscripten. --------- Co-authored-by: Malcolm Smith --- Android/android.py | 8 +++----- Lib/test/libregrtest/cmdline.py | 5 +++++ Lib/test/test_regrtest.py | 34 +++++++++++++++++++++++++++++++-- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/Android/android.py b/Android/android.py index 85874ad9b60f3d..15046b6fe1e1c0 100755 --- a/Android/android.py +++ b/Android/android.py @@ -737,12 +737,10 @@ def ci(context): # Prove the package is self-contained by using it to run the tests. shutil.unpack_archive(package_path, temp_dir) - # Arguments are similar to --fast-ci, but in single-process mode. + # Randomization is disabled because order-dependent failures are + # much less likely to pass on a rerun in single-process mode. launcher_args = ["--managed", "maxVersion", "-v"] - test_args = [ - "--single-process", "--fail-env-changed", "--rerun", "--slowest", - "--verbose3", "-u", "all,-cpu", "--timeout=600" - ] + test_args = ["--fast-ci", "--single-process", "--no-randomize"] run( ["./android.py", "test", *launcher_args, "--", *test_args], cwd=temp_dir diff --git a/Lib/test/libregrtest/cmdline.py b/Lib/test/libregrtest/cmdline.py index 07681d75448e24..b2daeadc7e7278 100644 --- a/Lib/test/libregrtest/cmdline.py +++ b/Lib/test/libregrtest/cmdline.py @@ -271,6 +271,9 @@ def _create_parser(): group = parser.add_argument_group('Selecting tests') group.add_argument('-r', '--randomize', action='store_true', help='randomize test execution order.' + more_details) + group.add_argument('--no-randomize', dest='no_randomize', action='store_true', + help='do not randomize test execution order, even if ' + 'it would be implied by another option') group.add_argument('--prioritize', metavar='TEST1,TEST2,...', action='append', type=priority_list, help='select these tests first, even if the order is' @@ -539,6 +542,8 @@ def _parse_args(args, **kwargs): ns.use_resources.append(r) if ns.random_seed is not None: ns.randomize = True + if ns.no_randomize: + ns.randomize = False if ns.verbose: ns.header = True diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index 5bc3c5924b07fb..50e6eb32817700 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -182,6 +182,22 @@ def test_randomize(self): self.assertTrue(regrtest.randomize) self.assertIsInstance(regrtest.random_seed, int) + def test_no_randomize(self): + ns = self.parse_args([]) + self.assertIs(ns.randomize, False) + + ns = self.parse_args(["--randomize"]) + self.assertIs(ns.randomize, True) + + ns = self.parse_args(["--no-randomize"]) + self.assertIs(ns.randomize, False) + + ns = self.parse_args(["--randomize", "--no-randomize"]) + self.assertIs(ns.randomize, False) + + ns = self.parse_args(["--no-randomize", "--randomize"]) + self.assertIs(ns.randomize, False) + def test_randseed(self): ns = self.parse_args(['--randseed', '12345']) self.assertEqual(ns.random_seed, 12345) @@ -189,6 +205,10 @@ def test_randseed(self): self.checkError(['--randseed'], 'expected one argument') self.checkError(['--randseed', 'foo'], 'invalid int value') + ns = self.parse_args(['--randseed', '12345', '--no-randomize']) + self.assertEqual(ns.random_seed, 12345) + self.assertFalse(ns.randomize) + def test_fromfile(self): for opt in '-f', '--fromfile': with self.subTest(opt=opt): @@ -428,11 +448,12 @@ def create_regrtest(self, args): return regrtest - def check_ci_mode(self, args, use_resources, rerun=True): + def check_ci_mode(self, args, use_resources, *, rerun=True, randomize=True): regrtest = self.create_regrtest(args) self.assertEqual(regrtest.num_workers, -1) self.assertEqual(regrtest.want_rerun, rerun) - self.assertTrue(regrtest.randomize) + self.assertEqual(regrtest.fail_rerun, False) + self.assertEqual(regrtest.randomize, randomize) self.assertIsInstance(regrtest.random_seed, int) self.assertTrue(regrtest.fail_env_changed) self.assertTrue(regrtest.print_slowest) @@ -469,6 +490,15 @@ def test_slow_ci(self): regrtest = self.check_ci_mode(args, use_resources) self.assertEqual(regrtest.timeout, 20 * 60) + def test_ci_no_randomize(self): + all_resources = set(cmdline.ALL_RESOURCES) + self.check_ci_mode( + ["--slow-ci", "--no-randomize"], all_resources, randomize=False + ) + self.check_ci_mode( + ["--fast-ci", "--no-randomize"], all_resources - {'cpu'}, randomize=False + ) + def test_dont_add_python_opts(self): args = ['--dont-add-python-opts'] ns = cmdline._parse_args(args)