diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 7fb002cd80369b..9a61ddc39a353f 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -490,6 +490,8 @@ function,PyObject_Calloc,3.7,, function,PyObject_CheckBuffer,3.11,, function,PyObject_ClearWeakRefs,3.2,, function,PyObject_CopyData,3.11,, +function,PyObject_DelAttr,3.13,, +function,PyObject_DelAttrString,3.13,, function,PyObject_DelItem,3.2,, function,PyObject_DelItemString,3.2,, function,PyObject_Dir,3.2,, diff --git a/Include/abstract.h b/Include/abstract.h index 016ace9bc89e96..c84d2c704e9605 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -80,7 +80,7 @@ extern "C" { This is the equivalent of the Python statement o.attr_name=v. */ -/* Implemented as a macro: +/* Implemented elsewhere: int PyObject_DelAttrString(PyObject *o, const char *attr_name); @@ -88,17 +88,15 @@ extern "C" { -1 on failure. This is the equivalent of the Python statement: del o.attr_name. */ -#define PyObject_DelAttrString(O, A) PyObject_SetAttrString((O), (A), NULL) -/* Implemented as a macro: +/* Implemented elsewhere: int PyObject_DelAttr(PyObject *o, PyObject *attr_name); Delete attribute named attr_name, for object o. Returns -1 on failure. This is the equivalent of the Python statement: del o.attr_name. */ -#define PyObject_DelAttr(O, A) PyObject_SetAttr((O), (A), NULL) /* Implemented elsewhere: diff --git a/Include/object.h b/Include/object.h index 3ef64511399c66..dccab07e5f2c6f 100644 --- a/Include/object.h +++ b/Include/object.h @@ -391,9 +391,11 @@ PyAPI_FUNC(PyObject *) PyObject_RichCompare(PyObject *, PyObject *, int); PyAPI_FUNC(int) PyObject_RichCompareBool(PyObject *, PyObject *, int); PyAPI_FUNC(PyObject *) PyObject_GetAttrString(PyObject *, const char *); PyAPI_FUNC(int) PyObject_SetAttrString(PyObject *, const char *, PyObject *); +PyAPI_FUNC(int) PyObject_DelAttrString(PyObject *v, const char *name); PyAPI_FUNC(int) PyObject_HasAttrString(PyObject *, const char *); PyAPI_FUNC(PyObject *) PyObject_GetAttr(PyObject *, PyObject *); PyAPI_FUNC(int) PyObject_SetAttr(PyObject *, PyObject *, PyObject *); +PyAPI_FUNC(int) PyObject_DelAttr(PyObject *v, PyObject *name); PyAPI_FUNC(int) PyObject_HasAttr(PyObject *, PyObject *); PyAPI_FUNC(PyObject *) PyObject_SelfIter(PyObject *); PyAPI_FUNC(PyObject *) PyObject_GenericGetAttr(PyObject *, PyObject *); diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py index 038c978e7bbd02..20bc2624c81361 100644 --- a/Lib/test/test_stable_abi_ctypes.py +++ b/Lib/test/test_stable_abi_ctypes.py @@ -509,6 +509,8 @@ def test_windows_feature_macros(self): "PyObject_CheckReadBuffer", "PyObject_ClearWeakRefs", "PyObject_CopyData", + "PyObject_DelAttr", + "PyObject_DelAttrString", "PyObject_DelItem", "PyObject_DelItemString", "PyObject_Dir", diff --git a/Misc/NEWS.d/next/C API/2023-07-11-01-07-39.gh-issue-106572.y1b35X.rst b/Misc/NEWS.d/next/C API/2023-07-11-01-07-39.gh-issue-106572.y1b35X.rst new file mode 100644 index 00000000000000..140e9fe7b9abf6 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2023-07-11-01-07-39.gh-issue-106572.y1b35X.rst @@ -0,0 +1,2 @@ +Convert :c:func:`PyObject_DelAttr` and :c:func:`PyObject_DelAttrString` +macros to functions. Patch by Victor Stinner. diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index bc7259f11816f3..c61fedf8390e28 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -2432,3 +2432,7 @@ added = '3.13' [function.PyWeakref_GetRef] added = '3.13' +[function.PyObject_DelAttr] + added = '3.13' +[function.PyObject_DelAttrString] + added = '3.13' diff --git a/Objects/object.c b/Objects/object.c index c27b13e9e0c31a..540ba5d07427cd 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -942,6 +942,12 @@ PyObject_SetAttrString(PyObject *v, const char *name, PyObject *w) return res; } +int +PyObject_DelAttrString(PyObject *v, const char *name) +{ + return PyObject_SetAttrString(v, name, NULL); +} + int _PyObject_IsAbstract(PyObject *obj) { @@ -1185,6 +1191,12 @@ PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value) return -1; } +int +PyObject_DelAttr(PyObject *v, PyObject *name) +{ + return PyObject_SetAttr(v, name, NULL); +} + PyObject ** _PyObject_ComputedDictPointer(PyObject *obj) { diff --git a/PC/python3dll.c b/PC/python3dll.c index 65bdf326ffbc7f..a7173911c7c1e8 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -447,6 +447,8 @@ EXPORT_FUNC(PyObject_CheckBuffer) EXPORT_FUNC(PyObject_CheckReadBuffer) EXPORT_FUNC(PyObject_ClearWeakRefs) EXPORT_FUNC(PyObject_CopyData) +EXPORT_FUNC(PyObject_DelAttr) +EXPORT_FUNC(PyObject_DelAttrString) EXPORT_FUNC(PyObject_DelItem) EXPORT_FUNC(PyObject_DelItemString) EXPORT_FUNC(PyObject_Dir) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 49efafc07f4245..20a86fc6f583d3 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1567,8 +1567,9 @@ static PyObject * builtin_delattr_impl(PyObject *module, PyObject *obj, PyObject *name) /*[clinic end generated code: output=85134bc58dff79fa input=164865623abe7216]*/ { - if (PyObject_SetAttr(obj, name, (PyObject *)NULL) != 0) + if (PyObject_DelAttr(obj, name) < 0) { return NULL; + } Py_RETURN_NONE; } diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 0848bbfd203ec4..88444293aa228b 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1240,7 +1240,7 @@ dummy_func( inst(DELETE_ATTR, (owner --)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - int err = PyObject_SetAttr(owner, name, (PyObject *)NULL); + int err = PyObject_DelAttr(owner, name); DECREF_INPUTS(); ERROR_IF(err, error); } diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 0ef752249ccb76..030d7ac15ef066 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -1018,7 +1018,7 @@ PyObject *owner = stack_pointer[-1]; #line 1242 "Python/bytecodes.c" PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - int err = PyObject_SetAttr(owner, name, (PyObject *)NULL); + int err = PyObject_DelAttr(owner, name); #line 1023 "Python/executor_cases.c.h" Py_DECREF(owner); #line 1245 "Python/bytecodes.c" @@ -1642,7 +1642,7 @@ PyObject *owner = stack_pointer[-1]; PyObject *res2 = NULL; PyObject *res; - #line 1815 "Python/bytecodes.c" + #line 1817 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyAttrCache *cache = (_PyAttrCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -1678,7 +1678,7 @@ */ #line 1680 "Python/executor_cases.c.h" Py_DECREF(owner); - #line 1849 "Python/bytecodes.c" + #line 1851 "Python/bytecodes.c" if (meth == NULL) goto pop_1_error; res2 = NULL; res = meth; @@ -1689,7 +1689,7 @@ res = PyObject_GetAttr(owner, name); #line 1691 "Python/executor_cases.c.h" Py_DECREF(owner); - #line 1858 "Python/bytecodes.c" + #line 1860 "Python/bytecodes.c" if (res == NULL) goto pop_1_error; } #line 1696 "Python/executor_cases.c.h" @@ -1704,7 +1704,7 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *res; - #line 2091 "Python/bytecodes.c" + #line 2093 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -1720,7 +1720,7 @@ #line 1721 "Python/executor_cases.c.h" Py_DECREF(left); Py_DECREF(right); - #line 2104 "Python/bytecodes.c" + #line 2106 "Python/bytecodes.c" if (res == NULL) goto pop_2_error; if (oparg & 16) { int res_bool = PyObject_IsTrue(res); @@ -2237,7 +2237,7 @@ PyObject *rhs = stack_pointer[-1]; PyObject *lhs = stack_pointer[-2]; PyObject *res; - #line 3537 "Python/bytecodes.c" + #line 3568 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyBinaryOpCache *cache = (_PyBinaryOpCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -2255,7 +2255,7 @@ #line 2256 "Python/executor_cases.c.h" Py_DECREF(lhs); Py_DECREF(rhs); - #line 3552 "Python/bytecodes.c" + #line 3583 "Python/bytecodes.c" if (res == NULL) goto pop_2_error; #line 2261 "Python/executor_cases.c.h" STACK_SHRINK(1); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 11823cf9cd293c..ecbf8ee59da1da 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1696,7 +1696,7 @@ PyObject *owner = stack_pointer[-1]; #line 1242 "Python/bytecodes.c" PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - int err = PyObject_SetAttr(owner, name, (PyObject *)NULL); + int err = PyObject_DelAttr(owner, name); #line 1701 "Python/generated_cases.c.h" Py_DECREF(owner); #line 1245 "Python/bytecodes.c"