Skip to content

Commit 0e2ac21

Browse files
authored
bpo-39573: Convert Py_TYPE() and Py_SIZE() back to macros (GH-23366)
This change partically reverts commit ad3252b and the commit fe2978b. Many third party C extension modules rely on the ability of using Py_TYPE() to set an object type: "Py_TYPE(obj) = type;" or to set an object type using: "Py_SIZE(obj) = size;".
1 parent 2156d96 commit 0e2ac21

File tree

5 files changed

+35
-26
lines changed

5 files changed

+35
-26
lines changed

Doc/c-api/structures.rst

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,7 @@ the definition of all other Python objects.
6868
6969
Return a :term:`borrowed reference`.
7070
71-
.. versionchanged:: 3.10
72-
:c:func:`Py_TYPE()` is changed to the inline static function.
73-
Use :c:func:`Py_SET_TYPE()` to set an object type.
71+
The :c:func:`Py_SET_TYPE` function must be used to set an object type.
7472
7573
7674
.. c:function:: int Py_IS_TYPE(PyObject *o, PyTypeObject *type)
@@ -108,9 +106,7 @@ the definition of all other Python objects.
108106
109107
Get the size of the Python object *o*.
110108
111-
.. versionchanged:: 3.10
112-
:c:func:`Py_SIZE()` is changed to the inline static function.
113-
Use :c:func:`Py_SET_SIZE()` to set an object size.
109+
The :c:func:`Py_SET_SIZE` function must be used to set an object size.
114110
115111
116112
.. c:function:: void Py_SET_SIZE(PyVarObject *o, Py_ssize_t size)

Doc/whatsnew/3.10.rst

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -489,17 +489,6 @@ Porting to Python 3.10
489489
<arg-parsing>` and the :pep:`353`.
490490
(Contributed by Victor Stinner in :issue:`40943`.)
491491

492-
* Since :c:func:`Py_TYPE()` is changed to the inline static function,
493-
``Py_TYPE(obj) = new_type`` must be replaced with ``Py_SET_TYPE(obj, new_type)``:
494-
see :c:func:`Py_SET_TYPE()` (available since Python 3.9). For backward
495-
compatibility, this macro can be used::
496-
497-
#if PY_VERSION_HEX < 0x030900A4
498-
# define Py_SET_TYPE(obj, type) ((Py_TYPE(obj) = (type)), (void)0)
499-
#endif
500-
501-
(Contributed by Dong-hee Na in :issue:`39573`.)
502-
503492
* Since :c:func:`Py_REFCNT()` is changed to the inline static function,
504493
``Py_REFCNT(obj) = new_refcnt`` must be replaced with ``Py_SET_REFCNT(obj, new_refcnt)``:
505494
see :c:func:`Py_SET_REFCNT()` (available since Python 3.9). For backward

Include/object.h

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -128,16 +128,11 @@ static inline Py_ssize_t _Py_REFCNT(const PyObject *ob) {
128128
#define Py_REFCNT(ob) _Py_REFCNT(_PyObject_CAST_CONST(ob))
129129

130130

131-
static inline Py_ssize_t _Py_SIZE(const PyVarObject *ob) {
132-
return ob->ob_size;
133-
}
134-
#define Py_SIZE(ob) _Py_SIZE(_PyVarObject_CAST_CONST(ob))
135-
131+
// bpo-39573: The Py_SET_TYPE() function must be used to set an object type.
132+
#define Py_TYPE(ob) (_PyObject_CAST(ob)->ob_type)
136133

137-
static inline PyTypeObject* _Py_TYPE(const PyObject *ob) {
138-
return ob->ob_type;
139-
}
140-
#define Py_TYPE(ob) _Py_TYPE(_PyObject_CAST_CONST(ob))
134+
// bpo-39573: The Py_SET_SIZE() function must be used to set an object size.
135+
#define Py_SIZE(ob) (_PyVarObject_CAST(ob)->ob_size)
141136

142137

143138
static inline int _Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Convert :c:func:`Py_TYPE` and :c:func:`Py_SIZE` back to macros to allow
2+
using them as an l-value. Many third party C extension modules rely on the
3+
ability of using Py_TYPE() and Py_SIZE() to set an object type and size:
4+
``Py_TYPE(obj) = type;`` and ``Py_SIZE(obj) = size;``.

Modules/_testcapimodule.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5612,6 +5612,30 @@ pynumber_tobase(PyObject *module, PyObject *args)
56125612

56135613
static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *);
56145614

5615+
5616+
static PyObject*
5617+
test_set_type_size(PyObject* self, PyObject* ignored)
5618+
{
5619+
PyObject *obj = PyList_New(0);
5620+
if (obj == NULL) {
5621+
return NULL;
5622+
}
5623+
5624+
// Ensure that following tests don't modify the object,
5625+
// to ensure that Py_DECREF() will not crash.
5626+
assert(Py_TYPE(obj) == &PyList_Type);
5627+
assert(Py_SIZE(obj) == 0);
5628+
5629+
// bpo-39573: Check that Py_TYPE() and Py_SIZE() can be used
5630+
// as l-values to set an object type and size.
5631+
Py_TYPE(obj) = &PyList_Type;
5632+
Py_SIZE(obj) = 0;
5633+
5634+
Py_DECREF(obj);
5635+
Py_RETURN_NONE;
5636+
}
5637+
5638+
56155639
static PyMethodDef TestMethods[] = {
56165640
{"raise_exception", raise_exception, METH_VARARGS},
56175641
{"raise_memoryerror", raise_memoryerror, METH_NOARGS},
@@ -5883,6 +5907,7 @@ static PyMethodDef TestMethods[] = {
58835907
{"meth_fastcall_keywords", (PyCFunction)(void(*)(void))meth_fastcall_keywords, METH_FASTCALL|METH_KEYWORDS},
58845908
{"pynumber_tobase", pynumber_tobase, METH_VARARGS},
58855909
{"without_gc", without_gc, METH_O},
5910+
{"test_set_type_size", test_set_type_size, METH_NOARGS},
58865911
{NULL, NULL} /* sentinel */
58875912
};
58885913

0 commit comments

Comments
 (0)