Author: Armin Rigo <[email protected]>
Branch: py3.5
Changeset: r86340:d5c8c1282a7d
Date: 2016-08-20 12:05 +0200
http://bitbucket.org/pypy/pypy/changeset/d5c8c1282a7d/
Log: Fix for test_close_on_collect
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -1,7 +1,7 @@
""" PyFrame class implementation with the interpreter main loop.
"""
-from rpython.rlib import jit
+from rpython.rlib import jit, rweakref
from rpython.rlib.debug import make_sure_not_resized, check_nonneg
from rpython.rlib.jit import hint
from rpython.rlib.objectmodel import instantiate, specialize, we_are_translated
@@ -62,7 +62,8 @@
__metaclass__ = extendabletype
frame_finished_execution = False
- frame_generator = None # for generators/coroutines
+ f_generator_wref = rweakref.dead_ref # for generators/coroutines
+ f_generator_nowref = None # (only one of the two attrs)
last_instr = -1
last_exception = None
f_backref = jit.vref_None
@@ -239,17 +240,23 @@
self.locals_cells_stack_w[index] = outer_func.closure[i]
index += 1
+ def _is_generator_or_coroutine(self):
+ return (self.getcode().co_flags & (pycode.CO_COROUTINE |
+ pycode.CO_GENERATOR)) != 0
+
def run(self):
"""Start this frame's execution."""
- if self.getcode().co_flags & (pycode.CO_COROUTINE |
- pycode.CO_GENERATOR):
+ if self._is_generator_or_coroutine():
if self.getcode().co_flags & pycode.CO_COROUTINE:
from pypy.interpreter.generator import Coroutine
gen = Coroutine(self)
else:
from pypy.interpreter.generator import GeneratorIterator
gen = GeneratorIterator(self)
- self.frame_generator = gen
+ if self.space.config.translation.rweakref:
+ self.f_generator_wref = rweakref.ref(gen)
+ else:
+ self.f_generator_nowref = gen
return self.space.wrap(gen)
else:
return self.execute_frame()
@@ -897,12 +904,20 @@
# is not quite like CPython when it clears f_exc_* (however
# there might not be an observable difference).
if not self.frame_finished_execution:
- if self.frame_generator is None or self.frame_generator.running:
+ if not self._is_generator_or_coroutine():
raise oefmt(space.w_RuntimeError,
"cannot clear an executing frame")
- # xxx CPython raises the RuntimeWarning "coroutine was never
- # awaited" in this case too. Does it make any sense?
- self.frame_generator.descr_close()
+ if space.config.translation.rweakref:
+ gen = self.f_generator_wref()
+ else:
+ gen = self.f_generator_nowref
+ if gen is not None:
+ if gen.running:
+ raise oefmt(space.w_RuntimeError,
+ "cannot clear an executing frame")
+ # xxx CPython raises the RuntimeWarning "coroutine was never
+ # awaited" in this case too. Does it make any sense?
+ gen.descr_close()
self.last_exception = None
debug = self.getdebug()
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
@@ -220,22 +220,17 @@
raises(RuntimeError, g.close)
def test_close_on_collect(self):
- ## we need to exec it, else it won't run on python2.4
- d = {}
- exec("""
def f():
try:
yield
finally:
f.x = 42
- """.strip(), d, d)
-
- g = d['f']()
+ g = f()
next(g)
del g
import gc
gc.collect()
- assert d['f'].x == 42
+ assert f.x == 42
def test_generator_raises_typeerror(self):
def f():
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit