[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

AltStyle によって変換されたページ (->オリジナル) /