Python-checkins
Threads by month
- ----- 2025 -----
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- 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
May 2023
- 1 participants
- 741 discussions

[3.12] gh-103921: Minor PEP-695 fixes to the `ast` module docs (GH-105093) (#105101)
by JelleZijlstra May 30, 2023
by JelleZijlstra May 30, 2023
May 30, 2023
https://github.com/python/cpython/commit/9fb7abba6d64dd345e09e13675b522aa20…
commit: 9fb7abba6d64dd345e09e13675b522aa2006d74f
branch: 3.12
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: JelleZijlstra <jelle.zijlstra(a)gmail.com>
date: 2023-05-30T09:34:57-07:00
summary:
[3.12] gh-103921: Minor PEP-695 fixes to the `ast` module docs (GH-105093) (#105101)
(cherry picked from commit c8c1e73d95d5dcd7a2c8d7c10cfafc3fe5a9377e)
Co-authored-by: Alex Waygood <Alex.Waygood(a)Gmail.com>
files:
M Doc/library/ast.rst
diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst
index 17d1de9fbb8f..f3b0bf0c4f77 100644
--- a/Doc/library/ast.rst
+++ b/Doc/library/ast.rst
@@ -1744,17 +1744,17 @@ aliases.
Function and class definitions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. class:: FunctionDef(name, type_params, args, body, decorator_list, returns, type_comment)
+.. class:: FunctionDef(name, args, body, decorator_list, returns, type_comment, type_params)
A function definition.
* ``name`` is a raw string of the function name.
- * ``type_params`` is a list of :ref:`type parameters <ast-type-params>`.
* ``args`` is an :class:`arguments` node.
* ``body`` is the list of nodes inside the function.
* ``decorator_list`` is the list of decorators to be applied, stored outermost
first (i.e. the first in the list will be applied last).
* ``returns`` is the return annotation.
+ * ``type_params`` is a list of :ref:`type parameters <ast-type-params>`.
.. attribute:: type_comment
@@ -1917,12 +1917,11 @@ Function and class definitions
type_ignores=[])
-.. class:: ClassDef(name, type_params, bases, keywords, body, decorator_list)
+.. class:: ClassDef(name, bases, keywords, body, decorator_list, type_params)
A class definition.
* ``name`` is a raw string for the class name
- * ``type_params`` is a list of :ref:`type parameters <ast-type-params>`.
* ``bases`` is a list of nodes for explicitly specified base classes.
* ``keywords`` is a list of :class:`keyword` nodes, principally for 'metaclass'.
Other keywords will be passed to the metaclass, as per `PEP-3115
@@ -1930,6 +1929,7 @@ Function and class definitions
* ``body`` is a list of nodes representing the code within the class
definition.
* ``decorator_list`` is a list of nodes, as in :class:`FunctionDef`.
+ * ``type_params`` is a list of :ref:`type parameters <ast-type-params>`.
.. doctest::
@@ -1961,7 +1961,7 @@ Function and class definitions
Async and await
^^^^^^^^^^^^^^^
-.. class:: AsyncFunctionDef(name, args, body, decorator_list, returns, type_comment)
+.. class:: AsyncFunctionDef(name, args, body, decorator_list, returns, type_comment, type_params)
An ``async def`` function definition. Has the same fields as
:class:`FunctionDef`.
1
0

[3.12] Enable the ABI check job to publish the updated ABI data file (GH-105088)
by zooba May 30, 2023
by zooba May 30, 2023
May 30, 2023
https://github.com/python/cpython/commit/4e7d41f9867676dc1aacdf0310f500b019…
commit: 4e7d41f9867676dc1aacdf0310f500b0191be0fc
branch: 3.12
author: Steve Dower <steve.dower(a)python.org>
committer: zooba <steve.dower(a)microsoft.com>
date: 2023-05-30T17:31:51+01:00
summary:
[3.12] Enable the ABI check job to publish the updated ABI data file (GH-105088)
files:
M .github/workflows/build.yml
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 3ada845c4cbb..046c2aaa55f6 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -100,15 +100,28 @@ jobs:
./configure --enable-shared
make -j4
- name: Check for changes in the ABI
+ id: check
run: |
if ! make check-abidump; then
echo "Generated ABI file is not up to date."
echo "Please add the release manager of this branch as a reviewer of this PR."
echo ""
+ echo "The up to date ABI file should be attached to this build as an artifact."
+ echo ""
echo "To learn more about this check: https://devguide.python.org/setup/#regenerate-the-abi-dump"
echo ""
exit 1
fi
+ - name: Generate updated ABI files
+ if: ${{ failure() && steps.check.conclusion == 'failure' }}
+ run: |
+ make regen-abidump
+ - uses: actions/upload-artifact@v3
+ name: Publish updated ABI files
+ if: ${{ failure() && steps.check.conclusion == 'failure' }}
+ with:
+ name: abi-data
+ path: ./Doc/data/*.abi
check_generated_files:
name: 'Check if generated files are up to date'
1
0

May 30, 2023
https://github.com/python/cpython/commit/c8c1e73d95d5dcd7a2c8d7c10cfafc3fe5…
commit: c8c1e73d95d5dcd7a2c8d7c10cfafc3fe5a9377e
branch: main
author: Alex Waygood <Alex.Waygood(a)Gmail.com>
committer: JelleZijlstra <jelle.zijlstra(a)gmail.com>
date: 2023-05-30T09:19:10-07:00
summary:
gh-103921: Minor PEP-695 fixes to the `ast` module docs (#105093)
files:
M Doc/library/ast.rst
diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst
index 17d1de9fbb8f..f3b0bf0c4f77 100644
--- a/Doc/library/ast.rst
+++ b/Doc/library/ast.rst
@@ -1744,17 +1744,17 @@ aliases.
Function and class definitions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. class:: FunctionDef(name, type_params, args, body, decorator_list, returns, type_comment)
+.. class:: FunctionDef(name, args, body, decorator_list, returns, type_comment, type_params)
A function definition.
* ``name`` is a raw string of the function name.
- * ``type_params`` is a list of :ref:`type parameters <ast-type-params>`.
* ``args`` is an :class:`arguments` node.
* ``body`` is the list of nodes inside the function.
* ``decorator_list`` is the list of decorators to be applied, stored outermost
first (i.e. the first in the list will be applied last).
* ``returns`` is the return annotation.
+ * ``type_params`` is a list of :ref:`type parameters <ast-type-params>`.
.. attribute:: type_comment
@@ -1917,12 +1917,11 @@ Function and class definitions
type_ignores=[])
-.. class:: ClassDef(name, type_params, bases, keywords, body, decorator_list)
+.. class:: ClassDef(name, bases, keywords, body, decorator_list, type_params)
A class definition.
* ``name`` is a raw string for the class name
- * ``type_params`` is a list of :ref:`type parameters <ast-type-params>`.
* ``bases`` is a list of nodes for explicitly specified base classes.
* ``keywords`` is a list of :class:`keyword` nodes, principally for 'metaclass'.
Other keywords will be passed to the metaclass, as per `PEP-3115
@@ -1930,6 +1929,7 @@ Function and class definitions
* ``body`` is a list of nodes representing the code within the class
definition.
* ``decorator_list`` is a list of nodes, as in :class:`FunctionDef`.
+ * ``type_params`` is a list of :ref:`type parameters <ast-type-params>`.
.. doctest::
@@ -1961,7 +1961,7 @@ Function and class definitions
Async and await
^^^^^^^^^^^^^^^
-.. class:: AsyncFunctionDef(name, args, body, decorator_list, returns, type_comment)
+.. class:: AsyncFunctionDef(name, args, body, decorator_list, returns, type_comment, type_params)
An ``async def`` function definition. Has the same fields as
:class:`FunctionDef`.
1
0

[3.12] gh-105071: add PyUnstable_Exc_PrepReraiseStar to expose except* implementation in the unstable API (GH-105072) (#105095)
by iritkatriel May 30, 2023
by iritkatriel May 30, 2023
May 30, 2023
https://github.com/python/cpython/commit/b45df737d43e809b1c41b9b2056ecb28c3…
commit: b45df737d43e809b1c41b9b2056ecb28c3cfb288
branch: 3.12
author: Irit Katriel <1055913+iritkatriel(a)users.noreply.github.com>
committer: iritkatriel <1055913+iritkatriel(a)users.noreply.github.com>
date: 2023-05-30T16:50:23+01:00
summary:
[3.12] gh-105071: add PyUnstable_Exc_PrepReraiseStar to expose except* implementation in the unstable API (GH-105072) (#105095)
(cherry picked from commit b7aadb4583b040ddc8564896b91f4e5e571c82d6)
files:
A Misc/NEWS.d/next/C API/2023-05-30-10-15-13.gh-issue-105071.dPtp7c.rst
M Doc/c-api/exceptions.rst
M Include/cpython/pyerrors.h
M Lib/test/test_capi/test_exceptions.py
M Modules/_testcapi/clinic/exceptions.c.h
M Modules/_testcapi/exceptions.c
M Objects/exceptions.c
diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst
index 4ed96f01dbbc..22666d705290 100644
--- a/Doc/c-api/exceptions.rst
+++ b/Doc/c-api/exceptions.rst
@@ -772,6 +772,16 @@ Exception Objects
Set :attr:`~BaseException.args` of exception *ex* to *args*.
+.. c:function:: PyObject* PyUnstable_Exc_PrepReraiseStar(PyObject *orig, PyObject *excs)
+
+ Implement part of the interpreter's implementation of :keyword:`!except*`.
+ *orig* is the original exception that was caught, and *excs* is the list of
+ the exceptions that need to be raised. This list contains the the unhandled
+ part of *orig*, if any, as well as the exceptions that were raised from the
+ :keyword:`!except*` clauses (so they have a different traceback from *orig*) and
+ those that were reraised (and have the same traceback as *orig*).
+ Return the :exc:`ExceptionGroup` that needs to be reraised in the end, or
+ ``None`` if there is nothing to reraise.
.. _unicodeexceptions:
diff --git a/Include/cpython/pyerrors.h b/Include/cpython/pyerrors.h
index 758804ade2ba..156665cbdb1b 100644
--- a/Include/cpython/pyerrors.h
+++ b/Include/cpython/pyerrors.h
@@ -116,6 +116,10 @@ PyAPI_FUNC(int) _PyException_AddNote(
PyObject *exc,
PyObject *note);
+PyAPI_FUNC(PyObject*) PyUnstable_Exc_PrepReraiseStar(
+ PyObject *orig,
+ PyObject *excs);
+
/* In signalmodule.c */
int PySignal_SetWakeupFd(int fd);
diff --git a/Lib/test/test_capi/test_exceptions.py b/Lib/test/test_capi/test_exceptions.py
index 1081f40b6981..118b575cba6d 100644
--- a/Lib/test/test_capi/test_exceptions.py
+++ b/Lib/test/test_capi/test_exceptions.py
@@ -5,6 +5,7 @@
from test import support
from test.support import import_helper
from test.support.script_helper import assert_python_failure
+from test.support.testcase import ExceptionIsLikeMixin
from .test_misc import decode_stderr
@@ -189,5 +190,97 @@ def __repr__(self):
'Normalization failed: type=Broken args=<unknown>')
+class Test_PyUnstable_Exc_PrepReraiseStar(ExceptionIsLikeMixin, unittest.TestCase):
+
+ def setUp(self):
+ super().setUp()
+ try:
+ raise ExceptionGroup("eg", [TypeError('bad type'), ValueError(42)])
+ except ExceptionGroup as e:
+ self.orig = e
+
+ def test_invalid_args(self):
+ with self.assertRaisesRegex(TypeError, "orig must be an exception"):
+ _testcapi.unstable_exc_prep_reraise_star(42, [None])
+
+ with self.assertRaisesRegex(TypeError, "excs must be a list"):
+ _testcapi.unstable_exc_prep_reraise_star(self.orig, 42)
+
+ with self.assertRaisesRegex(TypeError, "not an exception"):
+ _testcapi.unstable_exc_prep_reraise_star(self.orig, [TypeError(42), 42])
+
+ with self.assertRaisesRegex(ValueError, "orig must be a raised exception"):
+ _testcapi.unstable_exc_prep_reraise_star(ValueError(42), [TypeError(42)])
+
+ with self.assertRaisesRegex(ValueError, "orig must be a raised exception"):
+ _testcapi.unstable_exc_prep_reraise_star(ExceptionGroup("eg", [ValueError(42)]),
+ [TypeError(42)])
+
+
+ def test_nothing_to_reraise(self):
+ self.assertEqual(
+ _testcapi.unstable_exc_prep_reraise_star(self.orig, [None]), None)
+
+ try:
+ raise ValueError(42)
+ except ValueError as e:
+ orig = e
+ self.assertEqual(
+ _testcapi.unstable_exc_prep_reraise_star(orig, [None]), None)
+
+ def test_reraise_orig(self):
+ orig = self.orig
+ res = _testcapi.unstable_exc_prep_reraise_star(orig, [orig])
+ self.assertExceptionIsLike(res, orig)
+
+ def test_raise_orig_parts(self):
+ orig = self.orig
+ match, rest = orig.split(TypeError)
+
+ test_cases = [
+ ([match, rest], orig),
+ ([rest, match], orig),
+ ([match], match),
+ ([rest], rest),
+ ([], None),
+ ]
+
+ for input, expected in test_cases:
+ with self.subTest(input=input):
+ res = _testcapi.unstable_exc_prep_reraise_star(orig, input)
+ self.assertExceptionIsLike(res, expected)
+
+
+ def test_raise_with_new_exceptions(self):
+ orig = self.orig
+
+ match, rest = orig.split(TypeError)
+ new1 = OSError('bad file')
+ new2 = RuntimeError('bad runtime')
+
+ test_cases = [
+ ([new1, match, rest], ExceptionGroup("", [new1, orig])),
+ ([match, new1, rest], ExceptionGroup("", [new1, orig])),
+ ([match, rest, new1], ExceptionGroup("", [new1, orig])),
+
+ ([new1, new2, match, rest], ExceptionGroup("", [new1, new2, orig])),
+ ([new1, match, new2, rest], ExceptionGroup("", [new1, new2, orig])),
+ ([new2, rest, match, new1], ExceptionGroup("", [new2, new1, orig])),
+ ([rest, new2, match, new1], ExceptionGroup("", [new2, new1, orig])),
+
+
+ ([new1, new2, rest], ExceptionGroup("", [new1, new2, rest])),
+ ([new1, match, new2], ExceptionGroup("", [new1, new2, match])),
+ ([rest, new2, new1], ExceptionGroup("", [new2, new1, rest])),
+ ([new1, new2], ExceptionGroup("", [new1, new2])),
+ ([new2, new1], ExceptionGroup("", [new2, new1])),
+ ]
+
+ for (input, expected) in test_cases:
+ with self.subTest(input=input):
+ res = _testcapi.unstable_exc_prep_reraise_star(orig, input)
+ self.assertExceptionIsLike(res, expected)
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/Misc/NEWS.d/next/C API/2023-05-30-10-15-13.gh-issue-105071.dPtp7c.rst b/Misc/NEWS.d/next/C API/2023-05-30-10-15-13.gh-issue-105071.dPtp7c.rst
new file mode 100644
index 000000000000..3d916fcb961f
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-05-30-10-15-13.gh-issue-105071.dPtp7c.rst
@@ -0,0 +1 @@
+Add ``PyUnstable_Exc_PrepReraiseStar`` to the unstable C api to expose the implementation of :keyword:`except* <except_star>`.
diff --git a/Modules/_testcapi/clinic/exceptions.c.h b/Modules/_testcapi/clinic/exceptions.c.h
index 2cc4ef3dc0d4..01730ffa2ed0 100644
--- a/Modules/_testcapi/clinic/exceptions.c.h
+++ b/Modules/_testcapi/clinic/exceptions.c.h
@@ -395,4 +395,35 @@ _testcapi_traceback_print(PyObject *module, PyObject *const *args, Py_ssize_t na
exit:
return return_value;
}
-/*[clinic end generated code: output=ec1b2e62adea9846 input=a9049054013a1b77]*/
+
+PyDoc_STRVAR(_testcapi_unstable_exc_prep_reraise_star__doc__,
+"unstable_exc_prep_reraise_star($module, orig, excs, /)\n"
+"--\n"
+"\n"
+"To test PyUnstable_Exc_PrepReraiseStar.");
+
+#define _TESTCAPI_UNSTABLE_EXC_PREP_RERAISE_STAR_METHODDEF \
+ {"unstable_exc_prep_reraise_star", _PyCFunction_CAST(_testcapi_unstable_exc_prep_reraise_star), METH_FASTCALL, _testcapi_unstable_exc_prep_reraise_star__doc__},
+
+static PyObject *
+_testcapi_unstable_exc_prep_reraise_star_impl(PyObject *module,
+ PyObject *orig, PyObject *excs);
+
+static PyObject *
+_testcapi_unstable_exc_prep_reraise_star(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *orig;
+ PyObject *excs;
+
+ if (!_PyArg_CheckPositional("unstable_exc_prep_reraise_star", nargs, 2, 2)) {
+ goto exit;
+ }
+ orig = args[0];
+ excs = args[1];
+ return_value = _testcapi_unstable_exc_prep_reraise_star_impl(module, orig, excs);
+
+exit:
+ return return_value;
+}
+/*[clinic end generated code: output=fd6aef54f195c77b input=a9049054013a1b77]*/
diff --git a/Modules/_testcapi/exceptions.c b/Modules/_testcapi/exceptions.c
index 0a9902c135a7..a627bf1717fe 100644
--- a/Modules/_testcapi/exceptions.c
+++ b/Modules/_testcapi/exceptions.c
@@ -288,6 +288,22 @@ _testcapi_traceback_print_impl(PyObject *module, PyObject *traceback,
Py_RETURN_NONE;
}
+/*[clinic input]
+_testcapi.unstable_exc_prep_reraise_star
+ orig: object
+ excs: object
+ /
+To test PyUnstable_Exc_PrepReraiseStar.
+[clinic start generated code]*/
+
+static PyObject *
+_testcapi_unstable_exc_prep_reraise_star_impl(PyObject *module,
+ PyObject *orig, PyObject *excs)
+/*[clinic end generated code: output=850cf008e0563c77 input=27fbcda2203eb301]*/
+{
+ return PyUnstable_Exc_PrepReraiseStar(orig, excs);
+}
+
/*
* Define the PyRecurdingInfinitelyError_Type
@@ -328,6 +344,7 @@ static PyMethodDef test_methods[] = {
_TESTCAPI_SET_EXCEPTION_METHODDEF
_TESTCAPI_TRACEBACK_PRINT_METHODDEF
_TESTCAPI_WRITE_UNRAISABLE_EXC_METHODDEF
+ _TESTCAPI_UNSTABLE_EXC_PREP_RERAISE_STAR_METHODDEF
{NULL},
};
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index a8d4e3a696ce..7bec7395cc7f 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -1351,7 +1351,10 @@ is_same_exception_metadata(PyObject *exc1, PyObject *exc2)
PyObject *
_PyExc_PrepReraiseStar(PyObject *orig, PyObject *excs)
{
+ /* orig must be a raised & caught exception, so it has a traceback */
assert(PyExceptionInstance_Check(orig));
+ assert(_PyBaseExceptionObject_cast(orig)->traceback != NULL);
+
assert(PyList_Check(excs));
Py_ssize_t numexcs = PyList_GET_SIZE(excs);
@@ -1438,6 +1441,42 @@ _PyExc_PrepReraiseStar(PyObject *orig, PyObject *excs)
return result;
}
+PyObject *
+PyUnstable_Exc_PrepReraiseStar(PyObject *orig, PyObject *excs)
+{
+ if (orig == NULL || !PyExceptionInstance_Check(orig)) {
+ PyErr_SetString(PyExc_TypeError, "orig must be an exception instance");
+ return NULL;
+ }
+ if (excs == NULL || !PyList_Check(excs)) {
+ PyErr_SetString(PyExc_TypeError,
+ "excs must be a list of exception instances");
+ return NULL;
+ }
+ Py_ssize_t numexcs = PyList_GET_SIZE(excs);
+ for (Py_ssize_t i = 0; i < numexcs; i++) {
+ PyObject *exc = PyList_GET_ITEM(excs, i);
+ if (exc == NULL || !(PyExceptionInstance_Check(exc) || Py_IsNone(exc))) {
+ PyErr_Format(PyExc_TypeError,
+ "item %d of excs is not an exception", i);
+ return NULL;
+ }
+ }
+
+ /* Make sure that orig has something as traceback, in the interpreter
+ * it always does becuase it's a raised exception.
+ */
+ PyObject *tb = PyException_GetTraceback(orig);
+
+ if (tb == NULL) {
+ PyErr_Format(PyExc_ValueError, "orig must be a raised exception");
+ return NULL;
+ }
+ Py_DECREF(tb);
+
+ return _PyExc_PrepReraiseStar(orig, excs);
+}
+
static PyMemberDef BaseExceptionGroup_members[] = {
{"message", T_OBJECT, offsetof(PyBaseExceptionGroupObject, msg), READONLY,
PyDoc_STR("exception message")},
1
0

gh-105091: stable_abi.py: Remove "Unixy" check from --all on other platforms (GH-105092)
by encukou May 30, 2023
by encukou May 30, 2023
May 30, 2023
https://github.com/python/cpython/commit/0656d23d82cd5b88e578a26c65dd4a6441…
commit: 0656d23d82cd5b88e578a26c65dd4a64414c833b
branch: main
author: Petr Viktorin <encukou(a)gmail.com>
committer: encukou <encukou(a)gmail.com>
date: 2023-05-30T17:45:56+02:00
summary:
gh-105091: stable_abi.py: Remove "Unixy" check from --all on other platforms (GH-105092)
files:
M Tools/build/stable_abi.py
diff --git a/Tools/build/stable_abi.py b/Tools/build/stable_abi.py
index 88db93e935e9..42b2dd92307b 100644
--- a/Tools/build/stable_abi.py
+++ b/Tools/build/stable_abi.py
@@ -684,7 +684,8 @@ def main():
if args.all:
run_all_generators = True
- args.unixy_check = True
+ if UNIXY:
+ args.unixy_check = True
try:
file = args.file.open('rb')
1
0

[3.12] gh-104799: Move location of type_params AST fields (GH-104828) (#104974)
by JelleZijlstra May 30, 2023
by JelleZijlstra May 30, 2023
May 30, 2023
https://github.com/python/cpython/commit/7899fac3c5fba3b8258cdd72562230c511…
commit: 7899fac3c5fba3b8258cdd72562230c51164d778
branch: 3.12
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: JelleZijlstra <jelle.zijlstra(a)gmail.com>
date: 2023-05-30T14:33:01Z
summary:
[3.12] gh-104799: Move location of type_params AST fields (GH-104828) (#104974)
gh-104799: Move location of type_params AST fields (GH-104828)
(cherry picked from commit ba73473f4c18ba4cf7ab18d84d94a47d2d37a0c5)
Co-authored-by: Jelle Zijlstra <jelle.zijlstra(a)gmail.com>
Co-authored-by: Alex Waygood <Alex.Waygood(a)Gmail.com>
files:
A Misc/NEWS.d/next/Library/2023-05-23-18-31-49.gh-issue-104799.MJYOw6.rst
M Doc/data/python3.12.abi
M Doc/library/ast.rst
M Grammar/python.gram
M Include/internal/pycore_ast.h
M Lib/test/test_ast.py
M Parser/Python.asdl
M Parser/action_helpers.c
M Parser/parser.c
M Python/Python-ast.c
diff --git a/Doc/data/python3.12.abi b/Doc/data/python3.12.abi
index 79bf7ea6df829..9802893e69cca 100644
--- a/Doc/data/python3.12.abi
+++ b/Doc/data/python3.12.abi
@@ -10092,22 +10092,22 @@
<var-decl name='name' type-id='type-id-525' visibility='default' filepath='./Include/internal/pycore_ast.h' line='200' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='type_params' type-id='type-id-526' visibility='default' filepath='./Include/internal/pycore_ast.h' line='201' column='1'/>
+ <var-decl name='args' type-id='type-id-526' visibility='default' filepath='./Include/internal/pycore_ast.h' line='201' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='args' type-id='type-id-527' visibility='default' filepath='./Include/internal/pycore_ast.h' line='202' column='1'/>
+ <var-decl name='body' type-id='type-id-500' visibility='default' filepath='./Include/internal/pycore_ast.h' line='202' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='body' type-id='type-id-500' visibility='default' filepath='./Include/internal/pycore_ast.h' line='203' column='1'/>
+ <var-decl name='decorator_list' type-id='type-id-503' visibility='default' filepath='./Include/internal/pycore_ast.h' line='203' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='256'>
- <var-decl name='decorator_list' type-id='type-id-503' visibility='default' filepath='./Include/internal/pycore_ast.h' line='204' column='1'/>
+ <var-decl name='returns' type-id='type-id-502' visibility='default' filepath='./Include/internal/pycore_ast.h' line='204' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='320'>
- <var-decl name='returns' type-id='type-id-502' visibility='default' filepath='./Include/internal/pycore_ast.h' line='205' column='1'/>
+ <var-decl name='type_comment' type-id='type-id-527' visibility='default' filepath='./Include/internal/pycore_ast.h' line='205' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='384'>
- <var-decl name='type_comment' type-id='type-id-528' visibility='default' filepath='./Include/internal/pycore_ast.h' line='206' column='1'/>
+ <var-decl name='type_params' type-id='type-id-528' visibility='default' filepath='./Include/internal/pycore_ast.h' line='206' column='1'/>
</data-member>
</class-decl>
<class-decl name='__anonymous_struct__6' size-in-bits='384' is-struct='yes' is-anonymous='yes' visibility='default' filepath='./Include/internal/pycore_ast.h' line='219' column='1' id='type-id-508'>
@@ -10115,19 +10115,19 @@
<var-decl name='name' type-id='type-id-525' visibility='default' filepath='./Include/internal/pycore_ast.h' line='220' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='type_params' type-id='type-id-526' visibility='default' filepath='./Include/internal/pycore_ast.h' line='221' column='1'/>
+ <var-decl name='bases' type-id='type-id-503' visibility='default' filepath='./Include/internal/pycore_ast.h' line='221' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='bases' type-id='type-id-503' visibility='default' filepath='./Include/internal/pycore_ast.h' line='222' column='1'/>
+ <var-decl name='keywords' type-id='type-id-529' visibility='default' filepath='./Include/internal/pycore_ast.h' line='222' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='keywords' type-id='type-id-529' visibility='default' filepath='./Include/internal/pycore_ast.h' line='223' column='1'/>
+ <var-decl name='body' type-id='type-id-500' visibility='default' filepath='./Include/internal/pycore_ast.h' line='223' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='256'>
- <var-decl name='body' type-id='type-id-500' visibility='default' filepath='./Include/internal/pycore_ast.h' line='224' column='1'/>
+ <var-decl name='decorator_list' type-id='type-id-503' visibility='default' filepath='./Include/internal/pycore_ast.h' line='224' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='320'>
- <var-decl name='decorator_list' type-id='type-id-503' visibility='default' filepath='./Include/internal/pycore_ast.h' line='225' column='1'/>
+ <var-decl name='type_params' type-id='type-id-528' visibility='default' filepath='./Include/internal/pycore_ast.h' line='225' column='1'/>
</data-member>
</class-decl>
<class-decl name='__anonymous_struct__8' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' filepath='./Include/internal/pycore_ast.h' line='232' column='1' id='type-id-510'>
@@ -10143,7 +10143,7 @@
<var-decl name='value' type-id='type-id-502' visibility='default' filepath='./Include/internal/pycore_ast.h' line='238' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='type_comment' type-id='type-id-528' visibility='default' filepath='./Include/internal/pycore_ast.h' line='239' column='1'/>
+ <var-decl name='type_comment' type-id='type-id-527' visibility='default' filepath='./Include/internal/pycore_ast.h' line='239' column='1'/>
</data-member>
</class-decl>
<class-decl name='__anonymous_struct__10' size-in-bits='192' is-struct='yes' is-anonymous='yes' visibility='default' filepath='./Include/internal/pycore_ast.h' line='242' column='1' id='type-id-512'>
@@ -10151,7 +10151,7 @@
<var-decl name='name' type-id='type-id-502' visibility='default' filepath='./Include/internal/pycore_ast.h' line='243' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='type_params' type-id='type-id-526' visibility='default' filepath='./Include/internal/pycore_ast.h' line='244' column='1'/>
+ <var-decl name='type_params' type-id='type-id-528' visibility='default' filepath='./Include/internal/pycore_ast.h' line='244' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
<var-decl name='value' type-id='type-id-502' visibility='default' filepath='./Include/internal/pycore_ast.h' line='245' column='1'/>
@@ -10196,7 +10196,7 @@
<var-decl name='orelse' type-id='type-id-500' visibility='default' filepath='./Include/internal/pycore_ast.h' line='265' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='256'>
- <var-decl name='type_comment' type-id='type-id-528' visibility='default' filepath='./Include/internal/pycore_ast.h' line='266' column='1'/>
+ <var-decl name='type_comment' type-id='type-id-527' visibility='default' filepath='./Include/internal/pycore_ast.h' line='266' column='1'/>
</data-member>
</class-decl>
<class-decl name='__anonymous_struct__15' size-in-bits='192' is-struct='yes' is-anonymous='yes' visibility='default' filepath='./Include/internal/pycore_ast.h' line='277' column='1' id='type-id-516'>
@@ -10218,7 +10218,7 @@
<var-decl name='body' type-id='type-id-500' visibility='default' filepath='./Include/internal/pycore_ast.h' line='291' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='type_comment' type-id='type-id-528' visibility='default' filepath='./Include/internal/pycore_ast.h' line='292' column='1'/>
+ <var-decl name='type_comment' type-id='type-id-527' visibility='default' filepath='./Include/internal/pycore_ast.h' line='292' column='1'/>
</data-member>
</class-decl>
<class-decl name='__anonymous_struct__19' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' filepath='./Include/internal/pycore_ast.h' line='301' column='1' id='type-id-518'>
@@ -10481,7 +10481,7 @@
<var-decl name='lineno' type-id='type-id-8' visibility='default' filepath='./Include/internal/pycore_ast.h' line='646' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='tag' type-id='type-id-528' visibility='default' filepath='./Include/internal/pycore_ast.h' line='647' column='1'/>
+ <var-decl name='tag' type-id='type-id-527' visibility='default' filepath='./Include/internal/pycore_ast.h' line='647' column='1'/>
</data-member>
</class-decl>
<enum-decl name='_type_param_kind' filepath='./Include/internal/pycore_ast.h' line='653' column='1' id='type-id-558'>
@@ -10521,7 +10521,7 @@
<var-decl name='TypeVarTuple' type-id='type-id-550' visibility='default' filepath='./Include/internal/pycore_ast.h' line='668' column='1'/>
</data-member>
</union-decl>
- <class-decl name='__anonymous_struct__4' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' filepath='./Include/internal/pycore_ast.h' line='657' column='1' id='type-id-561'>
+ <class-decl name='__anonymous_struct__3' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' filepath='./Include/internal/pycore_ast.h' line='657' column='1' id='type-id-561'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='name' type-id='type-id-525' visibility='default' filepath='./Include/internal/pycore_ast.h' line='658' column='1'/>
</data-member>
@@ -10529,7 +10529,7 @@
<var-decl name='bound' type-id='type-id-502' visibility='default' filepath='./Include/internal/pycore_ast.h' line='659' column='1'/>
</data-member>
</class-decl>
- <class-decl name='__anonymous_struct__5' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' filepath='./Include/internal/pycore_ast.h' line='662' column='1' id='type-id-550'>
+ <class-decl name='__anonymous_struct__4' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' filepath='./Include/internal/pycore_ast.h' line='662' column='1' id='type-id-550'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='name' type-id='type-id-525' visibility='default' filepath='./Include/internal/pycore_ast.h' line='663' column='1'/>
</data-member>
@@ -10553,7 +10553,7 @@
<pointer-type-def type-id='type-id-487' size-in-bits='64' id='type-id-553'/>
<pointer-type-def type-id='type-id-477' size-in-bits='64' id='type-id-500'/>
<pointer-type-def type-id='type-id-489' size-in-bits='64' id='type-id-501'/>
- <pointer-type-def type-id='type-id-491' size-in-bits='64' id='type-id-526'/>
+ <pointer-type-def type-id='type-id-491' size-in-bits='64' id='type-id-528'/>
<pointer-type-def type-id='type-id-483' size-in-bits='64' id='type-id-531'/>
<function-decl name='PyBytes_FromString' mangled-name='PyBytes_FromString' filepath='./Include/bytesobject.h' line='35' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='PyBytes_FromString'>
<parameter type-id='type-id-12'/>
@@ -10630,10 +10630,10 @@
<function-decl name='_PyAST_FunctionDef' filepath='./Include/internal/pycore_ast.h' line='685' column='1' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='type-id-525'/>
<parameter type-id='type-id-526'/>
- <parameter type-id='type-id-527'/>
<parameter type-id='type-id-500'/>
<parameter type-id='type-id-503'/>
<parameter type-id='type-id-502'/>
+ <parameter type-id='type-id-527'/>
<parameter type-id='type-id-528'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
@@ -10645,10 +10645,10 @@
<function-decl name='_PyAST_AsyncFunctionDef' filepath='./Include/internal/pycore_ast.h' line='690' column='1' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='type-id-525'/>
<parameter type-id='type-id-526'/>
- <parameter type-id='type-id-527'/>
<parameter type-id='type-id-500'/>
<parameter type-id='type-id-503'/>
<parameter type-id='type-id-502'/>
+ <parameter type-id='type-id-527'/>
<parameter type-id='type-id-528'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
@@ -10659,11 +10659,11 @@
</function-decl>
<function-decl name='_PyAST_ClassDef' filepath='./Include/internal/pycore_ast.h' line='696' column='1' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='type-id-525'/>
- <parameter type-id='type-id-526'/>
<parameter type-id='type-id-503'/>
<parameter type-id='type-id-529'/>
<parameter type-id='type-id-500'/>
<parameter type-id='type-id-503'/>
+ <parameter type-id='type-id-528'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
@@ -10763,12 +10763,12 @@
<parameter type-id='type-id-567'/>
<parameter type-id='type-id-503'/>
<parameter type-id='type-id-563'/>
- <return type-id='type-id-527'/>
+ <return type-id='type-id-526'/>
</function-decl>
<function-decl name='_PyAST_arg' filepath='./Include/internal/pycore_ast.h' line='857' column='1' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='type-id-525'/>
<parameter type-id='type-id-502'/>
- <parameter type-id='type-id-528'/>
+ <parameter type-id='type-id-527'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
@@ -10788,7 +10788,7 @@
</function-decl>
<function-decl name='_PyAST_TypeIgnore' filepath='./Include/internal/pycore_ast.h' line='894' column='1' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='type-id-8'/>
- <parameter type-id='type-id-528'/>
+ <parameter type-id='type-id-527'/>
<parameter type-id='type-id-563'/>
<return type-id='type-id-454'/>
</function-decl>
@@ -10877,10 +10877,10 @@
<array-type-def dimensions='1' type-id='type-id-592' size-in-bits='5120' id='type-id-593'>
<subrange length='80' type-id='type-id-28' id='type-id-575'/>
</array-type-def>
- <array-type-def dimensions='1' type-id='type-id-594' size-in-bits='49152' id='type-id-595'>
+ <array-type-def dimensions='1' type-id='type-id-594' size-in-bits='65536' id='type-id-595'>
<subrange length='128' type-id='type-id-28' id='type-id-437'/>
</array-type-def>
- <array-type-def dimensions='1' type-id='type-id-596' size-in-bits='65536' id='type-id-597'>
+ <array-type-def dimensions='1' type-id='type-id-596' size-in-bits='49152' id='type-id-597'>
<subrange length='128' type-id='type-id-28' id='type-id-437'/>
</array-type-def>
<array-type-def dimensions='1' type-id='type-id-598' size-in-bits='98304' id='type-id-599'>
@@ -13441,10 +13441,10 @@
<var-decl name='identifiers' type-id='type-id-867' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='748' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='303232'>
- <var-decl name='ascii' type-id='type-id-595' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='752' column='1'/>
+ <var-decl name='ascii' type-id='type-id-597' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='752' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='352384'>
- <var-decl name='latin1' type-id='type-id-597' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='756' column='1'/>
+ <var-decl name='latin1' type-id='type-id-595' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='756' column='1'/>
</data-member>
</class-decl>
<class-decl name='__anonymous_struct__23' size-in-bits='11008' is-struct='yes' is-anonymous='yes' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='30' column='1' id='type-id-866'>
@@ -13473,7 +13473,7 @@
<var-decl name='_py_anon_unknown' type-id='type-id-869' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='38' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='3584'>
- <var-decl name='_py_close_br' type-id='type-id-594' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='39' column='1'/>
+ <var-decl name='_py_close_br' type-id='type-id-596' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='39' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='3968'>
<var-decl name='_py_dbl_close_br' type-id='type-id-871' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='40' column='1'/>
@@ -13488,7 +13488,7 @@
<var-decl name='_py_defaults' type-id='type-id-869' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='43' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='5568'>
- <var-decl name='_py_dot' type-id='type-id-594' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='44' column='1'/>
+ <var-decl name='_py_dot' type-id='type-id-596' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='44' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='5952'>
<var-decl name='_py_dot_locals' type-id='type-id-869' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='45' column='1'/>
@@ -13509,13 +13509,13 @@
<var-decl name='_py_list_err' type-id='type-id-876' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='50' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='8640'>
- <var-decl name='_py_newline' type-id='type-id-594' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='51' column='1'/>
+ <var-decl name='_py_newline' type-id='type-id-596' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='51' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='9024'>
- <var-decl name='_py_open_br' type-id='type-id-594' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='52' column='1'/>
+ <var-decl name='_py_open_br' type-id='type-id-596' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='52' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='9408'>
- <var-decl name='_py_percent' type-id='type-id-594' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='53' column='1'/>
+ <var-decl name='_py_percent' type-id='type-id-596' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='53' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='9792'>
<var-decl name='_py_shim_name' type-id='type-id-877' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='54' column='1'/>
@@ -13551,7 +13551,7 @@
<var-decl name='_data' type-id='type-id-694' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='33' column='1'/>
</data-member>
</class-decl>
- <class-decl name='__anonymous_struct__33' size-in-bits='384' is-struct='yes' is-anonymous='yes' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='39' column='1' id='type-id-594'>
+ <class-decl name='__anonymous_struct__33' size-in-bits='384' is-struct='yes' is-anonymous='yes' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='39' column='1' id='type-id-596'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='_ascii' type-id='type-id-792' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='39' column='1'/>
</data-member>
@@ -13652,7 +13652,7 @@
<var-decl name='_py_WarningMessage' type-id='type-id-882' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='68' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='3776'>
- <var-decl name='_py__' type-id='type-id-594' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='69' column='1'/>
+ <var-decl name='_py__' type-id='type-id-596' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='69' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='4160'>
<var-decl name='_py__WindowsConsoleIO' type-id='type-id-883' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='70' column='1'/>
@@ -14252,7 +14252,7 @@
<var-decl name='_py__xoptions' type-id='type-id-869' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='268' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='93440'>
- <var-decl name='_py_a' type-id='type-id-594' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='269' column='1'/>
+ <var-decl name='_py_a' type-id='type-id-596' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='269' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='93824'>
<var-decl name='_py_abs_tol' type-id='type-id-880' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='270' column='1'/>
@@ -14312,7 +14312,7 @@
<var-decl name='_py_autocommit' type-id='type-id-868' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='288' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='101888'>
- <var-decl name='_py_b' type-id='type-id-594' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='289' column='1'/>
+ <var-decl name='_py_b' type-id='type-id-596' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='289' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='102272'>
<var-decl name='_py_backtick' type-id='type-id-870' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='290' column='1'/>
@@ -14366,7 +14366,7 @@
<var-decl name='_py_bytes_per_sep' type-id='type-id-873' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='306' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='109312'>
- <var-decl name='_py_c' type-id='type-id-594' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='307' column='1'/>
+ <var-decl name='_py_c' type-id='type-id-596' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='307' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='109696'>
<var-decl name='_py_c_call' type-id='type-id-877' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='308' column='1'/>
@@ -14525,7 +14525,7 @@
<var-decl name='_py_cwd' type-id='type-id-891' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='359' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='131840'>
- <var-decl name='_py_d' type-id='type-id-594' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='360' column='1'/>
+ <var-decl name='_py_d' type-id='type-id-596' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='360' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='132224'>
<var-decl name='_py_data' type-id='type-id-881' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='361' column='1'/>
@@ -14609,7 +14609,7 @@
<var-decl name='_py_duration' type-id='type-id-870' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='387' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='143488'>
- <var-decl name='_py_e' type-id='type-id-594' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='388' column='1'/>
+ <var-decl name='_py_e' type-id='type-id-596' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='388' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='143872'>
<var-decl name='_py_eager_start' type-id='type-id-875' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='389' column='1'/>
@@ -15089,7 +15089,7 @@
<var-decl name='_py_mycmp' type-id='type-id-878' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='547' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='209472'>
- <var-decl name='_py_n' type-id='type-id-594' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='548' column='1'/>
+ <var-decl name='_py_n' type-id='type-id-596' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='548' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='209856'>
<var-decl name='_py_n_arg' type-id='type-id-878' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='549' column='1'/>
@@ -15221,7 +15221,7 @@
<var-decl name='_py_owner' type-id='type-id-878' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='591' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='227776'>
- <var-decl name='_py_p' type-id='type-id-594' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='592' column='1'/>
+ <var-decl name='_py_p' type-id='type-id-596' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='592' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='228160'>
<var-decl name='_py_pages' type-id='type-id-878' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='593' column='1'/>
@@ -15302,7 +15302,7 @@
<var-decl name='_py_quotetabs' type-id='type-id-869' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='618' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='238912'>
- <var-decl name='_py_r' type-id='type-id-594' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='619' column='1'/>
+ <var-decl name='_py_r' type-id='type-id-596' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='619' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='239296'>
<var-decl name='_py_raw' type-id='type-id-891' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='620' column='1'/>
@@ -15374,7 +15374,7 @@
<var-decl name='_py_reversed' type-id='type-id-870' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='642' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='248832'>
- <var-decl name='_py_s' type-id='type-id-594' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='643' column='1'/>
+ <var-decl name='_py_s' type-id='type-id-596' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='643' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='249216'>
<var-decl name='_py_salt' type-id='type-id-881' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='644' column='1'/>
@@ -15680,7 +15680,7 @@
<var-decl name='_py_write_through' type-id='type-id-873' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='744' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='291072'>
- <var-decl name='_py_x' type-id='type-id-594' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='745' column='1'/>
+ <var-decl name='_py_x' type-id='type-id-596' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='745' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='291456'>
<var-decl name='_py_year' type-id='type-id-881' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='746' column='1'/>
@@ -15817,7 +15817,7 @@
<var-decl name='_data' type-id='type-id-679' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='693' column='1'/>
</data-member>
</class-decl>
- <class-decl name='__anonymous_struct__741' size-in-bits='512' is-struct='yes' is-anonymous='yes' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='753' column='1' id='type-id-596'>
+ <class-decl name='__anonymous_struct__741' size-in-bits='512' is-struct='yes' is-anonymous='yes' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='753' column='1' id='type-id-594'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='_latin1' type-id='type-id-795' visibility='default' filepath='./Include/internal/pycore_global_strings.h' line='754' column='1'/>
</data-member>
@@ -17440,10 +17440,10 @@
<parameter type-id='type-id-8'/>
<return type-id='type-id-8'/>
</function-decl>
- <function-decl name='PyOS_Readline' mangled-name='PyOS_Readline' filepath='Parser/myreadline.c' line='358' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='PyOS_Readline'>
- <parameter type-id='type-id-229' name='sys_stdin' filepath='Parser/myreadline.c' line='358' column='1'/>
- <parameter type-id='type-id-229' name='sys_stdout' filepath='Parser/myreadline.c' line='358' column='1'/>
- <parameter type-id='type-id-12' name='prompt' filepath='Parser/myreadline.c' line='358' column='1'/>
+ <function-decl name='PyOS_Readline' mangled-name='PyOS_Readline' filepath='Parser/myreadline.c' line='364' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='PyOS_Readline'>
+ <parameter type-id='type-id-229' name='sys_stdin' filepath='Parser/myreadline.c' line='364' column='1'/>
+ <parameter type-id='type-id-229' name='sys_stdout' filepath='Parser/myreadline.c' line='364' column='1'/>
+ <parameter type-id='type-id-12' name='prompt' filepath='Parser/myreadline.c' line='364' column='1'/>
<return type-id='type-id-15'/>
</function-decl>
<function-type size-in-bits='64' id='type-id-1053'>
@@ -17916,7 +17916,7 @@
<function-decl name='_PyAST_Assign' filepath='./Include/internal/pycore_ast.h' line='705' column='1' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='type-id-503'/>
<parameter type-id='type-id-502'/>
- <parameter type-id='type-id-528'/>
+ <parameter type-id='type-id-527'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
@@ -17926,7 +17926,7 @@
</function-decl>
<function-decl name='_PyAST_TypeAlias' filepath='./Include/internal/pycore_ast.h' line='708' column='1' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='type-id-502'/>
- <parameter type-id='type-id-526'/>
+ <parameter type-id='type-id-528'/>
<parameter type-id='type-id-502'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
@@ -17963,7 +17963,7 @@
<parameter type-id='type-id-502'/>
<parameter type-id='type-id-500'/>
<parameter type-id='type-id-500'/>
- <parameter type-id='type-id-528'/>
+ <parameter type-id='type-id-527'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
@@ -17976,7 +17976,7 @@
<parameter type-id='type-id-502'/>
<parameter type-id='type-id-500'/>
<parameter type-id='type-id-500'/>
- <parameter type-id='type-id-528'/>
+ <parameter type-id='type-id-527'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
@@ -18009,7 +18009,7 @@
<function-decl name='_PyAST_With' filepath='./Include/internal/pycore_ast.h' line='731' column='1' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='type-id-531'/>
<parameter type-id='type-id-500'/>
- <parameter type-id='type-id-528'/>
+ <parameter type-id='type-id-527'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
@@ -18020,7 +18020,7 @@
<function-decl name='_PyAST_AsyncWith' filepath='./Include/internal/pycore_ast.h' line='734' column='1' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='type-id-531'/>
<parameter type-id='type-id-500'/>
- <parameter type-id='type-id-528'/>
+ <parameter type-id='type-id-527'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
@@ -18195,7 +18195,7 @@
<return type-id='type-id-502'/>
</function-decl>
<function-decl name='_PyAST_Lambda' filepath='./Include/internal/pycore_ast.h' line='782' column='1' visibility='default' binding='global' size-in-bits='64'>
- <parameter type-id='type-id-527'/>
+ <parameter type-id='type-id-526'/>
<parameter type-id='type-id-502'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
@@ -18714,11 +18714,11 @@
<parameter type-id='type-id-565'/>
<parameter type-id='type-id-1101'/>
<parameter type-id='type-id-1120'/>
- <return type-id='type-id-527'/>
+ <return type-id='type-id-526'/>
</function-decl>
<function-decl name='_PyPegen_empty_arguments' filepath='Parser/pegen.h' line='318' column='1' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='type-id-568'/>
- <return type-id='type-id-527'/>
+ <return type-id='type-id-526'/>
</function-decl>
<function-decl name='_PyPegen_formatted_value' filepath='Parser/pegen.h' line='319' column='1' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='type-id-568'/>
@@ -19370,7 +19370,7 @@
</data-member>
</class-decl>
<typedef-decl name='identifier' type-id='type-id-2' filepath='./Include/internal/pycore_asdl.h' line='13' column='1' id='type-id-525'/>
- <typedef-decl name='string' type-id='type-id-2' filepath='./Include/internal/pycore_asdl.h' line='14' column='1' id='type-id-528'/>
+ <typedef-decl name='string' type-id='type-id-2' filepath='./Include/internal/pycore_asdl.h' line='14' column='1' id='type-id-527'/>
<typedef-decl name='constant' type-id='type-id-2' filepath='./Include/internal/pycore_asdl.h' line='16' column='1' id='type-id-552'/>
<class-decl name='asdl_int_seq' size-in-bits='192' is-struct='yes' naming-typedef-id='type-id-1205' visibility='default' filepath='./Include/internal/pycore_asdl.h' line='42' column='1' id='type-id-1206'>
<data-member access='public' layout-offset-in-bits='0'>
@@ -19424,7 +19424,7 @@
</enum-decl>
<typedef-decl name='unaryop_ty' type-id='type-id-1211' filepath='./Include/internal/pycore_ast.h' line='29' column='1' id='type-id-1137'/>
<typedef-decl name='comprehension_ty' type-id='type-id-1212' filepath='./Include/internal/pycore_ast.h' line='34' column='1' id='type-id-1139'/>
- <typedef-decl name='arguments_ty' type-id='type-id-1213' filepath='./Include/internal/pycore_ast.h' line='38' column='1' id='type-id-527'/>
+ <typedef-decl name='arguments_ty' type-id='type-id-1213' filepath='./Include/internal/pycore_ast.h' line='38' column='1' id='type-id-526'/>
<typedef-decl name='arg_ty' type-id='type-id-1214' filepath='./Include/internal/pycore_ast.h' line='40' column='1' id='type-id-567'/>
<typedef-decl name='keyword_ty' type-id='type-id-1215' filepath='./Include/internal/pycore_ast.h' line='42' column='1' id='type-id-1140'/>
<class-decl name='asdl_expr_seq' size-in-bits='192' is-struct='yes' naming-typedef-id='type-id-1216' visibility='default' filepath='./Include/internal/pycore_ast.h' line='71' column='1' id='type-id-1217'>
@@ -19645,7 +19645,7 @@
</class-decl>
<class-decl name='__anonymous_struct__5' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' filepath='./Include/internal/pycore_ast.h' line='391' column='1' id='type-id-1230'>
<data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='args' type-id='type-id-527' visibility='default' filepath='./Include/internal/pycore_ast.h' line='392' column='1'/>
+ <var-decl name='args' type-id='type-id-526' visibility='default' filepath='./Include/internal/pycore_ast.h' line='392' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='body' type-id='type-id-502' visibility='default' filepath='./Include/internal/pycore_ast.h' line='393' column='1'/>
@@ -19742,7 +19742,7 @@
<var-decl name='value' type-id='type-id-552' visibility='default' filepath='./Include/internal/pycore_ast.h' line='467' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='kind' type-id='type-id-528' visibility='default' filepath='./Include/internal/pycore_ast.h' line='468' column='1'/>
+ <var-decl name='kind' type-id='type-id-527' visibility='default' filepath='./Include/internal/pycore_ast.h' line='468' column='1'/>
</data-member>
</class-decl>
<class-decl name='__anonymous_struct__21' size-in-bits='192' is-struct='yes' is-anonymous='yes' visibility='default' filepath='./Include/internal/pycore_ast.h' line='471' column='1' id='type-id-1241'>
@@ -19847,7 +19847,7 @@
<var-decl name='annotation' type-id='type-id-502' visibility='default' filepath='./Include/internal/pycore_ast.h' line='552' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='type_comment' type-id='type-id-528' visibility='default' filepath='./Include/internal/pycore_ast.h' line='553' column='1'/>
+ <var-decl name='type_comment' type-id='type-id-527' visibility='default' filepath='./Include/internal/pycore_ast.h' line='553' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='192'>
<var-decl name='lineno' type-id='type-id-8' visibility='default' filepath='./Include/internal/pycore_ast.h' line='554' column='1'/>
@@ -20608,7 +20608,7 @@
</function-decl>
<function-decl name='_PyAST_Constant' filepath='./Include/internal/pycore_ast.h' line='822' column='1' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='type-id-552'/>
- <parameter type-id='type-id-528'/>
+ <parameter type-id='type-id-527'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
<parameter type-id='type-id-8'/>
@@ -21234,7 +21234,7 @@
<parameter type-id='type-id-47'/>
<return type-id='type-id-8'/>
</function-decl>
- <function-decl name='PyInit__ast' mangled-name='PyInit__ast' filepath='Python/Python-ast.c' line='12916' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='PyInit__ast'>
+ <function-decl name='PyInit__ast' mangled-name='PyInit__ast' filepath='Python/Python-ast.c' line='12915' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='PyInit__ast'>
<return type-id='type-id-2'/>
</function-decl>
</abi-instr>
@@ -21244,7 +21244,7 @@
<parameter type-id='type-id-1'/>
<return type-id='type-id-8'/>
</function-decl>
- <function-decl name='PyInit__tokenize' mangled-name='PyInit__tokenize' filepath='Python/Python-tokenize.c' line='322' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='PyInit__tokenize'>
+ <function-decl name='PyInit__tokenize' mangled-name='PyInit__tokenize' filepath='Python/Python-tokenize.c' line='326' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='PyInit__tokenize'>
<return type-id='type-id-2'/>
</function-decl>
</abi-instr>
diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst
index 8a686354b9f65..17d1de9fbb8f1 100644
--- a/Doc/library/ast.rst
+++ b/Doc/library/ast.rst
@@ -1821,7 +1821,6 @@ Function and class definitions
body=[
FunctionDef(
name='f',
- type_params=[],
args=arguments(
posonlyargs=[],
args=[
@@ -1846,7 +1845,8 @@ Function and class definitions
decorator_list=[
Name(id='decorator1', ctx=Load()),
Name(id='decorator2', ctx=Load())],
- returns=Constant(value='return annotation'))],
+ returns=Constant(value='return annotation'),
+ type_params=[])],
type_ignores=[])
@@ -1943,7 +1943,6 @@ Function and class definitions
body=[
ClassDef(
name='Foo',
- type_params=[],
bases=[
Name(id='base1', ctx=Load()),
Name(id='base2', ctx=Load())],
@@ -1955,7 +1954,8 @@ Function and class definitions
Pass()],
decorator_list=[
Name(id='decorator1', ctx=Load()),
- Name(id='decorator2', ctx=Load())])],
+ Name(id='decorator2', ctx=Load())],
+ type_params=[])],
type_ignores=[])
Async and await
@@ -1982,7 +1982,6 @@ Async and await
body=[
AsyncFunctionDef(
name='f',
- type_params=[],
args=arguments(
posonlyargs=[],
args=[],
@@ -1996,7 +1995,8 @@ Async and await
func=Name(id='other_func', ctx=Load()),
args=[],
keywords=[])))],
- decorator_list=[])],
+ decorator_list=[],
+ type_params=[])],
type_ignores=[])
diff --git a/Grammar/python.gram b/Grammar/python.gram
index e6a983429e39d..9131835f7421b 100644
--- a/Grammar/python.gram
+++ b/Grammar/python.gram
@@ -254,10 +254,10 @@ class_def[stmt_ty]:
class_def_raw[stmt_ty]:
| invalid_class_def_raw
| 'class' a=NAME t=[type_params] b=['(' z=[arguments] ')' { z }] ':' c=block {
- _PyAST_ClassDef(a->v.Name.id, t,
+ _PyAST_ClassDef(a->v.Name.id,
(b) ? ((expr_ty) b)->v.Call.args : NULL,
(b) ? ((expr_ty) b)->v.Call.keywords : NULL,
- c, NULL, EXTRA) }
+ c, NULL, t, EXTRA) }
# Function definitions
# --------------------
@@ -269,17 +269,17 @@ function_def[stmt_ty]:
function_def_raw[stmt_ty]:
| invalid_def_raw
| 'def' n=NAME t=[type_params] &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block {
- _PyAST_FunctionDef(n->v.Name.id, t,
+ _PyAST_FunctionDef(n->v.Name.id,
(params) ? params : CHECK(arguments_ty, _PyPegen_empty_arguments(p)),
- b, NULL, a, NEW_TYPE_COMMENT(p, tc), EXTRA) }
+ b, NULL, a, NEW_TYPE_COMMENT(p, tc), t, EXTRA) }
| ASYNC 'def' n=NAME t=[type_params] &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block {
CHECK_VERSION(
stmt_ty,
5,
"Async functions are",
- _PyAST_AsyncFunctionDef(n->v.Name.id, t,
+ _PyAST_AsyncFunctionDef(n->v.Name.id,
(params) ? params : CHECK(arguments_ty, _PyPegen_empty_arguments(p)),
- b, NULL, a, NEW_TYPE_COMMENT(p, tc), EXTRA)
+ b, NULL, a, NEW_TYPE_COMMENT(p, tc), t, EXTRA)
) }
# Function parameters
diff --git a/Include/internal/pycore_ast.h b/Include/internal/pycore_ast.h
index 06a40239a2473..b568902bb1e38 100644
--- a/Include/internal/pycore_ast.h
+++ b/Include/internal/pycore_ast.h
@@ -198,31 +198,31 @@ struct _stmt {
union {
struct {
identifier name;
- asdl_type_param_seq *type_params;
arguments_ty args;
asdl_stmt_seq *body;
asdl_expr_seq *decorator_list;
expr_ty returns;
string type_comment;
+ asdl_type_param_seq *type_params;
} FunctionDef;
struct {
identifier name;
- asdl_type_param_seq *type_params;
arguments_ty args;
asdl_stmt_seq *body;
asdl_expr_seq *decorator_list;
expr_ty returns;
string type_comment;
+ asdl_type_param_seq *type_params;
} AsyncFunctionDef;
struct {
identifier name;
- asdl_type_param_seq *type_params;
asdl_expr_seq *bases;
asdl_keyword_seq *keywords;
asdl_stmt_seq *body;
asdl_expr_seq *decorator_list;
+ asdl_type_param_seq *type_params;
} ClassDef;
struct {
@@ -682,22 +682,22 @@ mod_ty _PyAST_Interactive(asdl_stmt_seq * body, PyArena *arena);
mod_ty _PyAST_Expression(expr_ty body, PyArena *arena);
mod_ty _PyAST_FunctionType(asdl_expr_seq * argtypes, expr_ty returns, PyArena
*arena);
-stmt_ty _PyAST_FunctionDef(identifier name, asdl_type_param_seq * type_params,
- arguments_ty args, asdl_stmt_seq * body,
- asdl_expr_seq * decorator_list, expr_ty returns,
- string type_comment, int lineno, int col_offset, int
+stmt_ty _PyAST_FunctionDef(identifier name, arguments_ty args, asdl_stmt_seq *
+ body, asdl_expr_seq * decorator_list, expr_ty
+ returns, string type_comment, asdl_type_param_seq *
+ type_params, int lineno, int col_offset, int
end_lineno, int end_col_offset, PyArena *arena);
-stmt_ty _PyAST_AsyncFunctionDef(identifier name, asdl_type_param_seq *
- type_params, arguments_ty args, asdl_stmt_seq *
- body, asdl_expr_seq * decorator_list, expr_ty
- returns, string type_comment, int lineno, int
- col_offset, int end_lineno, int end_col_offset,
- PyArena *arena);
-stmt_ty _PyAST_ClassDef(identifier name, asdl_type_param_seq * type_params,
- asdl_expr_seq * bases, asdl_keyword_seq * keywords,
- asdl_stmt_seq * body, asdl_expr_seq * decorator_list,
- int lineno, int col_offset, int end_lineno, int
- end_col_offset, PyArena *arena);
+stmt_ty _PyAST_AsyncFunctionDef(identifier name, arguments_ty args,
+ asdl_stmt_seq * body, asdl_expr_seq *
+ decorator_list, expr_ty returns, string
+ type_comment, asdl_type_param_seq *
+ type_params, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena);
+stmt_ty _PyAST_ClassDef(identifier name, asdl_expr_seq * bases,
+ asdl_keyword_seq * keywords, asdl_stmt_seq * body,
+ asdl_expr_seq * decorator_list, asdl_type_param_seq *
+ type_params, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena);
stmt_ty _PyAST_Return(expr_ty value, int lineno, int col_offset, int
end_lineno, int end_col_offset, PyArena *arena);
stmt_ty _PyAST_Delete(asdl_expr_seq * targets, int lineno, int col_offset, int
diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py
index cf128e1e8cd04..76edbf5121c80 100644
--- a/Lib/test/test_ast.py
+++ b/Lib/test/test_ast.py
@@ -4,6 +4,7 @@
import enum
import os
import sys
+import textwrap
import types
import unittest
import warnings
@@ -1583,20 +1584,41 @@ def arguments(args=None, posonlyargs=None, vararg=None,
def test_funcdef(self):
a = ast.arguments([], [], None, [], [], None, [])
- f = ast.FunctionDef("x", [], a, [], [], None)
+ f = ast.FunctionDef("x", a, [], [], None, None, [])
self.stmt(f, "empty body on FunctionDef")
- f = ast.FunctionDef("x", [], a, [ast.Pass()], [ast.Name("x", ast.Store())],
- None)
+ f = ast.FunctionDef("x", a, [ast.Pass()], [ast.Name("x", ast.Store())], None, None, [])
self.stmt(f, "must have Load context")
- f = ast.FunctionDef("x", [], a, [ast.Pass()], [],
- ast.Name("x", ast.Store()))
+ f = ast.FunctionDef("x", a, [ast.Pass()], [],
+ ast.Name("x", ast.Store()), None, [])
self.stmt(f, "must have Load context")
def fac(args):
- return ast.FunctionDef("x", [], args, [ast.Pass()], [], None)
+ return ast.FunctionDef("x", args, [ast.Pass()], [], None, None, [])
self._check_arguments(fac, self.stmt)
+ def test_funcdef_pattern_matching(self):
+ # gh-104799: New fields on FunctionDef should be added at the end
+ def matcher(node):
+ match node:
+ case ast.FunctionDef("foo", ast.arguments(args=[ast.arg("bar")]),
+ [ast.Pass()],
+ [ast.Name("capybara", ast.Load())],
+ ast.Name("pacarana", ast.Load())):
+ return True
+ case _:
+ return False
+
+ code = """
+ @capybara
+ def foo(bar) -> pacarana:
+ pass
+ """
+ source = ast.parse(textwrap.dedent(code))
+ funcdef = source.body[0]
+ self.assertIsInstance(funcdef, ast.FunctionDef)
+ self.assertTrue(matcher(funcdef))
+
def test_classdef(self):
- def cls(bases=None, keywords=None, body=None, decorator_list=None):
+ def cls(bases=None, keywords=None, body=None, decorator_list=None, type_params=None):
if bases is None:
bases = []
if keywords is None:
@@ -1605,8 +1627,10 @@ def cls(bases=None, keywords=None, body=None, decorator_list=None):
body = [ast.Pass()]
if decorator_list is None:
decorator_list = []
- return ast.ClassDef("myclass", [], bases, keywords,
- body, decorator_list)
+ if type_params is None:
+ type_params = []
+ return ast.ClassDef("myclass", bases, keywords,
+ body, decorator_list, type_params)
self.stmt(cls(bases=[ast.Name("x", ast.Store())]),
"must have Load context")
self.stmt(cls(keywords=[ast.keyword("x", ast.Name("x", ast.Store()))]),
@@ -2895,23 +2919,23 @@ def main():
exec_results = [
('Module', [('Expr', (1, 0, 1, 4), ('Constant', (1, 0, 1, 4), None, None))], []),
('Module', [('Expr', (1, 0, 1, 18), ('Constant', (1, 0, 1, 18), 'module docstring', None))], []),
-('Module', [('FunctionDef', (1, 0, 1, 13), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 9, 1, 13))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 29), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Expr', (1, 9, 1, 29), ('Constant', (1, 9, 1, 29), 'function docstring', None))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 14), 'f', [], ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, []), [('Pass', (1, 10, 1, 14))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 16), 'f', [], ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 0, None)]), [('Pass', (1, 12, 1, 16))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 18), 'f', [], ('arguments', [], [], ('arg', (1, 7, 1, 11), 'args', None, None), [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 23), 'f', [], ('arguments', [], [], ('arg', (1, 7, 1, 16), 'args', ('Starred', (1, 13, 1, 16), ('Name', (1, 14, 1, 16), 'Ts', ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 19, 1, 23))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 36), 'f', [], ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Constant', (1, 25, 1, 28), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 36), 'f', [], ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Starred', (1, 25, 1, 28), ('Name', (1, 26, 1, 28), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 21), 'f', [], ('arguments', [], [], None, [], [], ('arg', (1, 8, 1, 14), 'kwargs', None, None), []), [('Pass', (1, 17, 1, 21))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 71), 'f', [], ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None), ('arg', (1, 9, 1, 10), 'b', None, None), ('arg', (1, 14, 1, 15), 'c', None, None), ('arg', (1, 22, 1, 23), 'd', None, None), ('arg', (1, 28, 1, 29), 'e', None, None)], ('arg', (1, 35, 1, 39), 'args', None, None), [('arg', (1, 41, 1, 42), 'f', None, None)], [('Constant', (1, 43, 1, 45), 42, None)], ('arg', (1, 49, 1, 55), 'kwargs', None, None), [('Constant', (1, 11, 1, 12), 1, None), ('Constant', (1, 16, 1, 20), None, None), ('List', (1, 24, 1, 26), [], ('Load',)), ('Dict', (1, 30, 1, 32), [], [])]), [('Expr', (1, 58, 1, 71), ('Constant', (1, 58, 1, 71), 'doc for f()', None))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 27), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 23, 1, 27))], [], ('Subscript', (1, 11, 1, 21), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 20), [('Starred', (1, 17, 1, 20), ('Name', (1, 18, 1, 20), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 32), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 28, 1, 32))], [], ('Subscript', (1, 11, 1, 26), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 25), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 25), ('Name', (1, 23, 1, 25), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 45), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 41, 1, 45))], [], ('Subscript', (1, 11, 1, 39), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 38), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 38), ('Subscript', (1, 23, 1, 38), ('Name', (1, 23, 1, 28), 'tuple', ('Load',)), ('Tuple', (1, 29, 1, 37), [('Name', (1, 29, 1, 32), 'int', ('Load',)), ('Constant', (1, 34, 1, 37), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []),
-('Module', [('ClassDef', (1, 0, 1, 12), 'C', [], [], [], [('Pass', (1, 8, 1, 12))], [])], []),
-('Module', [('ClassDef', (1, 0, 1, 32), 'C', [], [], [], [('Expr', (1, 9, 1, 32), ('Constant', (1, 9, 1, 32), 'docstring for class C', None))], [])], []),
-('Module', [('ClassDef', (1, 0, 1, 21), 'C', [], [('Name', (1, 8, 1, 14), 'object', ('Load',))], [], [('Pass', (1, 17, 1, 21))], [])], []),
-('Module', [('FunctionDef', (1, 0, 1, 16), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Return', (1, 8, 1, 16), ('Constant', (1, 15, 1, 16), 1, None))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 9, 1, 13))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (1, 9, 1, 29), ('Constant', (1, 9, 1, 29), 'function docstring', None))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 14), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, []), [('Pass', (1, 10, 1, 14))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 16), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 0, None)]), [('Pass', (1, 12, 1, 16))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 18), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 11), 'args', None, None), [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 23), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 16), 'args', ('Starred', (1, 13, 1, 16), ('Name', (1, 14, 1, 16), 'Ts', ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 19, 1, 23))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 36), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Constant', (1, 25, 1, 28), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 36), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Starred', (1, 25, 1, 28), ('Name', (1, 26, 1, 28), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 21), 'f', ('arguments', [], [], None, [], [], ('arg', (1, 8, 1, 14), 'kwargs', None, None), []), [('Pass', (1, 17, 1, 21))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 71), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None), ('arg', (1, 9, 1, 10), 'b', None, None), ('arg', (1, 14, 1, 15), 'c', None, None), ('arg', (1, 22, 1, 23), 'd', None, None), ('arg', (1, 28, 1, 29), 'e', None, None)], ('arg', (1, 35, 1, 39), 'args', None, None), [('arg', (1, 41, 1, 42), 'f', None, None)], [('Constant', (1, 43, 1, 45), 42, None)], ('arg', (1, 49, 1, 55), 'kwargs', None, None), [('Constant', (1, 11, 1, 12), 1, None), ('Constant', (1, 16, 1, 20), None, None), ('List', (1, 24, 1, 26), [], ('Load',)), ('Dict', (1, 30, 1, 32), [], [])]), [('Expr', (1, 58, 1, 71), ('Constant', (1, 58, 1, 71), 'doc for f()', None))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 27), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 23, 1, 27))], [], ('Subscript', (1, 11, 1, 21), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 20), [('Starred', (1, 17, 1, 20), ('Name', (1, 18, 1, 20), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 32), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 28, 1, 32))], [], ('Subscript', (1, 11, 1, 26), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 25), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 25), ('Name', (1, 23, 1, 25), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 45), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 41, 1, 45))], [], ('Subscript', (1, 11, 1, 39), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 38), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 38), ('Subscript', (1, 23, 1, 38), ('Name', (1, 23, 1, 28), 'tuple', ('Load',)), ('Tuple', (1, 29, 1, 37), [('Name', (1, 29, 1, 32), 'int', ('Load',)), ('Constant', (1, 34, 1, 37), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',))], ('Load',)), ('Load',)), None, [])], []),
+('Module', [('ClassDef', (1, 0, 1, 12), 'C', [], [], [('Pass', (1, 8, 1, 12))], [], [])], []),
+('Module', [('ClassDef', (1, 0, 1, 32), 'C', [], [], [('Expr', (1, 9, 1, 32), ('Constant', (1, 9, 1, 32), 'docstring for class C', None))], [], [])], []),
+('Module', [('ClassDef', (1, 0, 1, 21), 'C', [('Name', (1, 8, 1, 14), 'object', ('Load',))], [], [('Pass', (1, 17, 1, 21))], [], [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 16), 'f', ('arguments', [], [], None, [], [], None, []), [('Return', (1, 8, 1, 16), ('Constant', (1, 15, 1, 16), 1, None))], [], None, None, [])], []),
('Module', [('Delete', (1, 0, 1, 5), [('Name', (1, 4, 1, 5), 'v', ('Del',))])], []),
('Module', [('Assign', (1, 0, 1, 5), [('Name', (1, 0, 1, 1), 'v', ('Store',))], ('Constant', (1, 4, 1, 5), 1, None), None)], []),
('Module', [('Assign', (1, 0, 1, 7), [('Tuple', (1, 0, 1, 3), [('Name', (1, 0, 1, 1), 'a', ('Store',)), ('Name', (1, 2, 1, 3), 'b', ('Store',))], ('Store',))], ('Name', (1, 6, 1, 7), 'c', ('Load',)), None)], []),
@@ -2948,41 +2972,41 @@ def main():
('Module', [('Expr', (1, 0, 1, 20), ('DictComp', (1, 0, 1, 20), ('Name', (1, 1, 1, 2), 'a', ('Load',)), ('Name', (1, 5, 1, 6), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 14), [('Name', (1, 11, 1, 12), 'v', ('Store',)), ('Name', (1, 13, 1, 14), 'w', ('Store',))], ('Store',)), ('Name', (1, 18, 1, 19), 'x', ('Load',)), [], 0)]))], []),
('Module', [('Expr', (1, 0, 1, 19), ('SetComp', (1, 0, 1, 19), ('Name', (1, 1, 1, 2), 'r', ('Load',)), [('comprehension', ('Name', (1, 7, 1, 8), 'l', ('Store',)), ('Name', (1, 12, 1, 13), 'x', ('Load',)), [('Name', (1, 17, 1, 18), 'g', ('Load',))], 0)]))], []),
('Module', [('Expr', (1, 0, 1, 16), ('SetComp', (1, 0, 1, 16), ('Name', (1, 1, 1, 2), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7, 1, 10), [('Name', (1, 7, 1, 8), 'l', ('Store',)), ('Name', (1, 9, 1, 10), 'm', ('Store',))], ('Store',)), ('Name', (1, 14, 1, 15), 'x', ('Load',)), [], 0)]))], []),
-('Module', [('AsyncFunctionDef', (1, 0, 3, 18), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 17), ('Constant', (2, 1, 2, 17), 'async function', None)), ('Expr', (3, 1, 3, 18), ('Await', (3, 1, 3, 18), ('Call', (3, 7, 3, 18), ('Name', (3, 7, 3, 16), 'something', ('Load',)), [], [])))], [], None, None)], []),
-('Module', [('AsyncFunctionDef', (1, 0, 3, 8), 'f', [], ('arguments', [], [], None, [], [], None, []), [('AsyncFor', (2, 1, 3, 8), ('Name', (2, 11, 2, 12), 'e', ('Store',)), ('Name', (2, 16, 2, 17), 'i', ('Load',)), [('Expr', (2, 19, 2, 20), ('Constant', (2, 19, 2, 20), 1, None))], [('Expr', (3, 7, 3, 8), ('Constant', (3, 7, 3, 8), 2, None))], None)], [], None, None)], []),
-('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', [], ('arguments', [], [], None, [], [], None, []), [('AsyncWith', (2, 1, 2, 21), [('withitem', ('Name', (2, 12, 2, 13), 'a', ('Load',)), ('Name', (2, 17, 2, 18), 'b', ('Store',)))], [('Expr', (2, 20, 2, 21), ('Constant', (2, 20, 2, 21), 1, None))], None)], [], None, None)], []),
+('Module', [('AsyncFunctionDef', (1, 0, 3, 18), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 17), ('Constant', (2, 1, 2, 17), 'async function', None)), ('Expr', (3, 1, 3, 18), ('Await', (3, 1, 3, 18), ('Call', (3, 7, 3, 18), ('Name', (3, 7, 3, 16), 'something', ('Load',)), [], [])))], [], None, None, [])], []),
+('Module', [('AsyncFunctionDef', (1, 0, 3, 8), 'f', ('arguments', [], [], None, [], [], None, []), [('AsyncFor', (2, 1, 3, 8), ('Name', (2, 11, 2, 12), 'e', ('Store',)), ('Name', (2, 16, 2, 17), 'i', ('Load',)), [('Expr', (2, 19, 2, 20), ('Constant', (2, 19, 2, 20), 1, None))], [('Expr', (3, 7, 3, 8), ('Constant', (3, 7, 3, 8), 2, None))], None)], [], None, None, [])], []),
+('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', ('arguments', [], [], None, [], [], None, []), [('AsyncWith', (2, 1, 2, 21), [('withitem', ('Name', (2, 12, 2, 13), 'a', ('Load',)), ('Name', (2, 17, 2, 18), 'b', ('Store',)))], [('Expr', (2, 20, 2, 21), ('Constant', (2, 20, 2, 21), 1, None))], None)], [], None, None, [])], []),
('Module', [('Expr', (1, 0, 1, 14), ('Dict', (1, 0, 1, 14), [None, ('Constant', (1, 10, 1, 11), 2, None)], [('Dict', (1, 3, 1, 8), [('Constant', (1, 4, 1, 5), 1, None)], [('Constant', (1, 6, 1, 7), 2, None)]), ('Constant', (1, 12, 1, 13), 3, None)]))], []),
('Module', [('Expr', (1, 0, 1, 12), ('Set', (1, 0, 1, 12), [('Starred', (1, 1, 1, 8), ('Set', (1, 2, 1, 8), [('Constant', (1, 3, 1, 4), 1, None), ('Constant', (1, 6, 1, 7), 2, None)]), ('Load',)), ('Constant', (1, 10, 1, 11), 3, None)]))], []),
-('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 21), ('ListComp', (2, 1, 2, 21), ('Name', (2, 2, 2, 3), 'i', ('Load',)), [('comprehension', ('Name', (2, 14, 2, 15), 'b', ('Store',)), ('Name', (2, 19, 2, 20), 'c', ('Load',)), [], 1)]))], [], None, None)], []),
-('Module', [('FunctionDef', (4, 0, 4, 13), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None)], []),
-('Module', [('AsyncFunctionDef', (4, 0, 4, 19), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 15, 4, 19))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None)], []),
-('Module', [('ClassDef', (4, 0, 4, 13), 'C', [], [], [], [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])])], []),
-('Module', [('FunctionDef', (2, 0, 2, 13), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Call', (1, 1, 1, 19), ('Name', (1, 1, 1, 5), 'deco', ('Load',)), [('GeneratorExp', (1, 5, 1, 19), ('Name', (1, 6, 1, 7), 'a', ('Load',)), [('comprehension', ('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 17, 1, 18), 'b', ('Load',)), [], 0)])], [])], None, None)], []),
-('Module', [('FunctionDef', (2, 0, 2, 13), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Attribute', (1, 1, 1, 6), ('Attribute', (1, 1, 1, 4), ('Name', (1, 1, 1, 2), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',))], None, None)], []),
+('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 21), ('ListComp', (2, 1, 2, 21), ('Name', (2, 2, 2, 3), 'i', ('Load',)), [('comprehension', ('Name', (2, 14, 2, 15), 'b', ('Store',)), ('Name', (2, 19, 2, 20), 'c', ('Load',)), [], 1)]))], [], None, None, [])], []),
+('Module', [('FunctionDef', (4, 0, 4, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None, [])], []),
+('Module', [('AsyncFunctionDef', (4, 0, 4, 19), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 15, 4, 19))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None, [])], []),
+('Module', [('ClassDef', (4, 0, 4, 13), 'C', [], [], [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], [])], []),
+('Module', [('FunctionDef', (2, 0, 2, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Call', (1, 1, 1, 19), ('Name', (1, 1, 1, 5), 'deco', ('Load',)), [('GeneratorExp', (1, 5, 1, 19), ('Name', (1, 6, 1, 7), 'a', ('Load',)), [('comprehension', ('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 17, 1, 18), 'b', ('Load',)), [], 0)])], [])], None, None, [])], []),
+('Module', [('FunctionDef', (2, 0, 2, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Attribute', (1, 1, 1, 6), ('Attribute', (1, 1, 1, 4), ('Name', (1, 1, 1, 2), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',))], None, None, [])], []),
('Module', [('Expr', (1, 0, 1, 8), ('NamedExpr', (1, 1, 1, 7), ('Name', (1, 1, 1, 2), 'a', ('Store',)), ('Constant', (1, 6, 1, 7), 1, None)))], []),
-('Module', [('FunctionDef', (1, 0, 1, 18), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 26), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None), ('arg', (1, 15, 1, 16), 'd', None, None), ('arg', (1, 18, 1, 19), 'e', None, None)], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 29), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], None, []), [('Pass', (1, 25, 1, 29))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 39), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], ('arg', (1, 26, 1, 32), 'kwargs', None, None), []), [('Pass', (1, 35, 1, 39))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 20), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None)]), [('Pass', (1, 16, 1, 20))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 29), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None), ('arg', (1, 19, 1, 20), 'c', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None), ('Constant', (1, 21, 1, 22), 4, None)]), [('Pass', (1, 25, 1, 29))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 32), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 28, 1, 32))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 30), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 26, 1, 30))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 42), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], ('arg', (1, 29, 1, 35), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 38, 1, 42))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 40), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], ('arg', (1, 27, 1, 33), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 36, 1, 40))], [], None, None)], []),
+('Module', [('FunctionDef', (1, 0, 1, 18), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 26), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None), ('arg', (1, 15, 1, 16), 'd', None, None), ('arg', (1, 18, 1, 19), 'e', None, None)], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], None, []), [('Pass', (1, 25, 1, 29))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 39), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], ('arg', (1, 26, 1, 32), 'kwargs', None, None), []), [('Pass', (1, 35, 1, 39))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 20), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None)]), [('Pass', (1, 16, 1, 20))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None), ('arg', (1, 19, 1, 20), 'c', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None), ('Constant', (1, 21, 1, 22), 4, None)]), [('Pass', (1, 25, 1, 29))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 32), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 28, 1, 32))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 30), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 26, 1, 30))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 42), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], ('arg', (1, 29, 1, 35), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 38, 1, 42))], [], None, None, [])], []),
+('Module', [('FunctionDef', (1, 0, 1, 40), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], ('arg', (1, 27, 1, 33), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 36, 1, 40))], [], None, None, [])], []),
('Module', [('TypeAlias', (1, 0, 1, 12), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [], ('Name', (1, 9, 1, 12), 'int', ('Load',)))], []),
('Module', [('TypeAlias', (1, 0, 1, 15), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 8), 'T', None)], ('Name', (1, 12, 1, 15), 'int', ('Load',)))], []),
('Module', [('TypeAlias', (1, 0, 1, 32), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 8), 'T', None), ('TypeVarTuple', (1, 10, 1, 13), 'Ts'), ('ParamSpec', (1, 15, 1, 18), 'P')], ('Tuple', (1, 22, 1, 32), [('Name', (1, 23, 1, 24), 'T', ('Load',)), ('Name', (1, 26, 1, 28), 'Ts', ('Load',)), ('Name', (1, 30, 1, 31), 'P', ('Load',))], ('Load',)))], []),
('Module', [('TypeAlias', (1, 0, 1, 37), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 13), 'T', ('Name', (1, 10, 1, 13), 'int', ('Load',))), ('TypeVarTuple', (1, 15, 1, 18), 'Ts'), ('ParamSpec', (1, 20, 1, 23), 'P')], ('Tuple', (1, 27, 1, 37), [('Name', (1, 28, 1, 29), 'T', ('Load',)), ('Name', (1, 31, 1, 33), 'Ts', ('Load',)), ('Name', (1, 35, 1, 36), 'P', ('Load',))], ('Load',)))], []),
('Module', [('TypeAlias', (1, 0, 1, 44), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 20), 'T', ('Tuple', (1, 10, 1, 20), [('Name', (1, 11, 1, 14), 'int', ('Load',)), ('Name', (1, 16, 1, 19), 'str', ('Load',))], ('Load',))), ('TypeVarTuple', (1, 22, 1, 25), 'Ts'), ('ParamSpec', (1, 27, 1, 30), 'P')], ('Tuple', (1, 34, 1, 44), [('Name', (1, 35, 1, 36), 'T', ('Load',)), ('Name', (1, 38, 1, 40), 'Ts', ('Load',)), ('Name', (1, 42, 1, 43), 'P', ('Load',))], ('Load',)))], []),
-('Module', [('ClassDef', (1, 0, 1, 16), 'X', [('TypeVar', (1, 8, 1, 9), 'T', None)], [], [], [('Pass', (1, 12, 1, 16))], [])], []),
-('Module', [('ClassDef', (1, 0, 1, 26), 'X', [('TypeVar', (1, 8, 1, 9), 'T', None), ('TypeVarTuple', (1, 11, 1, 14), 'Ts'), ('ParamSpec', (1, 16, 1, 19), 'P')], [], [], [('Pass', (1, 22, 1, 26))], [])], []),
-('Module', [('ClassDef', (1, 0, 1, 31), 'X', [('TypeVar', (1, 8, 1, 14), 'T', ('Name', (1, 11, 1, 14), 'int', ('Load',))), ('TypeVarTuple', (1, 16, 1, 19), 'Ts'), ('ParamSpec', (1, 21, 1, 24), 'P')], [], [], [('Pass', (1, 27, 1, 31))], [])], []),
-('Module', [('ClassDef', (1, 0, 1, 38), 'X', [('TypeVar', (1, 8, 1, 21), 'T', ('Tuple', (1, 11, 1, 21), [('Name', (1, 12, 1, 15), 'int', ('Load',)), ('Name', (1, 17, 1, 20), 'str', ('Load',))], ('Load',))), ('TypeVarTuple', (1, 23, 1, 26), 'Ts'), ('ParamSpec', (1, 28, 1, 31), 'P')], [], [], [('Pass', (1, 34, 1, 38))], [])], []),
-('Module', [('FunctionDef', (1, 0, 1, 16), 'f', [('TypeVar', (1, 6, 1, 7), 'T', None)], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 12, 1, 16))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 26), 'f', [('TypeVar', (1, 6, 1, 7), 'T', None), ('TypeVarTuple', (1, 9, 1, 12), 'Ts'), ('ParamSpec', (1, 14, 1, 17), 'P')], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 31), 'f', [('TypeVar', (1, 6, 1, 12), 'T', ('Name', (1, 9, 1, 12), 'int', ('Load',))), ('TypeVarTuple', (1, 14, 1, 17), 'Ts'), ('ParamSpec', (1, 19, 1, 22), 'P')], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 27, 1, 31))], [], None, None)], []),
-('Module', [('FunctionDef', (1, 0, 1, 38), 'f', [('TypeVar', (1, 6, 1, 19), 'T', ('Tuple', (1, 9, 1, 19), [('Name', (1, 10, 1, 13), 'int', ('Load',)), ('Name', (1, 15, 1, 18), 'str', ('Load',))], ('Load',))), ('TypeVarTuple', (1, 21, 1, 24), 'Ts'), ('ParamSpec', (1, 26, 1, 29), 'P')], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 34, 1, 38))], [], None, None)], []),
+('Module', [('ClassDef', (1, 0, 1, 16), 'X', [], [], [('Pass', (1, 12, 1, 16))], [], [('TypeVar', (1, 8, 1, 9), 'T', None)])], []),
+('Module', [('ClassDef', (1, 0, 1, 26), 'X', [], [], [('Pass', (1, 22, 1, 26))], [], [('TypeVar', (1, 8, 1, 9), 'T', None), ('TypeVarTuple', (1, 11, 1, 14), 'Ts'), ('ParamSpec', (1, 16, 1, 19), 'P')])], []),
+('Module', [('ClassDef', (1, 0, 1, 31), 'X', [], [], [('Pass', (1, 27, 1, 31))], [], [('TypeVar', (1, 8, 1, 14), 'T', ('Name', (1, 11, 1, 14), 'int', ('Load',))), ('TypeVarTuple', (1, 16, 1, 19), 'Ts'), ('ParamSpec', (1, 21, 1, 24), 'P')])], []),
+('Module', [('ClassDef', (1, 0, 1, 38), 'X', [], [], [('Pass', (1, 34, 1, 38))], [], [('TypeVar', (1, 8, 1, 21), 'T', ('Tuple', (1, 11, 1, 21), [('Name', (1, 12, 1, 15), 'int', ('Load',)), ('Name', (1, 17, 1, 20), 'str', ('Load',))], ('Load',))), ('TypeVarTuple', (1, 23, 1, 26), 'Ts'), ('ParamSpec', (1, 28, 1, 31), 'P')])], []),
+('Module', [('FunctionDef', (1, 0, 1, 16), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 12, 1, 16))], [], None, None, [('TypeVar', (1, 6, 1, 7), 'T', None)])], []),
+('Module', [('FunctionDef', (1, 0, 1, 26), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None, [('TypeVar', (1, 6, 1, 7), 'T', None), ('TypeVarTuple', (1, 9, 1, 12), 'Ts'), ('ParamSpec', (1, 14, 1, 17), 'P')])], []),
+('Module', [('FunctionDef', (1, 0, 1, 31), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 27, 1, 31))], [], None, None, [('TypeVar', (1, 6, 1, 12), 'T', ('Name', (1, 9, 1, 12), 'int', ('Load',))), ('TypeVarTuple', (1, 14, 1, 17), 'Ts'), ('ParamSpec', (1, 19, 1, 22), 'P')])], []),
+('Module', [('FunctionDef', (1, 0, 1, 38), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 34, 1, 38))], [], None, None, [('TypeVar', (1, 6, 1, 19), 'T', ('Tuple', (1, 9, 1, 19), [('Name', (1, 10, 1, 13), 'int', ('Load',)), ('Name', (1, 15, 1, 18), 'str', ('Load',))], ('Load',))), ('TypeVarTuple', (1, 21, 1, 24), 'Ts'), ('ParamSpec', (1, 26, 1, 29), 'P')])], []),
]
single_results = [
('Interactive', [('Expr', (1, 0, 1, 3), ('BinOp', (1, 0, 1, 3), ('Constant', (1, 0, 1, 1), 1, None), ('Add',), ('Constant', (1, 2, 1, 3), 2, None)))]),
diff --git a/Misc/NEWS.d/next/Library/2023-05-23-18-31-49.gh-issue-104799.MJYOw6.rst b/Misc/NEWS.d/next/Library/2023-05-23-18-31-49.gh-issue-104799.MJYOw6.rst
new file mode 100644
index 0000000000000..614918d757296
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-05-23-18-31-49.gh-issue-104799.MJYOw6.rst
@@ -0,0 +1,4 @@
+Adjust the location of the (see :pep:`695`) ``type_params`` field on
+:class:`ast.ClassDef`, :class:`ast.AsyncFunctionDef`, and
+:class:`ast.FunctionDef` to better preserve backward compatibility. Patch by
+Jelle Zijlstra
diff --git a/Parser/Python.asdl b/Parser/Python.asdl
index dc2eb802b0436..93632a09f0959 100644
--- a/Parser/Python.asdl
+++ b/Parser/Python.asdl
@@ -8,19 +8,19 @@ module Python
| Expression(expr body)
| FunctionType(expr* argtypes, expr returns)
- stmt = FunctionDef(identifier name, type_param* type_params, arguments args,
+ stmt = FunctionDef(identifier name, arguments args,
stmt* body, expr* decorator_list, expr? returns,
- string? type_comment)
- | AsyncFunctionDef(identifier name, type_param* type_params, arguments args,
+ string? type_comment, type_param* type_params)
+ | AsyncFunctionDef(identifier name, arguments args,
stmt* body, expr* decorator_list, expr? returns,
- string? type_comment)
+ string? type_comment, type_param* type_params)
| ClassDef(identifier name,
- type_param* type_params,
expr* bases,
keyword* keywords,
stmt* body,
- expr* decorator_list)
+ expr* decorator_list,
+ type_param* type_params)
| Return(expr? value)
| Delete(expr* targets)
diff --git a/Parser/action_helpers.c b/Parser/action_helpers.c
index 06d77b64cacbc..c4d8f75e54280 100644
--- a/Parser/action_helpers.c
+++ b/Parser/action_helpers.c
@@ -752,22 +752,25 @@ _PyPegen_function_def_decorators(Parser *p, asdl_expr_seq *decorators, stmt_ty f
assert(function_def != NULL);
if (function_def->kind == AsyncFunctionDef_kind) {
return _PyAST_AsyncFunctionDef(
- function_def->v.FunctionDef.name, function_def->v.FunctionDef.type_params,
- function_def->v.FunctionDef.args,
- function_def->v.FunctionDef.body, decorators, function_def->v.FunctionDef.returns,
- function_def->v.FunctionDef.type_comment, function_def->lineno,
- function_def->col_offset, function_def->end_lineno, function_def->end_col_offset,
- p->arena);
+ function_def->v.AsyncFunctionDef.name,
+ function_def->v.AsyncFunctionDef.args,
+ function_def->v.AsyncFunctionDef.body, decorators,
+ function_def->v.AsyncFunctionDef.returns,
+ function_def->v.AsyncFunctionDef.type_comment,
+ function_def->v.AsyncFunctionDef.type_params,
+ function_def->lineno, function_def->col_offset,
+ function_def->end_lineno, function_def->end_col_offset, p->arena);
}
return _PyAST_FunctionDef(
- function_def->v.FunctionDef.name, function_def->v.FunctionDef.type_params,
+ function_def->v.FunctionDef.name,
function_def->v.FunctionDef.args,
function_def->v.FunctionDef.body, decorators,
function_def->v.FunctionDef.returns,
- function_def->v.FunctionDef.type_comment, function_def->lineno,
- function_def->col_offset, function_def->end_lineno,
- function_def->end_col_offset, p->arena);
+ function_def->v.FunctionDef.type_comment,
+ function_def->v.FunctionDef.type_params,
+ function_def->lineno, function_def->col_offset,
+ function_def->end_lineno, function_def->end_col_offset, p->arena);
}
/* Construct a ClassDef equivalent to class_def, but with decorators */
@@ -776,9 +779,10 @@ _PyPegen_class_def_decorators(Parser *p, asdl_expr_seq *decorators, stmt_ty clas
{
assert(class_def != NULL);
return _PyAST_ClassDef(
- class_def->v.ClassDef.name, class_def->v.ClassDef.type_params,
+ class_def->v.ClassDef.name,
class_def->v.ClassDef.bases, class_def->v.ClassDef.keywords,
class_def->v.ClassDef.body, decorators,
+ class_def->v.ClassDef.type_params,
class_def->lineno, class_def->col_offset, class_def->end_lineno,
class_def->end_col_offset, p->arena);
}
diff --git a/Parser/parser.c b/Parser/parser.c
index fc5466fea2b3f..1705ebd456b5f 100644
--- a/Parser/parser.c
+++ b/Parser/parser.c
@@ -4425,7 +4425,7 @@ class_def_raw_rule(Parser *p)
UNUSED(_end_lineno); // Only used by EXTRA macro
int _end_col_offset = _token->end_col_offset;
UNUSED(_end_col_offset); // Only used by EXTRA macro
- _res = _PyAST_ClassDef ( a -> v . Name . id , t , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , c , NULL , EXTRA );
+ _res = _PyAST_ClassDef ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , c , NULL , t , EXTRA );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
p->level--;
@@ -4602,7 +4602,7 @@ function_def_raw_rule(Parser *p)
UNUSED(_end_lineno); // Only used by EXTRA macro
int _end_col_offset = _token->end_col_offset;
UNUSED(_end_col_offset); // Only used by EXTRA macro
- _res = _PyAST_FunctionDef ( n -> v . Name . id , t , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , EXTRA );
+ _res = _PyAST_FunctionDef ( n -> v . Name . id , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , t , EXTRA );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
p->level--;
@@ -4665,7 +4665,7 @@ function_def_raw_rule(Parser *p)
UNUSED(_end_lineno); // Only used by EXTRA macro
int _end_col_offset = _token->end_col_offset;
UNUSED(_end_col_offset); // Only used by EXTRA macro
- _res = CHECK_VERSION ( stmt_ty , 5 , "Async functions are" , _PyAST_AsyncFunctionDef ( n -> v . Name . id , t , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) );
+ _res = CHECK_VERSION ( stmt_ty , 5 , "Async functions are" , _PyAST_AsyncFunctionDef ( n -> v . Name . id , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , t , EXTRA ) );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
p->level--;
diff --git a/Python/Python-ast.c b/Python/Python-ast.c
index 87906d975d741..030c082a4a6b1 100644
--- a/Python/Python-ast.c
+++ b/Python/Python-ast.c
@@ -409,29 +409,29 @@ static const char * const stmt_attributes[] = {
static PyObject* ast2obj_stmt(struct ast_state *state, void*);
static const char * const FunctionDef_fields[]={
"name",
- "type_params",
"args",
"body",
"decorator_list",
"returns",
"type_comment",
+ "type_params",
};
static const char * const AsyncFunctionDef_fields[]={
"name",
- "type_params",
"args",
"body",
"decorator_list",
"returns",
"type_comment",
+ "type_params",
};
static const char * const ClassDef_fields[]={
"name",
- "type_params",
"bases",
"keywords",
"body",
"decorator_list",
+ "type_params",
};
static const char * const Return_fields[]={
"value",
@@ -1169,9 +1169,9 @@ init_types(struct ast_state *state)
"FunctionType(expr* argtypes, expr returns)");
if (!state->FunctionType_type) return 0;
state->stmt_type = make_type(state, "stmt", state->AST_type, NULL, 0,
- "stmt = FunctionDef(identifier name, type_param* type_params, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment)\n"
- " | AsyncFunctionDef(identifier name, type_param* type_params, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment)\n"
- " | ClassDef(identifier name, type_param* type_params, expr* bases, keyword* keywords, stmt* body, expr* decorator_list)\n"
+ "stmt = FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment, type_param* type_params)\n"
+ " | AsyncFunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment, type_param* type_params)\n"
+ " | ClassDef(identifier name, expr* bases, keyword* keywords, stmt* body, expr* decorator_list, type_param* type_params)\n"
" | Return(expr? value)\n"
" | Delete(expr* targets)\n"
" | Assign(expr* targets, expr value, string? type_comment)\n"
@@ -1206,7 +1206,7 @@ init_types(struct ast_state *state)
return 0;
state->FunctionDef_type = make_type(state, "FunctionDef", state->stmt_type,
FunctionDef_fields, 7,
- "FunctionDef(identifier name, type_param* type_params, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment)");
+ "FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment, type_param* type_params)");
if (!state->FunctionDef_type) return 0;
if (PyObject_SetAttr(state->FunctionDef_type, state->returns, Py_None) ==
-1)
@@ -1217,7 +1217,7 @@ init_types(struct ast_state *state)
state->AsyncFunctionDef_type = make_type(state, "AsyncFunctionDef",
state->stmt_type,
AsyncFunctionDef_fields, 7,
- "AsyncFunctionDef(identifier name, type_param* type_params, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment)");
+ "AsyncFunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment, type_param* type_params)");
if (!state->AsyncFunctionDef_type) return 0;
if (PyObject_SetAttr(state->AsyncFunctionDef_type, state->returns, Py_None)
== -1)
@@ -1227,7 +1227,7 @@ init_types(struct ast_state *state)
return 0;
state->ClassDef_type = make_type(state, "ClassDef", state->stmt_type,
ClassDef_fields, 6,
- "ClassDef(identifier name, type_param* type_params, expr* bases, keyword* keywords, stmt* body, expr* decorator_list)");
+ "ClassDef(identifier name, expr* bases, keyword* keywords, stmt* body, expr* decorator_list, type_param* type_params)");
if (!state->ClassDef_type) return 0;
state->Return_type = make_type(state, "Return", state->stmt_type,
Return_fields, 1,
@@ -2032,11 +2032,11 @@ _PyAST_FunctionType(asdl_expr_seq * argtypes, expr_ty returns, PyArena *arena)
}
stmt_ty
-_PyAST_FunctionDef(identifier name, asdl_type_param_seq * type_params,
- arguments_ty args, asdl_stmt_seq * body, asdl_expr_seq *
- decorator_list, expr_ty returns, string type_comment, int
- lineno, int col_offset, int end_lineno, int end_col_offset,
- PyArena *arena)
+_PyAST_FunctionDef(identifier name, arguments_ty args, asdl_stmt_seq * body,
+ asdl_expr_seq * decorator_list, expr_ty returns, string
+ type_comment, asdl_type_param_seq * type_params, int lineno,
+ int col_offset, int end_lineno, int end_col_offset, PyArena
+ *arena)
{
stmt_ty p;
if (!name) {
@@ -2054,12 +2054,12 @@ _PyAST_FunctionDef(identifier name, asdl_type_param_seq * type_params,
return NULL;
p->kind = FunctionDef_kind;
p->v.FunctionDef.name = name;
- p->v.FunctionDef.type_params = type_params;
p->v.FunctionDef.args = args;
p->v.FunctionDef.body = body;
p->v.FunctionDef.decorator_list = decorator_list;
p->v.FunctionDef.returns = returns;
p->v.FunctionDef.type_comment = type_comment;
+ p->v.FunctionDef.type_params = type_params;
p->lineno = lineno;
p->col_offset = col_offset;
p->end_lineno = end_lineno;
@@ -2068,9 +2068,9 @@ _PyAST_FunctionDef(identifier name, asdl_type_param_seq * type_params,
}
stmt_ty
-_PyAST_AsyncFunctionDef(identifier name, asdl_type_param_seq * type_params,
- arguments_ty args, asdl_stmt_seq * body, asdl_expr_seq
- * decorator_list, expr_ty returns, string type_comment,
+_PyAST_AsyncFunctionDef(identifier name, arguments_ty args, asdl_stmt_seq *
+ body, asdl_expr_seq * decorator_list, expr_ty returns,
+ string type_comment, asdl_type_param_seq * type_params,
int lineno, int col_offset, int end_lineno, int
end_col_offset, PyArena *arena)
{
@@ -2090,12 +2090,12 @@ _PyAST_AsyncFunctionDef(identifier name, asdl_type_param_seq * type_params,
return NULL;
p->kind = AsyncFunctionDef_kind;
p->v.AsyncFunctionDef.name = name;
- p->v.AsyncFunctionDef.type_params = type_params;
p->v.AsyncFunctionDef.args = args;
p->v.AsyncFunctionDef.body = body;
p->v.AsyncFunctionDef.decorator_list = decorator_list;
p->v.AsyncFunctionDef.returns = returns;
p->v.AsyncFunctionDef.type_comment = type_comment;
+ p->v.AsyncFunctionDef.type_params = type_params;
p->lineno = lineno;
p->col_offset = col_offset;
p->end_lineno = end_lineno;
@@ -2104,11 +2104,10 @@ _PyAST_AsyncFunctionDef(identifier name, asdl_type_param_seq * type_params,
}
stmt_ty
-_PyAST_ClassDef(identifier name, asdl_type_param_seq * type_params,
- asdl_expr_seq * bases, asdl_keyword_seq * keywords,
- asdl_stmt_seq * body, asdl_expr_seq * decorator_list, int
- lineno, int col_offset, int end_lineno, int end_col_offset,
- PyArena *arena)
+_PyAST_ClassDef(identifier name, asdl_expr_seq * bases, asdl_keyword_seq *
+ keywords, asdl_stmt_seq * body, asdl_expr_seq * decorator_list,
+ asdl_type_param_seq * type_params, int lineno, int col_offset,
+ int end_lineno, int end_col_offset, PyArena *arena)
{
stmt_ty p;
if (!name) {
@@ -2121,11 +2120,11 @@ _PyAST_ClassDef(identifier name, asdl_type_param_seq * type_params,
return NULL;
p->kind = ClassDef_kind;
p->v.ClassDef.name = name;
- p->v.ClassDef.type_params = type_params;
p->v.ClassDef.bases = bases;
p->v.ClassDef.keywords = keywords;
p->v.ClassDef.body = body;
p->v.ClassDef.decorator_list = decorator_list;
+ p->v.ClassDef.type_params = type_params;
p->lineno = lineno;
p->col_offset = col_offset;
p->end_lineno = end_lineno;
@@ -3883,12 +3882,6 @@ ast2obj_stmt(struct ast_state *state, void* _o)
if (PyObject_SetAttr(result, state->name, value) == -1)
goto failed;
Py_DECREF(value);
- value = ast2obj_list(state, (asdl_seq*)o->v.FunctionDef.type_params,
- ast2obj_type_param);
- if (!value) goto failed;
- if (PyObject_SetAttr(result, state->type_params, value) == -1)
- goto failed;
- Py_DECREF(value);
value = ast2obj_arguments(state, o->v.FunctionDef.args);
if (!value) goto failed;
if (PyObject_SetAttr(result, state->args, value) == -1)
@@ -3916,6 +3909,12 @@ ast2obj_stmt(struct ast_state *state, void* _o)
if (PyObject_SetAttr(result, state->type_comment, value) == -1)
goto failed;
Py_DECREF(value);
+ value = ast2obj_list(state, (asdl_seq*)o->v.FunctionDef.type_params,
+ ast2obj_type_param);
+ if (!value) goto failed;
+ if (PyObject_SetAttr(result, state->type_params, value) == -1)
+ goto failed;
+ Py_DECREF(value);
break;
case AsyncFunctionDef_kind:
tp = (PyTypeObject *)state->AsyncFunctionDef_type;
@@ -3926,13 +3925,6 @@ ast2obj_stmt(struct ast_state *state, void* _o)
if (PyObject_SetAttr(result, state->name, value) == -1)
goto failed;
Py_DECREF(value);
- value = ast2obj_list(state,
- (asdl_seq*)o->v.AsyncFunctionDef.type_params,
- ast2obj_type_param);
- if (!value) goto failed;
- if (PyObject_SetAttr(result, state->type_params, value) == -1)
- goto failed;
- Py_DECREF(value);
value = ast2obj_arguments(state, o->v.AsyncFunctionDef.args);
if (!value) goto failed;
if (PyObject_SetAttr(result, state->args, value) == -1)
@@ -3961,6 +3953,13 @@ ast2obj_stmt(struct ast_state *state, void* _o)
if (PyObject_SetAttr(result, state->type_comment, value) == -1)
goto failed;
Py_DECREF(value);
+ value = ast2obj_list(state,
+ (asdl_seq*)o->v.AsyncFunctionDef.type_params,
+ ast2obj_type_param);
+ if (!value) goto failed;
+ if (PyObject_SetAttr(result, state->type_params, value) == -1)
+ goto failed;
+ Py_DECREF(value);
break;
case ClassDef_kind:
tp = (PyTypeObject *)state->ClassDef_type;
@@ -3971,12 +3970,6 @@ ast2obj_stmt(struct ast_state *state, void* _o)
if (PyObject_SetAttr(result, state->name, value) == -1)
goto failed;
Py_DECREF(value);
- value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.type_params,
- ast2obj_type_param);
- if (!value) goto failed;
- if (PyObject_SetAttr(result, state->type_params, value) == -1)
- goto failed;
- Py_DECREF(value);
value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.bases,
ast2obj_expr);
if (!value) goto failed;
@@ -4001,6 +3994,12 @@ ast2obj_stmt(struct ast_state *state, void* _o)
if (PyObject_SetAttr(result, state->decorator_list, value) == -1)
goto failed;
Py_DECREF(value);
+ value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.type_params,
+ ast2obj_type_param);
+ if (!value) goto failed;
+ if (PyObject_SetAttr(result, state->type_params, value) == -1)
+ goto failed;
+ Py_DECREF(value);
break;
case Return_kind:
tp = (PyTypeObject *)state->Return_type;
@@ -6075,12 +6074,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
if (isinstance) {
identifier name;
- asdl_type_param_seq* type_params;
arguments_ty args;
asdl_stmt_seq* body;
asdl_expr_seq* decorator_list;
expr_ty returns;
string type_comment;
+ asdl_type_param_seq* type_params;
if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {
return 1;
@@ -6099,42 +6098,6 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) {
- return 1;
- }
- if (tmp == NULL) {
- PyErr_SetString(PyExc_TypeError, "required field \"type_params\" missing from FunctionDef");
- return 1;
- }
- else {
- int res;
- Py_ssize_t len;
- Py_ssize_t i;
- if (!PyList_Check(tmp)) {
- PyErr_Format(PyExc_TypeError, "FunctionDef field \"type_params\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp)));
- goto failed;
- }
- len = PyList_GET_SIZE(tmp);
- type_params = _Py_asdl_type_param_seq_new(len, arena);
- if (type_params == NULL) goto failed;
- for (i = 0; i < len; i++) {
- type_param_ty val;
- PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));
- if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) {
- goto failed;
- }
- res = obj2ast_type_param(state, tmp2, &val, arena);
- _Py_LeaveRecursiveCall();
- Py_DECREF(tmp2);
- if (res != 0) goto failed;
- if (len != PyList_GET_SIZE(tmp)) {
- PyErr_SetString(PyExc_RuntimeError, "FunctionDef field \"type_params\" changed size during iteration");
- goto failed;
- }
- asdl_seq_SET(type_params, i, val);
- }
- Py_CLEAR(tmp);
- }
if (_PyObject_LookupAttr(obj, state->args, &tmp) < 0) {
return 1;
}
@@ -6258,10 +6221,46 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = _PyAST_FunctionDef(name, type_params, args, body,
- decorator_list, returns, type_comment,
- lineno, col_offset, end_lineno,
- end_col_offset, arena);
+ if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) {
+ return 1;
+ }
+ if (tmp == NULL) {
+ PyErr_SetString(PyExc_TypeError, "required field \"type_params\" missing from FunctionDef");
+ return 1;
+ }
+ else {
+ int res;
+ Py_ssize_t len;
+ Py_ssize_t i;
+ if (!PyList_Check(tmp)) {
+ PyErr_Format(PyExc_TypeError, "FunctionDef field \"type_params\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp)));
+ goto failed;
+ }
+ len = PyList_GET_SIZE(tmp);
+ type_params = _Py_asdl_type_param_seq_new(len, arena);
+ if (type_params == NULL) goto failed;
+ for (i = 0; i < len; i++) {
+ type_param_ty val;
+ PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));
+ if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) {
+ goto failed;
+ }
+ res = obj2ast_type_param(state, tmp2, &val, arena);
+ _Py_LeaveRecursiveCall();
+ Py_DECREF(tmp2);
+ if (res != 0) goto failed;
+ if (len != PyList_GET_SIZE(tmp)) {
+ PyErr_SetString(PyExc_RuntimeError, "FunctionDef field \"type_params\" changed size during iteration");
+ goto failed;
+ }
+ asdl_seq_SET(type_params, i, val);
+ }
+ Py_CLEAR(tmp);
+ }
+ *out = _PyAST_FunctionDef(name, args, body, decorator_list, returns,
+ type_comment, type_params, lineno,
+ col_offset, end_lineno, end_col_offset,
+ arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6272,12 +6271,12 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
if (isinstance) {
identifier name;
- asdl_type_param_seq* type_params;
arguments_ty args;
asdl_stmt_seq* body;
asdl_expr_seq* decorator_list;
expr_ty returns;
string type_comment;
+ asdl_type_param_seq* type_params;
if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {
return 1;
@@ -6296,42 +6295,6 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) {
- return 1;
- }
- if (tmp == NULL) {
- PyErr_SetString(PyExc_TypeError, "required field \"type_params\" missing from AsyncFunctionDef");
- return 1;
- }
- else {
- int res;
- Py_ssize_t len;
- Py_ssize_t i;
- if (!PyList_Check(tmp)) {
- PyErr_Format(PyExc_TypeError, "AsyncFunctionDef field \"type_params\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp)));
- goto failed;
- }
- len = PyList_GET_SIZE(tmp);
- type_params = _Py_asdl_type_param_seq_new(len, arena);
- if (type_params == NULL) goto failed;
- for (i = 0; i < len; i++) {
- type_param_ty val;
- PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));
- if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) {
- goto failed;
- }
- res = obj2ast_type_param(state, tmp2, &val, arena);
- _Py_LeaveRecursiveCall();
- Py_DECREF(tmp2);
- if (res != 0) goto failed;
- if (len != PyList_GET_SIZE(tmp)) {
- PyErr_SetString(PyExc_RuntimeError, "AsyncFunctionDef field \"type_params\" changed size during iteration");
- goto failed;
- }
- asdl_seq_SET(type_params, i, val);
- }
- Py_CLEAR(tmp);
- }
if (_PyObject_LookupAttr(obj, state->args, &tmp) < 0) {
return 1;
}
@@ -6455,8 +6418,44 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = _PyAST_AsyncFunctionDef(name, type_params, args, body,
- decorator_list, returns, type_comment,
+ if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) {
+ return 1;
+ }
+ if (tmp == NULL) {
+ PyErr_SetString(PyExc_TypeError, "required field \"type_params\" missing from AsyncFunctionDef");
+ return 1;
+ }
+ else {
+ int res;
+ Py_ssize_t len;
+ Py_ssize_t i;
+ if (!PyList_Check(tmp)) {
+ PyErr_Format(PyExc_TypeError, "AsyncFunctionDef field \"type_params\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp)));
+ goto failed;
+ }
+ len = PyList_GET_SIZE(tmp);
+ type_params = _Py_asdl_type_param_seq_new(len, arena);
+ if (type_params == NULL) goto failed;
+ for (i = 0; i < len; i++) {
+ type_param_ty val;
+ PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));
+ if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) {
+ goto failed;
+ }
+ res = obj2ast_type_param(state, tmp2, &val, arena);
+ _Py_LeaveRecursiveCall();
+ Py_DECREF(tmp2);
+ if (res != 0) goto failed;
+ if (len != PyList_GET_SIZE(tmp)) {
+ PyErr_SetString(PyExc_RuntimeError, "AsyncFunctionDef field \"type_params\" changed size during iteration");
+ goto failed;
+ }
+ asdl_seq_SET(type_params, i, val);
+ }
+ Py_CLEAR(tmp);
+ }
+ *out = _PyAST_AsyncFunctionDef(name, args, body, decorator_list,
+ returns, type_comment, type_params,
lineno, col_offset, end_lineno,
end_col_offset, arena);
if (*out == NULL) goto failed;
@@ -6469,11 +6468,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
if (isinstance) {
identifier name;
- asdl_type_param_seq* type_params;
asdl_expr_seq* bases;
asdl_keyword_seq* keywords;
asdl_stmt_seq* body;
asdl_expr_seq* decorator_list;
+ asdl_type_param_seq* type_params;
if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {
return 1;
@@ -6492,42 +6491,6 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) {
- return 1;
- }
- if (tmp == NULL) {
- PyErr_SetString(PyExc_TypeError, "required field \"type_params\" missing from ClassDef");
- return 1;
- }
- else {
- int res;
- Py_ssize_t len;
- Py_ssize_t i;
- if (!PyList_Check(tmp)) {
- PyErr_Format(PyExc_TypeError, "ClassDef field \"type_params\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp)));
- goto failed;
- }
- len = PyList_GET_SIZE(tmp);
- type_params = _Py_asdl_type_param_seq_new(len, arena);
- if (type_params == NULL) goto failed;
- for (i = 0; i < len; i++) {
- type_param_ty val;
- PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));
- if (_Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) {
- goto failed;
- }
- res = obj2ast_type_param(state, tmp2, &val, arena);
- _Py_LeaveRecursiveCall();
- Py_DECREF(tmp2);
- if (res != 0) goto failed;
- if (len != PyList_GET_SIZE(tmp)) {
- PyErr_SetString(PyExc_RuntimeError, "ClassDef field \"type_params\" changed size during iteration");
- goto failed;
- }
- asdl_seq_SET(type_params, i, val);
- }
- Py_CLEAR(tmp);
- }
if (_PyObject_LookupAttr(obj, state->bases, &tmp) < 0) {
return 1;
}
@@ -6672,8 +6635,44 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
- *out = _PyAST_ClassDef(name, type_params, bases, keywords, body,
- decorator_list, lineno, col_offset, end_lineno,
+ if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) {
+ return 1;
+ }
+ if (tmp == NULL) {
+ PyErr_SetString(PyExc_TypeError, "required field \"type_params\" missing from ClassDef");
+ return 1;
+ }
+ else {
+ int res;
+ Py_ssize_t len;
+ Py_ssize_t i;
+ if (!PyList_Check(tmp)) {
+ PyErr_Format(PyExc_TypeError, "ClassDef field \"type_params\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp)));
+ goto failed;
+ }
+ len = PyList_GET_SIZE(tmp);
+ type_params = _Py_asdl_type_param_seq_new(len, arena);
+ if (type_params == NULL) goto failed;
+ for (i = 0; i < len; i++) {
+ type_param_ty val;
+ PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));
+ if (_Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) {
+ goto failed;
+ }
+ res = obj2ast_type_param(state, tmp2, &val, arena);
+ _Py_LeaveRecursiveCall();
+ Py_DECREF(tmp2);
+ if (res != 0) goto failed;
+ if (len != PyList_GET_SIZE(tmp)) {
+ PyErr_SetString(PyExc_RuntimeError, "ClassDef field \"type_params\" changed size during iteration");
+ goto failed;
+ }
+ asdl_seq_SET(type_params, i, val);
+ }
+ Py_CLEAR(tmp);
+ }
+ *out = _PyAST_ClassDef(name, bases, keywords, body, decorator_list,
+ type_params, lineno, col_offset, end_lineno,
end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
1
0

gh-105071: add PyUnstable_Exc_PrepReraiseStar to expose except* implementation in the unstable API (#105072)
by iritkatriel May 30, 2023
by iritkatriel May 30, 2023
May 30, 2023
https://github.com/python/cpython/commit/b7aadb4583b040ddc8564896b91f4e5e57…
commit: b7aadb4583b040ddc8564896b91f4e5e571c82d6
branch: main
author: Irit Katriel <1055913+iritkatriel(a)users.noreply.github.com>
committer: iritkatriel <1055913+iritkatriel(a)users.noreply.github.com>
date: 2023-05-30T15:03:36+01:00
summary:
gh-105071: add PyUnstable_Exc_PrepReraiseStar to expose except* implementation in the unstable API (#105072)
files:
A Misc/NEWS.d/next/C API/2023-05-30-10-15-13.gh-issue-105071.dPtp7c.rst
M Doc/c-api/exceptions.rst
M Include/cpython/pyerrors.h
M Lib/test/test_capi/test_exceptions.py
M Modules/_testcapi/clinic/exceptions.c.h
M Modules/_testcapi/exceptions.c
M Objects/exceptions.c
diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst
index 4ed96f01dbbc3..22666d7052906 100644
--- a/Doc/c-api/exceptions.rst
+++ b/Doc/c-api/exceptions.rst
@@ -772,6 +772,16 @@ Exception Objects
Set :attr:`~BaseException.args` of exception *ex* to *args*.
+.. c:function:: PyObject* PyUnstable_Exc_PrepReraiseStar(PyObject *orig, PyObject *excs)
+
+ Implement part of the interpreter's implementation of :keyword:`!except*`.
+ *orig* is the original exception that was caught, and *excs* is the list of
+ the exceptions that need to be raised. This list contains the the unhandled
+ part of *orig*, if any, as well as the exceptions that were raised from the
+ :keyword:`!except*` clauses (so they have a different traceback from *orig*) and
+ those that were reraised (and have the same traceback as *orig*).
+ Return the :exc:`ExceptionGroup` that needs to be reraised in the end, or
+ ``None`` if there is nothing to reraise.
.. _unicodeexceptions:
diff --git a/Include/cpython/pyerrors.h b/Include/cpython/pyerrors.h
index 758804ade2baa..156665cbdb1ba 100644
--- a/Include/cpython/pyerrors.h
+++ b/Include/cpython/pyerrors.h
@@ -116,6 +116,10 @@ PyAPI_FUNC(int) _PyException_AddNote(
PyObject *exc,
PyObject *note);
+PyAPI_FUNC(PyObject*) PyUnstable_Exc_PrepReraiseStar(
+ PyObject *orig,
+ PyObject *excs);
+
/* In signalmodule.c */
int PySignal_SetWakeupFd(int fd);
diff --git a/Lib/test/test_capi/test_exceptions.py b/Lib/test/test_capi/test_exceptions.py
index 1081f40b6981a..118b575cba6df 100644
--- a/Lib/test/test_capi/test_exceptions.py
+++ b/Lib/test/test_capi/test_exceptions.py
@@ -5,6 +5,7 @@
from test import support
from test.support import import_helper
from test.support.script_helper import assert_python_failure
+from test.support.testcase import ExceptionIsLikeMixin
from .test_misc import decode_stderr
@@ -189,5 +190,97 @@ def __repr__(self):
'Normalization failed: type=Broken args=<unknown>')
+class Test_PyUnstable_Exc_PrepReraiseStar(ExceptionIsLikeMixin, unittest.TestCase):
+
+ def setUp(self):
+ super().setUp()
+ try:
+ raise ExceptionGroup("eg", [TypeError('bad type'), ValueError(42)])
+ except ExceptionGroup as e:
+ self.orig = e
+
+ def test_invalid_args(self):
+ with self.assertRaisesRegex(TypeError, "orig must be an exception"):
+ _testcapi.unstable_exc_prep_reraise_star(42, [None])
+
+ with self.assertRaisesRegex(TypeError, "excs must be a list"):
+ _testcapi.unstable_exc_prep_reraise_star(self.orig, 42)
+
+ with self.assertRaisesRegex(TypeError, "not an exception"):
+ _testcapi.unstable_exc_prep_reraise_star(self.orig, [TypeError(42), 42])
+
+ with self.assertRaisesRegex(ValueError, "orig must be a raised exception"):
+ _testcapi.unstable_exc_prep_reraise_star(ValueError(42), [TypeError(42)])
+
+ with self.assertRaisesRegex(ValueError, "orig must be a raised exception"):
+ _testcapi.unstable_exc_prep_reraise_star(ExceptionGroup("eg", [ValueError(42)]),
+ [TypeError(42)])
+
+
+ def test_nothing_to_reraise(self):
+ self.assertEqual(
+ _testcapi.unstable_exc_prep_reraise_star(self.orig, [None]), None)
+
+ try:
+ raise ValueError(42)
+ except ValueError as e:
+ orig = e
+ self.assertEqual(
+ _testcapi.unstable_exc_prep_reraise_star(orig, [None]), None)
+
+ def test_reraise_orig(self):
+ orig = self.orig
+ res = _testcapi.unstable_exc_prep_reraise_star(orig, [orig])
+ self.assertExceptionIsLike(res, orig)
+
+ def test_raise_orig_parts(self):
+ orig = self.orig
+ match, rest = orig.split(TypeError)
+
+ test_cases = [
+ ([match, rest], orig),
+ ([rest, match], orig),
+ ([match], match),
+ ([rest], rest),
+ ([], None),
+ ]
+
+ for input, expected in test_cases:
+ with self.subTest(input=input):
+ res = _testcapi.unstable_exc_prep_reraise_star(orig, input)
+ self.assertExceptionIsLike(res, expected)
+
+
+ def test_raise_with_new_exceptions(self):
+ orig = self.orig
+
+ match, rest = orig.split(TypeError)
+ new1 = OSError('bad file')
+ new2 = RuntimeError('bad runtime')
+
+ test_cases = [
+ ([new1, match, rest], ExceptionGroup("", [new1, orig])),
+ ([match, new1, rest], ExceptionGroup("", [new1, orig])),
+ ([match, rest, new1], ExceptionGroup("", [new1, orig])),
+
+ ([new1, new2, match, rest], ExceptionGroup("", [new1, new2, orig])),
+ ([new1, match, new2, rest], ExceptionGroup("", [new1, new2, orig])),
+ ([new2, rest, match, new1], ExceptionGroup("", [new2, new1, orig])),
+ ([rest, new2, match, new1], ExceptionGroup("", [new2, new1, orig])),
+
+
+ ([new1, new2, rest], ExceptionGroup("", [new1, new2, rest])),
+ ([new1, match, new2], ExceptionGroup("", [new1, new2, match])),
+ ([rest, new2, new1], ExceptionGroup("", [new2, new1, rest])),
+ ([new1, new2], ExceptionGroup("", [new1, new2])),
+ ([new2, new1], ExceptionGroup("", [new2, new1])),
+ ]
+
+ for (input, expected) in test_cases:
+ with self.subTest(input=input):
+ res = _testcapi.unstable_exc_prep_reraise_star(orig, input)
+ self.assertExceptionIsLike(res, expected)
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/Misc/NEWS.d/next/C API/2023-05-30-10-15-13.gh-issue-105071.dPtp7c.rst b/Misc/NEWS.d/next/C API/2023-05-30-10-15-13.gh-issue-105071.dPtp7c.rst
new file mode 100644
index 0000000000000..3d916fcb961f6
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-05-30-10-15-13.gh-issue-105071.dPtp7c.rst
@@ -0,0 +1 @@
+Add ``PyUnstable_Exc_PrepReraiseStar`` to the unstable C api to expose the implementation of :keyword:`except* <except_star>`.
diff --git a/Modules/_testcapi/clinic/exceptions.c.h b/Modules/_testcapi/clinic/exceptions.c.h
index 2cc4ef3dc0d49..01730ffa2ed03 100644
--- a/Modules/_testcapi/clinic/exceptions.c.h
+++ b/Modules/_testcapi/clinic/exceptions.c.h
@@ -395,4 +395,35 @@ _testcapi_traceback_print(PyObject *module, PyObject *const *args, Py_ssize_t na
exit:
return return_value;
}
-/*[clinic end generated code: output=ec1b2e62adea9846 input=a9049054013a1b77]*/
+
+PyDoc_STRVAR(_testcapi_unstable_exc_prep_reraise_star__doc__,
+"unstable_exc_prep_reraise_star($module, orig, excs, /)\n"
+"--\n"
+"\n"
+"To test PyUnstable_Exc_PrepReraiseStar.");
+
+#define _TESTCAPI_UNSTABLE_EXC_PREP_RERAISE_STAR_METHODDEF \
+ {"unstable_exc_prep_reraise_star", _PyCFunction_CAST(_testcapi_unstable_exc_prep_reraise_star), METH_FASTCALL, _testcapi_unstable_exc_prep_reraise_star__doc__},
+
+static PyObject *
+_testcapi_unstable_exc_prep_reraise_star_impl(PyObject *module,
+ PyObject *orig, PyObject *excs);
+
+static PyObject *
+_testcapi_unstable_exc_prep_reraise_star(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *orig;
+ PyObject *excs;
+
+ if (!_PyArg_CheckPositional("unstable_exc_prep_reraise_star", nargs, 2, 2)) {
+ goto exit;
+ }
+ orig = args[0];
+ excs = args[1];
+ return_value = _testcapi_unstable_exc_prep_reraise_star_impl(module, orig, excs);
+
+exit:
+ return return_value;
+}
+/*[clinic end generated code: output=fd6aef54f195c77b input=a9049054013a1b77]*/
diff --git a/Modules/_testcapi/exceptions.c b/Modules/_testcapi/exceptions.c
index 0a9902c135a7e..a627bf1717fe0 100644
--- a/Modules/_testcapi/exceptions.c
+++ b/Modules/_testcapi/exceptions.c
@@ -288,6 +288,22 @@ _testcapi_traceback_print_impl(PyObject *module, PyObject *traceback,
Py_RETURN_NONE;
}
+/*[clinic input]
+_testcapi.unstable_exc_prep_reraise_star
+ orig: object
+ excs: object
+ /
+To test PyUnstable_Exc_PrepReraiseStar.
+[clinic start generated code]*/
+
+static PyObject *
+_testcapi_unstable_exc_prep_reraise_star_impl(PyObject *module,
+ PyObject *orig, PyObject *excs)
+/*[clinic end generated code: output=850cf008e0563c77 input=27fbcda2203eb301]*/
+{
+ return PyUnstable_Exc_PrepReraiseStar(orig, excs);
+}
+
/*
* Define the PyRecurdingInfinitelyError_Type
@@ -328,6 +344,7 @@ static PyMethodDef test_methods[] = {
_TESTCAPI_SET_EXCEPTION_METHODDEF
_TESTCAPI_TRACEBACK_PRINT_METHODDEF
_TESTCAPI_WRITE_UNRAISABLE_EXC_METHODDEF
+ _TESTCAPI_UNSTABLE_EXC_PREP_RERAISE_STAR_METHODDEF
{NULL},
};
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index a8d4e3a696ce8..7bec7395cc7f0 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -1351,7 +1351,10 @@ is_same_exception_metadata(PyObject *exc1, PyObject *exc2)
PyObject *
_PyExc_PrepReraiseStar(PyObject *orig, PyObject *excs)
{
+ /* orig must be a raised & caught exception, so it has a traceback */
assert(PyExceptionInstance_Check(orig));
+ assert(_PyBaseExceptionObject_cast(orig)->traceback != NULL);
+
assert(PyList_Check(excs));
Py_ssize_t numexcs = PyList_GET_SIZE(excs);
@@ -1438,6 +1441,42 @@ _PyExc_PrepReraiseStar(PyObject *orig, PyObject *excs)
return result;
}
+PyObject *
+PyUnstable_Exc_PrepReraiseStar(PyObject *orig, PyObject *excs)
+{
+ if (orig == NULL || !PyExceptionInstance_Check(orig)) {
+ PyErr_SetString(PyExc_TypeError, "orig must be an exception instance");
+ return NULL;
+ }
+ if (excs == NULL || !PyList_Check(excs)) {
+ PyErr_SetString(PyExc_TypeError,
+ "excs must be a list of exception instances");
+ return NULL;
+ }
+ Py_ssize_t numexcs = PyList_GET_SIZE(excs);
+ for (Py_ssize_t i = 0; i < numexcs; i++) {
+ PyObject *exc = PyList_GET_ITEM(excs, i);
+ if (exc == NULL || !(PyExceptionInstance_Check(exc) || Py_IsNone(exc))) {
+ PyErr_Format(PyExc_TypeError,
+ "item %d of excs is not an exception", i);
+ return NULL;
+ }
+ }
+
+ /* Make sure that orig has something as traceback, in the interpreter
+ * it always does becuase it's a raised exception.
+ */
+ PyObject *tb = PyException_GetTraceback(orig);
+
+ if (tb == NULL) {
+ PyErr_Format(PyExc_ValueError, "orig must be a raised exception");
+ return NULL;
+ }
+ Py_DECREF(tb);
+
+ return _PyExc_PrepReraiseStar(orig, excs);
+}
+
static PyMemberDef BaseExceptionGroup_members[] = {
{"message", T_OBJECT, offsetof(PyBaseExceptionGroupObject, msg), READONLY,
PyDoc_STR("exception message")},
1
0

gh-105084: Tests: Use setuptools+wheel from sysconfig.get_config_var('WHEEL_PKG_DIR') if set (#105056)
by pradyunsg May 30, 2023
by pradyunsg May 30, 2023
May 30, 2023
https://github.com/python/cpython/commit/bd98b65e974b7a1e086a51e7b55131582f…
commit: bd98b65e974b7a1e086a51e7b55131582f7a0491
branch: main
author: Miro Hrončok <miro(a)hroncok.cz>
committer: pradyunsg <pradyunsg(a)gmail.com>
date: 2023-05-30T11:20:30+01:00
summary:
gh-105084: Tests: Use setuptools+wheel from sysconfig.get_config_var('WHEEL_PKG_DIR') if set (#105056)
files:
A Misc/NEWS.d/next/Tests/2023-05-29-14-49-46.gh-issue-105084.lvVvoj.rst
M Lib/test/support/__init__.py
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 7f8b1d71dbd22..fee8343238885 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -2271,6 +2271,26 @@ def requires_venv_with_pip():
return unittest.skipUnless(ctypes, 'venv: pip requires ctypes')
+(a)functools.cache
+def _findwheel(pkgname):
+ """Try to find a wheel with the package specified as pkgname.
+
+ If set, the wheels are searched for in WHEEL_PKG_DIR (see ensurepip).
+ Otherwise, they are searched for in the test directory.
+ """
+ wheel_dir = sysconfig.get_config_var('WHEEL_PKG_DIR') or TEST_HOME_DIR
+ filenames = os.listdir(wheel_dir)
+ filenames = sorted(filenames, reverse=True) # approximate "newest" first
+ for filename in filenames:
+ # filename is like 'setuptools-67.6.1-py3-none-any.whl'
+ if not filename.endswith(".whl"):
+ continue
+ prefix = pkgname + '-'
+ if filename.startswith(prefix):
+ return os.path.join(wheel_dir, filename)
+ raise FileNotFoundError(f"No wheel for {pkgname} found in {wheel_dir}")
+
+
# Context manager that creates a virtual environment, install setuptools and wheel in it
# and returns the path to the venv directory and the path to the python executable
@contextlib.contextmanager
@@ -2297,8 +2317,8 @@ def setup_venv_with_pip_setuptools_wheel(venv_dir):
cmd = [python, '-X', 'dev',
'-m', 'pip', 'install',
- findfile('setuptools-67.6.1-py3-none-any.whl'),
- findfile('wheel-0.40.0-py3-none-any.whl')]
+ _findwheel('setuptools'),
+ _findwheel('wheel')]
if verbose:
print()
print('Run:', ' '.join(cmd))
diff --git a/Misc/NEWS.d/next/Tests/2023-05-29-14-49-46.gh-issue-105084.lvVvoj.rst b/Misc/NEWS.d/next/Tests/2023-05-29-14-49-46.gh-issue-105084.lvVvoj.rst
new file mode 100644
index 0000000000000..5f80d50714734
--- /dev/null
+++ b/Misc/NEWS.d/next/Tests/2023-05-29-14-49-46.gh-issue-105084.lvVvoj.rst
@@ -0,0 +1,3 @@
+When the Python build is configured ``--with-wheel-pkg-dir``, tests
+requiring the ``setuptools`` and ``wheel`` wheels will search for the wheels
+in ``WHEEL_PKG_DIR``.
1
0

May 30, 2023
https://github.com/python/cpython/commit/cda1bd3c9d3b2cecdeeba0c498cd2df83f…
commit: cda1bd3c9d3b2cecdeeba0c498cd2df83fbdb535
branch: main
author: Steve Dower <steve.dower(a)python.org>
committer: zooba <steve.dower(a)microsoft.com>
date: 2023-05-30T11:00:29+01:00
summary:
gh-88745: Add _winapi.CopyFile2 and update shutil.copy2 to use it (GH-105055)
files:
A Misc/NEWS.d/next/Windows/2023-05-29-11-38-53.gh-issue-88745.cldf9G.rst
M Include/internal/pycore_global_objects_fini_generated.h
M Include/internal/pycore_global_strings.h
M Include/internal/pycore_runtime_init_generated.h
M Include/internal/pycore_unicodeobject_generated.h
M Lib/shutil.py
M Modules/_winapi.c
M Modules/clinic/_winapi.c.h
diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h
index a83f8fc49fc5..546ba6d4c552 100644
--- a/Include/internal/pycore_global_objects_fini_generated.h
+++ b/Include/internal/pycore_global_objects_fini_generated.h
@@ -919,6 +919,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc_value));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(excepthook));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exception));
+ _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(existing_file_name));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exp));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(extend));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(extra_tokens));
@@ -1071,6 +1072,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(namespaces));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(narg));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ndigits));
+ _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(new_file_name));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(new_limit));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(newline));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(newlines));
@@ -1125,6 +1127,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(priority));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(progress));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(progress_handler));
+ _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(progress_routine));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(proto));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(protocol));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ps1));
diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h
index dd6a62f53a99..088bd96c756b 100644
--- a/Include/internal/pycore_global_strings.h
+++ b/Include/internal/pycore_global_strings.h
@@ -407,6 +407,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(exc_value)
STRUCT_FOR_ID(excepthook)
STRUCT_FOR_ID(exception)
+ STRUCT_FOR_ID(existing_file_name)
STRUCT_FOR_ID(exp)
STRUCT_FOR_ID(extend)
STRUCT_FOR_ID(extra_tokens)
@@ -559,6 +560,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(namespaces)
STRUCT_FOR_ID(narg)
STRUCT_FOR_ID(ndigits)
+ STRUCT_FOR_ID(new_file_name)
STRUCT_FOR_ID(new_limit)
STRUCT_FOR_ID(newline)
STRUCT_FOR_ID(newlines)
@@ -613,6 +615,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(priority)
STRUCT_FOR_ID(progress)
STRUCT_FOR_ID(progress_handler)
+ STRUCT_FOR_ID(progress_routine)
STRUCT_FOR_ID(proto)
STRUCT_FOR_ID(protocol)
STRUCT_FOR_ID(ps1)
diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h
index d689f717eaf9..2963423f6071 100644
--- a/Include/internal/pycore_runtime_init_generated.h
+++ b/Include/internal/pycore_runtime_init_generated.h
@@ -913,6 +913,7 @@ extern "C" {
INIT_ID(exc_value), \
INIT_ID(excepthook), \
INIT_ID(exception), \
+ INIT_ID(existing_file_name), \
INIT_ID(exp), \
INIT_ID(extend), \
INIT_ID(extra_tokens), \
@@ -1065,6 +1066,7 @@ extern "C" {
INIT_ID(namespaces), \
INIT_ID(narg), \
INIT_ID(ndigits), \
+ INIT_ID(new_file_name), \
INIT_ID(new_limit), \
INIT_ID(newline), \
INIT_ID(newlines), \
@@ -1119,6 +1121,7 @@ extern "C" {
INIT_ID(priority), \
INIT_ID(progress), \
INIT_ID(progress_handler), \
+ INIT_ID(progress_routine), \
INIT_ID(proto), \
INIT_ID(protocol), \
INIT_ID(ps1), \
diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h
index db6a157ee7af..9e13a9491b7d 100644
--- a/Include/internal/pycore_unicodeobject_generated.h
+++ b/Include/internal/pycore_unicodeobject_generated.h
@@ -1062,6 +1062,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(exception);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
+ string = &_Py_ID(existing_file_name);
+ assert(_PyUnicode_CheckConsistency(string, 1));
+ _PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(exp);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
@@ -1518,6 +1521,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(ndigits);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
+ string = &_Py_ID(new_file_name);
+ assert(_PyUnicode_CheckConsistency(string, 1));
+ _PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(new_limit);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
@@ -1680,6 +1686,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(progress_handler);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
+ string = &_Py_ID(progress_routine);
+ assert(_PyUnicode_CheckConsistency(string, 1));
+ _PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(proto);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
diff --git a/Lib/shutil.py b/Lib/shutil.py
index 7d1a3d00011f..3f2864af517e 100644
--- a/Lib/shutil.py
+++ b/Lib/shutil.py
@@ -42,6 +42,8 @@
if sys.platform == 'win32':
import _winapi
+else:
+ _winapi = None
COPY_BUFSIZE = 1024 * 1024 if _WINDOWS else 64 * 1024
# This should never be removed, see rationale in:
@@ -435,6 +437,29 @@ def copy2(src, dst, *, follow_symlinks=True):
"""
if os.path.isdir(dst):
dst = os.path.join(dst, os.path.basename(src))
+
+ if hasattr(_winapi, "CopyFile2"):
+ src_ = os.fsdecode(src)
+ dst_ = os.fsdecode(dst)
+ flags = _winapi.COPY_FILE_ALLOW_DECRYPTED_DESTINATION # for compat
+ if not follow_symlinks:
+ flags |= _winapi.COPY_FILE_COPY_SYMLINK
+ try:
+ _winapi.CopyFile2(src_, dst_, flags)
+ return dst
+ except OSError as exc:
+ if (exc.winerror == _winapi.ERROR_PRIVILEGE_NOT_HELD
+ and not follow_symlinks):
+ # Likely encountered a symlink we aren't allowed to create.
+ # Fall back on the old code
+ pass
+ elif exc.winerror == _winapi.ERROR_ACCESS_DENIED:
+ # Possibly encountered a hidden or readonly file we can't
+ # overwrite. Fall back on old code
+ pass
+ else:
+ raise
+
copyfile(src, dst, follow_symlinks=follow_symlinks)
copystat(src, dst, follow_symlinks=follow_symlinks)
return dst
diff --git a/Misc/NEWS.d/next/Windows/2023-05-29-11-38-53.gh-issue-88745.cldf9G.rst b/Misc/NEWS.d/next/Windows/2023-05-29-11-38-53.gh-issue-88745.cldf9G.rst
new file mode 100644
index 000000000000..258eb89d50d9
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2023-05-29-11-38-53.gh-issue-88745.cldf9G.rst
@@ -0,0 +1,3 @@
+Improve performance of :func:`shutil.copy2` by using the operating system's
+``CopyFile2`` function. This may result in subtle changes to metadata copied
+along with some files, bringing them in line with normal OS behavior.
diff --git a/Modules/_winapi.c b/Modules/_winapi.c
index 1e02dbc1a4bf..bbc9facd227c 100644
--- a/Modules/_winapi.c
+++ b/Modules/_winapi.c
@@ -1947,6 +1947,7 @@ _winapi_GetFileType_impl(PyObject *module, HANDLE handle)
return result;
}
+
/*[clinic input]
_winapi._mimetypes_read_windows_registry
@@ -2075,6 +2076,67 @@ _winapi_NeedCurrentDirectoryForExePath_impl(PyObject *module,
return result;
}
+
+/*[clinic input]
+_winapi.CopyFile2
+
+ existing_file_name: LPCWSTR
+ new_file_name: LPCWSTR
+ flags: DWORD
+ progress_routine: object = None
+
+Copies a file from one name to a new name.
+
+This is implemented using the CopyFile2 API, which preserves all stat
+and metadata information apart from security attributes.
+
+progress_routine is reserved for future use, but is currently not
+implemented. Its value is ignored.
+[clinic start generated code]*/
+
+static PyObject *
+_winapi_CopyFile2_impl(PyObject *module, LPCWSTR existing_file_name,
+ LPCWSTR new_file_name, DWORD flags,
+ PyObject *progress_routine)
+/*[clinic end generated code: output=43d960d9df73d984 input=fb976b8d1492d130]*/
+{
+ HRESULT hr;
+ COPYFILE2_EXTENDED_PARAMETERS params = { sizeof(COPYFILE2_EXTENDED_PARAMETERS) };
+
+ if (PySys_Audit("_winapi.CopyFile2", "uuI",
+ existing_file_name, new_file_name, flags) < 0) {
+ return NULL;
+ }
+
+ params.dwCopyFlags = flags;
+ /* For future implementation. We ignore the value for now so that
+ users only have to test for 'CopyFile2' existing and not whether
+ the additional parameter exists.
+ if (progress_routine != Py_None) {
+ params.pProgressRoutine = _winapi_CopyFile2ProgressRoutine;
+ params.pvCallbackContext = Py_NewRef(progress_routine);
+ }
+ */
+ Py_BEGIN_ALLOW_THREADS;
+ hr = CopyFile2(existing_file_name, new_file_name, ¶ms);
+ Py_END_ALLOW_THREADS;
+ /* For future implementation.
+ if (progress_routine != Py_None) {
+ Py_DECREF(progress_routine);
+ }
+ */
+ if (FAILED(hr)) {
+ if ((hr & 0xFFFF0000) == 0x80070000) {
+ PyErr_SetFromWindowsErr(hr & 0xFFFF);
+ } else {
+ PyErr_SetFromWindowsErr(hr);
+ }
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+
static PyMethodDef winapi_functions[] = {
_WINAPI_CLOSEHANDLE_METHODDEF
_WINAPI_CONNECTNAMEDPIPE_METHODDEF
@@ -2110,6 +2172,7 @@ static PyMethodDef winapi_functions[] = {
_WINAPI_GETFILETYPE_METHODDEF
_WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF
_WINAPI_NEEDCURRENTDIRECTORYFOREXEPATH_METHODDEF
+ _WINAPI_COPYFILE2_METHODDEF
{NULL, NULL}
};
@@ -2146,6 +2209,7 @@ static int winapi_exec(PyObject *m)
WINAPI_CONSTANT(F_DWORD, CREATE_NEW_PROCESS_GROUP);
WINAPI_CONSTANT(F_DWORD, DUPLICATE_SAME_ACCESS);
WINAPI_CONSTANT(F_DWORD, DUPLICATE_CLOSE_SOURCE);
+ WINAPI_CONSTANT(F_DWORD, ERROR_ACCESS_DENIED);
WINAPI_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS);
WINAPI_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE);
WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
@@ -2159,6 +2223,7 @@ static int winapi_exec(PyObject *m)
WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED);
WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED);
+ WINAPI_CONSTANT(F_DWORD, ERROR_PRIVILEGE_NOT_HELD);
WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
WINAPI_CONSTANT(F_DWORD, FILE_FLAG_FIRST_PIPE_INSTANCE);
WINAPI_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED);
@@ -2252,6 +2317,34 @@ static int winapi_exec(PyObject *m)
WINAPI_CONSTANT(F_DWORD, LCMAP_TRADITIONAL_CHINESE);
WINAPI_CONSTANT(F_DWORD, LCMAP_UPPERCASE);
+ WINAPI_CONSTANT(F_DWORD, COPY_FILE_ALLOW_DECRYPTED_DESTINATION);
+ WINAPI_CONSTANT(F_DWORD, COPY_FILE_COPY_SYMLINK);
+ WINAPI_CONSTANT(F_DWORD, COPY_FILE_FAIL_IF_EXISTS);
+ WINAPI_CONSTANT(F_DWORD, COPY_FILE_NO_BUFFERING);
+ WINAPI_CONSTANT(F_DWORD, COPY_FILE_NO_OFFLOAD);
+ WINAPI_CONSTANT(F_DWORD, COPY_FILE_OPEN_SOURCE_FOR_WRITE);
+ WINAPI_CONSTANT(F_DWORD, COPY_FILE_RESTARTABLE);
+ WINAPI_CONSTANT(F_DWORD, COPY_FILE_REQUEST_SECURITY_PRIVILEGES);
+ WINAPI_CONSTANT(F_DWORD, COPY_FILE_RESUME_FROM_PAUSE);
+#ifndef COPY_FILE_REQUEST_COMPRESSED_TRAFFIC
+ // Only defined in newer WinSDKs
+ #define COPY_FILE_REQUEST_COMPRESSED_TRAFFIC 0x10000000
+#endif
+ WINAPI_CONSTANT(F_DWORD, COPY_FILE_REQUEST_COMPRESSED_TRAFFIC);
+
+ WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_CHUNK_STARTED);
+ WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_CHUNK_FINISHED);
+ WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_STREAM_STARTED);
+ WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_STREAM_FINISHED);
+ WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_POLL_CONTINUE);
+ WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_ERROR);
+
+ WINAPI_CONSTANT(F_DWORD, COPYFILE2_PROGRESS_CONTINUE);
+ WINAPI_CONSTANT(F_DWORD, COPYFILE2_PROGRESS_CANCEL);
+ WINAPI_CONSTANT(F_DWORD, COPYFILE2_PROGRESS_STOP);
+ WINAPI_CONSTANT(F_DWORD, COPYFILE2_PROGRESS_QUIET);
+ WINAPI_CONSTANT(F_DWORD, COPYFILE2_PROGRESS_PAUSE);
+
WINAPI_CONSTANT("i", NULL);
return 0;
diff --git a/Modules/clinic/_winapi.c.h b/Modules/clinic/_winapi.c.h
index 7bc63e612be3..3767b19d76db 100644
--- a/Modules/clinic/_winapi.c.h
+++ b/Modules/clinic/_winapi.c.h
@@ -1411,4 +1411,74 @@ _winapi_NeedCurrentDirectoryForExePath(PyObject *module, PyObject *arg)
return return_value;
}
-/*[clinic end generated code: output=96ea65ece7912d0a input=a9049054013a1b77]*/
+
+PyDoc_STRVAR(_winapi_CopyFile2__doc__,
+"CopyFile2($module, /, existing_file_name, new_file_name, flags,\n"
+" progress_routine=None)\n"
+"--\n"
+"\n"
+"Copies a file from one name to a new name.\n"
+"\n"
+"This is implemented using the CopyFile2 API, which preserves all stat\n"
+"and metadata information apart from security attributes.\n"
+"\n"
+"progress_routine is reserved for future use, but is currently not\n"
+"implemented. Its value is ignored.");
+
+#define _WINAPI_COPYFILE2_METHODDEF \
+ {"CopyFile2", _PyCFunction_CAST(_winapi_CopyFile2), METH_FASTCALL|METH_KEYWORDS, _winapi_CopyFile2__doc__},
+
+static PyObject *
+_winapi_CopyFile2_impl(PyObject *module, LPCWSTR existing_file_name,
+ LPCWSTR new_file_name, DWORD flags,
+ PyObject *progress_routine);
+
+static PyObject *
+_winapi_CopyFile2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 4
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = { &_Py_ID(existing_file_name), &_Py_ID(new_file_name), &_Py_ID(flags), &_Py_ID(progress_routine), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"existing_file_name", "new_file_name", "flags", "progress_routine", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .format = "O&O&k|O:CopyFile2",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ LPCWSTR existing_file_name = NULL;
+ LPCWSTR new_file_name = NULL;
+ DWORD flags;
+ PyObject *progress_routine = Py_None;
+
+ if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
+ _PyUnicode_WideCharString_Converter, &existing_file_name, _PyUnicode_WideCharString_Converter, &new_file_name, &flags, &progress_routine)) {
+ goto exit;
+ }
+ return_value = _winapi_CopyFile2_impl(module, existing_file_name, new_file_name, flags, progress_routine);
+
+exit:
+ /* Cleanup for existing_file_name */
+ PyMem_Free((void *)existing_file_name);
+ /* Cleanup for new_file_name */
+ PyMem_Free((void *)new_file_name);
+
+ return return_value;
+}
+/*[clinic end generated code: output=be1343b3759e0c96 input=a9049054013a1b77]*/
1
0

[3.12] gh-102251: Fix reference leak in _testsinglephase initialization (GH-105082) (#105083)
by erlend-aasland May 30, 2023
by erlend-aasland May 30, 2023
May 30, 2023
https://github.com/python/cpython/commit/fd6b913535d78d3bfec710075ac930474c…
commit: fd6b913535d78d3bfec710075ac930474c1057ca
branch: 3.12
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: erlend-aasland <erlend.aasland(a)protonmail.com>
date: 2023-05-30T09:53:46Z
summary:
[3.12] gh-102251: Fix reference leak in _testsinglephase initialization (GH-105082) (#105083)
Correctly decref 'initialized' in init_module()
(cherry picked from commit d14eb3433cf2a40a202471b815f0a935f2840ead)
Co-authored-by: sunmy2019 <59365878+sunmy2019(a)users.noreply.github.com>
Co-authored-by: Erlend E. Aasland <erlend.aasland(a)protonmail.com>
files:
M Modules/_testsinglephase.c
diff --git a/Modules/_testsinglephase.c b/Modules/_testsinglephase.c
index a16157702ae7..8e6973f0b052 100644
--- a/Modules/_testsinglephase.c
+++ b/Modules/_testsinglephase.c
@@ -140,7 +140,9 @@ init_module(PyObject *module, module_state *state)
if (initialized == NULL) {
return -1;
}
- if (PyModule_AddObjectRef(module, "_module_initialized", initialized) != 0) {
+ int rc = PyModule_AddObjectRef(module, "_module_initialized", initialized);
+ Py_DECREF(initialized);
+ if (rc < 0) {
return -1;
}
1
0