Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit