Author: Raffael Tfirst <raffael.tfi...@gmail.com> 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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit