[Python-checkins] peps: PEP 492: Update __aiter__ protocol
yury.selivanov
python-checkins at python.org
Thu Jun 9 17:57:56 EDT 2016
https://hg.python.org/peps/rev/fef4b9969b9d
changeset: 6363:fef4b9969b9d
user: Yury Selivanov <yury at magic.io>
date: Thu Jun 09 17:57:41 2016 -0400
summary:
PEP 492: Update __aiter__ protocol
files:
pep-0492.txt | 113 ++++++++++++++++----------------------
1 files changed, 49 insertions(+), 64 deletions(-)
diff --git a/pep-0492.txt b/pep-0492.txt
--- a/pep-0492.txt
+++ b/pep-0492.txt
@@ -40,18 +40,36 @@
adopt, similar features: [2]_, [5]_, [6]_, [7]_, [8]_, [10]_.
-API Design and Implementation Note
-==================================
+API Design and Implementation Revisions
+=======================================
-Feedback on the initial beta release of Python 3.5 resulted in a redesign
-of the object model supporting this PEP to more clearly separate native
-coroutines from generators - rather than being a new kind of generator,
-native coroutines are now their own completely distinct type (implemented
-in [17]_).
+1. Feedback on the initial beta release of Python 3.5 resulted in a
+ redesign of the object model supporting this PEP to more clearly
+ separate native coroutines from generators - rather than being a
+ new kind of generator, native coroutines are now their own
+ completely distinct type (implemented in [17]_).
-This change was implemented based primarily due to problems encountered
-attempting to integrate support for native coroutines into the Tornado web
-server (reported in [18]_).
+ This change was implemented based primarily due to problems
+ encountered attempting to integrate support for native coroutines
+ into the Tornado web server (reported in [18]_).
+
+2. In CPython 3.5.2, the ``__aiter__`` protocol was updated.
+
+ Before 3.5.2, ``__aiter__`` was expected to return an *awaitable*
+ resolving to an *asynchronous iterator*. Starting with 3.5.2,
+ ``__aiter__`` should return asynchronous iterators directly.
+
+ If the old protocol is used in 3.5.2, Python will raise a
+ ``PendingDeprecationWarning``.
+
+ In CPython 3.6, the old ``__aiter__`` protocol will still be
+ supported with a ``DeprecationWarning`` being raised.
+
+ In CPython 3.7, the old ``__aiter__`` protocol will no longer be
+ supported: a ``RuntimeError`` will be raised if ``__aiter__``
+ returns anything but an asynchronous iterator.
+
+ See [19]_ for more details.
Rationale and Goals
@@ -209,11 +227,6 @@
Objects with ``__await__`` method are called *Future-like* objects in
the rest of this PEP.
- Also, please note that ``__aiter__`` method (see its definition
- below) cannot be used for this purpose. It is a different protocol,
- and would be like using ``__iter__`` instead of ``__call__`` for
- regular callables.
-
It is a ``TypeError`` if ``__await__`` returns anything but an
iterator.
@@ -428,7 +441,7 @@
1. An object must implement an ``__aiter__`` method (or, if defined
with CPython C API, ``tp_as_async.am_aiter`` slot) returning an
- *awaitable* resulting in an *asynchronous iterator object*.
+ *asynchronous iterator object*.
2. An *asynchronous iterator object* must implement an ``__anext__``
method (or, if defined with CPython C API, ``tp_as_async.am_anext``
@@ -440,7 +453,7 @@
An example of asynchronous iterable::
class AsyncIterable:
- async def __aiter__(self):
+ def __aiter__(self):
return self
async def __anext__(self):
@@ -468,7 +481,7 @@
which is semantically equivalent to::
iter = (ITER)
- iter = await type(iter).__aiter__(iter)
+ iter = type(iter).__aiter__(iter)
running = True
while running:
try:
@@ -510,7 +523,7 @@
async def _prefetch(self):
...
- async def __aiter__(self):
+ def __aiter__(self):
return self
async def __anext__(self):
@@ -527,7 +540,7 @@
which would be equivalent to the following code::
- i = await Cursor().__aiter__()
+ i = Cursor().__aiter__()
while True:
try:
row = await i.__anext__()
@@ -551,7 +564,7 @@
def __init__(self, obj):
self._it = iter(obj)
- async def __aiter__(self):
+ def __aiter__(self):
return self
async def __anext__(self):
@@ -814,37 +827,6 @@
`Asynchronous Iterators and "async for"`_ for details.
-List of functions and methods
-=============================
-
-================= =================================== =================
-Method Can contain Can't contain
-================= =================================== =================
-async def func await, return value yield, yield from
-async def __a*__ await, return value yield, yield from
-def __a*__ return awaitable await
-def __await__ yield, yield from, return iterable await
-generator yield, yield from, return value await
-================= =================================== =================
-
-Where:
-
-* "async def func": native coroutine;
-
-* "async def __a*__": ``__aiter__``, ``__anext__``, ``__aenter__``,
- ``__aexit__`` defined with the ``async`` keyword;
-
-* "def __a*__": ``__aiter__``, ``__anext__``, ``__aenter__``,
- ``__aexit__`` defined without the ``async`` keyword, must return an
- *awaitable*;
-
-* "def __await__": ``__await__`` method to implement *Future-like*
- objects;
-
-* generator: a "regular" generator, function defined with ``def`` and
- which contains a least one ``yield`` or ``yield from`` expression.
-
-
Transition Plan
===============
@@ -1080,19 +1062,20 @@
project easier (Python with ECMAScript 7 for instance).
-Why "__aiter__" returns awaitable
----------------------------------
+Why "__aiter__" does not return an awaitable
+--------------------------------------------
-In principle, ``__aiter__`` could be a regular function. There are
-several good reasons to make it a coroutine:
+PEP 492 was accepted in CPython 3.5.0 with ``__aiter__`` defined as
+a method, that was expected to return an awaitable resolving to an
+asynchronous iterator.
-* as most of the ``__anext__``, ``__aenter__``, and ``__aexit__``
- methods are coroutines, users would often make a mistake defining it
- as ``async`` anyways;
+In 3.5.2 (as PEP 492 was accepted on a provisional basis) the
+``__aiter__`` protocol was updated to return asynchronous iterators
+directly.
-* there might be a need to run some asynchronous operations in
- ``__aiter__``, for instance to prepare DB queries or do some file
- operation.
+The motivation behind this change is to make it possible to
+implement asynchronous generators in Python. See [19]_ for
+more details.
Importance of "async" keyword
@@ -1171,8 +1154,8 @@
New asynchronous magic methods ``__aiter__``, ``__anext__``,
``__aenter__``, and ``__aexit__`` all start with the same prefix "a".
-An alternative proposal is to use "async" prefix, so that ``__aiter__``
-becomes ``__async_iter__``. However, to align new magic methods with
+An alternative proposal is to use "async" prefix, so that ``__anext__``
+becomes ``__async_next__``. However, to align new magic methods with
the existing ones, such as ``__radd__`` and ``__iadd__`` it was decided
to use a shorter version.
@@ -1454,6 +1437,8 @@
.. [18] http://bugs.python.org/issue24400
+.. [19] http://bugs.python.org/issue27243
+
Acknowledgments
===============
--
Repository URL: https://hg.python.org/peps
More information about the Python-checkins
mailing list