Python-checkins
Threads by month
- ----- 2024 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
October 2024
- 1 participants
- 807 discussions
GH-109975: Copyedit 3.13 What's New: Note delayed expected release date for Python 3.13.0 (GH-124827)
by gpshead 01 Oct '24
by gpshead 01 Oct '24
01 Oct '24
https://github.com/python/cpython/commit/882369026481f904520784ebbbef989705…
commit: 882369026481f904520784ebbbef9897059dc6f6
branch: main
author: Adam Turner <9087854+AA-Turner(a)users.noreply.github.com>
committer: gpshead <greg(a)krypto.org>
date: 2024-10-01T07:18:59Z
summary:
GH-109975: Copyedit 3.13 What's New: Note delayed expected release date for Python 3.13.0 (GH-124827)
Note delayed expected release date of 3.13.0
files:
M Doc/whatsnew/3.13.rst
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index 52fe749697cfa4..506666d4dccb10 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -46,7 +46,7 @@
when researching a change.
This article explains the new features in Python 3.13, compared to 3.12.
-Python 3.13 will be released on October 1, 2024.
+Python 3.13 will be released on October 7, 2024.
For full details, see the :ref:`changelog <changelog>`.
.. seealso::
1
0
https://github.com/python/cpython/commit/0b05ead877f909b7efe712db758012d9db…
commit: 0b05ead877f909b7efe712db758012d9dbece7ce
branch: 3.12
author: Thomas Wouters <thomas(a)python.org>
committer: Yhg1s <thomas(a)python.org>
date: 2024-10-01T04:05:46+02:00
summary:
Python 3.12.7
files:
A Misc/NEWS.d/3.12.7.rst
D Misc/NEWS.d/next/Build/2024-09-11-16-06-42.gh-issue-123917.JuZl0r.rst
D Misc/NEWS.d/next/Build/2024-09-27-15-58-10.gh-issue-124487.PAZTQf.rst
D Misc/NEWS.d/next/C API/2024-07-04-15-41-10.gh-issue-113993.cLSiWV.rst
D Misc/NEWS.d/next/Core and Builtins/2024-06-14-22-02-25.gh-issue-113993.MiA0vX.rst
D Misc/NEWS.d/next/Core and Builtins/2024-06-19-21-34-21.gh-issue-98442.cqhjkN.rst
D Misc/NEWS.d/next/Core_and_Builtins/2024-09-10-13-27-16.gh-issue-77894.ZC-Olu.rst
D Misc/NEWS.d/next/Core_and_Builtins/2024-09-17-22-06-01.gh-issue-124188.aFqNAB.rst
D Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-12-05-45.gh-issue-116510.dhn8w8.rst
D Misc/NEWS.d/next/IDLE/2024-09-21-23-12-18.gh-issue-112938.OeiDru.rst
D Misc/NEWS.d/next/Library/2021-08-24-19-37-46.bpo-44864.KzxaDh.rst
D Misc/NEWS.d/next/Library/2024-07-03-14-23-04.gh-issue-119004.L5MoUu.rst
D Misc/NEWS.d/next/Library/2024-08-15-09-45-34.gh-issue-121735._1q0qf.rst
D Misc/NEWS.d/next/Library/2024-08-23-15-49-10.gh-issue-116810.QLBUU8.rst
D Misc/NEWS.d/next/Library/2024-09-10-11-26-14.gh-issue-123892.2gzIrz.rst
D Misc/NEWS.d/next/Library/2024-09-11-13-33-19.gh-issue-123935.fRZ_56.rst
D Misc/NEWS.d/next/Library/2024-09-13-10-34-19.gh-issue-123934.yMe7mL.rst
D Misc/NEWS.d/next/Library/2024-09-17-18-06-42.gh-issue-124171.PHCvRJ.rst
D Misc/NEWS.d/next/Library/2024-09-19-03-46-59.gh-issue-87041.9Ox7Bv.rst
D Misc/NEWS.d/next/Library/2024-09-19-10-36-18.gh-issue-81691.Hyhp_U.rst
D Misc/NEWS.d/next/Library/2024-09-19-11-47-39.gh-issue-124248.g7rufd.rst
D Misc/NEWS.d/next/Library/2024-09-19-20-15-00.gh-issue-124217.j0KlQB.rst
D Misc/NEWS.d/next/Library/2024-09-20-12-23-11.gh-issue-53780.mrV1zi.rst
D Misc/NEWS.d/next/Library/2024-09-21-19-02-37.gh-issue-59317.OAhNZZ.rst
D Misc/NEWS.d/next/Library/2024-09-21-22-32-21.gh-issue-72795.naLmkX.rst
D Misc/NEWS.d/next/Library/2024-09-21-23-56-41.gh-issue-63143.YKu-LQ.rst
D Misc/NEWS.d/next/Library/2024-09-23-17-33-47.gh-issue-104860.O86OSc.rst
D Misc/NEWS.d/next/Library/2024-09-24-12-34-48.gh-issue-124345.s3vKql.rst
D Misc/NEWS.d/next/Library/2024-09-25-12-14-58.gh-issue-124498.Ozxs55.rst
D Misc/NEWS.d/next/Library/2024-09-25-18-08-29.gh-issue-80259.kO5Tw7.rst
D Misc/NEWS.d/next/Library/2024-09-26-09-18-09.gh-issue-61181.dwjmch.rst
D Misc/NEWS.d/next/Library/2024-09-26-22-14-12.gh-issue-58573.hozbm9.rst
D Misc/NEWS.d/next/Library/2024-09-27-15-16-04.gh-issue-116850.dBkR0-.rst
D Misc/NEWS.d/next/Security/2024-08-07-10-42-13.gh-issue-122792.oiTMo9.rst
D Misc/NEWS.d/next/Tests/2024-09-25-12-39-34.gh-issue-124378.Ywwgia.rst
D Misc/NEWS.d/next/Windows/2024-04-24-22-50-33.gh-issue-117505.gcTb_p.rst
D Misc/NEWS.d/next/Windows/2024-09-10-19-23-00.gh-issue-123915.yZMEDO.rst
M Include/patchlevel.h
M Lib/pydoc_data/topics.py
M README.rst
diff --git a/Include/patchlevel.h b/Include/patchlevel.h
index e2a0d8db2d2635..4f0c8fb1aa4e48 100644
--- a/Include/patchlevel.h
+++ b/Include/patchlevel.h
@@ -18,12 +18,12 @@
/*--start constants--*/
#define PY_MAJOR_VERSION 3
#define PY_MINOR_VERSION 12
-#define PY_MICRO_VERSION 6
+#define PY_MICRO_VERSION 7
#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL
#define PY_RELEASE_SERIAL 0
/* Version as a string */
-#define PY_VERSION "3.12.6+"
+#define PY_VERSION "3.12.7"
/*--end constants--*/
/* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py
index 8113889a1f6c34..b5464cb4d04b9b 100644
--- a/Lib/pydoc_data/topics.py
+++ b/Lib/pydoc_data/topics.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Autogenerated by Sphinx on Fri Sep 6 21:00:45 2024
+# Autogenerated by Sphinx on Tue Oct 1 04:02:04 2024
# as part of the release process.
topics = {'assert': 'The "assert" statement\n'
'**********************\n'
@@ -1094,11 +1094,13 @@
'to the class\n'
' where it is defined. *__slots__* declared in parents '
'are available\n'
- ' in child classes. However, child subclasses will get a '
- '"__dict__"\n'
- ' and *__weakref__* unless they also define *__slots__* '
- '(which should\n'
- ' only contain names of any *additional* slots).\n'
+ ' in child classes. However, instances of a child '
+ 'subclass will get a\n'
+ ' "__dict__" and *__weakref__* unless the subclass also '
+ 'defines\n'
+ ' *__slots__* (which should only contain names of any '
+ '*additional*\n'
+ ' slots).\n'
'\n'
'* If a class defines a slot also defined in a base '
'class, the instance\n'
@@ -3571,10 +3573,12 @@
' parameter_list_no_posonly ::= defparameter ("," '
'defparameter)* ["," [parameter_list_starargs]]\n'
' | parameter_list_starargs\n'
- ' parameter_list_starargs ::= "*" [parameter] ("," '
+ ' parameter_list_starargs ::= "*" [star_parameter] ("," '
'defparameter)* ["," ["**" parameter [","]]]\n'
' | "**" parameter [","]\n'
' parameter ::= identifier [":" expression]\n'
+ ' star_parameter ::= identifier [":" ["*"] '
+ 'expression]\n'
' defparameter ::= parameter ["=" expression]\n'
' funcname ::= identifier\n'
'\n'
@@ -3702,27 +3706,31 @@
'expression"”\n'
'following the parameter name. Any parameter may have an '
'annotation,\n'
- 'even those of the form "*identifier" or "**identifier". '
- 'Functions may\n'
- 'have “return” annotation of the form “"-> expression"” after '
- 'the\n'
- 'parameter list. These annotations can be any valid Python '
- 'expression.\n'
- 'The presence of annotations does not change the semantics of a\n'
- 'function. The annotation values are available as values of a\n'
- 'dictionary keyed by the parameters’ names in the '
- '"__annotations__"\n'
- 'attribute of the function object. If the "annotations" import '
- 'from\n'
- '"__future__" is used, annotations are preserved as strings at '
- 'runtime\n'
- 'which enables postponed evaluation. Otherwise, they are '
- 'evaluated\n'
- 'when the function definition is executed. In this case '
- 'annotations\n'
- 'may be evaluated in a different order than they appear in the '
- 'source\n'
- 'code.\n'
+ 'even those of the form "*identifier" or "**identifier". (As a '
+ 'special\n'
+ 'case, parameters of the form "*identifier" may have an '
+ 'annotation “":\n'
+ '*expression"”.) Functions may have “return” annotation of the '
+ 'form\n'
+ '“"-> expression"” after the parameter list. These annotations '
+ 'can be\n'
+ 'any valid Python expression. The presence of annotations does '
+ 'not\n'
+ 'change the semantics of a function. The annotation values are\n'
+ 'available as values of a dictionary keyed by the parameters’ '
+ 'names in\n'
+ 'the "__annotations__" attribute of the function object. If the\n'
+ '"annotations" import from "__future__" is used, annotations are\n'
+ 'preserved as strings at runtime which enables postponed '
+ 'evaluation.\n'
+ 'Otherwise, they are evaluated when the function definition is\n'
+ 'executed. In this case annotations may be evaluated in a '
+ 'different\n'
+ 'order than they appear in the source code.\n'
+ '\n'
+ 'Changed in version 3.11: Parameters of the form “"*identifier"” '
+ 'may\n'
+ 'have an annotation “": *expression"”. See **PEP 646**.\n'
'\n'
'It is also possible to create anonymous functions (functions not '
'bound\n'
@@ -6231,11 +6239,11 @@
'\n'
'* While annotation scopes have an internal name, that name is '
'not\n'
- ' reflected in the *__qualname__* of objects defined within the '
- 'scope.\n'
- ' Instead, the "__qualname__" of such objects is as if the '
- 'object were\n'
- ' defined in the enclosing scope.\n'
+ ' reflected in the *qualified name* of objects defined within '
+ 'the\n'
+ ' scope. Instead, the "__qualname__" of such objects is as if '
+ 'the\n'
+ ' object were defined in the enclosing scope.\n'
'\n'
'Added in version 3.12: Annotation scopes were introduced in '
'Python\n'
@@ -6433,12 +6441,17 @@
'exprlists': 'Expression lists\n'
'****************\n'
'\n'
- ' expression_list ::= expression ("," expression)* [","]\n'
- ' starred_list ::= starred_item ("," starred_item)* '
+ ' starred_expression ::= ["*"] or_expr\n'
+ ' flexible_expression ::= assignment_expression | '
+ 'starred_expression\n'
+ ' flexible_expression_list ::= flexible_expression ("," '
+ 'flexible_expression)* [","]\n'
+ ' starred_expression_list ::= starred_expression ("," '
+ 'starred_expression)* [","]\n'
+ ' expression_list ::= expression ("," expression)* '
'[","]\n'
- ' starred_expression ::= expression | (starred_item ",")* '
- '[starred_item]\n'
- ' starred_item ::= assignment_expression | "*" or_expr\n'
+ ' yield_list ::= expression_list | '
+ 'starred_expression "," [starred_expression_list]\n'
'\n'
'Except when part of a list or set display, an expression list\n'
'containing at least one comma yields a tuple. The length of '
@@ -6457,6 +6470,10 @@
'Added in version 3.5: Iterable unpacking in expression lists,\n'
'originally proposed by **PEP 448**.\n'
'\n'
+ 'Added in version 3.11: Any item in an expression list may be '
+ 'starred.\n'
+ 'See **PEP 646**.\n'
+ '\n'
'A trailing comma is required only to create a one-item tuple, '
'such as\n'
'"1,"; it is optional in all other cases. A single expression '
@@ -7142,18 +7159,22 @@
'percent sign. |\n'
' '
'+-----------+------------------------------------------------------------+\n'
- ' | None | For "float" this is the same as "\'g\'", '
- 'except that when |\n'
- ' | | fixed-point notation is used to format the '
- 'result, it |\n'
+ ' | None | For "float" this is like the "\'g\'" type, '
+ 'except that when |\n'
+ ' | | fixed- point notation is used to format '
+ 'the result, it |\n'
' | | always includes at least one digit past '
- 'the decimal point. |\n'
- ' | | The precision used is as large as needed '
- 'to represent the |\n'
- ' | | given value faithfully. For "Decimal", '
- 'this is the same |\n'
- ' | | as either "\'g\'" or "\'G\'" depending on '
- 'the value of |\n'
+ 'the decimal point, |\n'
+ ' | | and switches to the scientific notation '
+ 'when "exp >= p - |\n'
+ ' | | 1". When the precision is not specified, '
+ 'the latter will |\n'
+ ' | | be as large as needed to represent the '
+ 'given value |\n'
+ ' | | faithfully. For "Decimal", this is the '
+ 'same as either |\n'
+ ' | | "\'g\'" or "\'G\'" depending on the value '
+ 'of |\n'
' | | "context.capitals" for the current decimal '
'context. The |\n'
' | | overall effect is to match the output of '
@@ -7343,10 +7364,12 @@
' parameter_list_no_posonly ::= defparameter ("," '
'defparameter)* ["," [parameter_list_starargs]]\n'
' | parameter_list_starargs\n'
- ' parameter_list_starargs ::= "*" [parameter] ("," '
+ ' parameter_list_starargs ::= "*" [star_parameter] ("," '
'defparameter)* ["," ["**" parameter [","]]]\n'
' | "**" parameter [","]\n'
' parameter ::= identifier [":" expression]\n'
+ ' star_parameter ::= identifier [":" ["*"] '
+ 'expression]\n'
' defparameter ::= parameter ["=" expression]\n'
' funcname ::= identifier\n'
'\n'
@@ -7474,27 +7497,31 @@
'expression"”\n'
'following the parameter name. Any parameter may have an '
'annotation,\n'
- 'even those of the form "*identifier" or "**identifier". '
- 'Functions may\n'
- 'have “return” annotation of the form “"-> expression"” after '
- 'the\n'
- 'parameter list. These annotations can be any valid Python '
- 'expression.\n'
- 'The presence of annotations does not change the semantics of a\n'
- 'function. The annotation values are available as values of a\n'
- 'dictionary keyed by the parameters’ names in the '
- '"__annotations__"\n'
- 'attribute of the function object. If the "annotations" import '
- 'from\n'
- '"__future__" is used, annotations are preserved as strings at '
- 'runtime\n'
- 'which enables postponed evaluation. Otherwise, they are '
- 'evaluated\n'
- 'when the function definition is executed. In this case '
- 'annotations\n'
- 'may be evaluated in a different order than they appear in the '
- 'source\n'
- 'code.\n'
+ 'even those of the form "*identifier" or "**identifier". (As a '
+ 'special\n'
+ 'case, parameters of the form "*identifier" may have an '
+ 'annotation “":\n'
+ '*expression"”.) Functions may have “return” annotation of the '
+ 'form\n'
+ '“"-> expression"” after the parameter list. These annotations '
+ 'can be\n'
+ 'any valid Python expression. The presence of annotations does '
+ 'not\n'
+ 'change the semantics of a function. The annotation values are\n'
+ 'available as values of a dictionary keyed by the parameters’ '
+ 'names in\n'
+ 'the "__annotations__" attribute of the function object. If the\n'
+ '"annotations" import from "__future__" is used, annotations are\n'
+ 'preserved as strings at runtime which enables postponed '
+ 'evaluation.\n'
+ 'Otherwise, they are evaluated when the function definition is\n'
+ 'executed. In this case annotations may be evaluated in a '
+ 'different\n'
+ 'order than they appear in the source code.\n'
+ '\n'
+ 'Changed in version 3.11: Parameters of the form “"*identifier"” '
+ 'may\n'
+ 'have an annotation “": *expression"”. See **PEP 646**.\n'
'\n'
'It is also possible to create anonymous functions (functions not '
'bound\n'
@@ -8250,7 +8277,8 @@
'in\n'
'square brackets:\n'
'\n'
- ' list_display ::= "[" [starred_list | comprehension] "]"\n'
+ ' list_display ::= "[" [flexible_expression_list | comprehension] '
+ '"]"\n'
'\n'
'A list display yields a new list object, the contents being '
'specified\n'
@@ -8501,11 +8529,9 @@
' can introduce new names.\n'
'\n'
'* While annotation scopes have an internal name, that name is not\n'
- ' reflected in the *__qualname__* of objects defined within the '
- 'scope.\n'
- ' Instead, the "__qualname__" of such objects is as if the object '
- 'were\n'
- ' defined in the enclosing scope.\n'
+ ' reflected in the *qualified name* of objects defined within the\n'
+ ' scope. Instead, the "__qualname__" of such objects is as if the\n'
+ ' object were defined in the enclosing scope.\n'
'\n'
'Added in version 3.12: Annotation scopes were introduced in '
'Python\n'
@@ -9721,20 +9747,6 @@
'not reported\n'
'by the "dir()" built-in function.\n'
'\n'
- 'object.__dict__\n'
- '\n'
- ' A dictionary or other mapping object used to store an '
- 'object’s\n'
- ' (writable) attributes.\n'
- '\n'
- 'instance.__class__\n'
- '\n'
- ' The class to which a class instance belongs.\n'
- '\n'
- 'class.__bases__\n'
- '\n'
- ' The tuple of base classes of a class object.\n'
- '\n'
'definition.__name__\n'
'\n'
' The name of the class, function, method, descriptor, or '
@@ -9749,39 +9761,26 @@
'\n'
' Added in version 3.3.\n'
'\n'
- 'definition.__type_params__\n'
- '\n'
- ' The type parameters of generic classes, functions, and '
- 'type\n'
- ' aliases.\n'
- '\n'
- ' Added in version 3.12.\n'
- '\n'
- 'class.__mro__\n'
+ 'definition.__module__\n'
'\n'
- ' This attribute is a tuple of classes that are considered '
- 'when\n'
- ' looking for base classes during method resolution.\n'
+ ' The name of the module in which a class or function was '
+ 'defined.\n'
'\n'
- 'class.mro()\n'
+ 'definition.__doc__\n'
'\n'
- ' This method can be overridden by a metaclass to customize '
- 'the\n'
- ' method resolution order for its instances. It is called '
- 'at class\n'
- ' instantiation, and its result is stored in "__mro__".\n'
+ ' The documentation string of a class or function, or '
+ '"None" if\n'
+ ' undefined.\n'
'\n'
- 'class.__subclasses__()\n'
+ 'definition.__type_params__\n'
'\n'
- ' Each class keeps a list of weak references to its '
- 'immediate\n'
- ' subclasses. This method returns a list of all those '
- 'references\n'
- ' still alive. The list is in definition order. Example:\n'
+ ' The type parameters of generic classes, functions, and '
+ 'type\n'
+ ' aliases. For classes and functions that are not generic, '
+ 'this will\n'
+ ' be an empty tuple.\n'
'\n'
- ' >>> int.__subclasses__()\n'
- " [<class 'bool'>, <enum 'IntEnum'>, <flag 'IntFlag'>, "
- "<class 're._constants._NamedIntConstant'>]\n",
+ ' Added in version 3.12.\n',
'specialnames': 'Special method names\n'
'********************\n'
'\n'
@@ -10727,11 +10726,13 @@
'the class\n'
' where it is defined. *__slots__* declared in parents are '
'available\n'
- ' in child classes. However, child subclasses will get a '
- '"__dict__"\n'
- ' and *__weakref__* unless they also define *__slots__* '
- '(which should\n'
- ' only contain names of any *additional* slots).\n'
+ ' in child classes. However, instances of a child subclass '
+ 'will get a\n'
+ ' "__dict__" and *__weakref__* unless the subclass also '
+ 'defines\n'
+ ' *__slots__* (which should only contain names of any '
+ '*additional*\n'
+ ' slots).\n'
'\n'
'* If a class defines a slot also defined in a base class, '
'the instance\n'
@@ -11148,7 +11149,7 @@
'built-in\n'
'types), including other ABCs.\n'
'\n'
- 'class.__instancecheck__(self, instance)\n'
+ 'type.__instancecheck__(self, instance)\n'
'\n'
' Return true if *instance* should be considered a (direct '
'or\n'
@@ -11156,7 +11157,7 @@
'implement\n'
' "isinstance(instance, class)".\n'
'\n'
- 'class.__subclasscheck__(self, subclass)\n'
+ 'type.__subclasscheck__(self, subclass)\n'
'\n'
' Return true if *subclass* should be considered a (direct '
'or\n'
@@ -13278,7 +13279,8 @@
'*generic\n'
'class* will generally return a GenericAlias object.\n'
'\n'
- ' subscription ::= primary "[" expression_list "]"\n'
+ ' subscription ::= primary "[" flexible_expression_list '
+ '"]"\n'
'\n'
'When an object is subscripted, the interpreter will '
'evaluate the\n'
@@ -13297,13 +13299,18 @@
'see\n'
'__class_getitem__ versus __getitem__.\n'
'\n'
- 'If the expression list contains at least one comma, it will '
- 'evaluate\n'
- 'to a "tuple" containing the items of the expression list. '
- 'Otherwise,\n'
- 'the expression list will evaluate to the value of the '
- 'list’s sole\n'
- 'member.\n'
+ 'If the expression list contains at least one comma, or if '
+ 'any of the\n'
+ 'expressions are starred, the expression list will evaluate '
+ 'to a\n'
+ '"tuple" containing the items of the expression list. '
+ 'Otherwise, the\n'
+ 'expression list will evaluate to the value of the list’s '
+ 'sole member.\n'
+ '\n'
+ 'Changed in version 3.11: Expressions in an expression list '
+ 'may be\n'
+ 'starred. See **PEP 646**.\n'
'\n'
'For built-in objects, there are two types of objects that '
'support\n'
@@ -14052,8 +14059,8 @@
'|====================================================|====================================================|\n'
'| function.__doc__ | The '
'function’s documentation string, or "None" if |\n'
- '| | unavailable. '
- 'Not inherited by subclasses. |\n'
+ '| | '
+ 'unavailable. |\n'
'+----------------------------------------------------+----------------------------------------------------+\n'
'| function.__name__ | The '
'function’s name. See also: "__name__ |\n'
@@ -14423,32 +14430,104 @@
'A class object can be called (see above) to yield a class instance\n'
'(see below).\n'
'\n'
- 'Special attributes:\n'
'\n'
- ' "__name__"\n'
- ' The class name.\n'
+ 'Special attributes\n'
+ '------------------\n'
'\n'
- ' "__module__"\n'
- ' The name of the module in which the class was defined.\n'
+ '+----------------------------------------------------+----------------------------------------------------+\n'
+ '| Attribute | '
+ 'Meaning |\n'
+ '|====================================================|====================================================|\n'
+ '| type.__name__ | The class’s '
+ 'name. See also: "__name__ attributes". |\n'
+ '+----------------------------------------------------+----------------------------------------------------+\n'
+ '| type.__qualname__ | The class’s '
+ '*qualified name*. See also: |\n'
+ '| | '
+ '"__qualname__ attributes". |\n'
+ '+----------------------------------------------------+----------------------------------------------------+\n'
+ '| type.__module__ | The name of '
+ 'the module in which the class was |\n'
+ '| | '
+ 'defined. |\n'
+ '+----------------------------------------------------+----------------------------------------------------+\n'
+ '| type.__dict__ | A "mapping '
+ 'proxy" providing a read-only view of |\n'
+ '| | the class’s '
+ 'namespace. See also: "__dict__ |\n'
+ '| | '
+ 'attributes". |\n'
+ '+----------------------------------------------------+----------------------------------------------------+\n'
+ '| type.__bases__ | A "tuple" '
+ 'containing the class’s bases. In most |\n'
+ '| | cases, for a '
+ 'class defined as "class X(A, B, C)", |\n'
+ '| | '
+ '"X.__bases__" will be exactly equal to "(A, B, |\n'
+ '| | '
+ 'C)". |\n'
+ '+----------------------------------------------------+----------------------------------------------------+\n'
+ '| type.__doc__ | The class’s '
+ 'documentation string, or "None" if |\n'
+ '| | undefined. '
+ 'Not inherited by subclasses. |\n'
+ '+----------------------------------------------------+----------------------------------------------------+\n'
+ '| type.__annotations__ | A dictionary '
+ 'containing *variable annotations* |\n'
+ '| | collected '
+ 'during class body execution. For best |\n'
+ '| | practices on '
+ 'working with "__annotations__", |\n'
+ '| | please see '
+ 'Annotations Best Practices. Caution: |\n'
+ '| | Accessing '
+ 'the "__annotations__" attribute of a |\n'
+ '| | class object '
+ 'directly may yield incorrect results |\n'
+ '| | in the '
+ 'presence of metaclasses. In addition, the |\n'
+ '| | attribute '
+ 'may not exist for some classes. Use |\n'
+ '| | '
+ '"inspect.get_annotations()" to retrieve class |\n'
+ '| | annotations '
+ 'safely. |\n'
+ '+----------------------------------------------------+----------------------------------------------------+\n'
+ '| type.__type_params__ | A "tuple" '
+ 'containing the type parameters of a |\n'
+ '| | generic '
+ 'class. Added in version 3.12. |\n'
+ '+----------------------------------------------------+----------------------------------------------------+\n'
+ '| type.__mro__ | The "tuple" '
+ 'of classes that are considered when |\n'
+ '| | looking for '
+ 'base classes during method resolution. |\n'
+ '+----------------------------------------------------+----------------------------------------------------+\n'
'\n'
- ' "__dict__"\n'
- ' The dictionary containing the class’s namespace.\n'
'\n'
- ' "__bases__"\n'
- ' A tuple containing the base classes, in the order of their\n'
- ' occurrence in the base class list.\n'
+ 'Special methods\n'
+ '---------------\n'
'\n'
- ' "__doc__"\n'
- ' The class’s documentation string, or "None" if undefined.\n'
+ 'In addition to the special attributes described above, all Python\n'
+ 'classes also have the following two methods available:\n'
'\n'
- ' "__annotations__"\n'
- ' A dictionary containing *variable annotations* collected '
- 'during\n'
- ' class body execution. For best practices on working with\n'
- ' "__annotations__", please see Annotations Best Practices.\n'
+ 'type.mro()\n'
'\n'
- ' "__type_params__"\n'
- ' A tuple containing the type parameters of a generic class.\n'
+ ' This method can be overridden by a metaclass to customize the\n'
+ ' method resolution order for its instances. It is called at '
+ 'class\n'
+ ' instantiation, and its result is stored in "__mro__".\n'
+ '\n'
+ 'type.__subclasses__()\n'
+ '\n'
+ ' Each class keeps a list of weak references to its immediate\n'
+ ' subclasses. This method returns a list of all those references\n'
+ ' still alive. The list is in definition order. Example:\n'
+ '\n'
+ ' >>> class A: pass\n'
+ ' >>> class B(A): pass\n'
+ ' >>> A.__subclasses__()\n'
+ " [<class 'B'>]\n"
'\n'
'\n'
'Class instances\n'
@@ -14488,8 +14567,19 @@
'they have methods with certain special names. See section Special\n'
'method names.\n'
'\n'
- 'Special attributes: "__dict__" is the attribute dictionary;\n'
- '"__class__" is the instance’s class.\n'
+ '\n'
+ 'Special attributes\n'
+ '------------------\n'
+ '\n'
+ 'object.__class__\n'
+ '\n'
+ ' The class to which a class instance belongs.\n'
+ '\n'
+ 'object.__dict__\n'
+ '\n'
+ ' A dictionary or other mapping object used to store an object’s\n'
+ ' (writable) attributes. Not all instances have a "__dict__"\n'
+ ' attribute; see the section on __slots__ for more details.\n'
'\n'
'\n'
'I/O objects (also known as file objects)\n'
diff --git a/Misc/NEWS.d/3.12.7.rst b/Misc/NEWS.d/3.12.7.rst
new file mode 100644
index 00000000000000..276166deca1a23
--- /dev/null
+++ b/Misc/NEWS.d/3.12.7.rst
@@ -0,0 +1,377 @@
+.. date: 2024-09-10-19-23-00
+.. gh-issue: 123915
+.. nonce: yZMEDO
+.. release date: 2024-10-01
+.. section: Windows
+
+Ensure that ``Tools\msi\buildrelease.bat`` uses different directories for
+AMD64 and ARM64 builds.
+
+..
+
+.. date: 2024-04-24-22-50-33
+.. gh-issue: 117505
+.. nonce: gcTb_p
+.. section: Windows
+
+Fixes an issue with the Windows installer not running ensurepip in a fully
+isolated environment. This could cause unexpected interactions with the user
+site-packages.
+
+..
+
+.. date: 2024-09-25-12-39-34
+.. gh-issue: 124378
+.. nonce: Ywwgia
+.. section: Tests
+
+Updated ``test_ttk`` to pass with Tcl/Tk 8.6.15.
+
+..
+
+.. date: 2024-08-07-10-42-13
+.. gh-issue: 122792
+.. nonce: oiTMo9
+.. section: Security
+
+Changed IPv4-mapped ``ipaddress.IPv6Address`` to consistently use the mapped
+IPv4 address value for deciding properties. Properties which have their
+behavior fixed are ``is_multicast``, ``is_reserved``, ``is_link_local``,
+``is_global``, and ``is_unspecified``.
+
+..
+
+.. date: 2024-09-27-15-16-04
+.. gh-issue: 116850
+.. nonce: dBkR0-
+.. section: Library
+
+Fix :mod:`argparse` for namespaces with not directly writable dict (e.g.
+classes).
+
+..
+
+.. date: 2024-09-26-22-14-12
+.. gh-issue: 58573
+.. nonce: hozbm9
+.. section: Library
+
+Fix conflicts between abbreviated long options in the parent parser and
+subparsers in :mod:`argparse`.
+
+..
+
+.. date: 2024-09-26-09-18-09
+.. gh-issue: 61181
+.. nonce: dwjmch
+.. section: Library
+
+Fix support of :ref:`choices` with string value in :mod:`argparse`.
+Substrings of the specified string no longer considered valid values.
+
+..
+
+.. date: 2024-09-25-18-08-29
+.. gh-issue: 80259
+.. nonce: kO5Tw7
+.. section: Library
+
+Fix :mod:`argparse` support of positional arguments with ``nargs='?'``,
+``default=argparse.SUPPRESS`` and specified ``type``.
+
+..
+
+.. date: 2024-09-25-12-14-58
+.. gh-issue: 124498
+.. nonce: Ozxs55
+.. section: Library
+
+Fix :class:`typing.TypeAliasType` not to be generic, when ``type_params`` is
+an empty tuple.
+
+..
+
+.. date: 2024-09-24-12-34-48
+.. gh-issue: 124345
+.. nonce: s3vKql
+.. section: Library
+
+:mod:`argparse` vim supports abbreviated single-dash long options separated
+by ``=`` from its value.
+
+..
+
+.. date: 2024-09-23-17-33-47
+.. gh-issue: 104860
+.. nonce: O86OSc
+.. section: Library
+
+Fix disallowing abbreviation of single-dash long options in :mod:`argparse`
+with ``allow_abbrev=False``.
+
+..
+
+.. date: 2024-09-21-23-56-41
+.. gh-issue: 63143
+.. nonce: YKu-LQ
+.. section: Library
+
+Fix parsing mutually exclusive arguments in :mod:`argparse`. Arguments with
+the value identical to the default value (e.g. booleans, small integers,
+empty or 1-character strings) are no longer considered "not present".
+
+..
+
+.. date: 2024-09-21-22-32-21
+.. gh-issue: 72795
+.. nonce: naLmkX
+.. section: Library
+
+Positional arguments with :ref:`nargs` equal to ``'*'`` or
+:data:`!argparse.REMAINDER` are no longer required. This allows to use
+positional argument with ``nargs='*'`` and without ``default`` in mutually
+exclusive group and improves error message about required arguments.
+
+..
+
+.. date: 2024-09-21-19-02-37
+.. gh-issue: 59317
+.. nonce: OAhNZZ
+.. section: Library
+
+Fix parsing positional argument with :ref:`nargs` equal to ``'?'`` or
+``'*'`` if it is preceded by an option and another positional argument.
+
+..
+
+.. date: 2024-09-20-12-23-11
+.. gh-issue: 53780
+.. nonce: mrV1zi
+.. section: Library
+
+:mod:`argparse` now ignores the first ``"--"`` (double dash) between an
+option and command.
+
+..
+
+.. date: 2024-09-19-20-15-00
+.. gh-issue: 124217
+.. nonce: j0KlQB
+.. section: Library
+
+Add RFC 9637 reserved IPv6 block ``3fff::/20`` in :mod:`ipaddress` module.
+
+..
+
+.. date: 2024-09-19-11-47-39
+.. gh-issue: 124248
+.. nonce: g7rufd
+.. section: Library
+
+Fixed potential crash when using :mod:`struct` to process zero-width 'Pascal
+string' fields (``0p``).
+
+..
+
+.. date: 2024-09-19-10-36-18
+.. gh-issue: 81691
+.. nonce: Hyhp_U
+.. section: Library
+
+Fix handling of multiple ``"--"`` (double dashes) in :mod:`argparse`. Only
+the first one has now been removed, all subsequent ones are now taken
+literally.
+
+..
+
+.. date: 2024-09-19-03-46-59
+.. gh-issue: 87041
+.. nonce: 9Ox7Bv
+.. section: Library
+
+Fix a bug in :mod:`argparse` where lengthy subparser argument help is
+incorrectly indented.
+
+..
+
+.. date: 2024-09-17-18-06-42
+.. gh-issue: 124171
+.. nonce: PHCvRJ
+.. section: Library
+
+Add workaround for broken :c:func:`!fmod()` implementations on Windows, that
+loose zero sign (e.g. ``fmod(-10, 1)`` returns ``0.0``). Patch by Sergey B
+Kirpichev.
+
+..
+
+.. date: 2024-09-13-10-34-19
+.. gh-issue: 123934
+.. nonce: yMe7mL
+.. section: Library
+
+Fix :class:`unittest.mock.MagicMock` reseting magic methods return values
+after ``.reset_mock(return_value=True)`` was called.
+
+..
+
+.. date: 2024-09-11-13-33-19
+.. gh-issue: 123935
+.. nonce: fRZ_56
+.. section: Library
+
+Fix parent slots detection for dataclasses that inherit from classes with
+``__dictoffset__``.
+
+..
+
+.. date: 2024-09-10-11-26-14
+.. gh-issue: 123892
+.. nonce: 2gzIrz
+.. section: Library
+
+Add ``"_wmi"`` to :data:`sys.stdlib_module_names`. Patch by Victor Stinner.
+
+..
+
+.. date: 2024-08-23-15-49-10
+.. gh-issue: 116810
+.. nonce: QLBUU8
+.. section: Library
+
+Resolve a memory leak introduced in CPython 3.10's :mod:`ssl` when the
+:attr:`ssl.SSLSocket.session` property was accessed. Speeds up read and
+write access to said property by no longer unnecessarily cloning session
+objects via serialization.
+
+..
+
+.. date: 2024-08-15-09-45-34
+.. gh-issue: 121735
+.. nonce: _1q0qf
+.. section: Library
+
+When working with zip archives, importlib.resources now properly honors
+module-adjacent references (e.g. ``files(pkg.mod)`` and not just
+``files(pkg)``).
+
+..
+
+.. date: 2024-07-03-14-23-04
+.. gh-issue: 119004
+.. nonce: L5MoUu
+.. section: Library
+
+Fix a crash in :ref:`OrderedDict.__eq__ <collections_OrderedDict__eq__>`
+when operands are mutated during the check. Patch by Bénédikt Tran.
+
+..
+
+.. bpo: 44864
+.. date: 2021-08-24-19-37-46
+.. nonce: KzxaDh
+.. section: Library
+
+Do not translate user-provided strings in :class:`argparse.ArgumentParser`.
+
+..
+
+.. date: 2024-09-21-23-12-18
+.. gh-issue: 112938
+.. nonce: OeiDru
+.. section: IDLE
+
+Fix uninteruptable hang when Shell gets rapid continuous output.
+
+..
+
+.. date: 2024-09-25-12-05-45
+.. gh-issue: 116510
+.. nonce: dhn8w8
+.. section: Core and Builtins
+
+Fix a bug that can cause a crash when sub-interpreters use "basic"
+single-phase extension modules. Shared objects could refer to PyGC_Head
+nodes that had been freed as part of interpreter cleanup.
+
+..
+
+.. date: 2024-09-17-22-06-01
+.. gh-issue: 124188
+.. nonce: aFqNAB
+.. section: Core and Builtins
+
+Fix reading and decoding a line from the source file witn non-UTF-8 encoding
+for syntax errors raised in the compiler.
+
+..
+
+.. date: 2024-09-10-13-27-16
+.. gh-issue: 77894
+.. nonce: ZC-Olu
+.. section: Core and Builtins
+
+Fix possible crash in the garbage collector when it tries to break a
+reference loop containing a :class:`memoryview` object. Now a
+:class:`!memoryview` object can only be cleared if there are no buffers that
+refer it.
+
+..
+
+.. date: 2024-06-19-21-34-21
+.. gh-issue: 98442
+.. nonce: cqhjkN
+.. section: Core and Builtins
+
+Fix too wide source locations of the cleanup instructions of a with
+statement.
+
+..
+
+.. date: 2024-06-14-22-02-25
+.. gh-issue: 113993
+.. nonce: MiA0vX
+.. section: Core and Builtins
+
+Strings interned with :func:`sys.intern` are again garbage-collected when no
+longer used, as per the documentation. Strings interned with the C function
+:c:func:`PyUnicode_InternInPlace` are still immortal. Internals of the
+string interning mechanism have been changed. This may affect performance
+and identities of :class:`str` objects.
+
+..
+
+.. date: 2024-07-04-15-41-10
+.. gh-issue: 113993
+.. nonce: cLSiWV
+.. section: C API
+
+:c:func:`PyUnicode_InternInPlace` no longer prevents its argument from being
+garbage collected.
+
+Several functions that take ``char *`` are now documented as possibly
+preventing string objects from being garbage collected; refer to their
+documentation for details: :c:func:`PyUnicode_InternFromString`,
+:c:func:`PyDict_SetItemString`, :c:func:`PyObject_SetAttrString`,
+:c:func:`PyObject_DelAttrString`, :c:func:`PyUnicode_InternFromString`, and
+``PyModule_Add*`` convenience functions.
+
+..
+
+.. date: 2024-09-27-15-58-10
+.. gh-issue: 124487
+.. nonce: PAZTQf
+.. section: Build
+
+Windows builds now use Windows 8.1 as their API baseline (installation
+already required Windows 8.1).
+
+..
+
+.. date: 2024-09-11-16-06-42
+.. gh-issue: 123917
+.. nonce: JuZl0r
+.. section: Build
+
+Fix the check for the ``crypt()`` function in the configure script. Patch by
+Paul Smith and Victor Stinner.
diff --git a/Misc/NEWS.d/next/Build/2024-09-11-16-06-42.gh-issue-123917.JuZl0r.rst b/Misc/NEWS.d/next/Build/2024-09-11-16-06-42.gh-issue-123917.JuZl0r.rst
deleted file mode 100644
index 4cf4a177f1513f..00000000000000
--- a/Misc/NEWS.d/next/Build/2024-09-11-16-06-42.gh-issue-123917.JuZl0r.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Fix the check for the ``crypt()`` function in the configure script. Patch by
-Paul Smith and Victor Stinner.
diff --git a/Misc/NEWS.d/next/Build/2024-09-27-15-58-10.gh-issue-124487.PAZTQf.rst b/Misc/NEWS.d/next/Build/2024-09-27-15-58-10.gh-issue-124487.PAZTQf.rst
deleted file mode 100644
index 0ffadb2755a2d0..00000000000000
--- a/Misc/NEWS.d/next/Build/2024-09-27-15-58-10.gh-issue-124487.PAZTQf.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Windows builds now use Windows 8.1 as their API baseline (installation
-already required Windows 8.1).
diff --git a/Misc/NEWS.d/next/C API/2024-07-04-15-41-10.gh-issue-113993.cLSiWV.rst b/Misc/NEWS.d/next/C API/2024-07-04-15-41-10.gh-issue-113993.cLSiWV.rst
deleted file mode 100644
index 9b7f2082065eaa..00000000000000
--- a/Misc/NEWS.d/next/C API/2024-07-04-15-41-10.gh-issue-113993.cLSiWV.rst
+++ /dev/null
@@ -1,12 +0,0 @@
-:c:func:`PyUnicode_InternInPlace` no longer prevents its argument from being
-garbage collected.
-
-Several functions that take ``char *`` are now
-documented as possibly preventing string objects from being garbage
-collected; refer to their documentation for details:
-:c:func:`PyUnicode_InternFromString`,
-:c:func:`PyDict_SetItemString`,
-:c:func:`PyObject_SetAttrString`,
-:c:func:`PyObject_DelAttrString`,
-:c:func:`PyUnicode_InternFromString`,
-and ``PyModule_Add*`` convenience functions.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-06-14-22-02-25.gh-issue-113993.MiA0vX.rst b/Misc/NEWS.d/next/Core and Builtins/2024-06-14-22-02-25.gh-issue-113993.MiA0vX.rst
deleted file mode 100644
index 9931787cb36d4c..00000000000000
--- a/Misc/NEWS.d/next/Core and Builtins/2024-06-14-22-02-25.gh-issue-113993.MiA0vX.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-Strings interned with :func:`sys.intern` are again garbage-collected when no
-longer used, as per the documentation. Strings interned with the C function
-:c:func:`PyUnicode_InternInPlace` are still immortal. Internals of the
-string interning mechanism have been changed. This may affect performance
-and identities of :class:`str` objects.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-06-19-21-34-21.gh-issue-98442.cqhjkN.rst b/Misc/NEWS.d/next/Core and Builtins/2024-06-19-21-34-21.gh-issue-98442.cqhjkN.rst
deleted file mode 100644
index fb0a93f41a583f..00000000000000
--- a/Misc/NEWS.d/next/Core and Builtins/2024-06-19-21-34-21.gh-issue-98442.cqhjkN.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Fix too wide source locations of the cleanup instructions of a with
-statement.
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-10-13-27-16.gh-issue-77894.ZC-Olu.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-10-13-27-16.gh-issue-77894.ZC-Olu.rst
deleted file mode 100644
index a714033dd296b9..00000000000000
--- a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-10-13-27-16.gh-issue-77894.ZC-Olu.rst
+++ /dev/null
@@ -1,4 +0,0 @@
-Fix possible crash in the garbage collector when it tries to break a
-reference loop containing a :class:`memoryview` object. Now a
-:class:`!memoryview` object can only be cleared if there are no buffers that
-refer it.
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-17-22-06-01.gh-issue-124188.aFqNAB.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-17-22-06-01.gh-issue-124188.aFqNAB.rst
deleted file mode 100644
index 0c2935fbe000bc..00000000000000
--- a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-17-22-06-01.gh-issue-124188.aFqNAB.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Fix reading and decoding a line from the source file witn non-UTF-8 encoding
-for syntax errors raised in the compiler.
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-12-05-45.gh-issue-116510.dhn8w8.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-12-05-45.gh-issue-116510.dhn8w8.rst
deleted file mode 100644
index fc3f8af72d87bf..00000000000000
--- a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-12-05-45.gh-issue-116510.dhn8w8.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-Fix a bug that can cause a crash when sub-interpreters use "basic"
-single-phase extension modules. Shared objects could refer to PyGC_Head
-nodes that had been freed as part of interpreter cleanup.
diff --git a/Misc/NEWS.d/next/IDLE/2024-09-21-23-12-18.gh-issue-112938.OeiDru.rst b/Misc/NEWS.d/next/IDLE/2024-09-21-23-12-18.gh-issue-112938.OeiDru.rst
deleted file mode 100644
index 0cd058eeffb1d5..00000000000000
--- a/Misc/NEWS.d/next/IDLE/2024-09-21-23-12-18.gh-issue-112938.OeiDru.rst
+++ /dev/null
@@ -1 +0,0 @@
-Fix uninteruptable hang when Shell gets rapid continuous output.
diff --git a/Misc/NEWS.d/next/Library/2021-08-24-19-37-46.bpo-44864.KzxaDh.rst b/Misc/NEWS.d/next/Library/2021-08-24-19-37-46.bpo-44864.KzxaDh.rst
deleted file mode 100644
index 9610fa90ef0a98..00000000000000
--- a/Misc/NEWS.d/next/Library/2021-08-24-19-37-46.bpo-44864.KzxaDh.rst
+++ /dev/null
@@ -1 +0,0 @@
-Do not translate user-provided strings in :class:`argparse.ArgumentParser`.
diff --git a/Misc/NEWS.d/next/Library/2024-07-03-14-23-04.gh-issue-119004.L5MoUu.rst b/Misc/NEWS.d/next/Library/2024-07-03-14-23-04.gh-issue-119004.L5MoUu.rst
deleted file mode 100644
index 899bd163d36644..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-07-03-14-23-04.gh-issue-119004.L5MoUu.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Fix a crash in :ref:`OrderedDict.__eq__ <collections_OrderedDict__eq__>`
-when operands are mutated during the check. Patch by Bénédikt Tran.
diff --git a/Misc/NEWS.d/next/Library/2024-08-15-09-45-34.gh-issue-121735._1q0qf.rst b/Misc/NEWS.d/next/Library/2024-08-15-09-45-34.gh-issue-121735._1q0qf.rst
deleted file mode 100644
index e10b2e760bc063..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-08-15-09-45-34.gh-issue-121735._1q0qf.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-When working with zip archives, importlib.resources now properly honors
-module-adjacent references (e.g. ``files(pkg.mod)`` and not just
-``files(pkg)``).
diff --git a/Misc/NEWS.d/next/Library/2024-08-23-15-49-10.gh-issue-116810.QLBUU8.rst b/Misc/NEWS.d/next/Library/2024-08-23-15-49-10.gh-issue-116810.QLBUU8.rst
deleted file mode 100644
index 0e5256e7151c5a..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-08-23-15-49-10.gh-issue-116810.QLBUU8.rst
+++ /dev/null
@@ -1,4 +0,0 @@
-Resolve a memory leak introduced in CPython 3.10's :mod:`ssl` when the
-:attr:`ssl.SSLSocket.session` property was accessed. Speeds up read and
-write access to said property by no longer unnecessarily cloning session
-objects via serialization.
diff --git a/Misc/NEWS.d/next/Library/2024-09-10-11-26-14.gh-issue-123892.2gzIrz.rst b/Misc/NEWS.d/next/Library/2024-09-10-11-26-14.gh-issue-123892.2gzIrz.rst
deleted file mode 100644
index bef534427d9a67..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-10-11-26-14.gh-issue-123892.2gzIrz.rst
+++ /dev/null
@@ -1 +0,0 @@
-Add ``"_wmi"`` to :data:`sys.stdlib_module_names`. Patch by Victor Stinner.
diff --git a/Misc/NEWS.d/next/Library/2024-09-11-13-33-19.gh-issue-123935.fRZ_56.rst b/Misc/NEWS.d/next/Library/2024-09-11-13-33-19.gh-issue-123935.fRZ_56.rst
deleted file mode 100644
index de720c3714c6ff..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-11-13-33-19.gh-issue-123935.fRZ_56.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Fix parent slots detection for dataclasses that inherit from classes with
-``__dictoffset__``.
diff --git a/Misc/NEWS.d/next/Library/2024-09-13-10-34-19.gh-issue-123934.yMe7mL.rst b/Misc/NEWS.d/next/Library/2024-09-13-10-34-19.gh-issue-123934.yMe7mL.rst
deleted file mode 100644
index cec7741bcabbda..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-13-10-34-19.gh-issue-123934.yMe7mL.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Fix :class:`unittest.mock.MagicMock` reseting magic methods return values
-after ``.reset_mock(return_value=True)`` was called.
diff --git a/Misc/NEWS.d/next/Library/2024-09-17-18-06-42.gh-issue-124171.PHCvRJ.rst b/Misc/NEWS.d/next/Library/2024-09-17-18-06-42.gh-issue-124171.PHCvRJ.rst
deleted file mode 100644
index c2f0bb14f55251..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-17-18-06-42.gh-issue-124171.PHCvRJ.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-Add workaround for broken :c:func:`!fmod()` implementations on Windows, that
-loose zero sign (e.g. ``fmod(-10, 1)`` returns ``0.0``). Patch by Sergey B
-Kirpichev.
diff --git a/Misc/NEWS.d/next/Library/2024-09-19-03-46-59.gh-issue-87041.9Ox7Bv.rst b/Misc/NEWS.d/next/Library/2024-09-19-03-46-59.gh-issue-87041.9Ox7Bv.rst
deleted file mode 100644
index 47a5f0c7ba520f..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-19-03-46-59.gh-issue-87041.9Ox7Bv.rst
+++ /dev/null
@@ -1 +0,0 @@
-Fix a bug in :mod:`argparse` where lengthy subparser argument help is incorrectly indented.
diff --git a/Misc/NEWS.d/next/Library/2024-09-19-10-36-18.gh-issue-81691.Hyhp_U.rst b/Misc/NEWS.d/next/Library/2024-09-19-10-36-18.gh-issue-81691.Hyhp_U.rst
deleted file mode 100644
index 8f0108502efde6..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-19-10-36-18.gh-issue-81691.Hyhp_U.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-Fix handling of multiple ``"--"`` (double dashes) in :mod:`argparse`. Only
-the first one has now been removed, all subsequent ones are now taken
-literally.
diff --git a/Misc/NEWS.d/next/Library/2024-09-19-11-47-39.gh-issue-124248.g7rufd.rst b/Misc/NEWS.d/next/Library/2024-09-19-11-47-39.gh-issue-124248.g7rufd.rst
deleted file mode 100644
index 1bd333f485a2ab..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-19-11-47-39.gh-issue-124248.g7rufd.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Fixed potential crash when using :mod:`struct` to process zero-width
-'Pascal string' fields (``0p``).
diff --git a/Misc/NEWS.d/next/Library/2024-09-19-20-15-00.gh-issue-124217.j0KlQB.rst b/Misc/NEWS.d/next/Library/2024-09-19-20-15-00.gh-issue-124217.j0KlQB.rst
deleted file mode 100644
index 46f9866f8d427c..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-19-20-15-00.gh-issue-124217.j0KlQB.rst
+++ /dev/null
@@ -1 +0,0 @@
-Add RFC 9637 reserved IPv6 block ``3fff::/20`` in :mod:`ipaddress` module.
diff --git a/Misc/NEWS.d/next/Library/2024-09-20-12-23-11.gh-issue-53780.mrV1zi.rst b/Misc/NEWS.d/next/Library/2024-09-20-12-23-11.gh-issue-53780.mrV1zi.rst
deleted file mode 100644
index fb700c722c8a8b..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-20-12-23-11.gh-issue-53780.mrV1zi.rst
+++ /dev/null
@@ -1 +0,0 @@
-:mod:`argparse` now ignores the first ``"--"`` (double dash) between an option and command.
diff --git a/Misc/NEWS.d/next/Library/2024-09-21-19-02-37.gh-issue-59317.OAhNZZ.rst b/Misc/NEWS.d/next/Library/2024-09-21-19-02-37.gh-issue-59317.OAhNZZ.rst
deleted file mode 100644
index 0b1df9e3b7dea8..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-21-19-02-37.gh-issue-59317.OAhNZZ.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Fix parsing positional argument with :ref:`nargs` equal to ``'?'`` or ``'*'``
-if it is preceded by an option and another positional argument.
diff --git a/Misc/NEWS.d/next/Library/2024-09-21-22-32-21.gh-issue-72795.naLmkX.rst b/Misc/NEWS.d/next/Library/2024-09-21-22-32-21.gh-issue-72795.naLmkX.rst
deleted file mode 100644
index 15c0918097367f..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-21-22-32-21.gh-issue-72795.naLmkX.rst
+++ /dev/null
@@ -1,4 +0,0 @@
-Positional arguments with :ref:`nargs` equal to ``'*'`` or
-:data:`!argparse.REMAINDER` are no longer required. This allows to use
-positional argument with ``nargs='*'`` and without ``default`` in mutually
-exclusive group and improves error message about required arguments.
diff --git a/Misc/NEWS.d/next/Library/2024-09-21-23-56-41.gh-issue-63143.YKu-LQ.rst b/Misc/NEWS.d/next/Library/2024-09-21-23-56-41.gh-issue-63143.YKu-LQ.rst
deleted file mode 100644
index cb031fd601a9bd..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-21-23-56-41.gh-issue-63143.YKu-LQ.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-Fix parsing mutually exclusive arguments in :mod:`argparse`. Arguments with
-the value identical to the default value (e.g. booleans, small integers,
-empty or 1-character strings) are no longer considered "not present".
diff --git a/Misc/NEWS.d/next/Library/2024-09-23-17-33-47.gh-issue-104860.O86OSc.rst b/Misc/NEWS.d/next/Library/2024-09-23-17-33-47.gh-issue-104860.O86OSc.rst
deleted file mode 100644
index 707c4d651cb5e6..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-23-17-33-47.gh-issue-104860.O86OSc.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Fix disallowing abbreviation of single-dash long options in :mod:`argparse`
-with ``allow_abbrev=False``.
diff --git a/Misc/NEWS.d/next/Library/2024-09-24-12-34-48.gh-issue-124345.s3vKql.rst b/Misc/NEWS.d/next/Library/2024-09-24-12-34-48.gh-issue-124345.s3vKql.rst
deleted file mode 100644
index dff902d8c6139a..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-24-12-34-48.gh-issue-124345.s3vKql.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-:mod:`argparse` vim supports abbreviated single-dash long options separated
-by ``=`` from its value.
diff --git a/Misc/NEWS.d/next/Library/2024-09-25-12-14-58.gh-issue-124498.Ozxs55.rst b/Misc/NEWS.d/next/Library/2024-09-25-12-14-58.gh-issue-124498.Ozxs55.rst
deleted file mode 100644
index 4dbf4eb709733d..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-25-12-14-58.gh-issue-124498.Ozxs55.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Fix :class:`typing.TypeAliasType` not to be generic, when ``type_params`` is
-an empty tuple.
diff --git a/Misc/NEWS.d/next/Library/2024-09-25-18-08-29.gh-issue-80259.kO5Tw7.rst b/Misc/NEWS.d/next/Library/2024-09-25-18-08-29.gh-issue-80259.kO5Tw7.rst
deleted file mode 100644
index bb451cdd9ae44c..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-25-18-08-29.gh-issue-80259.kO5Tw7.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Fix :mod:`argparse` support of positional arguments with ``nargs='?'``,
-``default=argparse.SUPPRESS`` and specified ``type``.
diff --git a/Misc/NEWS.d/next/Library/2024-09-26-09-18-09.gh-issue-61181.dwjmch.rst b/Misc/NEWS.d/next/Library/2024-09-26-09-18-09.gh-issue-61181.dwjmch.rst
deleted file mode 100644
index 801a5fdd4abd4f..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-26-09-18-09.gh-issue-61181.dwjmch.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Fix support of :ref:`choices` with string value in :mod:`argparse`. Substrings
-of the specified string no longer considered valid values.
diff --git a/Misc/NEWS.d/next/Library/2024-09-26-22-14-12.gh-issue-58573.hozbm9.rst b/Misc/NEWS.d/next/Library/2024-09-26-22-14-12.gh-issue-58573.hozbm9.rst
deleted file mode 100644
index 37d64ee536ff49..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-26-22-14-12.gh-issue-58573.hozbm9.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Fix conflicts between abbreviated long options in the parent parser and
-subparsers in :mod:`argparse`.
diff --git a/Misc/NEWS.d/next/Library/2024-09-27-15-16-04.gh-issue-116850.dBkR0-.rst b/Misc/NEWS.d/next/Library/2024-09-27-15-16-04.gh-issue-116850.dBkR0-.rst
deleted file mode 100644
index 62639a16c52aa0..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-27-15-16-04.gh-issue-116850.dBkR0-.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-Fix :mod:`argparse` for namespaces with not directly writable dict (e.g.
-classes).
diff --git a/Misc/NEWS.d/next/Security/2024-08-07-10-42-13.gh-issue-122792.oiTMo9.rst b/Misc/NEWS.d/next/Security/2024-08-07-10-42-13.gh-issue-122792.oiTMo9.rst
deleted file mode 100644
index 18e293ba0c03b5..00000000000000
--- a/Misc/NEWS.d/next/Security/2024-08-07-10-42-13.gh-issue-122792.oiTMo9.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-Changed IPv4-mapped ``ipaddress.IPv6Address`` to consistently use the mapped IPv4
-address value for deciding properties. Properties which have their behavior fixed
-are ``is_multicast``, ``is_reserved``, ``is_link_local``, ``is_global``, and ``is_unspecified``.
diff --git a/Misc/NEWS.d/next/Tests/2024-09-25-12-39-34.gh-issue-124378.Ywwgia.rst b/Misc/NEWS.d/next/Tests/2024-09-25-12-39-34.gh-issue-124378.Ywwgia.rst
deleted file mode 100644
index 9ddcca0eb6036d..00000000000000
--- a/Misc/NEWS.d/next/Tests/2024-09-25-12-39-34.gh-issue-124378.Ywwgia.rst
+++ /dev/null
@@ -1 +0,0 @@
-Updated ``test_ttk`` to pass with Tcl/Tk 8.6.15.
diff --git a/Misc/NEWS.d/next/Windows/2024-04-24-22-50-33.gh-issue-117505.gcTb_p.rst b/Misc/NEWS.d/next/Windows/2024-04-24-22-50-33.gh-issue-117505.gcTb_p.rst
deleted file mode 100644
index 0931687ecc521c..00000000000000
--- a/Misc/NEWS.d/next/Windows/2024-04-24-22-50-33.gh-issue-117505.gcTb_p.rst
+++ /dev/null
@@ -1 +0,0 @@
-Fixes an issue with the Windows installer not running ensurepip in a fully isolated environment. This could cause unexpected interactions with the user site-packages.
diff --git a/Misc/NEWS.d/next/Windows/2024-09-10-19-23-00.gh-issue-123915.yZMEDO.rst b/Misc/NEWS.d/next/Windows/2024-09-10-19-23-00.gh-issue-123915.yZMEDO.rst
deleted file mode 100644
index 026b09d3601272..00000000000000
--- a/Misc/NEWS.d/next/Windows/2024-09-10-19-23-00.gh-issue-123915.yZMEDO.rst
+++ /dev/null
@@ -1 +0,0 @@
-Ensure that ``Tools\msi\buildrelease.bat`` uses different directories for AMD64 and ARM64 builds.
diff --git a/README.rst b/README.rst
index 49d503bbe458df..f7fbe2083d8774 100644
--- a/README.rst
+++ b/README.rst
@@ -1,4 +1,4 @@
-This is Python version 3.12.6
+This is Python version 3.12.7
=============================
.. image:: https://github.com/python/cpython/workflows/Tests/badge.svg
1
0
[3.12] gh-124309: Revert eager task factory fix to prevent breaking downstream (GH-124810) (#124817)
by Yhg1s 01 Oct '24
by Yhg1s 01 Oct '24
01 Oct '24
https://github.com/python/cpython/commit/3b5bc8d22898cb079d8e6b922ff0e1d17a…
commit: 3b5bc8d22898cb079d8e6b922ff0e1d17a088e83
branch: 3.12
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: Yhg1s <thomas(a)python.org>
date: 2024-10-01T01:55:03Z
summary:
[3.12] gh-124309: Revert eager task factory fix to prevent breaking downstream (GH-124810) (#124817)
gh-124309: Revert eager task factory fix to prevent breaking downstream (GH-124810)
* Revert "GH-124639: add back loop param to staggered_race (GH-124700)"
This reverts commit e0a41a5dd12cb6e9277b05abebac5c70be684dd7.
* Revert "gh-124309: Modernize the `staggered_race` implementation to support eager task factories (GH-124390)"
This reverts commit de929f353c413459834a2a37b2d9b0240673d874.
(cherry picked from commit 133e929a791d209b578b4822a7a07f4570b3803b)
Co-authored-by: Peter Bierma <zintensitydev(a)gmail.com>
files:
D Misc/NEWS.d/next/Library/2024-09-23-18-18-23.gh-issue-124309.iFcarA.rst
M Lib/asyncio/base_events.py
M Lib/asyncio/staggered.py
M Lib/test/test_asyncio/test_eager_task_factory.py
M Lib/test/test_asyncio/test_staggered.py
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
index 02b900891949b3..cb037fd472c5aa 100644
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -1110,7 +1110,7 @@ async def create_connection(
(functools.partial(self._connect_sock,
exceptions, addrinfo, laddr_infos)
for addrinfo in infos),
- happy_eyeballs_delay)
+ happy_eyeballs_delay, loop=self)
if sock is None:
exceptions = [exc for sub in exceptions for exc in sub]
diff --git a/Lib/asyncio/staggered.py b/Lib/asyncio/staggered.py
index 6ccf5c3c269ff0..c3a7441a7b091d 100644
--- a/Lib/asyncio/staggered.py
+++ b/Lib/asyncio/staggered.py
@@ -4,12 +4,11 @@
import contextlib
+from . import events
+from . import exceptions as exceptions_mod
from . import locks
from . import tasks
-from . import taskgroups
-class _Done(Exception):
- pass
async def staggered_race(coro_fns, delay, *, loop=None):
"""Run coroutines with staggered start times and take the first to finish.
@@ -43,6 +42,8 @@ async def staggered_race(coro_fns, delay, *, loop=None):
delay: amount of time, in seconds, between starting coroutines. If
``None``, the coroutines will run sequentially.
+ loop: the event loop to use.
+
Returns:
tuple *(winner_result, winner_index, exceptions)* where
@@ -61,11 +62,36 @@ async def staggered_race(coro_fns, delay, *, loop=None):
"""
# TODO: when we have aiter() and anext(), allow async iterables in coro_fns.
+ loop = loop or events.get_running_loop()
+ enum_coro_fns = enumerate(coro_fns)
winner_result = None
winner_index = None
exceptions = []
+ running_tasks = []
+
+ async def run_one_coro(previous_failed) -> None:
+ # Wait for the previous task to finish, or for delay seconds
+ if previous_failed is not None:
+ with contextlib.suppress(exceptions_mod.TimeoutError):
+ # Use asyncio.wait_for() instead of asyncio.wait() here, so
+ # that if we get cancelled at this point, Event.wait() is also
+ # cancelled, otherwise there will be a "Task destroyed but it is
+ # pending" later.
+ await tasks.wait_for(previous_failed.wait(), delay)
+ # Get the next coroutine to run
+ try:
+ this_index, coro_fn = next(enum_coro_fns)
+ except StopIteration:
+ return
+ # Start task that will run the next coroutine
+ this_failed = locks.Event()
+ next_task = loop.create_task(run_one_coro(this_failed))
+ running_tasks.append(next_task)
+ assert len(running_tasks) == this_index + 2
+ # Prepare place to put this coroutine's exceptions if not won
+ exceptions.append(None)
+ assert len(exceptions) == this_index + 1
- async def run_one_coro(this_index, coro_fn, this_failed):
try:
result = await coro_fn()
except (SystemExit, KeyboardInterrupt):
@@ -79,23 +105,34 @@ async def run_one_coro(this_index, coro_fn, this_failed):
assert winner_index is None
winner_index = this_index
winner_result = result
- raise _Done
-
+ # Cancel all other tasks. We take care to not cancel the current
+ # task as well. If we do so, then since there is no `await` after
+ # here and CancelledError are usually thrown at one, we will
+ # encounter a curious corner case where the current task will end
+ # up as done() == True, cancelled() == False, exception() ==
+ # asyncio.CancelledError. This behavior is specified in
+ # https://bugs.python.org/issue30048
+ for i, t in enumerate(running_tasks):
+ if i != this_index:
+ t.cancel()
+
+ first_task = loop.create_task(run_one_coro(None))
+ running_tasks.append(first_task)
try:
- tg = taskgroups.TaskGroup()
- # Intentionally override the loop in the TaskGroup to avoid
- # using the running loop, preserving backwards compatibility
- # TaskGroup only starts using `_loop` after `__aenter__`
- # so overriding it here is safe.
- tg._loop = loop
- async with tg:
- for this_index, coro_fn in enumerate(coro_fns):
- this_failed = locks.Event()
- exceptions.append(None)
- tg.create_task(run_one_coro(this_index, coro_fn, this_failed))
- with contextlib.suppress(TimeoutError):
- await tasks.wait_for(this_failed.wait(), delay)
- except* _Done:
- pass
-
- return winner_result, winner_index, exceptions
+ # Wait for a growing list of tasks to all finish: poor man's version of
+ # curio's TaskGroup or trio's nursery
+ done_count = 0
+ while done_count != len(running_tasks):
+ done, _ = await tasks.wait(running_tasks)
+ done_count = len(done)
+ # If run_one_coro raises an unhandled exception, it's probably a
+ # programming error, and I want to see it.
+ if __debug__:
+ for d in done:
+ if d.done() and not d.cancelled() and d.exception():
+ raise d.exception()
+ return winner_result, winner_index, exceptions
+ finally:
+ # Make sure no tasks are left running if we leave this function
+ for t in running_tasks:
+ t.cancel()
diff --git a/Lib/test/test_asyncio/test_eager_task_factory.py b/Lib/test/test_asyncio/test_eager_task_factory.py
index ed74c6ecbd83f4..58c06287bc3c5d 100644
--- a/Lib/test/test_asyncio/test_eager_task_factory.py
+++ b/Lib/test/test_asyncio/test_eager_task_factory.py
@@ -218,53 +218,6 @@ async def run():
self.run_coro(run())
- def test_staggered_race_with_eager_tasks(self):
- # See https://github.com/python/cpython/issues/124309
-
- async def fail():
- await asyncio.sleep(0)
- raise ValueError("no good")
-
- async def run():
- winner, index, excs = await asyncio.staggered.staggered_race(
- [
- lambda: asyncio.sleep(2, result="sleep2"),
- lambda: asyncio.sleep(1, result="sleep1"),
- lambda: fail()
- ],
- delay=0.25
- )
- self.assertEqual(winner, 'sleep1')
- self.assertEqual(index, 1)
- self.assertIsNone(excs[index])
- self.assertIsInstance(excs[0], asyncio.CancelledError)
- self.assertIsInstance(excs[2], ValueError)
-
- self.run_coro(run())
-
- def test_staggered_race_with_eager_tasks_no_delay(self):
- # See https://github.com/python/cpython/issues/124309
- async def fail():
- raise ValueError("no good")
-
- async def run():
- winner, index, excs = await asyncio.staggered.staggered_race(
- [
- lambda: fail(),
- lambda: asyncio.sleep(1, result="sleep1"),
- lambda: asyncio.sleep(0, result="sleep0"),
- ],
- delay=None
- )
- self.assertEqual(winner, 'sleep1')
- self.assertEqual(index, 1)
- self.assertIsNone(excs[index])
- self.assertIsInstance(excs[0], ValueError)
- self.assertEqual(len(excs), 2)
-
- self.run_coro(run())
-
-
class PyEagerTaskFactoryLoopTests(EagerTaskFactoryLoopTests, test_utils.TestCase):
Task = tasks._PyTask
diff --git a/Lib/test/test_asyncio/test_staggered.py b/Lib/test/test_asyncio/test_staggered.py
index 8cd98394aea8f8..e6e32f7dbbbcba 100644
--- a/Lib/test/test_asyncio/test_staggered.py
+++ b/Lib/test/test_asyncio/test_staggered.py
@@ -82,64 +82,16 @@ async def test_none_successful(self):
async def coro(index):
raise ValueError(index)
- for delay in [None, 0, 0.1, 1]:
- with self.subTest(delay=delay):
- winner, index, excs = await staggered_race(
- [
- lambda: coro(0),
- lambda: coro(1),
- ],
- delay=delay,
- )
-
- self.assertIs(winner, None)
- self.assertIs(index, None)
- self.assertEqual(len(excs), 2)
- self.assertIsInstance(excs[0], ValueError)
- self.assertIsInstance(excs[1], ValueError)
-
- async def test_long_delay_early_failure(self):
- async def coro(index):
- await asyncio.sleep(0) # Dummy coroutine for the 1 case
- if index == 0:
- await asyncio.sleep(0.1) # Dummy coroutine
- raise ValueError(index)
-
- return f'Res: {index}'
-
winner, index, excs = await staggered_race(
[
lambda: coro(0),
lambda: coro(1),
],
- delay=10,
+ delay=None,
)
- self.assertEqual(winner, 'Res: 1')
- self.assertEqual(index, 1)
+ self.assertIs(winner, None)
+ self.assertIs(index, None)
self.assertEqual(len(excs), 2)
self.assertIsInstance(excs[0], ValueError)
- self.assertIsNone(excs[1])
-
- def test_loop_argument(self):
- loop = asyncio.new_event_loop()
- async def coro():
- self.assertEqual(loop, asyncio.get_running_loop())
- return 'coro'
-
- async def main():
- winner, index, excs = await staggered_race(
- [coro],
- delay=0.1,
- loop=loop
- )
-
- self.assertEqual(winner, 'coro')
- self.assertEqual(index, 0)
-
- loop.run_until_complete(main())
- loop.close()
-
-
-if __name__ == "__main__":
- unittest.main()
+ self.assertIsInstance(excs[1], ValueError)
diff --git a/Misc/NEWS.d/next/Library/2024-09-23-18-18-23.gh-issue-124309.iFcarA.rst b/Misc/NEWS.d/next/Library/2024-09-23-18-18-23.gh-issue-124309.iFcarA.rst
deleted file mode 100644
index 89610fa44bf743..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-23-18-18-23.gh-issue-124309.iFcarA.rst
+++ /dev/null
@@ -1 +0,0 @@
-Fixed :exc:`AssertionError` when using :func:`!asyncio.staggered.staggered_race` with :attr:`asyncio.eager_task_factory`.
1
0
[3.12] gh-124785: Revert "[3.12] gh-116510: Fix a crash due to shared immortal interned strings. (gh-124541)" (#124814)
by Yhg1s 01 Oct '24
by Yhg1s 01 Oct '24
01 Oct '24
https://github.com/python/cpython/commit/ffc6a101495ec84ef1023fea125075b921…
commit: ffc6a101495ec84ef1023fea125075b921e743c3
branch: 3.12
author: Neil Schemenauer <nas-github(a)arctrix.com>
committer: Yhg1s <thomas(a)python.org>
date: 2024-09-30T18:54:41-07:00
summary:
[3.12] gh-124785: Revert "[3.12] gh-116510: Fix a crash due to shared immortal interned strings. (gh-124541)" (#124814)
Revert "[3.12] gh-116510: Fix a crash due to shared immortal interned strings. (gh-124541)"
This reverts commit 5dd07ebc0c27e2fffdfd041401c8cc7f0cda0dfc.
files:
D Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-12-37-58.gh-issue-116510.WeBAx1.rst
M Objects/unicodeobject.c
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-12-37-58.gh-issue-116510.WeBAx1.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-12-37-58.gh-issue-116510.WeBAx1.rst
deleted file mode 100644
index e1e0408f548498..00000000000000
--- a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-12-37-58.gh-issue-116510.WeBAx1.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-Fix a crash caused by immortal interned strings being shared between
-sub-interpreters that use basic single-phase init. In that case, the string
-can be used by an interpreter that outlives the interpeter that created and
-interned it. For interpreters that share obmalloc state, also share the
-interned dict with the main interpreter.
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 1a3b37f6db5e6a..815747e1b1ed9c 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -286,37 +286,13 @@ hashtable_unicode_compare(const void *key1, const void *key2)
}
}
-/* Return true if this interpreter should share the main interpreter's
- intern_dict. That's important for interpreters which load basic
- single-phase init extension modules (m_size == -1). There could be interned
- immortal strings that are shared between interpreters, due to the
- PyDict_Update(mdict, m_copy) call in import_find_extension().
-
- It's not safe to deallocate those strings until all interpreters that
- potentially use them are freed. By storing them in the main interpreter, we
- ensure they get freed after all other interpreters are freed.
-*/
-static bool
-has_shared_intern_dict(PyInterpreterState *interp)
-{
- PyInterpreterState *main_interp = _PyInterpreterState_Main();
- return interp != main_interp && interp->feature_flags & Py_RTFLAGS_USE_MAIN_OBMALLOC;
-}
-
static int
init_interned_dict(PyInterpreterState *interp)
{
assert(get_interned_dict(interp) == NULL);
- PyObject *interned;
- if (has_shared_intern_dict(interp)) {
- interned = get_interned_dict(_PyInterpreterState_Main());
- Py_INCREF(interned);
- }
- else {
- interned = PyDict_New();
- if (interned == NULL) {
- return -1;
- }
+ PyObject *interned = interned = PyDict_New();
+ if (interned == NULL) {
+ return -1;
}
_Py_INTERP_CACHED_OBJECT(interp, interned_strings) = interned;
return 0;
@@ -327,10 +303,7 @@ clear_interned_dict(PyInterpreterState *interp)
{
PyObject *interned = get_interned_dict(interp);
if (interned != NULL) {
- if (!has_shared_intern_dict(interp)) {
- // only clear if the dict belongs to this interpreter
- PyDict_Clear(interned);
- }
+ PyDict_Clear(interned);
Py_DECREF(interned);
_Py_INTERP_CACHED_OBJECT(interp, interned_strings) = NULL;
}
@@ -15163,13 +15136,6 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
}
assert(PyDict_CheckExact(interned));
- if (has_shared_intern_dict(interp)) {
- // the dict doesn't belong to this interpreter, skip the debug
- // checks on it and just clear the pointer to it
- clear_interned_dict(interp);
- return;
- }
-
#ifdef INTERNED_STATS
fprintf(stderr, "releasing %zd interned strings\n",
PyDict_GET_SIZE(interned));
@@ -15688,10 +15654,8 @@ _PyUnicode_Fini(PyInterpreterState *interp)
{
struct _Py_unicode_state *state = &interp->unicode;
- if (!has_shared_intern_dict(interp)) {
- // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini()
- assert(get_interned_dict(interp) == NULL);
- }
+ // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini()
+ assert(get_interned_dict(interp) == NULL);
_PyUnicode_FiniEncodings(&state->fs_codec);
1
0
[3.13] gh-124442: make `__static_attributes__` deterministic by sorting (GH-124492) (#124738)
by Yhg1s 01 Oct '24
by Yhg1s 01 Oct '24
01 Oct '24
https://github.com/python/cpython/commit/b99c6620b282b9ccac1018c86310aa5324…
commit: b99c6620b282b9ccac1018c86310aa5324fca753
branch: 3.13
author: Jelle Zijlstra <jelle.zijlstra(a)gmail.com>
committer: Yhg1s <thomas(a)python.org>
date: 2024-09-30T18:53:17-07:00
summary:
[3.13] gh-124442: make `__static_attributes__` deterministic by sorting (GH-124492) (#124738)
* [3.13] gh-124442: make `__static_attributes__` deterministic by sorting (GH-124492)
(cherry picked from commit 04c837d9d8a474777ef9c1412fbba14f0682366c)
Co-authored-by: Kira <kp2pml30(a)gmail.com>
Signed-off-by: kp2pml30 <kp2pml30(a)gmail.com>
Co-authored-by: Jelle Zijlstra <jelle.zijlstra(a)gmail.com>
Co-authored-by: Adam Turner <9087854+AA-Turner(a)users.noreply.github.com>
files:
A Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-11-53-22.gh-issue-124442.EXC1Ve.rst
M Lib/test/test_compile.py
M Python/compile.c
diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py
index 9c6bc31ff4922e..cdd942b56cb7e5 100644
--- a/Lib/test/test_compile.py
+++ b/Lib/test/test_compile.py
@@ -1,6 +1,7 @@
import contextlib
import dis
import io
+import itertools
import math
import opcode
import os
@@ -2619,6 +2620,22 @@ def test_nested(self):
self.compare_instructions(seq, [('LOAD_CONST', 1, 1, 0, 0, 0)])
self.compare_instructions(seq.get_nested()[0], [('LOAD_CONST', 2, 2, 0, 0, 0)])
+ def test_static_attributes_are_sorted(self):
+ code = (
+ 'class T:\n'
+ ' def __init__(self):\n'
+ ' self.{V1} = 10\n'
+ ' self.{V2} = 10\n'
+ ' def foo(self):\n'
+ ' self.{V3} = 10\n'
+ )
+ attributes = ("a", "b", "c")
+ for perm in itertools.permutations(attributes):
+ var_names = {f'V{i + 1}': name for i, name in enumerate(perm)}
+ ns = run_code(code.format(**var_names))
+ t = ns['T']
+ self.assertEqual(t.__static_attributes__, attributes)
+
if __name__ == "__main__":
unittest.main()
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-11-53-22.gh-issue-124442.EXC1Ve.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-11-53-22.gh-issue-124442.EXC1Ve.rst
new file mode 100644
index 00000000000000..58e79f22ac0f90
--- /dev/null
+++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-11-53-22.gh-issue-124442.EXC1Ve.rst
@@ -0,0 +1,2 @@
+Fix nondeterminism in compilation by sorting the value of
+:attr:`~type.__static_attributes__`. Patch by kp2pml30.
diff --git a/Python/compile.c b/Python/compile.c
index 7752a6885cc4e2..7d93f2a05f66d9 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -2544,7 +2544,18 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)
return ERROR;
}
assert(c->u->u_static_attributes);
- PyObject *static_attributes = PySequence_Tuple(c->u->u_static_attributes);
+ PyObject *static_attributes_unsorted = PySequence_List(c->u->u_static_attributes);
+ if (static_attributes_unsorted == NULL) {
+ compiler_exit_scope(c);
+ return ERROR;
+ }
+ if (PyList_Sort(static_attributes_unsorted) != 0) {
+ compiler_exit_scope(c);
+ Py_DECREF(static_attributes_unsorted);
+ return ERROR;
+ }
+ PyObject *static_attributes = PySequence_Tuple(static_attributes_unsorted);
+ Py_DECREF(static_attributes_unsorted);
if (static_attributes == NULL) {
compiler_exit_scope(c);
return ERROR;
1
0
[3.13] gh-124785: Revert "gh-116510: Fix crash due to shared immortal interned strings (gh-124646)" (gh-124807) (#124812)
by Yhg1s 01 Oct '24
by Yhg1s 01 Oct '24
01 Oct '24
https://github.com/python/cpython/commit/b843974ab4e50994e7bbb58b80afefb202…
commit: b843974ab4e50994e7bbb58b80afefb20236ada7
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: Yhg1s <thomas(a)python.org>
date: 2024-09-30T18:38:26-07:00
summary:
[3.13] gh-124785: Revert "gh-116510: Fix crash due to shared immortal interned strings (gh-124646)" (gh-124807) (#124812)
gh-124785: Revert "gh-116510: Fix crash due to shared immortal interned strings (gh-124646)" (gh-124807)
Revert "gh-116510: Fix crash due to shared immortal interned strings. (gh-124646)"
This reverts commit 98b2ed7e239c807f379cd2bf864f372d79064aac.
(cherry picked from commit 7bdfabe2d1ec353ecdc75a5aec41cce83e572391)
Co-authored-by: T. Wouters <thomas(a)python.org>
files:
D Misc/NEWS.d/next/Core_and_Builtins/2024-09-26-18-21-06.gh-issue-116510.FacUWO.rst
M Objects/unicodeobject.c
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-26-18-21-06.gh-issue-116510.FacUWO.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-26-18-21-06.gh-issue-116510.FacUWO.rst
deleted file mode 100644
index e3741321006548..00000000000000
--- a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-26-18-21-06.gh-issue-116510.FacUWO.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-Fix a crash caused by immortal interned strings being shared between
-sub-interpreters that use basic single-phase init. In that case, the string
-can be used by an interpreter that outlives the interpreter that created and
-interned it. For interpreters that share obmalloc state, also share the
-interned dict with the main interpreter.
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index c69a64de062baa..5a6ae78fe23bae 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -277,37 +277,13 @@ hashtable_unicode_compare(const void *key1, const void *key2)
}
}
-/* Return true if this interpreter should share the main interpreter's
- intern_dict. That's important for interpreters which load basic
- single-phase init extension modules (m_size == -1). There could be interned
- immortal strings that are shared between interpreters, due to the
- PyDict_Update(mdict, m_copy) call in import_find_extension().
-
- It's not safe to deallocate those strings until all interpreters that
- potentially use them are freed. By storing them in the main interpreter, we
- ensure they get freed after all other interpreters are freed.
-*/
-static bool
-has_shared_intern_dict(PyInterpreterState *interp)
-{
- PyInterpreterState *main_interp = _PyInterpreterState_Main();
- return interp != main_interp && interp->feature_flags & Py_RTFLAGS_USE_MAIN_OBMALLOC;
-}
-
static int
init_interned_dict(PyInterpreterState *interp)
{
assert(get_interned_dict(interp) == NULL);
- PyObject *interned;
- if (has_shared_intern_dict(interp)) {
- interned = get_interned_dict(_PyInterpreterState_Main());
- Py_INCREF(interned);
- }
- else {
- interned = PyDict_New();
- if (interned == NULL) {
- return -1;
- }
+ PyObject *interned = interned = PyDict_New();
+ if (interned == NULL) {
+ return -1;
}
_Py_INTERP_CACHED_OBJECT(interp, interned_strings) = interned;
return 0;
@@ -318,10 +294,7 @@ clear_interned_dict(PyInterpreterState *interp)
{
PyObject *interned = get_interned_dict(interp);
if (interned != NULL) {
- if (!has_shared_intern_dict(interp)) {
- // only clear if the dict belongs to this interpreter
- PyDict_Clear(interned);
- }
+ PyDict_Clear(interned);
Py_DECREF(interned);
_Py_INTERP_CACHED_OBJECT(interp, interned_strings) = NULL;
}
@@ -15333,13 +15306,6 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
}
assert(PyDict_CheckExact(interned));
- if (has_shared_intern_dict(interp)) {
- // the dict doesn't belong to this interpreter, skip the debug
- // checks on it and just clear the pointer to it
- clear_interned_dict(interp);
- return;
- }
-
#ifdef INTERNED_STATS
fprintf(stderr, "releasing %zd interned strings\n",
PyDict_GET_SIZE(interned));
@@ -15861,10 +15827,8 @@ _PyUnicode_Fini(PyInterpreterState *interp)
{
struct _Py_unicode_state *state = &interp->unicode;
- if (!has_shared_intern_dict(interp)) {
- // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini()
- assert(get_interned_dict(interp) == NULL);
- }
+ // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini()
+ assert(get_interned_dict(interp) == NULL);
_PyUnicode_FiniEncodings(&state->fs_codec);
1
0
gh-124309: Revert eager task factory fix to prevent breaking downstream (#124810)
by Yhg1s 01 Oct '24
by Yhg1s 01 Oct '24
01 Oct '24
https://github.com/python/cpython/commit/133e929a791d209b578b4822a7a07f4570…
commit: 133e929a791d209b578b4822a7a07f4570b3803b
branch: main
author: Peter Bierma <zintensitydev(a)gmail.com>
committer: Yhg1s <thomas(a)python.org>
date: 2024-09-30T18:37:27-07:00
summary:
gh-124309: Revert eager task factory fix to prevent breaking downstream (#124810)
* Revert "GH-124639: add back loop param to staggered_race (#124700)"
This reverts commit e0a41a5dd12cb6e9277b05abebac5c70be684dd7.
* Revert "gh-124309: Modernize the `staggered_race` implementation to support eager task factories (#124390)"
This reverts commit de929f353c413459834a2a37b2d9b0240673d874.
files:
D Misc/NEWS.d/next/Library/2024-09-23-18-18-23.gh-issue-124309.iFcarA.rst
M Lib/asyncio/base_events.py
M Lib/asyncio/staggered.py
M Lib/test/test_asyncio/test_eager_task_factory.py
M Lib/test/test_asyncio/test_staggered.py
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
index ffcc0174e1e245..000647f57dd9e3 100644
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -1144,7 +1144,7 @@ async def create_connection(
(functools.partial(self._connect_sock,
exceptions, addrinfo, laddr_infos)
for addrinfo in infos),
- happy_eyeballs_delay)
+ happy_eyeballs_delay, loop=self)
if sock is None:
exceptions = [exc for sub in exceptions for exc in sub]
diff --git a/Lib/asyncio/staggered.py b/Lib/asyncio/staggered.py
index 6ccf5c3c269ff0..c3a7441a7b091d 100644
--- a/Lib/asyncio/staggered.py
+++ b/Lib/asyncio/staggered.py
@@ -4,12 +4,11 @@
import contextlib
+from . import events
+from . import exceptions as exceptions_mod
from . import locks
from . import tasks
-from . import taskgroups
-class _Done(Exception):
- pass
async def staggered_race(coro_fns, delay, *, loop=None):
"""Run coroutines with staggered start times and take the first to finish.
@@ -43,6 +42,8 @@ async def staggered_race(coro_fns, delay, *, loop=None):
delay: amount of time, in seconds, between starting coroutines. If
``None``, the coroutines will run sequentially.
+ loop: the event loop to use.
+
Returns:
tuple *(winner_result, winner_index, exceptions)* where
@@ -61,11 +62,36 @@ async def staggered_race(coro_fns, delay, *, loop=None):
"""
# TODO: when we have aiter() and anext(), allow async iterables in coro_fns.
+ loop = loop or events.get_running_loop()
+ enum_coro_fns = enumerate(coro_fns)
winner_result = None
winner_index = None
exceptions = []
+ running_tasks = []
+
+ async def run_one_coro(previous_failed) -> None:
+ # Wait for the previous task to finish, or for delay seconds
+ if previous_failed is not None:
+ with contextlib.suppress(exceptions_mod.TimeoutError):
+ # Use asyncio.wait_for() instead of asyncio.wait() here, so
+ # that if we get cancelled at this point, Event.wait() is also
+ # cancelled, otherwise there will be a "Task destroyed but it is
+ # pending" later.
+ await tasks.wait_for(previous_failed.wait(), delay)
+ # Get the next coroutine to run
+ try:
+ this_index, coro_fn = next(enum_coro_fns)
+ except StopIteration:
+ return
+ # Start task that will run the next coroutine
+ this_failed = locks.Event()
+ next_task = loop.create_task(run_one_coro(this_failed))
+ running_tasks.append(next_task)
+ assert len(running_tasks) == this_index + 2
+ # Prepare place to put this coroutine's exceptions if not won
+ exceptions.append(None)
+ assert len(exceptions) == this_index + 1
- async def run_one_coro(this_index, coro_fn, this_failed):
try:
result = await coro_fn()
except (SystemExit, KeyboardInterrupt):
@@ -79,23 +105,34 @@ async def run_one_coro(this_index, coro_fn, this_failed):
assert winner_index is None
winner_index = this_index
winner_result = result
- raise _Done
-
+ # Cancel all other tasks. We take care to not cancel the current
+ # task as well. If we do so, then since there is no `await` after
+ # here and CancelledError are usually thrown at one, we will
+ # encounter a curious corner case where the current task will end
+ # up as done() == True, cancelled() == False, exception() ==
+ # asyncio.CancelledError. This behavior is specified in
+ # https://bugs.python.org/issue30048
+ for i, t in enumerate(running_tasks):
+ if i != this_index:
+ t.cancel()
+
+ first_task = loop.create_task(run_one_coro(None))
+ running_tasks.append(first_task)
try:
- tg = taskgroups.TaskGroup()
- # Intentionally override the loop in the TaskGroup to avoid
- # using the running loop, preserving backwards compatibility
- # TaskGroup only starts using `_loop` after `__aenter__`
- # so overriding it here is safe.
- tg._loop = loop
- async with tg:
- for this_index, coro_fn in enumerate(coro_fns):
- this_failed = locks.Event()
- exceptions.append(None)
- tg.create_task(run_one_coro(this_index, coro_fn, this_failed))
- with contextlib.suppress(TimeoutError):
- await tasks.wait_for(this_failed.wait(), delay)
- except* _Done:
- pass
-
- return winner_result, winner_index, exceptions
+ # Wait for a growing list of tasks to all finish: poor man's version of
+ # curio's TaskGroup or trio's nursery
+ done_count = 0
+ while done_count != len(running_tasks):
+ done, _ = await tasks.wait(running_tasks)
+ done_count = len(done)
+ # If run_one_coro raises an unhandled exception, it's probably a
+ # programming error, and I want to see it.
+ if __debug__:
+ for d in done:
+ if d.done() and not d.cancelled() and d.exception():
+ raise d.exception()
+ return winner_result, winner_index, exceptions
+ finally:
+ # Make sure no tasks are left running if we leave this function
+ for t in running_tasks:
+ t.cancel()
diff --git a/Lib/test/test_asyncio/test_eager_task_factory.py b/Lib/test/test_asyncio/test_eager_task_factory.py
index 1579ad1188d725..0777f39b572486 100644
--- a/Lib/test/test_asyncio/test_eager_task_factory.py
+++ b/Lib/test/test_asyncio/test_eager_task_factory.py
@@ -213,53 +213,6 @@ async def run():
self.run_coro(run())
- def test_staggered_race_with_eager_tasks(self):
- # See https://github.com/python/cpython/issues/124309
-
- async def fail():
- await asyncio.sleep(0)
- raise ValueError("no good")
-
- async def run():
- winner, index, excs = await asyncio.staggered.staggered_race(
- [
- lambda: asyncio.sleep(2, result="sleep2"),
- lambda: asyncio.sleep(1, result="sleep1"),
- lambda: fail()
- ],
- delay=0.25
- )
- self.assertEqual(winner, 'sleep1')
- self.assertEqual(index, 1)
- self.assertIsNone(excs[index])
- self.assertIsInstance(excs[0], asyncio.CancelledError)
- self.assertIsInstance(excs[2], ValueError)
-
- self.run_coro(run())
-
- def test_staggered_race_with_eager_tasks_no_delay(self):
- # See https://github.com/python/cpython/issues/124309
- async def fail():
- raise ValueError("no good")
-
- async def run():
- winner, index, excs = await asyncio.staggered.staggered_race(
- [
- lambda: fail(),
- lambda: asyncio.sleep(1, result="sleep1"),
- lambda: asyncio.sleep(0, result="sleep0"),
- ],
- delay=None
- )
- self.assertEqual(winner, 'sleep1')
- self.assertEqual(index, 1)
- self.assertIsNone(excs[index])
- self.assertIsInstance(excs[0], ValueError)
- self.assertEqual(len(excs), 2)
-
- self.run_coro(run())
-
-
class PyEagerTaskFactoryLoopTests(EagerTaskFactoryLoopTests, test_utils.TestCase):
Task = tasks._PyTask
diff --git a/Lib/test/test_asyncio/test_staggered.py b/Lib/test/test_asyncio/test_staggered.py
index 8cd98394aea8f8..e6e32f7dbbbcba 100644
--- a/Lib/test/test_asyncio/test_staggered.py
+++ b/Lib/test/test_asyncio/test_staggered.py
@@ -82,64 +82,16 @@ async def test_none_successful(self):
async def coro(index):
raise ValueError(index)
- for delay in [None, 0, 0.1, 1]:
- with self.subTest(delay=delay):
- winner, index, excs = await staggered_race(
- [
- lambda: coro(0),
- lambda: coro(1),
- ],
- delay=delay,
- )
-
- self.assertIs(winner, None)
- self.assertIs(index, None)
- self.assertEqual(len(excs), 2)
- self.assertIsInstance(excs[0], ValueError)
- self.assertIsInstance(excs[1], ValueError)
-
- async def test_long_delay_early_failure(self):
- async def coro(index):
- await asyncio.sleep(0) # Dummy coroutine for the 1 case
- if index == 0:
- await asyncio.sleep(0.1) # Dummy coroutine
- raise ValueError(index)
-
- return f'Res: {index}'
-
winner, index, excs = await staggered_race(
[
lambda: coro(0),
lambda: coro(1),
],
- delay=10,
+ delay=None,
)
- self.assertEqual(winner, 'Res: 1')
- self.assertEqual(index, 1)
+ self.assertIs(winner, None)
+ self.assertIs(index, None)
self.assertEqual(len(excs), 2)
self.assertIsInstance(excs[0], ValueError)
- self.assertIsNone(excs[1])
-
- def test_loop_argument(self):
- loop = asyncio.new_event_loop()
- async def coro():
- self.assertEqual(loop, asyncio.get_running_loop())
- return 'coro'
-
- async def main():
- winner, index, excs = await staggered_race(
- [coro],
- delay=0.1,
- loop=loop
- )
-
- self.assertEqual(winner, 'coro')
- self.assertEqual(index, 0)
-
- loop.run_until_complete(main())
- loop.close()
-
-
-if __name__ == "__main__":
- unittest.main()
+ self.assertIsInstance(excs[1], ValueError)
diff --git a/Misc/NEWS.d/next/Library/2024-09-23-18-18-23.gh-issue-124309.iFcarA.rst b/Misc/NEWS.d/next/Library/2024-09-23-18-18-23.gh-issue-124309.iFcarA.rst
deleted file mode 100644
index 89610fa44bf743..00000000000000
--- a/Misc/NEWS.d/next/Library/2024-09-23-18-18-23.gh-issue-124309.iFcarA.rst
+++ /dev/null
@@ -1 +0,0 @@
-Fixed :exc:`AssertionError` when using :func:`!asyncio.staggered.staggered_race` with :attr:`asyncio.eager_task_factory`.
1
0