Commit 314d2c4d authored by Stefan Behnel's avatar Stefan Behnel

remove support for the pre-Py3.5.2 aiter protocol that slows down the overall implementation

parent d41842dc
...@@ -9571,13 +9571,6 @@ class AwaitExprNode(_YieldDelegationExprNode): ...@@ -9571,13 +9571,6 @@ class AwaitExprNode(_YieldDelegationExprNode):
return "__Pyx_Coroutine_Yield_From" return "__Pyx_Coroutine_Yield_From"
class AIterAwaitExprNode(AwaitExprNode):
# 'await' expression node used in async-for loops to support the pre-Py3.5.2 'aiter' protocol
def yield_from_func(self, code):
code.globalstate.use_utility_code(UtilityCode.load_cached("CoroutineAIterYieldFrom", "Coroutine.c"))
return "__Pyx_Coroutine_AIter_Yield_From"
class AwaitIterNextExprNode(AwaitExprNode): class AwaitIterNextExprNode(AwaitExprNode):
# 'await' expression node as part of 'async for' iteration # 'await' expression node as part of 'async for' iteration
# #
......
...@@ -6315,12 +6315,11 @@ class AsyncForStatNode(_ForInStatNode): ...@@ -6315,12 +6315,11 @@ class AsyncForStatNode(_ForInStatNode):
is_async = True is_async = True
def __init__(self, pos, iterator, **kw): def __init__(self, pos, **kw):
assert 'item' not in kw assert 'item' not in kw
from . import ExprNodes from . import ExprNodes
# AwaitExprNodes must appear before running MarkClosureVisitor # AwaitExprNodes must appear before running MarkClosureVisitor
kw['iterator'] = ExprNodes.AIterAwaitExprNode(iterator.pos, arg=iterator) kw['item'] = ExprNodes.AwaitIterNextExprNode(kw['iterator'].pos, arg=None)
kw['item'] = ExprNodes.AwaitIterNextExprNode(iterator.pos, arg=None)
_ForInStatNode.__init__(self, pos, **kw) _ForInStatNode.__init__(self, pos, **kw)
def _create_item_node(self): def _create_item_node(self):
......
...@@ -45,44 +45,18 @@ static CYTHON_INLINE PyObject* __Pyx_Generator_Yield_From(__pyx_CoroutineObject ...@@ -45,44 +45,18 @@ static CYTHON_INLINE PyObject* __Pyx_Generator_Yield_From(__pyx_CoroutineObject
//////////////////// CoroutineYieldFrom.proto //////////////////// //////////////////// CoroutineYieldFrom.proto ////////////////////
#define __Pyx_Coroutine_Yield_From(gen, source) __Pyx__Coroutine_Yield_From(gen, source, 0) static CYTHON_INLINE PyObject* __Pyx_Coroutine_Yield_From(__pyx_CoroutineObject *gen, PyObject *source);
static CYTHON_INLINE PyObject* __Pyx__Coroutine_Yield_From(__pyx_CoroutineObject *gen, PyObject *source, int warn);
//////////////////// CoroutineYieldFrom //////////////////// //////////////////// CoroutineYieldFrom ////////////////////
//@requires: Coroutine //@requires: Coroutine
//@requires: GetAwaitIter //@requires: GetAwaitIter
static int __Pyx_WarnAIterDeprecation(CYTHON_UNUSED PyObject *aiter) { static PyObject* __Pyx__Coroutine_Yield_From_Generic(__pyx_CoroutineObject *gen, PyObject *source) {
int result;
#if PY_MAJOR_VERSION >= 3
result = PyErr_WarnFormat(
PyExc_DeprecationWarning, 1,
"'%.100s' implements legacy __aiter__ protocol; "
"__aiter__ should return an asynchronous "
"iterator, not awaitable",
Py_TYPE(aiter)->tp_name);
#else
result = PyErr_WarnEx(
PyExc_DeprecationWarning,
"object implements legacy __aiter__ protocol; "
"__aiter__ should return an asynchronous "
"iterator, not awaitable",
1);
#endif
return result != 0;
}
static PyObject* __Pyx__Coroutine_Yield_From_Generic(__pyx_CoroutineObject *gen, PyObject *source, int warn) {
PyObject *retval; PyObject *retval;
PyObject *source_gen = __Pyx__Coroutine_GetAwaitableIter(source); PyObject *source_gen = __Pyx__Coroutine_GetAwaitableIter(source);
if (unlikely(!source_gen)) { if (unlikely(!source_gen)) {
return NULL; return NULL;
} }
if (warn && unlikely(__Pyx_WarnAIterDeprecation(source))) {
/* Warning was converted to an error. */
Py_DECREF(source_gen);
return NULL;
}
// source_gen is now the iterator, make the first next() call // source_gen is now the iterator, make the first next() call
if (__Pyx_Coroutine_CheckExact(source_gen)) { if (__Pyx_Coroutine_CheckExact(source_gen)) {
retval = __Pyx_Generator_Next(source_gen); retval = __Pyx_Generator_Next(source_gen);
...@@ -97,13 +71,9 @@ static PyObject* __Pyx__Coroutine_Yield_From_Generic(__pyx_CoroutineObject *gen, ...@@ -97,13 +71,9 @@ static PyObject* __Pyx__Coroutine_Yield_From_Generic(__pyx_CoroutineObject *gen,
return NULL; return NULL;
} }
static CYTHON_INLINE PyObject* __Pyx__Coroutine_Yield_From(__pyx_CoroutineObject *gen, PyObject *source, int warn) { static CYTHON_INLINE PyObject* __Pyx_Coroutine_Yield_From(__pyx_CoroutineObject *gen, PyObject *source) {
PyObject *retval; PyObject *retval;
if (__Pyx_Coroutine_CheckExact(source)) { if (__Pyx_Coroutine_CheckExact(source)) {
if (warn && unlikely(__Pyx_WarnAIterDeprecation(source))) {
/* Warning was converted to an error. */
return NULL;
}
if (unlikely(((__pyx_CoroutineObject*)source)->yieldfrom)) { if (unlikely(((__pyx_CoroutineObject*)source)->yieldfrom)) {
PyErr_SetString( PyErr_SetString(
PyExc_RuntimeError, PyExc_RuntimeError,
...@@ -128,63 +98,7 @@ static CYTHON_INLINE PyObject* __Pyx__Coroutine_Yield_From(__pyx_CoroutineObject ...@@ -128,63 +98,7 @@ static CYTHON_INLINE PyObject* __Pyx__Coroutine_Yield_From(__pyx_CoroutineObject
} }
#endif #endif
} else { } else {
return __Pyx__Coroutine_Yield_From_Generic(gen, source, warn); return __Pyx__Coroutine_Yield_From_Generic(gen, source);
}
return NULL;
}
//////////////////// CoroutineAIterYieldFrom.proto ////////////////////
static CYTHON_INLINE PyObject* __Pyx_Coroutine_AIter_Yield_From(__pyx_CoroutineObject *gen, PyObject *source);
//////////////////// CoroutineAIterYieldFrom ////////////////////
//@requires: CoroutineYieldFrom
static CYTHON_INLINE PyObject* __Pyx_Coroutine_AIter_Yield_From(__pyx_CoroutineObject *gen, PyObject *source) {
#if CYTHON_USE_ASYNC_SLOTS
__Pyx_PyAsyncMethodsStruct* am = __Pyx_PyType_AsAsync(source);
if (likely(am && am->am_anext)) {
// Starting with CPython 3.5.2, __aiter__ should return
// asynchronous iterators directly (not awaitables that
// resolve to asynchronous iterators.)
//
// Therefore, we check if the object that was returned
// from __aiter__ has an __anext__ method. If it does,
// we return it directly as StopIteration result,
// which avoids yielding.
//
// See http://bugs.python.org/issue27243 for more
// details.
goto store_result;
}
#endif
#if PY_VERSION_HEX < 0x030500B2
if (!__Pyx_PyType_AsAsync(source)) {
#ifdef __Pyx_Coroutine_USED
if (!__Pyx_Coroutine_CheckExact(source)) /* quickly rule out a likely case */
#endif
{
// same as above in slow
PyObject *method = __Pyx_PyObject_GetAttrStr(source, PYIDENT("__anext__"));
if (method) {
Py_DECREF(method);
goto store_result;
}
PyErr_Clear();
}
}
#endif
return __Pyx__Coroutine_Yield_From(gen, source, 1);
store_result:
if (unlikely(PyTuple_Check(source) || __Pyx_TypeCheck(source, (PyTypeObject*)PyExc_StopIteration))) {
PyObject *t = PyTuple_Pack(1, source);
if (unlikely(!t)) return NULL;
PyErr_SetObject(PyExc_StopIteration, t);
Py_DECREF(t);
} else {
PyErr_SetObject(PyExc_StopIteration, source);
} }
return NULL; return NULL;
} }
......
...@@ -279,9 +279,10 @@ def test_with_for(): ...@@ -279,9 +279,10 @@ def test_with_for():
print(I[0]) print(I[0])
cdef class AI_old: # old-style pre-3.5.2 AIter protocol - no longer supported
async def __aiter__(self): #cdef class AI_old:
1/0 # async def __aiter__(self):
# 1/0
cdef class AI_new: cdef class AI_new:
...@@ -291,9 +292,9 @@ cdef class AI_new: ...@@ -291,9 +292,9 @@ cdef class AI_new:
def test_aiter_raises(AI): def test_aiter_raises(AI):
""" """
>>> test_aiter_raises(AI_old) #>>> test_aiter_raises(AI_old)
RAISED #RAISED
0 #0
>>> test_aiter_raises(AI_new) >>> test_aiter_raises(AI_new)
RAISED RAISED
0 0
......
...@@ -1789,7 +1789,8 @@ class CoroutineTest(unittest.TestCase): ...@@ -1789,7 +1789,8 @@ class CoroutineTest(unittest.TestCase):
run_async(foo()) run_async(foo())
self.assertEqual(CNT, 1) self.assertEqual(CNT, 1)
def test_for_1(self): # old-style pre-Py3.5.2 protocol - no longer supported
def __test_for_1(self):
aiter_calls = 0 aiter_calls = 0
class AsyncIter(object): class AsyncIter(object):
...@@ -2029,7 +2030,8 @@ class CoroutineTest(unittest.TestCase): ...@@ -2029,7 +2030,8 @@ class CoroutineTest(unittest.TestCase):
run_async(main()) run_async(main())
self.assertEqual(I, 20555255) self.assertEqual(I, 20555255)
def test_for_7(self): # old-style pre-Py3.5.2 protocol - no longer supported
def __test_for_7(self):
CNT = 0 CNT = 0
class AI(object): class AI(object):
async def __aiter__(self): async def __aiter__(self):
...@@ -2063,8 +2065,9 @@ class CoroutineTest(unittest.TestCase): ...@@ -2063,8 +2065,9 @@ class CoroutineTest(unittest.TestCase):
run_async(foo()) run_async(foo())
self.assertEqual(CNT, 0) self.assertEqual(CNT, 0)
# old-style pre-Py3.5.2 protocol - no longer supported
@min_py27 @min_py27
def test_for_9(self): def __test_for_9(self):
# Test that DeprecationWarning can safely be converted into # Test that DeprecationWarning can safely be converted into
# an exception (__aiter__ should not have a chance to raise # an exception (__aiter__ should not have a chance to raise
# a ZeroDivisionError.) # a ZeroDivisionError.)
...@@ -2080,8 +2083,9 @@ class CoroutineTest(unittest.TestCase): ...@@ -2080,8 +2083,9 @@ class CoroutineTest(unittest.TestCase):
warnings.simplefilter("error") warnings.simplefilter("error")
run_async(foo()) run_async(foo())
# old-style pre-Py3.5.2 protocol - no longer supported
@min_py27 @min_py27
def test_for_10(self): def __test_for_10(self):
# Test that DeprecationWarning can safely be converted into # Test that DeprecationWarning can safely be converted into
# an exception. # an exception.
class AI(object): class AI(object):
...@@ -2120,7 +2124,8 @@ class CoroutineTest(unittest.TestCase): ...@@ -2120,7 +2124,8 @@ class CoroutineTest(unittest.TestCase):
err = c.exception err = c.exception
self.assertIsInstance(err.__cause__, ZeroDivisionError) self.assertIsInstance(err.__cause__, ZeroDivisionError)
def test_for_12(self): # old-style pre-Py3.5.2 protocol - no longer supported
def __test_for_12(self):
class F(object): class F(object):
def __aiter__(self): def __aiter__(self):
return self return self
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment