From 2c3474a637949aa6f2f7e15f9764c2dfc49cdba1 Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Tue, 7 Sep 2021 03:52:30 -0700 Subject: [PATCH] bpo-45123: PyAiter_Check and PyObject_GetAiter fix & rename. (GH-28194) Fix PyAiter_Check to only check for the `__anext__` presense (not for `__aiter__`). Rename `PyAiter_Check()` to `PyAIter_Check()`, `PyObject_GetAiter()` -> `PyObject_GetAIter()`. Co-authored-by: Pablo Galindo Salgado --- Doc/c-api/iter.rst | 2 +- Doc/c-api/object.rst | 2 +- Doc/data/refcounts.dat | 8 ++++---- Doc/data/stable_abi.dat | 4 ++-- Include/abstract.h | 4 ++-- .../2021-09-06-21-52-45.bpo-45123.8Eh9iI.rst | 3 +++ Misc/stable_abi.txt | 4 ++-- Objects/abstract.c | 12 +++++------- PC/python3dll.c | 4 ++-- Python/bltinmodule.c | 2 +- 10 files changed, 23 insertions(+), 22 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2021-09-06-21-52-45.bpo-45123.8Eh9iI.rst diff --git a/Doc/c-api/iter.rst b/Doc/c-api/iter.rst index 63290e0a7f0..f7106f4ef09 100644 --- a/Doc/c-api/iter.rst +++ b/Doc/c-api/iter.rst @@ -12,7 +12,7 @@ There are two functions specifically for working with iterators. Return non-zero if the object *o* supports the iterator protocol, and ``0`` otherwise. This function always succeeds. -.. c:function:: int PyAiter_Check(PyObject *o) +.. c:function:: int PyAIter_Check(PyObject *o) Returns non-zero if the object 'obj' provides :class:`AsyncIterator` protocols, and ``0`` otherwise. This function always succeeds. diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst index 70cff69dc16..17e37077994 100644 --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -358,7 +358,7 @@ Object Protocol iterated. -.. c:function:: PyObject* PyObject_GetAiter(PyObject *o) +.. c:function:: PyObject* PyObject_GetAIter(PyObject *o) This is the equivalent to the Python expression ``aiter(o)``. Takes an :class:`AsyncIterable` object and returns an :class:`AsyncIterator` for it. diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index 3ef1b280e11..1694cad6f43 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -1073,8 +1073,8 @@ PyInterpreterState_New:PyInterpreterState*::: PyIter_Check:int::: PyIter_Check:PyObject*:o:0: -PyAiter_Check:int::: -PyAiter_Check:PyObject*:o:0: +PyAIter_Check:int::: +PyAIter_Check:PyObject*:o:0: PyIter_Next:PyObject*::+1: PyIter_Next:PyObject*:o:0: @@ -1700,8 +1700,8 @@ PyObject_GetItem:PyObject*:key:0: PyObject_GetIter:PyObject*::+1: PyObject_GetIter:PyObject*:o:0: -PyObject_GetAiter:PyObject*::+1: -PyObject_GetAiter:PyObject*:o:0: +PyObject_GetAIter:PyObject*::+1: +PyObject_GetAIter:PyObject*:o:0: PyObject_HasAttr:int::: PyObject_HasAttr:PyObject*:o:0: diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index ea57cc83f7a..b41027dee87 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -1,5 +1,5 @@ role,name,added,ifdef_note -function,PyAiter_Check,3.10, +function,PyAIter_Check,3.10, function,PyArg_Parse,3.2, function,PyArg_ParseTuple,3.2, function,PyArg_ParseTupleAndKeywords,3.2, @@ -491,7 +491,7 @@ function,PyObject_GenericGetAttr,3.2, function,PyObject_GenericGetDict,3.10, function,PyObject_GenericSetAttr,3.2, function,PyObject_GenericSetDict,3.7, -function,PyObject_GetAiter,3.10, +function,PyObject_GetAIter,3.10, function,PyObject_GetAttr,3.2, function,PyObject_GetAttrString,3.2, function,PyObject_GetItem,3.2, diff --git a/Include/abstract.h b/Include/abstract.h index 929861e4a50..e8d3f9293b9 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -374,7 +374,7 @@ PyAPI_FUNC(PyObject *) PyObject_GetIter(PyObject *); /* Takes an AsyncIterable object and returns an AsyncIterator for it. This is typically a new iterator but if the argument is an AsyncIterator, this returns itself. */ -PyAPI_FUNC(PyObject *) PyObject_GetAiter(PyObject *); +PyAPI_FUNC(PyObject *) PyObject_GetAIter(PyObject *); /* Returns non-zero if the object 'obj' provides iterator protocols, and 0 otherwise. @@ -384,7 +384,7 @@ PyAPI_FUNC(int) PyIter_Check(PyObject *); /* Returns non-zero if the object 'obj' provides AsyncIterator protocols, and 0 otherwise. This function always succeeds. */ -PyAPI_FUNC(int) PyAiter_Check(PyObject *); +PyAPI_FUNC(int) PyAIter_Check(PyObject *); /* Takes an iterator object and calls its tp_iternext slot, returning the next value. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-06-21-52-45.bpo-45123.8Eh9iI.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-06-21-52-45.bpo-45123.8Eh9iI.rst new file mode 100644 index 00000000000..6cc7303766f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-09-06-21-52-45.bpo-45123.8Eh9iI.rst @@ -0,0 +1,3 @@ +Fix PyAiter_Check to only check for the __anext__ presence (not for +__aiter__). Rename PyAiter_Check to PyAIter_Check, PyObject_GetAiter -> +PyObject_GetAIter. diff --git a/Misc/stable_abi.txt b/Misc/stable_abi.txt index a3ee0f01bec..72fa426cd79 100644 --- a/Misc/stable_abi.txt +++ b/Misc/stable_abi.txt @@ -2110,9 +2110,9 @@ function _Py_IncRef function _Py_DecRef added 3.10 abi_only -function PyAiter_Check +function PyAIter_Check added 3.10 -function PyObject_GetAiter +function PyObject_GetAIter added 3.10 data PyExc_EncodingWarning added 3.10 diff --git a/Objects/abstract.c b/Objects/abstract.c index 8ad1910fb1b..33eb8577a9b 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2816,18 +2816,18 @@ PyObject_GetIter(PyObject *o) } PyObject * -PyObject_GetAiter(PyObject *o) { +PyObject_GetAIter(PyObject *o) { PyTypeObject *t = Py_TYPE(o); unaryfunc f; if (t->tp_as_async == NULL || t->tp_as_async->am_aiter == NULL) { - return type_error("'%.200s' object is not an AsyncIterable", o); + return type_error("'%.200s' object is not an async iterable", o); } f = t->tp_as_async->am_aiter; PyObject *it = (*f)(o); - if (it != NULL && !PyAiter_Check(it)) { + if (it != NULL && !PyAIter_Check(it)) { PyErr_Format(PyExc_TypeError, - "aiter() returned non-AsyncIterator of type '%.100s'", + "aiter() returned not an async iterator of type '%.100s'", Py_TYPE(it)->tp_name); Py_DECREF(it); it = NULL; @@ -2844,12 +2844,10 @@ PyIter_Check(PyObject *obj) } int -PyAiter_Check(PyObject *obj) +PyAIter_Check(PyObject *obj) { PyTypeObject *tp = Py_TYPE(obj); return (tp->tp_as_async != NULL && - tp->tp_as_async->am_aiter != NULL && - tp->tp_as_async->am_aiter != &_PyObject_NextNotImplemented && tp->tp_as_async->am_anext != NULL && tp->tp_as_async->am_anext != &_PyObject_NextNotImplemented); } diff --git a/PC/python3dll.c b/PC/python3dll.c index 2420e53e705..49b51e69d62 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -86,7 +86,7 @@ EXPORT_FUNC(Py_SetPythonHome) EXPORT_FUNC(Py_SetRecursionLimit) EXPORT_FUNC(Py_VaBuildValue) EXPORT_FUNC(Py_XNewRef) -EXPORT_FUNC(PyAiter_Check) +EXPORT_FUNC(PyAIter_Check) EXPORT_FUNC(PyArg_Parse) EXPORT_FUNC(PyArg_ParseTuple) EXPORT_FUNC(PyArg_ParseTupleAndKeywords) @@ -443,7 +443,7 @@ EXPORT_FUNC(PyObject_GenericGetAttr) EXPORT_FUNC(PyObject_GenericGetDict) EXPORT_FUNC(PyObject_GenericSetAttr) EXPORT_FUNC(PyObject_GenericSetDict) -EXPORT_FUNC(PyObject_GetAiter) +EXPORT_FUNC(PyObject_GetAIter) EXPORT_FUNC(PyObject_GetAttr) EXPORT_FUNC(PyObject_GetAttrString) EXPORT_FUNC(PyObject_GetItem) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 761dc08d1d6..73541835d6c 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1610,7 +1610,7 @@ static PyObject * builtin_aiter(PyObject *module, PyObject *async_iterable) /*[clinic end generated code: output=1bae108d86f7960e input=473993d0cacc7d23]*/ { - return PyObject_GetAiter(async_iterable); + return PyObject_GetAIter(async_iterable); } PyObject *PyAnextAwaitable_New(PyObject *, PyObject *);