Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cython
Commits
314d2c4d
Commit
314d2c4d
authored
Aug 08, 2017
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
remove support for the pre-Py3.5.2 aiter protocol that slows down the overall implementation
parent
d41842dc
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
23 additions
and
111 deletions
+23
-111
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+0
-7
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+2
-3
Cython/Utility/Coroutine.c
Cython/Utility/Coroutine.c
+4
-90
tests/run/async_iter_pep492.pyx
tests/run/async_iter_pep492.pyx
+7
-6
tests/run/test_coroutines_pep492.pyx
tests/run/test_coroutines_pep492.pyx
+10
-5
No files found.
Cython/Compiler/ExprNodes.py
View file @
314d2c4d
...
...
@@ -9571,13 +9571,6 @@ class AwaitExprNode(_YieldDelegationExprNode):
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
):
# 'await' expression node as part of 'async for' iteration
#
...
...
Cython/Compiler/Nodes.py
View file @
314d2c4d
...
...
@@ -6315,12 +6315,11 @@ class AsyncForStatNode(_ForInStatNode):
is_async
=
True
def
__init__
(
self
,
pos
,
iterator
,
**
kw
):
def
__init__
(
self
,
pos
,
**
kw
):
assert
'item'
not
in
kw
from
.
import
ExprNodes
# AwaitExprNodes must appear before running MarkClosureVisitor
kw
[
'iterator'
]
=
ExprNodes
.
AIterAwaitExprNode
(
iterator
.
pos
,
arg
=
iterator
)
kw
[
'item'
]
=
ExprNodes
.
AwaitIterNextExprNode
(
iterator
.
pos
,
arg
=
None
)
kw
[
'item'
]
=
ExprNodes
.
AwaitIterNextExprNode
(
kw
[
'iterator'
].
pos
,
arg
=
None
)
_ForInStatNode
.
__init__
(
self
,
pos
,
**
kw
)
def
_create_item_node
(
self
):
...
...
Cython/Utility/Coroutine.c
View file @
314d2c4d
...
...
@@ -45,44 +45,18 @@ static CYTHON_INLINE PyObject* __Pyx_Generator_Yield_From(__pyx_CoroutineObject
//////////////////// 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
,
int
warn
);
static
CYTHON_INLINE
PyObject
*
__Pyx_Coroutine_Yield_From
(
__pyx_CoroutineObject
*
gen
,
PyObject
*
source
);
//////////////////// CoroutineYieldFrom ////////////////////
//@requires: Coroutine
//@requires: GetAwaitIter
static
int
__Pyx_WarnAIterDeprecation
(
CYTHON_UNUSED
PyObject
*
aiter
)
{
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
)
{
static
PyObject
*
__Pyx__Coroutine_Yield_From_Generic
(
__pyx_CoroutineObject
*
gen
,
PyObject
*
source
)
{
PyObject
*
retval
;
PyObject
*
source_gen
=
__Pyx__Coroutine_GetAwaitableIter
(
source
);
if
(
unlikely
(
!
source_gen
))
{
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
if
(
__Pyx_Coroutine_CheckExact
(
source_gen
))
{
retval
=
__Pyx_Generator_Next
(
source_gen
);
...
...
@@ -97,13 +71,9 @@ static PyObject* __Pyx__Coroutine_Yield_From_Generic(__pyx_CoroutineObject *gen,
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
;
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
))
{
PyErr_SetString
(
PyExc_RuntimeError
,
...
...
@@ -128,63 +98,7 @@ static CYTHON_INLINE PyObject* __Pyx__Coroutine_Yield_From(__pyx_CoroutineObject
}
#endif
}
else
{
return
__Pyx__Coroutine_Yield_From_Generic
(
gen
,
source
,
warn
);
}
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
__Pyx__Coroutine_Yield_From_Generic
(
gen
,
source
);
}
return
NULL
;
}
...
...
tests/run/async_iter_pep492.pyx
View file @
314d2c4d
...
...
@@ -279,9 +279,10 @@ def test_with_for():
print
(
I
[
0
])
cdef
class
AI_old
:
async
def
__aiter__
(
self
):
1
/
0
# old-style pre-3.5.2 AIter protocol - no longer supported
#cdef class AI_old:
# async def __aiter__(self):
# 1/0
cdef
class
AI_new
:
...
...
@@ -291,9 +292,9 @@ cdef class AI_new:
def
test_aiter_raises
(
AI
):
"""
>>> test_aiter_raises(AI_old)
RAISED
0
#
>>> test_aiter_raises(AI_old)
#
RAISED
#
0
>>> test_aiter_raises(AI_new)
RAISED
0
...
...
tests/run/test_coroutines_pep492.pyx
View file @
314d2c4d
...
...
@@ -1789,7 +1789,8 @@ class CoroutineTest(unittest.TestCase):
run_async
(
foo
())
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
class
AsyncIter
(
object
):
...
...
@@ -2029,7 +2030,8 @@ class CoroutineTest(unittest.TestCase):
run_async(main())
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
class AI(object):
async def __aiter__(self):
...
...
@@ -2063,8 +2065,9 @@ class CoroutineTest(unittest.TestCase):
run_async(foo())
self.assertEqual(CNT, 0)
# old-style pre-Py3.5.2 protocol - no longer supported
@min_py27
def test_for_9(self):
def
__
test_for_9(self):
# Test that DeprecationWarning can safely be converted into
# an exception (__aiter__ should not have a chance to raise
# a ZeroDivisionError.)
...
...
@@ -2080,8 +2083,9 @@ class CoroutineTest(unittest.TestCase):
warnings.simplefilter("
error
")
run_async(foo())
# old-style pre-Py3.5.2 protocol - no longer supported
@min_py27
def test_for_10(self):
def
__
test_for_10(self):
# Test that DeprecationWarning can safely be converted into
# an exception.
class AI(object):
...
...
@@ -2120,7 +2124,8 @@ class CoroutineTest(unittest.TestCase):
err = c.exception
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):
def __aiter__(self):
return self
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment