return None
+_null_yield_point = _NullYieldPoint()
+
+
class Runner(object):
"""Internal implementation of `tornado.gen.engine`.
def __init__(self, gen, final_callback):
self.gen = gen
self.final_callback = final_callback
- self.yield_point = _NullYieldPoint()
+ self.yield_point = _null_yield_point
self.pending_callbacks = set()
self.results = {}
self.running = False
yielded = self.gen.send(next)
except (StopIteration, Return) as e:
self.finished = True
+ self.yield_point = _null_yield_point
if self.pending_callbacks and not self.had_exception:
# If we ran cleanly without waiting on all callbacks
# raise an error (really more of a warning). If we
return
except Exception:
self.finished = True
+ self.yield_point = _null_yield_point
raise
if isinstance(yielded, list):
yielded = Multi(yielded)
import sys
import textwrap
import time
+import platform
from tornado.concurrent import return_future
from tornado.escape import url_escape
skipBefore33 = unittest.skipIf(sys.version_info < (3, 3), 'PEP 380 not available')
+skipNotCPython = unittest.skipIf(platform.python_implementation() != 'CPython',
+ 'Not CPython implementation')
class GenEngineTest(AsyncTestCase):
with self.assertRaises(gen.ReturnValueIgnoredError):
self.run_gen(f)
+ @skipNotCPython
+ def test_task_refcounting(self):
+ # Task with arguments on CPython should be relased immediately after
+ # engine stop. And should not be delayed to garbage collection.
+ class Task(gen.Task):
+ "Task class which count self instances release."
+ relased = 0
+ def __del__(self):
+ type(self).relased += 1
+
+ @gen.engine
+ def f():
+ yield Task(lambda _arg, callback: callback(), Task(None))
+ self.stop()
+
+ self.run_gen(f)
+ self.assertEqual(Task.relased, 2)
+
class GenCoroutineTest(AsyncTestCase):
def setUp(self):