Author: Raffael Tfirst <[email protected]>
Branch: py3.5
Changeset: r86288:10f2791aaf2d
Date: 2016-08-18 20:22 +0200
http://bitbucket.org/pypy/pypy/changeset/10f2791aaf2d/
Log: Merge with py3.5-async
diff --git a/pypy/interpreter/astcompiler/assemble.py
b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -609,7 +609,7 @@
ops.WITH_CLEANUP_FINISH: -2,
ops.LOAD_BUILD_CLASS: 1,
ops.POP_BLOCK: 0,
- ops.POP_EXCEPT: -1,
+ ops.POP_EXCEPT: -2,
ops.END_FINALLY: -4, # assume always 4: we pretend that SETUP_FINALLY
# pushes 4. In truth, it would only push 1 and
# the corresponding END_FINALLY only pops 1.
diff --git a/pypy/interpreter/astcompiler/codegen.py
b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -599,17 +599,21 @@
b_try_cleanup = self.new_block()
b_after_loop = self.new_block()
b_after_loop_else = self.new_block()
+
self.emit_jump(ops.SETUP_LOOP, b_after_loop)
self.push_frame_block(F_BLOCK_LOOP, b_try)
+
fr.iter.walkabout(self)
self.emit_op(ops.GET_AITER)
self.load_const(self.space.w_None)
self.emit_op(ops.YIELD_FROM)
+
self.use_next_block(b_try)
# This adds another line, so each for iteration can be traced.
self.lineno_set = False
self.emit_jump(ops.SETUP_EXCEPT, b_except)
self.push_frame_block(F_BLOCK_EXCEPT, b_try)
+
self.emit_op(ops.GET_ANEXT)
self.load_const(self.space.w_None)
self.emit_op(ops.YIELD_FROM)
@@ -617,9 +621,10 @@
self.emit_op(ops.POP_BLOCK)
self.pop_frame_block(F_BLOCK_EXCEPT, b_try)
self.emit_jump(ops.JUMP_FORWARD, b_after_try)
+
self.use_next_block(b_except)
- self.emit_op(ops.POP_TOP)
- self.emit_op_name(ops.LOAD_GLOBAL, self.names, "StopIterError")
+ self.emit_op(ops.DUP_TOP)
+ self.emit_op_name(ops.LOAD_GLOBAL, self.names, "StopAsyncIteration")
self.emit_op_arg(ops.COMPARE_OP, 10)
self.emit_jump(ops.POP_JUMP_IF_FALSE, b_try_cleanup, True)
@@ -632,13 +637,17 @@
self.use_next_block(b_try_cleanup)
self.emit_op(ops.END_FINALLY)
+
self.use_next_block(b_after_try)
self.visit_sequence(fr.body)
self.emit_jump(ops.JUMP_ABSOLUTE, b_try, True)
+
self.emit_op(ops.POP_BLOCK) # for SETUP_LOOP
self.pop_frame_block(F_BLOCK_LOOP, b_try)
+
self.use_next_block(b_after_loop)
self.emit_jump(ops.JUMP_ABSOLUTE, b_end, True)
+
self.use_next_block(b_after_loop_else)
self.visit_sequence(fr.orelse)
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -798,10 +798,15 @@
)
assert not GeneratorIterator.typedef.acceptable_as_base_class # no __new__
+# TODO: to have the same distinction (Coroutine | Iterator) as in cpython 3.5,
+# a wrapper typedef with __anext__ has to be created, and __anext__ has to be
+# removed in coroutine
Coroutine.typedef = TypeDef("coroutine",
__repr__ = interp2app(Coroutine.descr__repr__),
__reduce__ = interp2app(Coroutine.descr__reduce__),
__setstate__ = interp2app(Coroutine.descr__setstate__),
+ __anext__ = interp2app(Coroutine.descr_next,
+ descrmismatch='__anext__'),
send = interp2app(Coroutine.descr_send,
descrmismatch='send'),
throw = interp2app(Coroutine.descr_throw,
diff --git a/pypy/module/_asyncio/test/test_asyncio.py
b/pypy/module/_asyncio/test/test_asyncio.py
--- a/pypy/module/_asyncio/test/test_asyncio.py
+++ b/pypy/module/_asyncio/test/test_asyncio.py
@@ -1,4 +1,5 @@
class AppTestAsyncIO(object):
+ """These tests are based on the async-await syntax of Python 3.5."""
spaceconfig = dict(usemodules=["select","_socket","thread","signal",
"struct","_multiprocessing","array",
@@ -9,17 +10,71 @@
# the problem occured at await asyncio.open_connection
# after calling run_until_complete
"""
- import encodings.idna
- import asyncio
- async def f():
- reader, writer = await asyncio.open_connection('example.com', 80)
-
- loop = asyncio.get_event_loop()
- loop.run_until_complete(f())
- print("done with async loop")
+import encodings.idna
+import asyncio
+
+async def f():
+ reader, writer = await asyncio.open_connection('example.com', 80)
+ writer.close()
+
+loop = asyncio.get_event_loop()
+loop.run_until_complete(f())
+ """
+
+ def test_async_for(self):
+ # tests if async for receives all stores values in the right order
+ # and if the correct methods __aiter__ and __anext__ get called
+ # and if the end results of run_until_complete are None (in a tuple)
+ """
+import asyncio
+
+class AsyncIter:
+ def __init__(self):
+ self._data = list(range(5))
+ self._index = 0
+
+ async def __aiter__(self):
+ return self
+
+ async def __anext__(self):
+ while self._index < 5:
+ await asyncio.sleep(1)
+ self._index += 1
+ return self._data[self._index-1]
+ raise StopAsyncIteration
+
+class Corotest(object):
+ def __init__(self):
+ self.res = "-"
+
+ async def do_loop(self):
+ async for x in AsyncIter():
+ self.res += str(x)
+ self.res += "-"
+
+cor = Corotest()
+loop = asyncio.get_event_loop()
+futures = [asyncio.ensure_future(cor.do_loop()),
asyncio.ensure_future(cor.do_loop())]
+taskres = loop.run_until_complete(asyncio.wait(futures))
+assert cor.res.count('0') == 2
+assert cor.res.count('1') == 2
+assert cor.res.count('2') == 2
+assert cor.res.count('3') == 2
+assert cor.res.count('4') == 2
+assert cor.res.find("0") < cor.res.find("1")
+assert cor.res.find("1") < cor.res.find("2")
+assert cor.res.find("2") < cor.res.find("3")
+assert cor.res.find("3") < cor.res.find("4")
+assert isinstance(taskres, tuple)
+assert len(taskres) == 2
+assert "result=None" in repr(taskres[0].pop())
+assert "result=None" in repr(taskres[0].pop())
"""
def test_asynchronous_context_managers(self):
+ # it is important that "releasing lock A" happens before "holding lock
B"
+ # or the other way around, but it is not allowed that both coroutines
+ # hold the lock at the same time
"""
import encodings.idna
import asyncio
@@ -44,5 +99,12 @@
finally:
loop.close()
-assert cor.res == "- coro 1: waiting for lock - coro 1: holding the lock -
coro 2: waiting for lock - coro 1: releasing the lock - coro 2: holding the
lock - coro 2: releasing the lock -"
+assert "coro 1: waiting for lock" in cor.res
+assert "coro 1: holding the lock" in cor.res
+assert "coro 1: releasing the lock" in cor.res
+assert "coro 2: waiting for lock" in cor.res
+assert "coro 2: holding the lock" in cor.res
+assert "coro 2: releasing the lock" in cor.res
+assert cor.res.find("coro 1: releasing the lock") < cor.res.find("coro 2:
holding the lock") or \
+cor.res.find("coro 2: releasing the lock") < cor.res.find("coro 1: holding the
lock")
"""
diff --git a/pypy/module/exceptions/__init__.py
b/pypy/module/exceptions/__init__.py
--- a/pypy/module/exceptions/__init__.py
+++ b/pypy/module/exceptions/__init__.py
@@ -52,6 +52,7 @@
'ResourceWarning' : 'interp_exceptions.W_ResourceWarning',
'RuntimeError' : 'interp_exceptions.W_RuntimeError',
'RuntimeWarning' : 'interp_exceptions.W_RuntimeWarning',
+ 'StopAsyncIteration' : 'interp_exceptions.W_StopAsyncIteration',
'StopIteration' : 'interp_exceptions.W_StopIteration',
'SyntaxError' : 'interp_exceptions.W_SyntaxError',
'SyntaxWarning' : 'interp_exceptions.W_SyntaxWarning',
diff --git a/pypy/module/exceptions/interp_exceptions.py
b/pypy/module/exceptions/interp_exceptions.py
--- a/pypy/module/exceptions/interp_exceptions.py
+++ b/pypy/module/exceptions/interp_exceptions.py
@@ -65,6 +65,7 @@
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+ +-- StopAsyncIteration
+-- SyntaxError
| +-- IndentationError
| +-- TabError
@@ -834,6 +835,9 @@
W_AssertionError = _new_exception('AssertionError', W_Exception,
"""Assertion failed.""")
+W_StopAsyncIteration = _new_exception('StopAsyncIteration', W_Exception,
+ """Signal the end from
iterator.__anext__().""")
+
class W_UnicodeDecodeError(W_UnicodeError):
"""Unicode decoding error."""
w_encoding = None
diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -298,7 +298,10 @@
return w_iter
def next(space, w_obj):
- w_descr = space.lookup(w_obj, '__next__')
+ if space.type(w_obj).name == 'coroutine':
+ w_descr = space.lookup(w_obj, '__anext__')
+ else:
+ w_descr = space.lookup(w_obj, '__next__')
if w_descr is None:
raise oefmt(space.w_TypeError,
"'%T' object is not an iterator", w_obj)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit