Issue #10220: Add inspect.getgeneratorstate(). Initial patch by Rodolpho Eckhardt

This commit is contained in:
Nick Coghlan 2010-11-21 03:44:04 +00:00
parent d3309df40b
commit e0f04659cd
5 changed files with 99 additions and 1 deletions

View File

@ -620,3 +620,25 @@ code execution::
# in which case the descriptor itself will
# have to do
pass
Current State of a Generator
----------------------------
When implementing coroutine schedulers and for other advanced uses of
generators, it is useful to determine whether a generator is currently
executing, is waiting to start or resume or execution, or has already
terminated. func:`getgeneratorstate` allows the current state of a
generator to be determined easily.
.. function:: getgeneratorstate(generator)
Get current state of a generator-iterator.
Possible states are:
GEN_CREATED: Waiting to start execution.
GEN_RUNNING: Currently being executed by the interpreter.
GEN_SUSPENDED: Currently suspended at a yield expression.
GEN_CLOSED: Execution has completed.

View File

@ -554,6 +554,14 @@ New, Improved, and Deprecated Modules
(Contributed by R. David Murray, :issue:`10321`.)
* The :mod:`inspect` module has a new function :func:`getgenatorstate`
to easily identify the current state of a generator as one of
``GEN_CREATED``, ``GEN_RUNNING``, ``GEN_SUSPENDED`` or ``GEN_CLOSED``.
(Contributed by Rodolpho Eckhardt and Nick Coghlan, :issue:`10220`.)
.. XXX: Mention inspect.getattr_static (Michael Foord)
Multi-threading
===============

View File

@ -1128,3 +1128,23 @@ def getattr_static(obj, attr, default=_sentinel):
if default is not _sentinel:
return default
raise AttributeError(attr)
GEN_CREATED, GEN_RUNNING, GEN_SUSPENDED, GEN_CLOSED = range(4)
def getgeneratorstate(generator):
"""Get current state of a generator-iterator.
Possible states are:
GEN_CREATED: Waiting to start execution.
GEN_RUNNING: Currently being executed by the interpreter.
GEN_SUSPENDED: Currently suspended at a yield expression.
GEN_CLOSED: Execution has completed.
"""
if generator.gi_running:
return GEN_RUNNING
if generator.gi_frame is None:
return GEN_CLOSED
if generator.gi_frame.f_lasti == -1:
return GEN_CREATED
return GEN_SUSPENDED

View File

@ -887,12 +887,57 @@ class TestGetattrStatic(unittest.TestCase):
self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
class TestGetGeneratorState(unittest.TestCase):
def setUp(self):
def number_generator():
for number in range(5):
yield number
self.generator = number_generator()
def _generatorstate(self):
return inspect.getgeneratorstate(self.generator)
def test_created(self):
self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
def test_suspended(self):
next(self.generator)
self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
def test_closed_after_exhaustion(self):
for i in self.generator:
pass
self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
def test_closed_after_immediate_exception(self):
with self.assertRaises(RuntimeError):
self.generator.throw(RuntimeError)
self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
def test_running(self):
# As mentioned on issue #10220, checking for the RUNNING state only
# makes sense inside the generator itself.
# The following generator checks for this by using the closure's
# reference to self and the generator state checking helper method
def running_check_generator():
for number in range(5):
self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
yield number
self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
self.generator = running_check_generator()
# Running up to the first yield
next(self.generator)
# Running after the first yield
next(self.generator)
def test_main():
run_unittest(
TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
TestGetcallargsFunctions, TestGetcallargsMethods,
TestGetcallargsUnboundMethods, TestGetattrStatic
TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState
)
if __name__ == "__main__":

View File

@ -32,6 +32,9 @@ Core and Builtins
Library
-------
- Issue #10220: Added inspect.getgeneratorstate. Initial patch by
Rodolpho Eckhardt.
- Issue #10453: compileall now uses argparse instead of getopt, and thus
provides clean output when called with '-h'.