https://github.com/python/cpython/commit/cb12c5e514e378ef4e75a3402d2eff1162a321c5
commit: cb12c5e514e378ef4e75a3402d2eff1162a321c5
branch: main
author: Kumar Aditya <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2026-10-20T15:33:36+05:30
summary:
gh-157361: Implement `aiter()` in Python instead of C (#157687)
gh-157361: Implement aiter() in Python instead of C
Move both forms of aiter() into the frozen _pybuiltins module and remove
the C async_callable_iterator types. The callable form now returns an
iterator whose __anext__() is a plain coroutine, so call-graph tools can
see through it into the awaited result of the callable.
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2026-09-13-10-00-00.gh-issue-157361.aiterpy.rst
M Include/internal/pycore_interp_structs.h
M Include/internal/pycore_iterobject.h
M Lib/_pybuiltins.py
M Lib/test/test_asyncio/test_graph.py
M Lib/test/test_inspect/test_inspect.py
M Objects/iterobject.c
M Objects/object.c
M Python/bltinmodule.c
M Python/clinic/bltinmodule.c.h
M Tools/c-analyzer/cpython/globals-to-fix.tsv
diff --git a/Include/internal/pycore_interp_structs.h
b/Include/internal/pycore_interp_structs.h
index dca86dec8be7979..a9ad61f458944ab 100644
--- a/Include/internal/pycore_interp_structs.h
+++ b/Include/internal/pycore_interp_structs.h
@@ -538,7 +538,7 @@ struct _py_func_state {
If you add a new static type to the standard library, you may have to
update one of these numbers.
*/
-#define _Py_NUM_MANAGED_PREINITIALIZED_TYPES 122
+#define _Py_NUM_MANAGED_PREINITIALIZED_TYPES 120
#define _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES \
(_Py_NUM_MANAGED_PREINITIALIZED_TYPES + 83)
#define _Py_MAX_MANAGED_STATIC_EXT_TYPES 10
diff --git a/Include/internal/pycore_iterobject.h
b/Include/internal/pycore_iterobject.h
index 90b444976e2f19c..b02eaa83b535146 100644
--- a/Include/internal/pycore_iterobject.h
+++ b/Include/internal/pycore_iterobject.h
@@ -8,20 +8,12 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif
-extern PyTypeObject _PyACallIter_Type;
-extern PyTypeObject _PyACallIterAwaitable_Type;
-
// Like PyCallIter_New(), but the iteration also stops when *callable* raises
// an exception matching *stop_exc* (an exception class or a tuple of exception
// classes). *sentinel* can be NULL; NULL *stop_exc* means StopIteration.
extern PyObject *_PyCallIter_NewEx(PyObject *callable, PyObject *sentinel,
PyObject *stop_exc);
-// The asynchronous counterpart of _PyCallIter_NewEx(): the result of
-// *callable* is awaited, and NULL *stop_exc* means StopAsyncIteration.
-extern PyObject *_PyACallIter_New(PyObject *callable, PyObject *sentinel,
- PyObject *stop_exc);
-
#ifdef __cplusplus
}
#endif
diff --git a/Lib/_pybuiltins.py b/Lib/_pybuiltins.py
index 01da295f53d0c73..dfcbeb57d07ebfd 100644
--- a/Lib/_pybuiltins.py
+++ b/Lib/_pybuiltins.py
@@ -5,11 +5,96 @@
copied into the ``builtins`` module.
"""
-__all__ = ['anext']
+__all__ = ['aiter', 'anext']
_NOT_GIVEN = sentinel("_NOT_GIVEN")
+def aiter(object, /, stop_value=_NOT_GIVEN, *, stop_exception=_NOT_GIVEN):
+ """Return an AsyncIterator for an AsyncIterable object.
+
+ In the second form, the callable is called and its result is awaited
+ until it returns the stop value or raises the specified exception.
+ """
+ if stop_value is _NOT_GIVEN and stop_exception is _NOT_GIVEN:
+ cls = type(object)
+ try:
+ # Looked up on the type, like the C slot am_aiter.
+ aiter_method = cls.__aiter__
+ except AttributeError:
+ raise TypeError(
+ f"'{cls.__name__}' object is not an async iterable"
+ ) from None
+ iterator = aiter_method(object)
+ if not hasattr(type(iterator), '__anext__'):
+ raise TypeError(
+ f"{cls.__name__}.__aiter__() must return an async iterator, "
+ f"not {type(iterator).__name__}"
+ )
+ return iterator
+
+ if not callable(object):
+ raise TypeError("aiter(): the first argument must be callable")
+ if stop_exception is _NOT_GIVEN:
+ stop_exception = StopAsyncIteration
+ else:
+ # Like _PyEval_CheckExceptTypeValid(): an exception class or a tuple
+ # of exception classes.
+ if isinstance(stop_exception, tuple):
+ items = stop_exception
+ else:
+ items = (stop_exception,)
+ for item in items:
+ if not (isinstance(item, type) and issubclass(item,
BaseException)):
+ raise TypeError(
+ "catching classes that do not inherit from BaseException "
+ "is not allowed"
+ )
+ return async_callable_iterator(object, stop_value, stop_exception)
+
+
+class async_callable_iterator:
+ """The asynchronous counterpart of callable_iterator.
+
+ The callable is called and its result is awaited for every
+ __anext__().
+ """
+
+ __slots__ = ('_callable', '_stop_value', '_stop_exception')
+ __module__ = 'builtins'
+
+ def __init__(self, callable, stop_value, stop_exception):
+ # _callable is set to None when the iterator is exhausted.
+ self._callable = callable
+ self._stop_value = stop_value
+ self._stop_exception = stop_exception
+
+ def __aiter__(self):
+ return self
+
+ async def __anext__(self):
+ callable = self._callable
+ if callable is None:
+ raise StopAsyncIteration
+ try:
+ value = await callable()
+ except self._stop_exception:
+ self._exhaust()
+ raise StopAsyncIteration from None
+ except (StopIteration, StopAsyncIteration) as exc:
+ raise RuntimeError(
+ f"callable raised {type(exc).__name__}") from exc
+ stop_value = self._stop_value
+ if stop_value is not _NOT_GIVEN and stop_value == value:
+ self._exhaust()
+ raise StopAsyncIteration
+ return value
+
+ def _exhaust(self):
+ self._callable = None
+ self._stop_value = _NOT_GIVEN
+
+
def anext(async_iterator, default=_NOT_GIVEN, /):
"""Return the next item from the async iterator.
diff --git a/Lib/test/test_asyncio/test_graph.py
b/Lib/test/test_asyncio/test_graph.py
index 1326ef50c149b0b..7f6e0cc477774e1 100644
--- a/Lib/test/test_asyncio/test_graph.py
+++ b/Lib/test/test_asyncio/test_graph.py
@@ -148,6 +148,45 @@ async def main():
'async generator
CallStackTestBase.test_stack_async_gen.<locals>.gen()',
stack_for_gen_nested_call[1])
+ async def test_stack_anext(self):
+ # anext() without a default returns the __anext__() coroutine
+ # itself, so nothing is inserted between it and main().
+
+ loop = asyncio.get_running_loop()
+ blocker = loop.create_future()
+
+ async def inner():
+ await blocker
+
+ class AIter:
+ def __aiter__(self):
+ return self
+
+ async def __anext__(self):
+ await inner()
+ return 1
+
+ async def main():
+ await anext(AIter())
+
+ task = asyncio.create_task(main(), name='anext task')
+ await asyncio.sleep(0)
+ try:
+ stack = capture_test_stack(fut=task)
+ finally:
+ blocker.set_result(None)
+ await task
+
+ self.assertEqual(stack[0], [
+ 'T<anext task>',
+ [
+ 'a inner',
+ 'a __anext__',
+ 'a main',
+ ],
+ []
+ ])
+
async def test_stack_anext_default(self):
# anext() with a default wraps the awaitable in a coroutine, so the
# call graph of a suspended task sees through it into __anext__().
@@ -188,6 +227,84 @@ async def main():
[]
])
+ async def test_stack_aiter(self):
+ # The one-argument form of aiter() returns the object's own
+ # iterator, so it adds no frame of its own to the call graph.
+
+ loop = asyncio.get_running_loop()
+ blocker = loop.create_future()
+
+ async def inner():
+ await blocker
+
+ class AIter:
+ def __aiter__(self):
+ return self
+
+ async def __anext__(self):
+ await inner()
+ return 1
+
+ async def main():
+ async for _ in aiter(AIter()):
+ break
+
+ task = asyncio.create_task(main(), name='aiter task')
+ await asyncio.sleep(0)
+ try:
+ stack = capture_test_stack(fut=task)
+ finally:
+ blocker.set_result(None)
+ await task
+
+ self.assertEqual(stack[0], [
+ 'T<aiter task>',
+ [
+ 'a inner',
+ 'a __anext__',
+ 'a main',
+ ],
+ []
+ ])
+
+ async def test_stack_aiter_callable(self):
+ # aiter(callable, ...) returns an iterator whose __anext__() is a
+ # coroutine, so the call graph of a suspended task sees through it
+ # into the awaited result of the callable.
+
+ loop = asyncio.get_running_loop()
+ blocker = loop.create_future()
+
+ async def inner():
+ await blocker
+
+ async def spam():
+ await inner()
+ return 1
+
+ async def main():
+ async for _ in aiter(spam, 1):
+ pass
+
+ task = asyncio.create_task(main(), name='aiter task')
+ await asyncio.sleep(0)
+ try:
+ stack = capture_test_stack(fut=task)
+ finally:
+ blocker.set_result(None)
+ await task
+
+ self.assertEqual(stack[0], [
+ 'T<aiter task>',
+ [
+ 'a inner',
+ 'a spam',
+ 'a __anext__',
+ 'a main',
+ ],
+ []
+ ])
+
def test_ag_frame_used_for_async_generator(self):
# Regression test for gh-148736: the ag_await branch of
# _build_graph_for_future must read ag_frame, not cr_frame.
diff --git a/Lib/test/test_inspect/test_inspect.py
b/Lib/test/test_inspect/test_inspect.py
index 3f14a9e66226eaa..5a3aa3e43fb2b2d 100644
--- a/Lib/test/test_inspect/test_inspect.py
+++ b/Lib/test/test_inspect/test_inspect.py
@@ -6229,7 +6229,7 @@ def test_builtins_have_signatures(self):
needs_groups = {"range", "slice", "getattr", "next"}
no_signature |= needs_groups
# These have unrepresentable parameter default values of NULL
- unsupported_signature = {"aiter", "iter", "dir", "vars"}
+ unsupported_signature = {"iter", "dir", "vars"}
# These need *args support in Argument Clinic
needs_varargs = {"min", "max", "__build_class__"}
no_signature |= needs_varargs
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2026-09-13-10-00-00.gh-issue-157361.aiterpy.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2026-09-13-10-00-00.gh-issue-157361.aiterpy.rst
new file mode 100644
index 000000000000000..b0a3c584da911fb
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2026-09-13-10-00-00.gh-issue-157361.aiterpy.rst
@@ -0,0 +1,5 @@
+Implement :func:`aiter` in Python instead of C, in the frozen ``_pybuiltins``
+module. The async iterator returned by ``aiter(callable, ...)`` now has a
+plain coroutine ``__anext__()``, so introspection tools such as
+:func:`asyncio.print_call_graph` can see through it into the awaited
+callable result.
diff --git a/Objects/iterobject.c b/Objects/iterobject.c
index 2d5e3709a27dfb0..fcef1cc9c301434 100644
--- a/Objects/iterobject.c
+++ b/Objects/iterobject.c
@@ -399,381 +399,3 @@ PyTypeObject PyCallIter_Type = {
calliter_iternext, /* tp_iternext */
calliter_methods, /* tp_methods */
};
-
-
-/* -------------------------------------- */
-
-static PyObject *
-awaitable_getiter(PyObject *owner, PyObject *wrapped)
-{
- assert(wrapped != NULL);
- PyObject *awaitable = _PyCoro_GetAwaitableIter(wrapped);
- if (awaitable == NULL) {
- return NULL;
- }
- if (Py_TYPE(awaitable)->tp_iternext == NULL) {
- /* _PyCoro_GetAwaitableIter returns a Coroutine, a Generator,
- * or an iterator. Of these, only coroutines lack tp_iternext.
- */
- assert(PyCoro_CheckExact(awaitable));
- unaryfunc getter = Py_TYPE(awaitable)->tp_as_async->am_await;
- PyObject *new_awaitable = getter(awaitable);
- if (new_awaitable == NULL) {
- Py_DECREF(awaitable);
- return NULL;
- }
- Py_SETREF(awaitable, new_awaitable);
- if (!PyIter_Check(awaitable)) {
- PyErr_Format(PyExc_TypeError,
- "%T.__await__() must return an iterable, not %T",
- owner, awaitable);
- Py_DECREF(awaitable);
- return NULL;
- }
- }
- return awaitable;
-}
-
-
-PyDoc_STRVAR(send_doc,
-"send(arg) -> send 'arg' into the wrapped iterator,\n\
-return next yielded value or raise StopIteration.");
-
-
-PyDoc_STRVAR(throw_doc,
-"throw(value)\n\
-throw(typ[,val[,tb]])\n\
-\n\
-raise exception in the wrapped iterator, return next yielded value\n\
-or raise StopIteration.\n\
-the (type, val, tb) signature is deprecated, \n\
-and may be removed in a future version of Python.");
-
-
-PyDoc_STRVAR(close_doc,
-"close() -> raise GeneratorExit inside generator.");
-
-
-/* -------------------------------------- */
-
-/* The asynchronous counterpart of calliterobject: the callable is called
- and its result is awaited for every __anext__(). */
-
-typedef struct {
- PyObject_HEAD
- PyObject *it_callable; /* set to NULL when the iterator is exhausted */
- PyObject *it_sentinel; /* can be NULL, and is when exhausted */
- PyObject *it_stop_exc; /* never NULL */
-} acalliterobject;
-
-#define acalliterobject_CAST(op) ((acalliterobject *)(op))
-
-/* The awaitable returned by acalliter_anext(). The callable is only
- called when this object is awaited. */
-typedef struct {
- PyObject_HEAD
- PyObject *aw_iterator; /* the iterator which created this object */
- PyObject *aw_wrapped; /* the awaitable returned by the callable */
- bool aw_closed;
-} acallawaitableobject;
-
-#define acallawaitableobject_CAST(op) ((acallawaitableobject *)(op))
-
-PyObject *
-_PyACallIter_New(PyObject *callable, PyObject *sentinel, PyObject *stop_exc)
-{
- if (stop_exc == NULL) {
- stop_exc = PyExc_StopAsyncIteration;
- }
- else if (_PyEval_CheckExceptTypeValid(_PyThreadState_GET(), stop_exc) < 0)
{
- return NULL;
- }
- acalliterobject *it = PyObject_GC_New(acalliterobject, &_PyACallIter_Type);
- if (it == NULL) {
- return NULL;
- }
- it->it_callable = Py_NewRef(callable);
- it->it_sentinel = Py_XNewRef(sentinel);
- it->it_stop_exc = Py_NewRef(stop_exc);
- _PyObject_GC_TRACK(it);
- return (PyObject *)it;
-}
-
-static void
-acalliter_exhaust(acalliterobject *it)
-{
- Py_CLEAR(it->it_callable);
- Py_CLEAR(it->it_sentinel);
-}
-
-static void
-acalliter_dealloc(PyObject *op)
-{
- acalliterobject *it = acalliterobject_CAST(op);
- _PyObject_GC_UNTRACK(it);
- Py_XDECREF(it->it_callable);
- Py_XDECREF(it->it_sentinel);
- Py_XDECREF(it->it_stop_exc);
- PyObject_GC_Del(it);
-}
-
-static int
-acalliter_traverse(PyObject *op, visitproc visit, void *arg)
-{
- acalliterobject *it = acalliterobject_CAST(op);
- Py_VISIT(it->it_callable);
- Py_VISIT(it->it_sentinel);
- Py_VISIT(it->it_stop_exc);
- return 0;
-}
-
-static PyObject *acallawaitable_new(PyObject *iterator);
-
-static PyObject *
-acalliter_anext(PyObject *op)
-{
- return acallawaitable_new(op);
-}
-
-static PyAsyncMethods acalliter_as_async = {
- 0, /* am_await */
- PyObject_SelfIter, /* am_aiter */
- acalliter_anext, /* am_anext */
- 0, /* am_send */
-};
-
-PyTypeObject _PyACallIter_Type = {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
- .tp_name = "async_callable_iterator",
- .tp_basicsize = sizeof(acalliterobject),
- .tp_dealloc = acalliter_dealloc,
- .tp_as_async = &acalliter_as_async,
- .tp_getattro = PyObject_GenericGetAttr,
- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
- .tp_traverse = acalliter_traverse,
-};
-
-/* -------------------------------------- */
-
-static PyObject *
-acallawaitable_new(PyObject *iterator)
-{
- acallawaitableobject *aw = PyObject_GC_New(
- acallawaitableobject, &_PyACallIterAwaitable_Type);
- if (aw == NULL) {
- return NULL;
- }
- aw->aw_iterator = Py_NewRef(iterator);
- aw->aw_wrapped = NULL;
- aw->aw_closed = false;
- _PyObject_GC_TRACK(aw);
- return (PyObject *)aw;
-}
-
-static void
-acallawaitable_dealloc(PyObject *op)
-{
- acallawaitableobject *aw = acallawaitableobject_CAST(op);
- _PyObject_GC_UNTRACK(aw);
- Py_XDECREF(aw->aw_iterator);
- Py_XDECREF(aw->aw_wrapped);
- PyObject_GC_Del(aw);
-}
-
-static int
-acallawaitable_traverse(PyObject *op, visitproc visit, void *arg)
-{
- acallawaitableobject *aw = acallawaitableobject_CAST(op);
- Py_VISIT(aw->aw_iterator);
- Py_VISIT(aw->aw_wrapped);
- return 0;
-}
-
-/* Call the callable. Return 0 on success, -1 on failure. */
-static int
-acallawaitable_start(acallawaitableobject *aw)
-{
- acalliterobject *it = acalliterobject_CAST(aw->aw_iterator);
-
- if (aw->aw_closed) {
- PyErr_SetString(PyExc_RuntimeError,
- "cannot reuse already awaited __anext__()");
- return -1;
- }
- if (it->it_callable == NULL) {
- PyErr_SetNone(PyExc_StopAsyncIteration);
- return -1;
- }
- PyObject *awaitable = _PyObject_CallNoArgs(it->it_callable);
- if (awaitable == NULL) {
- if (PyErr_ExceptionMatches(it->it_stop_exc)) {
- PyErr_Clear();
- acalliter_exhaust(it);
- PyErr_SetNone(PyExc_StopAsyncIteration);
- }
- else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
- /* It would be mistaken for the result of the await (PEP 525). */
- _PyErr_FormatFromCause(PyExc_RuntimeError,
- "callable raised StopIteration");
- }
- else if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration)) {
- /* It would be mistaken for the end of the iteration (PEP 525). */
- _PyErr_FormatFromCause(PyExc_RuntimeError,
- "callable raised StopAsyncIteration");
- }
- return -1;
- }
- aw->aw_wrapped = awaitable;
- return 0;
-}
-
-/* Turn the exception raised by the wrapped awaitable into the result of
- the await. Always returns NULL. */
-static PyObject *
-acallawaitable_handle_error(acallawaitableobject *aw)
-{
- acalliterobject *it = acalliterobject_CAST(aw->aw_iterator);
-
- if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
- PyObject *value;
- if (_PyGen_FetchStopIterationValue(&value) < 0) {
- return NULL;
- }
- int ok = 0;
- if (it->it_sentinel != NULL) {
- ok = PyObject_RichCompareBool(it->it_sentinel, value, Py_EQ);
- }
- if (ok == 0) {
- (void)_PyGen_SetStopIterationValue(value);
- }
- else if (ok > 0) {
- acalliter_exhaust(it);
- PyErr_SetNone(PyExc_StopAsyncIteration);
- }
- Py_DECREF(value);
- return NULL;
- }
- if (PyErr_ExceptionMatches(it->it_stop_exc)) {
- PyErr_Clear();
- acalliter_exhaust(it);
- PyErr_SetNone(PyExc_StopAsyncIteration);
- }
- else if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration)) {
- /* It would be mistaken for the end of the iteration (see PEP 525). */
- _PyErr_FormatFromCause(PyExc_RuntimeError,
- "callable raised StopAsyncIteration");
- }
- return NULL;
-}
-
-static PyObject *
-acallawaitable_iternext(PyObject *op)
-{
- acallawaitableobject *aw = acallawaitableobject_CAST(op);
-
- if (aw->aw_wrapped == NULL && acallawaitable_start(aw) < 0) {
- return NULL;
- }
- PyObject *awaitable = awaitable_getiter(op, aw->aw_wrapped);
- if (awaitable == NULL) {
- return NULL;
- }
- PyObject *result = (*Py_TYPE(awaitable)->tp_iternext)(awaitable);
- Py_DECREF(awaitable);
- if (result != NULL) {
- return result;
- }
- return acallawaitable_handle_error(aw);
-}
-
-static PyObject *
-acallawaitable_proxy(acallawaitableobject *aw, char *meth, PyObject *arg)
-{
- PyObject *awaitable = awaitable_getiter((PyObject *)aw, aw->aw_wrapped);
- if (awaitable == NULL) {
- return NULL;
- }
- // When specified, 'arg' may be a tuple (if coming from a METH_VARARGS
- // method) or a single object (if coming from a METH_O method).
- PyObject *ret = arg == NULL
- ? PyObject_CallMethod(awaitable, meth, NULL)
- : PyObject_CallMethod(awaitable, meth, "O", arg);
- Py_DECREF(awaitable);
- if (ret != NULL) {
- return ret;
- }
- return acallawaitable_handle_error(aw);
-}
-
-static PyObject *
-acallawaitable_send(PyObject *op, PyObject *arg)
-{
- acallawaitableobject *aw = acallawaitableobject_CAST(op);
-
- if (aw->aw_wrapped == NULL && acallawaitable_start(aw) < 0) {
- return NULL;
- }
- return acallawaitable_proxy(aw, "send", arg);
-}
-
-static PyObject *
-acallawaitable_throw(PyObject *op, PyObject *args)
-{
- acallawaitableobject *aw = acallawaitableobject_CAST(op);
-
- if (aw->aw_wrapped == NULL) {
- /* Not started, so the exception is raised at the point of the
- await, as for a not started coroutine. */
- PyObject *typ, *val = NULL, *tb = NULL;
- if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb)) {
- return NULL;
- }
- aw->aw_closed = true;
- (void)_PyGen_SetException(typ, val, tb);
- return NULL;
- }
- return acallawaitable_proxy(aw, "throw", args);
-}
-
-static PyObject *
-acallawaitable_close(PyObject *op, PyObject *Py_UNUSED(dummy))
-{
- acallawaitableobject *aw = acallawaitableobject_CAST(op);
-
- if (aw->aw_wrapped == NULL) {
- /* Not started, so there is nothing to close. */
- aw->aw_closed = true;
- Py_RETURN_NONE;
- }
- PyObject *result = acallawaitable_proxy(aw, "close", NULL);
- aw->aw_closed = true;
- return result;
-}
-
-static PyMethodDef acallawaitable_methods[] = {
- {"send", acallawaitable_send, METH_O, send_doc},
- {"throw", acallawaitable_throw, METH_VARARGS, throw_doc},
- {"close", acallawaitable_close, METH_NOARGS, close_doc},
- {NULL, NULL} /* Sentinel */
-};
-
-static PyAsyncMethods acallawaitable_as_async = {
- PyObject_SelfIter, /* am_await */
- 0, /* am_aiter */
- 0, /* am_anext */
- 0, /* am_send */
-};
-
-PyTypeObject _PyACallIterAwaitable_Type = {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
- .tp_name = "async_callable_iterator_awaitable",
- .tp_basicsize = sizeof(acallawaitableobject),
- .tp_dealloc = acallawaitable_dealloc,
- .tp_as_async = &acallawaitable_as_async,
- .tp_getattro = PyObject_GenericGetAttr,
- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
- .tp_traverse = acallawaitable_traverse,
- .tp_iter = PyObject_SelfIter,
- .tp_iternext = acallawaitable_iternext,
- .tp_methods = acallawaitable_methods,
-};
diff --git a/Objects/object.c b/Objects/object.c
index e334097d31c4325..f8206e5d3eca329 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -2533,8 +2533,6 @@ _PyObject_FiniState(PyInterpreterState *interp)
}
-extern PyTypeObject _PyACallIter_Type;
-extern PyTypeObject _PyACallIterAwaitable_Type;
extern PyTypeObject _PyLegacyEventHandler_Type;
extern PyTypeObject _PyLineIterator;
extern PyTypeObject _PyMemoryIter_Type;
@@ -2627,8 +2625,6 @@ static PyTypeObject*
static_types[_Py_NUM_MANAGED_PREINITIALIZED_TYPES] = {
&PyWrapperDescr_Type,
&PyZip_Type,
&Py_GenericAliasType,
- &_PyACallIter_Type,
- &_PyACallIterAwaitable_Type,
&_PyAsyncGenASend_Type,
&_PyAsyncGenAThrow_Type,
&_PyAsyncGenWrappedValue_Type,
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 796897ff24cdc02..10c5428159e66f9 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -1931,38 +1931,6 @@ builtin_iter_impl(PyObject *module, PyObject *object,
PyObject *stop_value,
}
-/*[clinic input]
-@text_signature "($module, object, /, [stop_value], *,
stop_exception=StopAsyncIteration)"
-aiter as builtin_aiter
-
- object: object
- /
- stop_value: object = NULL
- *
- stop_exception: object = NULL
-
-Return an AsyncIterator for an AsyncIterable object.
-
-In the second form, the callable is called and its result is awaited
-until it returns the stop value or raises the specified exception.
-[clinic start generated code]*/
-
-static PyObject *
-builtin_aiter_impl(PyObject *module, PyObject *object, PyObject *stop_value,
- PyObject *stop_exception)
-/*[clinic end generated code: output=2865edb3fbc45693 input=2adb37d12adafd0c]*/
-{
- if (stop_value == NULL && stop_exception == NULL) {
- return PyObject_GetAIter(object);
- }
- if (!PyCallable_Check(object)) {
- PyErr_SetString(PyExc_TypeError,
- "aiter(): the first argument must be callable");
- return NULL;
- }
- return _PyACallIter_New(object, stop_value, stop_exception);
-}
-
/*[clinic input]
len as builtin_len
@@ -3455,7 +3423,6 @@ static PyMethodDef builtin_methods[] = {
BUILTIN_ISINSTANCE_METHODDEF
BUILTIN_ISSUBCLASS_METHODDEF
BUILTIN_ITER_METHODDEF
- BUILTIN_AITER_METHODDEF
BUILTIN_LEN_METHODDEF
BUILTIN_LOCALS_METHODDEF
{"max", _PyCFunction_CAST(builtin_max), METH_FASTCALL | METH_KEYWORDS,
max_doc},
diff --git a/Python/clinic/bltinmodule.c.h b/Python/clinic/bltinmodule.c.h
index 0a32ca28da2ef2d..bdb3dd560b39b8b 100644
--- a/Python/clinic/bltinmodule.c.h
+++ b/Python/clinic/bltinmodule.c.h
@@ -970,86 +970,6 @@ builtin_iter(PyObject *module, PyObject *const *args,
Py_ssize_t nargs, PyObject
return return_value;
}
-PyDoc_STRVAR(builtin_aiter__doc__,
-"aiter($module, object, /, [stop_value], *,
stop_exception=StopAsyncIteration)\n"
-"--\n"
-"\n"
-"Return an AsyncIterator for an AsyncIterable object.\n"
-"\n"
-"In the second form, the callable is called and its result is awaited\n"
-"until it returns the stop value or raises the specified exception.");
-
-#define BUILTIN_AITER_METHODDEF \
- {"aiter", _PyCFunction_CAST(builtin_aiter), METH_FASTCALL|METH_KEYWORDS,
builtin_aiter__doc__},
-
-static PyObject *
-builtin_aiter_impl(PyObject *module, PyObject *object, PyObject *stop_value,
- PyObject *stop_exception);
-
-static PyObject *
-builtin_aiter(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
PyObject *kwnames)
-{
- PyObject *return_value = NULL;
- #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
-
- #define NUM_KEYWORDS 2
- static struct {
- PyGC_Head _this_is_not_used;
- PyObject_VAR_HEAD
- Py_hash_t ob_hash;
- PyObject *ob_item[NUM_KEYWORDS];
- } _kwtuple = {
- .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
- .ob_hash = -1,
- .ob_item = { &_Py_ID(stop_value), &_Py_ID(stop_exception), },
- };
- #undef NUM_KEYWORDS
- #define KWTUPLE (&_kwtuple.ob_base.ob_base)
-
- #else // !Py_BUILD_CORE
- # define KWTUPLE NULL
- #endif // !Py_BUILD_CORE
-
- static const char * const _keywords[] = {"", "stop_value",
"stop_exception", NULL};
- static _PyArg_Parser _parser = {
- .keywords = _keywords,
- .fname = "aiter",
- .kwtuple = KWTUPLE,
- };
- #undef KWTUPLE
- PyObject *argsbuf[3];
- Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) -
1;
- PyObject *object;
- PyObject *stop_value = NULL;
- PyObject *stop_exception = NULL;
-
- args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
- /*minpos*/ 1, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
- if (!args) {
- goto exit;
- }
- object = args[0];
- if (!noptargs) {
- goto skip_optional_pos;
- }
- if (args[1]) {
- stop_value = args[1];
- if (!--noptargs) {
- goto skip_optional_pos;
- }
- }
-skip_optional_pos:
- if (!noptargs) {
- goto skip_optional_kwonly;
- }
- stop_exception = args[2];
-skip_optional_kwonly:
- return_value = builtin_aiter_impl(module, object, stop_value,
stop_exception);
-
-exit:
- return return_value;
-}
-
PyDoc_STRVAR(builtin_len__doc__,
"len($module, obj, /)\n"
"--\n"
@@ -1575,4 +1495,4 @@ builtin_issubclass(PyObject *module, PyObject *const
*args, Py_ssize_t nargs)
exit:
return return_value;
}
-/*[clinic end generated code: output=ac4800dc25f87f6e input=a9049054013a1b77]*/
+/*[clinic end generated code: output=1dacff294aaa7485 input=a9049054013a1b77]*/
diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv
b/Tools/c-analyzer/cpython/globals-to-fix.tsv
index 67ced170243e4a2..251af27908cfc38 100644
--- a/Tools/c-analyzer/cpython/globals-to-fix.tsv
+++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv
@@ -58,8 +58,6 @@ Objects/genobject.c - _PyCoroWrapper_Type -
Objects/interpolationobject.c - _PyInterpolation_Type -
Objects/iterobject.c - PyCallIter_Type -
Objects/iterobject.c - PySeqIter_Type -
-Objects/iterobject.c - _PyACallIter_Type -
-Objects/iterobject.c - _PyACallIterAwaitable_Type -
Objects/lazyimportobject.c - PyLazyImport_Type -
Objects/listobject.c - PyListIter_Type -
Objects/listobject.c - PyListRevIter_Type -
@@ -74,8 +72,6 @@ Objects/moduleobject.c - PyModule_Type -
Objects/namespaceobject.c - _PyNamespace_Type -
Objects/object.c - _PyNone_Type -
Objects/object.c - _PyNotImplemented_Type -
-Objects/object.c - _PyACallIter_Type -
-Objects/object.c - _PyACallIterAwaitable_Type -
Objects/odictobject.c - PyODictItems_Type -
Objects/odictobject.c - PyODictIter_Type -
Objects/odictobject.c - PyODictKeys_Type -
_______________________________________________
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]