Author: Armin Rigo <ar...@tunes.org> Branch: py3.5-corowrapper Changeset: r87115:209720711d97 Date: 2016-09-14 20:11 +0200 http://bitbucket.org/pypy/pypy/changeset/209720711d97/
Log: CO_FUTURE_GENERATOR_STOP, not tested so far diff --git a/pypy/interpreter/astcompiler/consts.py b/pypy/interpreter/astcompiler/consts.py --- a/pypy/interpreter/astcompiler/consts.py +++ b/pypy/interpreter/astcompiler/consts.py @@ -25,7 +25,8 @@ PyCF_MASK = (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | - CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL) + CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | + CO_FUTURE_GENERATOR_STOP) PyCF_SOURCE_IS_UTF8 = 0x0100 PyCF_DONT_IMPLY_DEDENT = 0x0200 PyCF_ONLY_AST = 0x0400 diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py --- a/pypy/interpreter/generator.py +++ b/pypy/interpreter/generator.py @@ -116,10 +116,15 @@ try: try: w_result = frame.execute_frame(w_arg, operr) - except OperationError: + except OperationError as e: # errors finish a frame - self.frame = None + try: + if e.match(space, space.w_StopIteration): + self._leak_stopiteration(e) + finally: + self.frame = None raise + # # if the frame is now marked as finished, it was RETURNed from if frame.frame_finished_execution: self.frame = None @@ -135,6 +140,25 @@ frame.f_backref = jit.vref_None self.running = False + def _leak_stopiteration(self, e): + # Check for __future__ generator_stop and conditionally turn + # a leaking StopIteration into RuntimeError (with its cause + # set appropriately). + space = self.space + if self.pycode.co_flags & (consts.CO_FUTURE_GENERATOR_STOP | + consts.CO_COROUTINE | + consts.CO_ITERABLE_COROUTINE): + e2 = OperationError(space.w_RuntimeError, + space.wrap("%s raised StopIteration" % + self.KIND), + w_cause=e.get_w_value(space)) + e2.record_context(space, self.frame) + raise e2 + else: + space.warn(space.wrap("generator '%s' raised StopIteration" + % self.get_qualname()), + space.w_PendingDeprecationWarning) + def descr_throw(self, w_type, w_val=None, w_tb=None): """throw(typ[,val[,tb]]) -> raise exception in generator/coroutine, return next yielded value or raise StopIteration.""" diff --git a/pypy/interpreter/pycompiler.py b/pypy/interpreter/pycompiler.py --- a/pypy/interpreter/pycompiler.py +++ b/pypy/interpreter/pycompiler.py @@ -101,7 +101,7 @@ """ def __init__(self, space, override_version=None): PyCodeCompiler.__init__(self, space) - self.future_flags = future.futureFlags_3_2 + self.future_flags = future.futureFlags_3_5 self.parser = pyparse.PythonParser(space, self.future_flags) self.additional_rules = {} self.compiler_flags = self.future_flags.allowed_flags diff --git a/pypy/interpreter/pyparser/future.py b/pypy/interpreter/pyparser/future.py --- a/pypy/interpreter/pyparser/future.py +++ b/pypy/interpreter/pyparser/future.py @@ -30,6 +30,7 @@ futureFlags_2_5 = FutureFlags((2, 5, 0, 'final', 0)) futureFlags_2_7 = FutureFlags((2, 7, 0, 'final', 0)) futureFlags_3_2 = FutureFlags((3, 2, 0, 'final', 0)) +futureFlags_3_5 = FutureFlags((3, 5, 0, 'final', 0)) class TokenIterator: diff --git a/pypy/interpreter/pyparser/pyparse.py b/pypy/interpreter/pyparser/pyparse.py --- a/pypy/interpreter/pyparser/pyparse.py +++ b/pypy/interpreter/pyparser/pyparse.py @@ -95,7 +95,7 @@ class PythonParser(parser.Parser): - def __init__(self, space, future_flags=future.futureFlags_3_2, + def __init__(self, space, future_flags=future.futureFlags_3_5, grammar=pygram.python_grammar): parser.Parser.__init__(self, grammar) self.space = space diff --git a/pypy/interpreter/test/test_generator.py b/pypy/interpreter/test/test_generator.py --- a/pypy/interpreter/test/test_generator.py +++ b/pypy/interpreter/test/test_generator.py @@ -641,3 +641,23 @@ 2, ] + +class AppTestGeneratorStop: + + def test_past_generator_stop(self): + # how it works without 'from __future__' import generator_stop + def f(x): + raise StopIteration + yield x + raises(StopIteration, next, f(5)) + + def test_future_generator_stop(self): + d = {} + exec("""from __future__ import generator_stop + +def f(x): + raise StopIteration + yield x +""", d) + f = d['f'] + raises(RuntimeError, next, f(5)) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit