[Python-checkins] r86633 - in python/branches/py3k: Doc/library/inspect.rst Doc/whatsnew/3.2.rst Lib/inspect.py Lib/test/test_inspect.py Misc/NEWS

nick.coghlan python-checkins at python.org
Sun Nov 21 04:44:04 CET 2010


Author: nick.coghlan
Date: Sun Nov 21 04:44:04 2010
New Revision: 86633

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

Modified:
   python/branches/py3k/Doc/library/inspect.rst
   python/branches/py3k/Doc/whatsnew/3.2.rst
   python/branches/py3k/Lib/inspect.py
   python/branches/py3k/Lib/test/test_inspect.py
   python/branches/py3k/Misc/NEWS

Modified: python/branches/py3k/Doc/library/inspect.rst
==============================================================================
--- python/branches/py3k/Doc/library/inspect.rst	(original)
+++ python/branches/py3k/Doc/library/inspect.rst	Sun Nov 21 04:44:04 2010
@@ -620,3 +620,25 @@
            # 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.
+
+
+

Modified: python/branches/py3k/Doc/whatsnew/3.2.rst
==============================================================================
--- python/branches/py3k/Doc/whatsnew/3.2.rst	(original)
+++ python/branches/py3k/Doc/whatsnew/3.2.rst	Sun Nov 21 04:44:04 2010
@@ -554,6 +554,14 @@
   (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
 ===============
 

Modified: python/branches/py3k/Lib/inspect.py
==============================================================================
--- python/branches/py3k/Lib/inspect.py	(original)
+++ python/branches/py3k/Lib/inspect.py	Sun Nov 21 04:44:04 2010
@@ -1128,3 +1128,23 @@
     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

Modified: python/branches/py3k/Lib/test/test_inspect.py
==============================================================================
--- python/branches/py3k/Lib/test/test_inspect.py	(original)
+++ python/branches/py3k/Lib/test/test_inspect.py	Sun Nov 21 04:44:04 2010
@@ -887,12 +887,57 @@
         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__":

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Sun Nov 21 04:44:04 2010
@@ -32,6 +32,9 @@
 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'.
 


More information about the Python-checkins mailing list