[Python-checkins] gh-121615: Improve `module.rst` C-API docs with better error descriptions (#121616)

2024-07-11 Thread sobolevn
https://github.com/python/cpython/commit/e6264b44dc7221c713b14dfa0f5929b33d362829
commit: e6264b44dc7221c713b14dfa0f5929b33d362829
branch: main
author: sobolevn 
committer: sobolevn 
date: 2024-07-11T11:57:22+03:00
summary:

gh-121615: Improve `module.rst` C-API docs with better error descriptions 
(#121616)

files:
M Doc/c-api/module.rst

diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst
index 63e3bed6727987..ce9d5a0f758b29 100644
--- a/Doc/c-api/module.rst
+++ b/Doc/c-api/module.rst
@@ -43,6 +43,8 @@ Module Objects
to ``None``); the caller is responsible for providing a :attr:`__file__`
attribute.
 
+   Return ``NULL`` with an exception set on error.
+
.. versionadded:: 3.3
 
.. versionchanged:: 3.4
@@ -265,6 +267,8 @@ of the following two module creation functions:
API version *module_api_version*.  If that version does not match the 
version
of the running interpreter, a :exc:`RuntimeWarning` is emitted.
 
+   Return ``NULL`` with an exception set on error.
+
.. note::
 
   Most uses of this function should be using :c:func:`PyModule_Create`
@@ -461,6 +465,8 @@ objects dynamically. Note that both 
``PyModule_FromDefAndSpec`` and
If that version does not match the version of the running interpreter,
a :exc:`RuntimeWarning` is emitted.
 
+   Return ``NULL`` with an exception set on error.
+
.. note::
 
   Most uses of this function should be using 
:c:func:`PyModule_FromDefAndSpec`
@@ -601,15 +607,16 @@ state:
 .. c:function:: int PyModule_AddIntConstant(PyObject *module, const char 
*name, long value)
 
Add an integer constant to *module* as *name*.  This convenience function 
can be
-   used from the module's initialization function. Return ``-1`` on error, 
``0`` on
-   success.
+   used from the module's initialization function.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
 
 .. c:function:: int PyModule_AddStringConstant(PyObject *module, const char 
*name, const char *value)
 
Add a string constant to *module* as *name*.  This convenience function can 
be
used from the module's initialization function.  The string *value* must be
-   ``NULL``-terminated.  Return ``-1`` on error, ``0`` on success.
+   ``NULL``-terminated.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
 
 .. c:macro:: PyModule_AddIntMacro(module, macro)
@@ -617,7 +624,7 @@ state:
Add an int constant to *module*. The name and the value are taken from
*macro*. For example ``PyModule_AddIntMacro(module, AF_INET)`` adds the int
constant *AF_INET* with the value of *AF_INET* to *module*.
-   Return ``-1`` on error, ``0`` on success.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
 
 .. c:macro:: PyModule_AddStringMacro(module, macro)
@@ -630,7 +637,7 @@ state:
The type object is finalized by calling internally :c:func:`PyType_Ready`.
The name of the type object is taken from the last component of
:c:member:`~PyTypeObject.tp_name` after dot.
-   Return ``-1`` on error, ``0`` on success.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
.. versionadded:: 3.9
 
@@ -643,7 +650,7 @@ state:
import machinery assumes the module does not support running without the
GIL. This function is only available in Python builds configured with
:option:`--disable-gil`.
-   Return ``-1`` on error, ``0`` on success.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
.. versionadded:: 3.13
 
@@ -682,14 +689,14 @@ since multiple such modules can be created from a single 
definition.
 
The caller must hold the GIL.
 
-   Return 0 on success or -1 on failure.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
.. versionadded:: 3.3
 
 .. c:function:: int PyState_RemoveModule(PyModuleDef *def)
 
Removes the module object created from *def* from the interpreter state.
-   Return 0 on success or -1 on failure.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
The caller must hold the GIL.
 

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]


[Python-checkins] [3.12] gh-121615: Improve `module.rst` C-API docs with better error descriptions (GH-121616) (#121619)

2024-07-11 Thread sobolevn
https://github.com/python/cpython/commit/5492f84c14bc0c93a24863349b6c998bdb18e93f
commit: 5492f84c14bc0c93a24863349b6c998bdb18e93f
branch: 3.12
author: sobolevn 
committer: sobolevn 
date: 2024-07-11T09:12:06Z
summary:

[3.12] gh-121615: Improve `module.rst` C-API docs with better error 
descriptions (GH-121616) (#121619)

(cherry picked from commit e6264b44dc7221c713b14dfa0f5929b33d362829)

files:
M Doc/c-api/module.rst

diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst
index f941f0c7d42b2b..02efb9921a9b99 100644
--- a/Doc/c-api/module.rst
+++ b/Doc/c-api/module.rst
@@ -43,6 +43,8 @@ Module Objects
to ``None``); the caller is responsible for providing a :attr:`__file__`
attribute.
 
+   Return ``NULL`` with an exception set on error.
+
.. versionadded:: 3.3
 
.. versionchanged:: 3.4
@@ -265,6 +267,8 @@ of the following two module creation functions:
API version *module_api_version*.  If that version does not match the 
version
of the running interpreter, a :exc:`RuntimeWarning` is emitted.
 
+   Return ``NULL`` with an exception set on error.
+
.. note::
 
   Most uses of this function should be using :c:func:`PyModule_Create`
@@ -436,6 +440,8 @@ objects dynamically. Note that both 
``PyModule_FromDefAndSpec`` and
If that version does not match the version of the running interpreter,
a :exc:`RuntimeWarning` is emitted.
 
+   Return ``NULL`` with an exception set on error.
+
.. note::
 
   Most uses of this function should be using 
:c:func:`PyModule_FromDefAndSpec`
@@ -579,15 +585,16 @@ state:
 .. c:function:: int PyModule_AddIntConstant(PyObject *module, const char 
*name, long value)
 
Add an integer constant to *module* as *name*.  This convenience function 
can be
-   used from the module's initialization function. Return ``-1`` on error, 
``0`` on
-   success.
+   used from the module's initialization function.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
 
 .. c:function:: int PyModule_AddStringConstant(PyObject *module, const char 
*name, const char *value)
 
Add a string constant to *module* as *name*.  This convenience function can 
be
used from the module's initialization function.  The string *value* must be
-   ``NULL``-terminated.  Return ``-1`` on error, ``0`` on success.
+   ``NULL``-terminated.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
 
 .. c:macro:: PyModule_AddIntMacro(module, macro)
@@ -595,7 +602,7 @@ state:
Add an int constant to *module*. The name and the value are taken from
*macro*. For example ``PyModule_AddIntMacro(module, AF_INET)`` adds the int
constant *AF_INET* with the value of *AF_INET* to *module*.
-   Return ``-1`` on error, ``0`` on success.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
 
 .. c:macro:: PyModule_AddStringMacro(module, macro)
@@ -608,7 +615,7 @@ state:
The type object is finalized by calling internally :c:func:`PyType_Ready`.
The name of the type object is taken from the last component of
:c:member:`~PyTypeObject.tp_name` after dot.
-   Return ``-1`` on error, ``0`` on success.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
.. versionadded:: 3.9
 
@@ -647,14 +654,14 @@ since multiple such modules can be created from a single 
definition.
 
The caller must hold the GIL.
 
-   Return 0 on success or -1 on failure.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
.. versionadded:: 3.3
 
 .. c:function:: int PyState_RemoveModule(PyModuleDef *def)
 
Removes the module object created from *def* from the interpreter state.
-   Return 0 on success or -1 on failure.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
The caller must hold the GIL.
 

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]


[Python-checkins] [3.13] gh-121615: Improve `module.rst` C-API docs with better error descriptions (GH-121616) (#121618)

2024-07-11 Thread sobolevn
https://github.com/python/cpython/commit/261c8e9d476653a48c775f4b1820c0554bae232a
commit: 261c8e9d476653a48c775f4b1820c0554bae232a
branch: 3.13
author: Miss Islington (bot) <[email protected]>
committer: sobolevn 
date: 2024-07-11T09:15:18Z
summary:

[3.13] gh-121615: Improve `module.rst` C-API docs with better error 
descriptions (GH-121616) (#121618)

gh-121615: Improve `module.rst` C-API docs with better error descriptions 
(GH-121616)
(cherry picked from commit e6264b44dc7221c713b14dfa0f5929b33d362829)

Co-authored-by: sobolevn 

files:
M Doc/c-api/module.rst

diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst
index 63e3bed6727987..ce9d5a0f758b29 100644
--- a/Doc/c-api/module.rst
+++ b/Doc/c-api/module.rst
@@ -43,6 +43,8 @@ Module Objects
to ``None``); the caller is responsible for providing a :attr:`__file__`
attribute.
 
+   Return ``NULL`` with an exception set on error.
+
.. versionadded:: 3.3
 
.. versionchanged:: 3.4
@@ -265,6 +267,8 @@ of the following two module creation functions:
API version *module_api_version*.  If that version does not match the 
version
of the running interpreter, a :exc:`RuntimeWarning` is emitted.
 
+   Return ``NULL`` with an exception set on error.
+
.. note::
 
   Most uses of this function should be using :c:func:`PyModule_Create`
@@ -461,6 +465,8 @@ objects dynamically. Note that both 
``PyModule_FromDefAndSpec`` and
If that version does not match the version of the running interpreter,
a :exc:`RuntimeWarning` is emitted.
 
+   Return ``NULL`` with an exception set on error.
+
.. note::
 
   Most uses of this function should be using 
:c:func:`PyModule_FromDefAndSpec`
@@ -601,15 +607,16 @@ state:
 .. c:function:: int PyModule_AddIntConstant(PyObject *module, const char 
*name, long value)
 
Add an integer constant to *module* as *name*.  This convenience function 
can be
-   used from the module's initialization function. Return ``-1`` on error, 
``0`` on
-   success.
+   used from the module's initialization function.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
 
 .. c:function:: int PyModule_AddStringConstant(PyObject *module, const char 
*name, const char *value)
 
Add a string constant to *module* as *name*.  This convenience function can 
be
used from the module's initialization function.  The string *value* must be
-   ``NULL``-terminated.  Return ``-1`` on error, ``0`` on success.
+   ``NULL``-terminated.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
 
 .. c:macro:: PyModule_AddIntMacro(module, macro)
@@ -617,7 +624,7 @@ state:
Add an int constant to *module*. The name and the value are taken from
*macro*. For example ``PyModule_AddIntMacro(module, AF_INET)`` adds the int
constant *AF_INET* with the value of *AF_INET* to *module*.
-   Return ``-1`` on error, ``0`` on success.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
 
 .. c:macro:: PyModule_AddStringMacro(module, macro)
@@ -630,7 +637,7 @@ state:
The type object is finalized by calling internally :c:func:`PyType_Ready`.
The name of the type object is taken from the last component of
:c:member:`~PyTypeObject.tp_name` after dot.
-   Return ``-1`` on error, ``0`` on success.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
.. versionadded:: 3.9
 
@@ -643,7 +650,7 @@ state:
import machinery assumes the module does not support running without the
GIL. This function is only available in Python builds configured with
:option:`--disable-gil`.
-   Return ``-1`` on error, ``0`` on success.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
.. versionadded:: 3.13
 
@@ -682,14 +689,14 @@ since multiple such modules can be created from a single 
definition.
 
The caller must hold the GIL.
 
-   Return 0 on success or -1 on failure.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
.. versionadded:: 3.3
 
 .. c:function:: int PyState_RemoveModule(PyModuleDef *def)
 
Removes the module object created from *def* from the interpreter state.
-   Return 0 on success or -1 on failure.
+   Return ``-1`` with an exception set on error, ``0`` on success.
 
The caller must hold the GIL.
 

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]


[Python-checkins] gh-121592: Make select.poll() and related objects thread-safe (#121594)

2024-07-11 Thread colesbury
https://github.com/python/cpython/commit/44937d11a6a045a624918db78aa36e715ffabcd4
commit: 44937d11a6a045a624918db78aa36e715ffabcd4
branch: main
author: Sam Gross 
committer: colesbury 
date: 2024-07-11T10:21:09-04:00
summary:

gh-121592: Make select.poll() and related objects thread-safe (#121594)

This makes select.poll() and kqueue() objects thread-safe in the
free-threaded build. Note that calling close() concurrently with other
functions is still not thread-safe due to races on file descriptors
(gh-121544).

files:
M Modules/clinic/selectmodule.c.h
M Modules/selectmodule.c

diff --git a/Modules/clinic/selectmodule.c.h b/Modules/clinic/selectmodule.c.h
index dc7d3fb814396d..0ccbf63b688f1b 100644
--- a/Modules/clinic/selectmodule.c.h
+++ b/Modules/clinic/selectmodule.c.h
@@ -6,6 +6,7 @@ preserve
 #  include "pycore_gc.h"  // PyGC_Head
 #  include "pycore_runtime.h" // _Py_ID()
 #endif
+#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
 #include "pycore_long.h"  // _PyLong_UnsignedShort_Converter()
 #include "pycore_modsupport.h"// _PyArg_CheckPositional()
 
@@ -110,7 +111,9 @@ select_poll_register(pollObject *self, PyObject *const 
*args, Py_ssize_t nargs)
 goto exit;
 }
 skip_optional:
+Py_BEGIN_CRITICAL_SECTION(self);
 return_value = select_poll_register_impl(self, fd, eventmask);
+Py_END_CRITICAL_SECTION();
 
 exit:
 return return_value;
@@ -155,7 +158,9 @@ select_poll_modify(pollObject *self, PyObject *const *args, 
Py_ssize_t nargs)
 if (!_PyLong_UnsignedShort_Converter(args[1], &eventmask)) {
 goto exit;
 }
+Py_BEGIN_CRITICAL_SECTION(self);
 return_value = select_poll_modify_impl(self, fd, eventmask);
+Py_END_CRITICAL_SECTION();
 
 exit:
 return return_value;
@@ -187,7 +192,9 @@ select_poll_unregister(pollObject *self, PyObject *arg)
 if (fd < 0) {
 goto exit;
 }
+Py_BEGIN_CRITICAL_SECTION(self);
 return_value = select_poll_unregister_impl(self, fd);
+Py_END_CRITICAL_SECTION();
 
 exit:
 return return_value;
@@ -230,7 +237,9 @@ select_poll_poll(pollObject *self, PyObject *const *args, 
Py_ssize_t nargs)
 }
 timeout_obj = args[0];
 skip_optional:
+Py_BEGIN_CRITICAL_SECTION(self);
 return_value = select_poll_poll_impl(self, timeout_obj);
+Py_END_CRITICAL_SECTION();
 
 exit:
 return return_value;
@@ -281,7 +290,9 @@ select_devpoll_register(devpollObject *self, PyObject 
*const *args, Py_ssize_t n
 goto exit;
 }
 skip_optional:
+Py_BEGIN_CRITICAL_SECTION(self);
 return_value = select_devpoll_register_impl(self, fd, eventmask);
+Py_END_CRITICAL_SECTION();
 
 exit:
 return return_value;
@@ -332,7 +343,9 @@ select_devpoll_modify(devpollObject *self, PyObject *const 
*args, Py_ssize_t nar
 goto exit;
 }
 skip_optional:
+Py_BEGIN_CRITICAL_SECTION(self);
 return_value = select_devpoll_modify_impl(self, fd, eventmask);
+Py_END_CRITICAL_SECTION();
 
 exit:
 return return_value;
@@ -364,7 +377,9 @@ select_devpoll_unregister(devpollObject *self, PyObject 
*arg)
 if (fd < 0) {
 goto exit;
 }
+Py_BEGIN_CRITICAL_SECTION(self);
 return_value = select_devpoll_unregister_impl(self, fd);
+Py_END_CRITICAL_SECTION();
 
 exit:
 return return_value;
@@ -407,7 +422,9 @@ select_devpoll_poll(devpollObject *self, PyObject *const 
*args, Py_ssize_t nargs
 }
 timeout_obj = args[0];
 skip_optional:
+Py_BEGIN_CRITICAL_SECTION(self);
 return_value = select_devpoll_poll_impl(self, timeout_obj);
+Py_END_CRITICAL_SECTION();
 
 exit:
 return return_value;
@@ -434,7 +451,13 @@ select_devpoll_close_impl(devpollObject *self);
 static PyObject *
 select_devpoll_close(devpollObject *self, PyObject *Py_UNUSED(ignored))
 {
-return select_devpoll_close_impl(self);
+PyObject *return_value = NULL;
+
+Py_BEGIN_CRITICAL_SECTION(self);
+return_value = select_devpoll_close_impl(self);
+Py_END_CRITICAL_SECTION();
+
+return return_value;
 }
 
 #endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && 
defined(HAVE_SYS_DEVPOLL_H) */
@@ -456,7 +479,13 @@ select_devpoll_fileno_impl(devpollObject *self);
 static PyObject *
 select_devpoll_fileno(devpollObject *self, PyObject *Py_UNUSED(ignored))
 {
-return select_devpoll_fileno_impl(self);
+PyObject *return_value = NULL;
+
+Py_BEGIN_CRITICAL_SECTION(self);
+return_value = select_devpoll_fileno_impl(self);
+Py_END_CRITICAL_SECTION();
+
+return return_value;
 }
 
 #endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && 
defined(HAVE_SYS_DEVPOLL_H) */
@@ -615,7 +644,13 @@ select_epoll_close_impl(pyEpoll_Object *self);
 static PyObject *
 select_epoll_close(pyEpoll_Object *self, PyObject *Py_UNUSED(ignored))
 {
-return select_epoll_close_impl(self);
+PyObject *return_value = NULL;
+
+Py_BEGIN_CRITICAL_SECTION(self);
+return_value = select_epoll_close_impl(self);
+P

[Python-checkins] gh-121332: Make AST node constructor check _attributes instead of hardcoding attributes (#121334)

2024-07-11 Thread JelleZijlstra
https://github.com/python/cpython/commit/58e8cf2bb61f82df9eabd1209fe5e3d146e4c8cd
commit: 58e8cf2bb61f82df9eabd1209fe5e3d146e4c8cd
branch: main
author: Jelle Zijlstra 
committer: JelleZijlstra 
date: 2024-07-11T14:34:53Z
summary:

gh-121332: Make AST node constructor check _attributes instead of hardcoding 
attributes (#121334)

files:
A Misc/NEWS.d/next/Library/2024-07-03-07-25-21.gh-issue-121332.Iz6FEq.rst
M Lib/test/test_ast.py
M Parser/asdl_c.py
M Python/Python-ast.c

diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py
index eb3aefd5c262f6..497c3f261a1fca 100644
--- a/Lib/test/test_ast.py
+++ b/Lib/test/test_ast.py
@@ -1386,15 +1386,7 @@ class MyNode(ast.AST):
 self.assertEqual(node.y, 1)
 
 y = object()
-# custom attributes are currently not supported and raise a warning
-# because the allowed attributes are hard-coded !
-msg = (
-"MyNode.__init__ got an unexpected keyword argument 'y'. "
-"Support for arbitrary keyword arguments is deprecated and "
-"will be removed in Python 3.15"
-)
-with self.assertWarnsRegex(DeprecationWarning, re.escape(msg)):
-repl = copy.replace(node, y=y)
+repl = copy.replace(node, y=y)
 # assert that there is no side-effect
 self.assertEqual(node.x, 0)
 self.assertEqual(node.y, 1)
@@ -3250,6 +3242,18 @@ class FieldsAndTypes(ast.AST):
 obj = FieldsAndTypes(a=1)
 self.assertEqual(obj.a, 1)
 
+def test_custom_attributes(self):
+class MyAttrs(ast.AST):
+_attributes = ("a", "b")
+
+obj = MyAttrs(a=1, b=2)
+self.assertEqual(obj.a, 1)
+self.assertEqual(obj.b, 2)
+
+with self.assertWarnsRegex(DeprecationWarning,
+   r"MyAttrs.__init__ got an unexpected 
keyword argument 'c'."):
+obj = MyAttrs(c=3)
+
 def test_fields_and_types_no_default(self):
 class FieldsAndTypesNoDefault(ast.AST):
 _fields = ('a',)
diff --git 
a/Misc/NEWS.d/next/Library/2024-07-03-07-25-21.gh-issue-121332.Iz6FEq.rst 
b/Misc/NEWS.d/next/Library/2024-07-03-07-25-21.gh-issue-121332.Iz6FEq.rst
new file mode 100644
index 00..480f27e05953a6
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-07-03-07-25-21.gh-issue-121332.Iz6FEq.rst
@@ -0,0 +1,4 @@
+Fix constructor of :mod:`ast` nodes with custom ``_attributes``. Previously,
+passing custom attributes would raise a :py:exc:`DeprecationWarning`. Passing
+arguments to the constructor that are not in ``_fields`` or ``_attributes``
+remains deprecated. Patch by Jelle Zijlstra.
diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py
index f3667801782f2b..e6867f138a5ccb 100755
--- a/Parser/asdl_c.py
+++ b/Parser/asdl_c.py
@@ -880,7 +880,7 @@ def visitModule(self, mod):
 
 Py_ssize_t i, numfields = 0;
 int res = -1;
-PyObject *key, *value, *fields, *remaining_fields = NULL;
+PyObject *key, *value, *fields, *attributes = NULL, *remaining_fields = 
NULL;
 if (PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self), state->_fields, 
&fields) < 0) {
 goto cleanup;
 }
@@ -947,22 +947,32 @@ def visitModule(self, mod):
 goto cleanup;
 }
 }
-else if (
-PyUnicode_CompareWithASCIIString(key, "lineno") != 0 &&
-PyUnicode_CompareWithASCIIString(key, "col_offset") != 0 &&
-PyUnicode_CompareWithASCIIString(key, "end_lineno") != 0 &&
-PyUnicode_CompareWithASCIIString(key, "end_col_offset") != 0
-) {
-if (PyErr_WarnFormat(
-PyExc_DeprecationWarning, 1,
-"%.400s.__init__ got an unexpected keyword argument '%U'. "
-"Support for arbitrary keyword arguments is deprecated "
-"and will be removed in Python 3.15.",
-Py_TYPE(self)->tp_name, key
-) < 0) {
+else {
+// Lazily initialize "attributes"
+if (attributes == NULL) {
+attributes = PyObject_GetAttr((PyObject*)Py_TYPE(self), 
state->_attributes);
+if (attributes == NULL) {
+res = -1;
+goto cleanup;
+}
+}
+int contains = PySequence_Contains(attributes, key);
+if (contains == -1) {
 res = -1;
 goto cleanup;
 }
+else if (contains == 0) {
+if (PyErr_WarnFormat(
+PyExc_DeprecationWarning, 1,
+"%.400s.__init__ got an unexpected keyword argument 
'%U'. "
+"Support for arbitrary keyword arguments is deprecated 
"
+"and will be removed in Python 3.15.",
+Py_TYPE(self)->tp_name, key
+

[Python-checkins] [3.13] gh-121592: Make select.poll() and related objects thread-safe (GH-121594) (#121623)

2024-07-11 Thread colesbury
https://github.com/python/cpython/commit/3b5f8d256c534e9b2baa64ec151da0d590213667
commit: 3b5f8d256c534e9b2baa64ec151da0d590213667
branch: 3.13
author: Miss Islington (bot) <[email protected]>
committer: colesbury 
date: 2024-07-11T14:44:54Z
summary:

[3.13] gh-121592: Make select.poll() and related objects thread-safe 
(GH-121594) (#121623)

This makes select.poll() and kqueue() objects thread-safe in the
free-threaded build. Note that calling close() concurrently with other
functions is still not thread-safe due to races on file descriptors
(gh-121544).
(cherry picked from commit 44937d11a6a045a624918db78aa36e715ffabcd4)

Co-authored-by: Sam Gross 

files:
M Modules/clinic/selectmodule.c.h
M Modules/selectmodule.c

diff --git a/Modules/clinic/selectmodule.c.h b/Modules/clinic/selectmodule.c.h
index dc7d3fb814396d..0ccbf63b688f1b 100644
--- a/Modules/clinic/selectmodule.c.h
+++ b/Modules/clinic/selectmodule.c.h
@@ -6,6 +6,7 @@ preserve
 #  include "pycore_gc.h"  // PyGC_Head
 #  include "pycore_runtime.h" // _Py_ID()
 #endif
+#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
 #include "pycore_long.h"  // _PyLong_UnsignedShort_Converter()
 #include "pycore_modsupport.h"// _PyArg_CheckPositional()
 
@@ -110,7 +111,9 @@ select_poll_register(pollObject *self, PyObject *const 
*args, Py_ssize_t nargs)
 goto exit;
 }
 skip_optional:
+Py_BEGIN_CRITICAL_SECTION(self);
 return_value = select_poll_register_impl(self, fd, eventmask);
+Py_END_CRITICAL_SECTION();
 
 exit:
 return return_value;
@@ -155,7 +158,9 @@ select_poll_modify(pollObject *self, PyObject *const *args, 
Py_ssize_t nargs)
 if (!_PyLong_UnsignedShort_Converter(args[1], &eventmask)) {
 goto exit;
 }
+Py_BEGIN_CRITICAL_SECTION(self);
 return_value = select_poll_modify_impl(self, fd, eventmask);
+Py_END_CRITICAL_SECTION();
 
 exit:
 return return_value;
@@ -187,7 +192,9 @@ select_poll_unregister(pollObject *self, PyObject *arg)
 if (fd < 0) {
 goto exit;
 }
+Py_BEGIN_CRITICAL_SECTION(self);
 return_value = select_poll_unregister_impl(self, fd);
+Py_END_CRITICAL_SECTION();
 
 exit:
 return return_value;
@@ -230,7 +237,9 @@ select_poll_poll(pollObject *self, PyObject *const *args, 
Py_ssize_t nargs)
 }
 timeout_obj = args[0];
 skip_optional:
+Py_BEGIN_CRITICAL_SECTION(self);
 return_value = select_poll_poll_impl(self, timeout_obj);
+Py_END_CRITICAL_SECTION();
 
 exit:
 return return_value;
@@ -281,7 +290,9 @@ select_devpoll_register(devpollObject *self, PyObject 
*const *args, Py_ssize_t n
 goto exit;
 }
 skip_optional:
+Py_BEGIN_CRITICAL_SECTION(self);
 return_value = select_devpoll_register_impl(self, fd, eventmask);
+Py_END_CRITICAL_SECTION();
 
 exit:
 return return_value;
@@ -332,7 +343,9 @@ select_devpoll_modify(devpollObject *self, PyObject *const 
*args, Py_ssize_t nar
 goto exit;
 }
 skip_optional:
+Py_BEGIN_CRITICAL_SECTION(self);
 return_value = select_devpoll_modify_impl(self, fd, eventmask);
+Py_END_CRITICAL_SECTION();
 
 exit:
 return return_value;
@@ -364,7 +377,9 @@ select_devpoll_unregister(devpollObject *self, PyObject 
*arg)
 if (fd < 0) {
 goto exit;
 }
+Py_BEGIN_CRITICAL_SECTION(self);
 return_value = select_devpoll_unregister_impl(self, fd);
+Py_END_CRITICAL_SECTION();
 
 exit:
 return return_value;
@@ -407,7 +422,9 @@ select_devpoll_poll(devpollObject *self, PyObject *const 
*args, Py_ssize_t nargs
 }
 timeout_obj = args[0];
 skip_optional:
+Py_BEGIN_CRITICAL_SECTION(self);
 return_value = select_devpoll_poll_impl(self, timeout_obj);
+Py_END_CRITICAL_SECTION();
 
 exit:
 return return_value;
@@ -434,7 +451,13 @@ select_devpoll_close_impl(devpollObject *self);
 static PyObject *
 select_devpoll_close(devpollObject *self, PyObject *Py_UNUSED(ignored))
 {
-return select_devpoll_close_impl(self);
+PyObject *return_value = NULL;
+
+Py_BEGIN_CRITICAL_SECTION(self);
+return_value = select_devpoll_close_impl(self);
+Py_END_CRITICAL_SECTION();
+
+return return_value;
 }
 
 #endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && 
defined(HAVE_SYS_DEVPOLL_H) */
@@ -456,7 +479,13 @@ select_devpoll_fileno_impl(devpollObject *self);
 static PyObject *
 select_devpoll_fileno(devpollObject *self, PyObject *Py_UNUSED(ignored))
 {
-return select_devpoll_fileno_impl(self);
+PyObject *return_value = NULL;
+
+Py_BEGIN_CRITICAL_SECTION(self);
+return_value = select_devpoll_fileno_impl(self);
+Py_END_CRITICAL_SECTION();
+
+return return_value;
 }
 
 #endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && 
defined(HAVE_SYS_DEVPOLL_H) */
@@ -615,7 +644,13 @@ select_epoll_close_impl(pyEpoll_Object *self);
 static PyObject *
 select_epoll_close(pyEpoll_Object *self, PyObject *Py_UNUSED(ignored))
 {
-  

[Python-checkins] [3.13] gh-121332: Make AST node constructor check _attributes instead of hardcoding attributes (GH-121334) (#121625)

2024-07-11 Thread JelleZijlstra
https://github.com/python/cpython/commit/38c4028dd9aeeeb1fe4ba1444307e3f06fc63aa0
commit: 38c4028dd9aeeeb1fe4ba1444307e3f06fc63aa0
branch: 3.13
author: Jelle Zijlstra 
committer: JelleZijlstra 
date: 2024-07-11T15:51:32Z
summary:

[3.13] gh-121332: Make AST node constructor check _attributes instead of 
hardcoding attributes (GH-121334) (#121625)

(cherry picked from commit 58e8cf2bb61f82df9eabd1209fe5e3d146e4c8cd)

files:
A Misc/NEWS.d/next/Library/2024-07-03-07-25-21.gh-issue-121332.Iz6FEq.rst
M Lib/test/test_ast.py
M Parser/asdl_c.py
M Python/Python-ast.c

diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py
index 93bd5dec6eac74..744cd238ea1407 100644
--- a/Lib/test/test_ast.py
+++ b/Lib/test/test_ast.py
@@ -3148,6 +3148,18 @@ class FieldsAndTypes(ast.AST):
 obj = FieldsAndTypes(a=1)
 self.assertEqual(obj.a, 1)
 
+def test_custom_attributes(self):
+class MyAttrs(ast.AST):
+_attributes = ("a", "b")
+
+obj = MyAttrs(a=1, b=2)
+self.assertEqual(obj.a, 1)
+self.assertEqual(obj.b, 2)
+
+with self.assertWarnsRegex(DeprecationWarning,
+   r"MyAttrs.__init__ got an unexpected 
keyword argument 'c'."):
+obj = MyAttrs(c=3)
+
 def test_fields_and_types_no_default(self):
 class FieldsAndTypesNoDefault(ast.AST):
 _fields = ('a',)
diff --git 
a/Misc/NEWS.d/next/Library/2024-07-03-07-25-21.gh-issue-121332.Iz6FEq.rst 
b/Misc/NEWS.d/next/Library/2024-07-03-07-25-21.gh-issue-121332.Iz6FEq.rst
new file mode 100644
index 00..480f27e05953a6
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-07-03-07-25-21.gh-issue-121332.Iz6FEq.rst
@@ -0,0 +1,4 @@
+Fix constructor of :mod:`ast` nodes with custom ``_attributes``. Previously,
+passing custom attributes would raise a :py:exc:`DeprecationWarning`. Passing
+arguments to the constructor that are not in ``_fields`` or ``_attributes``
+remains deprecated. Patch by Jelle Zijlstra.
diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py
index e338656a5b1eb9..3711cf1280f7bf 100755
--- a/Parser/asdl_c.py
+++ b/Parser/asdl_c.py
@@ -880,7 +880,7 @@ def visitModule(self, mod):
 
 Py_ssize_t i, numfields = 0;
 int res = -1;
-PyObject *key, *value, *fields, *remaining_fields = NULL;
+PyObject *key, *value, *fields, *attributes = NULL, *remaining_fields = 
NULL;
 if (PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self), state->_fields, 
&fields) < 0) {
 goto cleanup;
 }
@@ -947,22 +947,32 @@ def visitModule(self, mod):
 goto cleanup;
 }
 }
-else if (
-PyUnicode_CompareWithASCIIString(key, "lineno") != 0 &&
-PyUnicode_CompareWithASCIIString(key, "col_offset") != 0 &&
-PyUnicode_CompareWithASCIIString(key, "end_lineno") != 0 &&
-PyUnicode_CompareWithASCIIString(key, "end_col_offset") != 0
-) {
-if (PyErr_WarnFormat(
-PyExc_DeprecationWarning, 1,
-"%.400s.__init__ got an unexpected keyword argument '%U'. "
-"Support for arbitrary keyword arguments is deprecated "
-"and will be removed in Python 3.15.",
-Py_TYPE(self)->tp_name, key
-) < 0) {
+else {
+// Lazily initialize "attributes"
+if (attributes == NULL) {
+attributes = PyObject_GetAttr((PyObject*)Py_TYPE(self), 
state->_attributes);
+if (attributes == NULL) {
+res = -1;
+goto cleanup;
+}
+}
+int contains = PySequence_Contains(attributes, key);
+if (contains == -1) {
 res = -1;
 goto cleanup;
 }
+else if (contains == 0) {
+if (PyErr_WarnFormat(
+PyExc_DeprecationWarning, 1,
+"%.400s.__init__ got an unexpected keyword argument 
'%U'. "
+"Support for arbitrary keyword arguments is deprecated 
"
+"and will be removed in Python 3.15.",
+Py_TYPE(self)->tp_name, key
+) < 0) {
+res = -1;
+goto cleanup;
+}
+}
 }
 res = PyObject_SetAttr(self, key, value);
 if (res < 0) {
@@ -1045,6 +1055,7 @@ def visitModule(self, mod):
 Py_DECREF(field_types);
 }
   cleanup:
+Py_XDECREF(attributes);
 Py_XDECREF(fields);
 Py_XDECREF(remaining_fields);
 return res;
diff --git a/Python/Python-ast.c b/Python/Python-ast.c
index 01ffea1869350b..e38a145271589a 100644
--- a/Python/Python-ast.c
+++ b/Python/Python-ast.c
@@ -5079,7 +5079,7 @@ ast_type_init(PyObject *self

[Python-checkins] gh-117482: Fix Builtin Types Slot Wrappers (gh-121602)

2024-07-11 Thread ericsnowcurrently
https://github.com/python/cpython/commit/5250a031332eb9499d5fc190d7287642e5a144b9
commit: 5250a031332eb9499d5fc190d7287642e5a144b9
branch: main
author: Eric Snow 
committer: ericsnowcurrently 
date: 2024-07-11T20:20:14Z
summary:

gh-117482: Fix Builtin Types Slot Wrappers (gh-121602)

When builtin static types are initialized for a subinterpreter, various "tp" 
slots have already been inherited (for the main interpreter).  This was 
interfering with the logic in add_operators() (in Objects/typeobject.c), 
causing a wrapper to get created when it shouldn't.  This change fixes that by 
preserving the original data from the static type struct and checking that.

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-07-10-15-43-54.gh-issue-117482.5WYaXR.rst
M Include/internal/pycore_typeobject.h
M Lib/test/test_types.py
M Objects/typeobject.c

diff --git a/Include/internal/pycore_typeobject.h 
b/Include/internal/pycore_typeobject.h
index 32bd19d968b917..df6bfef715dd34 100644
--- a/Include/internal/pycore_typeobject.h
+++ b/Include/internal/pycore_typeobject.h
@@ -33,6 +33,7 @@ struct _types_runtime_state {
 struct {
 struct {
 PyTypeObject *type;
+PyTypeObject def;
 int64_t interp_count;
 } types[_Py_MAX_MANAGED_STATIC_TYPES];
 } managed_static;
diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py
index fbca198aab5180..38a98828085e2f 100644
--- a/Lib/test/test_types.py
+++ b/Lib/test/test_types.py
@@ -10,6 +10,7 @@
 import pickle
 import locale
 import sys
+import textwrap
 import types
 import unittest.mock
 import weakref
@@ -2345,5 +2346,40 @@ def ex(a, /, b, *, c):
 )
 
 
+class SubinterpreterTests(unittest.TestCase):
+
+@classmethod
+def setUpClass(cls):
+global interpreters
+try:
+from test.support import interpreters
+except ModuleNotFoundError:
+raise unittest.SkipTest('subinterpreters required')
+import test.support.interpreters.channels
+
+@cpython_only
+def test_slot_wrappers(self):
+rch, sch = interpreters.channels.create()
+
+# For now it's sufficient to check int.__str__.
+# See https://github.com/python/cpython/issues/117482
+# and https://github.com/python/cpython/pull/117660.
+script = textwrap.dedent('''
+text = repr(int.__str__)
+sch.send_nowait(text)
+''')
+
+exec(script)
+expected = rch.recv()
+
+interp = interpreters.create()
+interp.exec('from test.support import interpreters')
+interp.prepare_main(sch=sch)
+interp.exec(script)
+results = rch.recv()
+
+self.assertEqual(results, expected)
+
+
 if __name__ == '__main__':
 unittest.main()
diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2024-07-10-15-43-54.gh-issue-117482.5WYaXR.rst b/Misc/NEWS.d/next/Core 
and Builtins/2024-07-10-15-43-54.gh-issue-117482.5WYaXR.rst
new file mode 100644
index 00..ec1e7327b77f19
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2024-07-10-15-43-54.gh-issue-117482.5WYaXR.rst 
@@ -0,0 +1,2 @@
+Unexpected slot wrappers are no longer created for builtin static types in
+subinterpreters.
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 587632cecfba9d..7d01b680605a38 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -314,6 +314,16 @@ managed_static_type_state_clear(PyInterpreterState 
*interp, PyTypeObject *self,
 }
 }
 
+static PyTypeObject *
+managed_static_type_get_def(PyTypeObject *self, int isbuiltin)
+{
+size_t index = managed_static_type_index_get(self);
+size_t full_index = isbuiltin
+? index
+: index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES;
+return &_PyRuntime.types.managed_static.types[full_index].def;
+}
+
 // Also see _PyStaticType_InitBuiltin() and _PyStaticType_FiniBuiltin().
 
 /* end static builtin helpers */
@@ -5840,7 +5850,6 @@ fini_static_type(PyInterpreterState *interp, PyTypeObject 
*type,
 
 _PyStaticType_ClearWeakRefs(interp, type);
 managed_static_type_state_clear(interp, type, isbuiltin, final);
-/* We leave _Py_TPFLAGS_STATIC_BUILTIN set on tp_flags. */
 }
 
 void
@@ -7850,7 +7859,7 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
 return 0;
 }
 
-static int add_operators(PyTypeObject *);
+static int add_operators(PyTypeObject *, PyTypeObject *);
 static int add_tp_new_wrapper(PyTypeObject *type);
 
 #define COLLECTION_FLAGS (Py_TPFLAGS_SEQUENCE | Py_TPFLAGS_MAPPING)
@@ -8015,10 +8024,10 @@ type_dict_set_doc(PyTypeObject *type)
 
 
 static int
-type_ready_fill_dict(PyTypeObject *type)
+type_ready_fill_dict(PyTypeObject *type, PyTypeObject *def)
 {
 /* Add type-specific descriptors to tp_dict */
-if (add_operators(type) < 0) {
+if (add_operators(type, def) < 0) {
 return -1;
 }
 if (type_add_methods(type) < 0) {
@@ -8337,7 +8346,7 @@ type_ready_post_checks(PyTypeObject *type)

[Python-checkins] gh-121103: Put free-threaded libraries in `lib/python3.14t` (#121293)

2024-07-11 Thread colesbury
https://github.com/python/cpython/commit/e8c91d90ba8fab410a27fad4f709cc73f6ffcbf4
commit: e8c91d90ba8fab410a27fad4f709cc73f6ffcbf4
branch: main
author: Sam Gross 
committer: colesbury 
date: 2024-07-11T16:21:37-04:00
summary:

gh-121103: Put free-threaded libraries in `lib/python3.14t` (#121293)

On POSIX systems, excluding macOS framework installs, the lib directory
for the free-threaded build now includes a "t" suffix to avoid conflicts
with a co-located default build installation.

files:
A Misc/NEWS.d/next/Build/2024-07-02-20-16-09.gh-issue-121103.TMef9j.rst
M Lib/site.py
M Lib/sysconfig/__init__.py
M Lib/test/test_embed.py
M Lib/test/test_getpath.py
M Lib/test/test_site.py
M Lib/test/test_sysconfig.py
M Lib/test/test_venv.py
M Makefile.pre.in
M Modules/getpath.c
M Modules/getpath.py
M configure
M configure.ac

diff --git a/Lib/site.py b/Lib/site.py
index daa56e158949db..460269433f021c 100644
--- a/Lib/site.py
+++ b/Lib/site.py
@@ -312,6 +312,10 @@ def joinuser(*args):
 # Same to sysconfig.get_path('purelib', os.name+'_user')
 def _get_path(userbase):
 version = sys.version_info
+if hasattr(sys, 'abiflags') and 't' in sys.abiflags:
+abi_thread = 't'
+else:
+abi_thread = ''
 
 implementation = _get_implementation()
 implementation_lower = implementation.lower()
@@ -322,7 +326,7 @@ def _get_path(userbase):
 if sys.platform == 'darwin' and sys._framework:
 return f'{userbase}/lib/{implementation_lower}/site-packages'
 
-return f'{userbase}/lib/python{version[0]}.{version[1]}/site-packages'
+return 
f'{userbase}/lib/python{version[0]}.{version[1]}{abi_thread}/site-packages'
 
 
 def getuserbase():
@@ -390,6 +394,10 @@ def getsitepackages(prefixes=None):
 
 implementation = _get_implementation().lower()
 ver = sys.version_info
+if hasattr(sys, 'abiflags') and 't' in sys.abiflags:
+abi_thread = 't'
+else:
+abi_thread = ''
 if os.sep == '/':
 libdirs = [sys.platlibdir]
 if sys.platlibdir != "lib":
@@ -397,7 +405,7 @@ def getsitepackages(prefixes=None):
 
 for libdir in libdirs:
 path = os.path.join(prefix, libdir,
-f"{implementation}{ver[0]}.{ver[1]}",
+
f"{implementation}{ver[0]}.{ver[1]}{abi_thread}",
 "site-packages")
 sitepackages.append(path)
 else:
diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py
index 98a14e5d3a3187..83e057c177f8c0 100644
--- a/Lib/sysconfig/__init__.py
+++ b/Lib/sysconfig/__init__.py
@@ -27,10 +27,10 @@
 
 _INSTALL_SCHEMES = {
 'posix_prefix': {
-'stdlib': 
'{installed_base}/{platlibdir}/{implementation_lower}{py_version_short}',
-'platstdlib': 
'{platbase}/{platlibdir}/{implementation_lower}{py_version_short}',
-'purelib': 
'{base}/lib/{implementation_lower}{py_version_short}/site-packages',
-'platlib': 
'{platbase}/{platlibdir}/{implementation_lower}{py_version_short}/site-packages',
+'stdlib': 
'{installed_base}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}',
+'platstdlib': 
'{platbase}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}',
+'purelib': 
'{base}/lib/{implementation_lower}{py_version_short}{abi_thread}/site-packages',
+'platlib': 
'{platbase}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}/site-packages',
 'include':
 
'{installed_base}/include/{implementation_lower}{py_version_short}{abiflags}',
 'platinclude':
@@ -77,10 +77,10 @@
 # Downstream distributors who patch posix_prefix/nt scheme are encouraged 
to
 # leave the following schemes unchanged
 'posix_venv': {
-'stdlib': 
'{installed_base}/{platlibdir}/{implementation_lower}{py_version_short}',
-'platstdlib': 
'{platbase}/{platlibdir}/{implementation_lower}{py_version_short}',
-'purelib': 
'{base}/lib/{implementation_lower}{py_version_short}/site-packages',
-'platlib': 
'{platbase}/{platlibdir}/{implementation_lower}{py_version_short}/site-packages',
+'stdlib': 
'{installed_base}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}',
+'platstdlib': 
'{platbase}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}',
+'purelib': 
'{base}/lib/{implementation_lower}{py_version_short}{abi_thread}/site-packages',
+'platlib': 
'{platbase}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}/site-packages',
 'include':
 
'{installed_base}/include/{implementation_lower}{py_version_short}{abiflags}',
 'platinclude':
@@ -148,11 +148,11 @@ def joinuser(*args):
 'data': '{userbase}',
 },
 'posix_user': {
-'stdlib': 
'{userbase}/{platlibdir}/{implementation_lower}{py_version_short}

[Python-checkins] [3.13] gh-117482: Fix Builtin Types Slot Wrappers (gh-121630)

2024-07-11 Thread ericsnowcurrently
https://github.com/python/cpython/commit/c6dbfbbe3c24cf2dd6a589904383f28cd1a1f4db
commit: c6dbfbbe3c24cf2dd6a589904383f28cd1a1f4db
branch: 3.13
author: Miss Islington (bot) <[email protected]>
committer: ericsnowcurrently 
date: 2024-07-11T20:47:38Z
summary:

[3.13] gh-117482: Fix Builtin Types Slot Wrappers (gh-121630)

When builtin static types are initialized for a subinterpreter, various "tp" 
slots have already been inherited (for the main interpreter).  This was 
interfering with the logic in add_operators() (in Objects/typeobject.c), 
causing a wrapper to get created when it shouldn't.  This change fixes that by 
preserving the original data from the static type struct and checking that.

(cherry picked from commit 5250a031332eb9499d5fc190d7287642e5a144b9, AKA 
gh-121602)

Co-authored-by: Eric Snow 

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-07-10-15-43-54.gh-issue-117482.5WYaXR.rst
M Include/internal/pycore_typeobject.h
M Lib/test/test_types.py
M Objects/typeobject.c

diff --git a/Include/internal/pycore_typeobject.h 
b/Include/internal/pycore_typeobject.h
index 05f125f928ca68..124efccb48bebd 100644
--- a/Include/internal/pycore_typeobject.h
+++ b/Include/internal/pycore_typeobject.h
@@ -33,6 +33,7 @@ struct _types_runtime_state {
 struct {
 struct {
 PyTypeObject *type;
+PyTypeObject def;
 int64_t interp_count;
 } types[_Py_MAX_MANAGED_STATIC_TYPES];
 } managed_static;
diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py
index fbca198aab5180..38a98828085e2f 100644
--- a/Lib/test/test_types.py
+++ b/Lib/test/test_types.py
@@ -10,6 +10,7 @@
 import pickle
 import locale
 import sys
+import textwrap
 import types
 import unittest.mock
 import weakref
@@ -2345,5 +2346,40 @@ def ex(a, /, b, *, c):
 )
 
 
+class SubinterpreterTests(unittest.TestCase):
+
+@classmethod
+def setUpClass(cls):
+global interpreters
+try:
+from test.support import interpreters
+except ModuleNotFoundError:
+raise unittest.SkipTest('subinterpreters required')
+import test.support.interpreters.channels
+
+@cpython_only
+def test_slot_wrappers(self):
+rch, sch = interpreters.channels.create()
+
+# For now it's sufficient to check int.__str__.
+# See https://github.com/python/cpython/issues/117482
+# and https://github.com/python/cpython/pull/117660.
+script = textwrap.dedent('''
+text = repr(int.__str__)
+sch.send_nowait(text)
+''')
+
+exec(script)
+expected = rch.recv()
+
+interp = interpreters.create()
+interp.exec('from test.support import interpreters')
+interp.prepare_main(sch=sch)
+interp.exec(script)
+results = rch.recv()
+
+self.assertEqual(results, expected)
+
+
 if __name__ == '__main__':
 unittest.main()
diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2024-07-10-15-43-54.gh-issue-117482.5WYaXR.rst b/Misc/NEWS.d/next/Core 
and Builtins/2024-07-10-15-43-54.gh-issue-117482.5WYaXR.rst
new file mode 100644
index 00..ec1e7327b77f19
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2024-07-10-15-43-54.gh-issue-117482.5WYaXR.rst 
@@ -0,0 +1,2 @@
+Unexpected slot wrappers are no longer created for builtin static types in
+subinterpreters.
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 4fc241e1190fc1..edcdc6e9c4f5c2 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -314,6 +314,16 @@ managed_static_type_state_clear(PyInterpreterState 
*interp, PyTypeObject *self,
 }
 }
 
+static PyTypeObject *
+managed_static_type_get_def(PyTypeObject *self, int isbuiltin)
+{
+size_t index = managed_static_type_index_get(self);
+size_t full_index = isbuiltin
+? index
+: index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES;
+return &_PyRuntime.types.managed_static.types[full_index].def;
+}
+
 // Also see _PyStaticType_InitBuiltin() and _PyStaticType_FiniBuiltin().
 
 /* end static builtin helpers */
@@ -5668,7 +5678,6 @@ fini_static_type(PyInterpreterState *interp, PyTypeObject 
*type,
 
 _PyStaticType_ClearWeakRefs(interp, type);
 managed_static_type_state_clear(interp, type, isbuiltin, final);
-/* We leave _Py_TPFLAGS_STATIC_BUILTIN set on tp_flags. */
 }
 
 void
@@ -7671,7 +7680,7 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
 return 0;
 }
 
-static int add_operators(PyTypeObject *);
+static int add_operators(PyTypeObject *, PyTypeObject *);
 static int add_tp_new_wrapper(PyTypeObject *type);
 
 #define COLLECTION_FLAGS (Py_TPFLAGS_SEQUENCE | Py_TPFLAGS_MAPPING)
@@ -7836,10 +7845,10 @@ type_dict_set_doc(PyTypeObject *type)
 
 
 static int
-type_ready_fill_dict(PyTypeObject *type)
+type_ready_fill_dict(PyTypeObject *type, PyTypeObject *def)
 {
 /* Add type-specific descriptors to tp_dict */
-if (add_operators(ty

[Python-checkins] [3.13] gh-121103: Put free-threaded libraries in `lib/python3.14t` (GH-121293) (#121631)

2024-07-11 Thread colesbury
https://github.com/python/cpython/commit/35f7155bc39b8e5212b90a2ee96cb107b51e0e83
commit: 35f7155bc39b8e5212b90a2ee96cb107b51e0e83
branch: 3.13
author: Miss Islington (bot) <[email protected]>
committer: colesbury 
date: 2024-07-11T21:00:28Z
summary:

[3.13] gh-121103: Put free-threaded libraries in `lib/python3.14t` (GH-121293) 
(#121631)

On POSIX systems, excluding macOS framework installs, the lib directory
for the free-threaded build now includes a "t" suffix to avoid conflicts
with a co-located default build installation.
(cherry picked from commit e8c91d90ba8fab410a27fad4f709cc73f6ffcbf4)

Co-authored-by: Sam Gross 

files:
A Misc/NEWS.d/next/Build/2024-07-02-20-16-09.gh-issue-121103.TMef9j.rst
M Lib/site.py
M Lib/sysconfig/__init__.py
M Lib/test/test_embed.py
M Lib/test/test_getpath.py
M Lib/test/test_site.py
M Lib/test/test_sysconfig.py
M Lib/test/test_venv.py
M Makefile.pre.in
M Modules/getpath.c
M Modules/getpath.py
M configure
M configure.ac

diff --git a/Lib/site.py b/Lib/site.py
index 95c7ebf2fdf146..650fa2b01835f9 100644
--- a/Lib/site.py
+++ b/Lib/site.py
@@ -312,6 +312,10 @@ def joinuser(*args):
 # Same to sysconfig.get_path('purelib', os.name+'_user')
 def _get_path(userbase):
 version = sys.version_info
+if hasattr(sys, 'abiflags') and 't' in sys.abiflags:
+abi_thread = 't'
+else:
+abi_thread = ''
 
 implementation = _get_implementation()
 implementation_lower = implementation.lower()
@@ -322,7 +326,7 @@ def _get_path(userbase):
 if sys.platform == 'darwin' and sys._framework:
 return f'{userbase}/lib/{implementation_lower}/site-packages'
 
-return f'{userbase}/lib/python{version[0]}.{version[1]}/site-packages'
+return 
f'{userbase}/lib/python{version[0]}.{version[1]}{abi_thread}/site-packages'
 
 
 def getuserbase():
@@ -390,6 +394,10 @@ def getsitepackages(prefixes=None):
 
 implementation = _get_implementation().lower()
 ver = sys.version_info
+if hasattr(sys, 'abiflags') and 't' in sys.abiflags:
+abi_thread = 't'
+else:
+abi_thread = ''
 if os.sep == '/':
 libdirs = [sys.platlibdir]
 if sys.platlibdir != "lib":
@@ -397,7 +405,7 @@ def getsitepackages(prefixes=None):
 
 for libdir in libdirs:
 path = os.path.join(prefix, libdir,
-f"{implementation}{ver[0]}.{ver[1]}",
+
f"{implementation}{ver[0]}.{ver[1]}{abi_thread}",
 "site-packages")
 sitepackages.append(path)
 else:
diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py
index 98a14e5d3a3187..83e057c177f8c0 100644
--- a/Lib/sysconfig/__init__.py
+++ b/Lib/sysconfig/__init__.py
@@ -27,10 +27,10 @@
 
 _INSTALL_SCHEMES = {
 'posix_prefix': {
-'stdlib': 
'{installed_base}/{platlibdir}/{implementation_lower}{py_version_short}',
-'platstdlib': 
'{platbase}/{platlibdir}/{implementation_lower}{py_version_short}',
-'purelib': 
'{base}/lib/{implementation_lower}{py_version_short}/site-packages',
-'platlib': 
'{platbase}/{platlibdir}/{implementation_lower}{py_version_short}/site-packages',
+'stdlib': 
'{installed_base}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}',
+'platstdlib': 
'{platbase}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}',
+'purelib': 
'{base}/lib/{implementation_lower}{py_version_short}{abi_thread}/site-packages',
+'platlib': 
'{platbase}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}/site-packages',
 'include':
 
'{installed_base}/include/{implementation_lower}{py_version_short}{abiflags}',
 'platinclude':
@@ -77,10 +77,10 @@
 # Downstream distributors who patch posix_prefix/nt scheme are encouraged 
to
 # leave the following schemes unchanged
 'posix_venv': {
-'stdlib': 
'{installed_base}/{platlibdir}/{implementation_lower}{py_version_short}',
-'platstdlib': 
'{platbase}/{platlibdir}/{implementation_lower}{py_version_short}',
-'purelib': 
'{base}/lib/{implementation_lower}{py_version_short}/site-packages',
-'platlib': 
'{platbase}/{platlibdir}/{implementation_lower}{py_version_short}/site-packages',
+'stdlib': 
'{installed_base}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}',
+'platstdlib': 
'{platbase}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}',
+'purelib': 
'{base}/lib/{implementation_lower}{py_version_short}{abi_thread}/site-packages',
+'platlib': 
'{platbase}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}/site-packages',
 'include':
 
'{installed_base}/include/{implementation_lower}{py_version_short}{abiflags}',
 'platinclude':
@@ -148,11 +148,11 @@ def joinuser(

[Python-checkins] [3.12] gh-117482: Fix Builtin Types Slot Wrappers (gh-121632)

2024-07-11 Thread ericsnowcurrently
https://github.com/python/cpython/commit/0ec761a96a80f4b84b98aad5e784e4ac8f385c3f
commit: 0ec761a96a80f4b84b98aad5e784e4ac8f385c3f
branch: 3.12
author: Eric Snow 
committer: ericsnowcurrently 
date: 2024-07-11T21:20:08Z
summary:

[3.12] gh-117482: Fix Builtin Types Slot Wrappers (gh-121632)

When builtin static types are initialized for a subinterpreter, various "tp" 
slots have already been inherited (for the main interpreter).  This was 
interfering with the logic in add_operators() (in Objects/typeobject.c), 
causing a wrapper to get created when it shouldn't.  This change fixes that by 
preserving the original data from the static type struct and checking that.

(cherry picked from commit 5250a031332eb9499d5fc190d7287642e5a144b9, AKA 
gh-121602)

Co-authored-by: Eric Snow 

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-07-10-15-43-54.gh-issue-117482.5WYaXR.rst
M Lib/test/test_types.py
M Objects/typeobject.c
M Tools/c-analyzer/cpython/globals-to-fix.tsv

diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py
index 5ffe4085f09548..ca41c76649ca99 100644
--- a/Lib/test/test_types.py
+++ b/Lib/test/test_types.py
@@ -9,6 +9,7 @@
 import pickle
 import locale
 import sys
+import textwrap
 import types
 import unittest.mock
 import weakref
@@ -2252,5 +2253,39 @@ def coro():
 'close', 'throw'}))
 
 
+class SubinterpreterTests(unittest.TestCase):
+
+@classmethod
+def setUpClass(cls):
+global interpreters
+try:
+from test.support import interpreters
+except ModuleNotFoundError:
+raise unittest.SkipTest('subinterpreters required')
+
+@cpython_only
+def test_slot_wrappers(self):
+rch, sch = interpreters.create_channel()
+
+# For now it's sufficient to check int.__str__.
+# See https://github.com/python/cpython/issues/117482
+# and https://github.com/python/cpython/pull/117660.
+script = textwrap.dedent(f'''
+text = repr(int.__str__)
+sch = interpreters.SendChannel({sch.id})
+sch.send_nowait(text)
+''')
+
+exec(script)
+expected = rch.recv()
+
+interp = interpreters.create()
+interp.run('from test.support import interpreters')
+interp.run(script)
+results = rch.recv()
+
+self.assertEqual(results, expected)
+
+
 if __name__ == '__main__':
 unittest.main()
diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2024-07-10-15-43-54.gh-issue-117482.5WYaXR.rst b/Misc/NEWS.d/next/Core 
and Builtins/2024-07-10-15-43-54.gh-issue-117482.5WYaXR.rst
new file mode 100644
index 00..ec1e7327b77f19
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2024-07-10-15-43-54.gh-issue-117482.5WYaXR.rst 
@@ -0,0 +1,2 @@
+Unexpected slot wrappers are no longer created for builtin static types in
+subinterpreters.
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 9d05798e1715b4..1436b225f375a0 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -116,6 +116,18 @@ static_builtin_index_clear(PyTypeObject *self)
 self->tp_subclasses = NULL;
 }
 
+
+/* In 3.13+ this is stored in _PyRuntimeState. */
+static PyTypeObject static_type_defs[_Py_MAX_STATIC_BUILTIN_TYPES];
+
+static inline PyTypeObject *
+static_builtin_get_def(PyTypeObject *type)
+{
+size_t index = static_builtin_index_get(type);
+return &static_type_defs[index];
+}
+
+
 static inline static_builtin_state *
 static_builtin_state_get(PyInterpreterState *interp, PyTypeObject *self)
 {
@@ -6982,7 +6994,7 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
 return 0;
 }
 
-static int add_operators(PyTypeObject *);
+static int add_operators(PyTypeObject *, PyTypeObject *);
 static int add_tp_new_wrapper(PyTypeObject *type);
 
 #define COLLECTION_FLAGS (Py_TPFLAGS_SEQUENCE | Py_TPFLAGS_MAPPING)
@@ -7147,10 +7159,10 @@ type_dict_set_doc(PyTypeObject *type)
 
 
 static int
-type_ready_fill_dict(PyTypeObject *type)
+type_ready_fill_dict(PyTypeObject *type, PyTypeObject *def)
 {
 /* Add type-specific descriptors to tp_dict */
-if (add_operators(type) < 0) {
+if (add_operators(type, def) < 0) {
 return -1;
 }
 if (type_add_methods(type) < 0) {
@@ -7462,7 +7474,7 @@ type_ready_post_checks(PyTypeObject *type)
 
 
 static int
-type_ready(PyTypeObject *type, int rerunbuiltin)
+type_ready(PyTypeObject *type, PyTypeObject *def, int rerunbuiltin)
 {
 _PyObject_ASSERT((PyObject *)type, !is_readying(type));
 start_readying(type);
@@ -7499,7 +7511,7 @@ type_ready(PyTypeObject *type, int rerunbuiltin)
 if (type_ready_set_new(type, rerunbuiltin) < 0) {
 goto error;
 }
-if (type_ready_fill_dict(type) < 0) {
+if (type_ready_fill_dict(type, def) < 0) {
 goto error;
 }
 if (!rerunbuiltin) {
@@ -7551,7 +7563,7 @@ PyType_Ready(PyTypeObject *type)
 type->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
 }
 
-return type_ready(type, 0);
+return typ