From cc54001c2eb3b14320c1667b22602d69c90d5865 Mon Sep 17 00:00:00 2001 From: Erlend Egeberg Aasland Date: Tue, 16 Feb 2021 16:05:58 +0100 Subject: [PATCH] bpo-40170: Always define PyIter_Check() as a function (GH-24548) --- Doc/c-api/iter.rst | 4 ++-- Include/abstract.h | 2 +- Include/cpython/abstract.h | 6 ------ .../2021-02-15-15-06-43.bpo-40170.ZYeSii.rst | 3 +++ Objects/abstract.c | 10 +++++----- 5 files changed, 11 insertions(+), 14 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2021-02-15-15-06-43.bpo-40170.ZYeSii.rst diff --git a/Doc/c-api/iter.rst b/Doc/c-api/iter.rst index 74fb5578abd..5706777c41d 100644 --- a/Doc/c-api/iter.rst +++ b/Doc/c-api/iter.rst @@ -9,8 +9,8 @@ There are two functions specifically for working with iterators. .. c:function:: int PyIter_Check(PyObject *o) - Return true if the object *o* supports the iterator protocol. This - function always succeeds. + Return non-zero if the object *o* supports the iterator protocol, and ``0`` + otherwise. This function always succeeds. .. c:function:: PyObject* PyIter_Next(PyObject *o) diff --git a/Include/abstract.h b/Include/abstract.h index 0bd1ca93684..a47c944060d 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -324,7 +324,7 @@ PyAPI_FUNC(PyObject *) PyObject_Format(PyObject *obj, returns itself. */ PyAPI_FUNC(PyObject *) PyObject_GetIter(PyObject *); -/* Returns 1 if the object 'obj' provides iterator protocols, and 0 otherwise. +/* Returns non-zero if the object 'obj' provides iterator protocols, and 0 otherwise. This function always succeeds. */ PyAPI_FUNC(int) PyIter_Check(PyObject *); diff --git a/Include/cpython/abstract.h b/Include/cpython/abstract.h index 7a4219c8b33..db5055d2011 100644 --- a/Include/cpython/abstract.h +++ b/Include/cpython/abstract.h @@ -325,12 +325,6 @@ PyAPI_FUNC(int) PyBuffer_FillInfo(Py_buffer *view, PyObject *o, void *buf, /* Releases a Py_buffer obtained from getbuffer ParseTuple's "s*". */ PyAPI_FUNC(void) PyBuffer_Release(Py_buffer *view); -/* ==== Iterators ================================================ */ - -#define PyIter_Check(obj) \ - (Py_TYPE(obj)->tp_iternext != NULL && \ - Py_TYPE(obj)->tp_iternext != &_PyObject_NextNotImplemented) - /* === Sequence protocol ================================================ */ /* Assume tp_as_sequence and sq_item exist and that 'i' does not diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-02-15-15-06-43.bpo-40170.ZYeSii.rst b/Misc/NEWS.d/next/Core and Builtins/2021-02-15-15-06-43.bpo-40170.ZYeSii.rst new file mode 100644 index 00000000000..df6f3dcfc14 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-02-15-15-06-43.bpo-40170.ZYeSii.rst @@ -0,0 +1,3 @@ +:c:func:`PyIter_Check` is now always declared as a function, in order to hide implementation +details. The macro accessed :c:member:`PyTypeObject.tp_iternext` directly. +Patch by Erlend E. Aasland. diff --git a/Objects/abstract.c b/Objects/abstract.c index 74a73ee4698..c93309b3527 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2732,12 +2732,12 @@ PyObject_GetIter(PyObject *o) } } -#undef PyIter_Check - -int PyIter_Check(PyObject *obj) +int +PyIter_Check(PyObject *obj) { - return Py_TYPE(obj)->tp_iternext != NULL && - Py_TYPE(obj)->tp_iternext != &_PyObject_NextNotImplemented; + PyTypeObject *tp = Py_TYPE(obj); + return (tp->tp_iternext != NULL && + tp->tp_iternext != &_PyObject_NextNotImplemented); } /* Return next item.