Issue #1916. Added isgenerator() and isgeneratorfunction() to

inspect.py.  Thanks Javi Mansilla for patch review and
corrections.
This commit is contained in:
Facundo Batista 2008-02-18 03:43:43 +00:00
parent b169eaa917
commit 759bfc6207
4 changed files with 104 additions and 15 deletions

View File

@ -28,7 +28,7 @@ Types and members
-----------------
The :func:`getmembers` function retrieves the members of an object such as a
class or module. The eleven functions whose names begin with "is" are mainly
class or module. The fifteen functions whose names begin with "is" are mainly
provided as convenient choices for the second argument to :func:`getmembers`.
They also help you determine when you can expect to find the following special
attributes:
@ -81,6 +81,35 @@ attributes:
+-----------+-----------------+---------------------------+-------+
| | func_name | (same as __name__) | |
+-----------+-----------------+---------------------------+-------+
| generator | __iter__ | defined to support | |
| | | iteration over container | |
+-----------+-----------------+---------------------------+-------+
| | close | raises new GeneratorExit | |
| | | exception inside the | |
| | | generator to terminate | |
| | | the iteration | |
+-----------+-----------------+---------------------------+-------+
| | gi_code | code object | |
+-----------+-----------------+---------------------------+-------+
| | gi_frame | frame object or possibly | |
| | | None once the generator | |
| | | has been exhausted | |
+-----------+-----------------+---------------------------+-------+
| | gi_running | set to 1 when generator | |
| | | is executing, 0 otherwise | |
+-----------+-----------------+---------------------------+-------+
| | next | return the next item from | |
| | | the container | |
+-----------+-----------------+---------------------------+-------+
| | send | resumes the generator and | |
| | | "sends" a value that | |
| | | becomes the result of the | |
| | | current yield-expression | |
+-----------+-----------------+---------------------------+-------+
| | throw | used to raise an | |
| | | exception inside the | |
| | | generator | |
+-----------+-----------------+---------------------------+-------+
| traceback | tb_frame | frame object at this | |
| | | level | |
+-----------+-----------------+---------------------------+-------+
@ -246,6 +275,13 @@ Note:
Return true if the object is a Python function or unnamed (:term:`lambda`) function.
.. function:: isgeneratorfunction(object)
Return true if the object is a Python generator function.
.. function:: isgenerator(object)
Return true if the object is a generator.
.. function:: istraceback(object)

View File

@ -7,8 +7,9 @@ It also provides some help for examining source code and class layout.
Here are some of the useful functions provided by this module:
ismodule(), isclass(), ismethod(), isfunction(), istraceback(),
isframe(), iscode(), isbuiltin(), isroutine() - check object types
ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(),
isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(),
isroutine() - check object types
getmembers() - get members of an object that satisfy a given condition
getfile(), getsourcefile(), getsource() - find an object's source code
@ -28,9 +29,19 @@ Here are some of the useful functions provided by this module:
__author__ = 'Ka-Ping Yee <ping@lfw.org>'
__date__ = '1 Jan 2001'
import sys, os, types, string, re, dis, imp, tokenize, linecache
import sys
import os
import types
import string
import re
import dis
import imp
import tokenize
import linecache
from operator import attrgetter
from collections import namedtuple
from compiler.consts import (CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS,
CO_VARKEYWORDS, CO_GENERATOR)
# ----------------------------------------------------------- type-checking
def ismodule(object):
@ -137,6 +148,33 @@ def isfunction(object):
func_name (same as __name__)"""
return isinstance(object, types.FunctionType)
def isgeneratorfunction(object):
"""Return true if the object is a user-defined generator function.
Generator function objects provides same attributes as functions.
See isfunction.__doc__ for attributes listing."""
if (isfunction(object) or ismethod(object)) and \
object.func_code.co_flags & CO_GENERATOR:
return True
def isgenerator(object):
"""Return true if the object is a generator.
Generator objects provide these attributes:
__iter__ defined to support interation over container
close raises a new GeneratorExit exception inside the
generator to terminate the iteration
gi_code code object
gi_frame frame object or possibly None once the generator has
been exhausted
gi_running set to 1 when generator is executing, 0 otherwise
next return the next item from the container
send resumes the generator and "sends" a value that becomes
the result of the current yield-expression
throw used to raise an exception inside the generator"""
return isinstance(object, types.GeneratorType)
def istraceback(object):
"""Return true if the object is a traceback.
@ -199,6 +237,10 @@ def isroutine(object):
or ismethod(object)
or ismethoddescriptor(object))
def isgenerator(object):
"""Return true if the object is a generator object."""
return isinstance(object, types.GeneratorType)
def getmembers(object, predicate=None):
"""Return all members of an object as (name, value) pairs sorted by name.
Optionally, only return members that satisfy a given predicate."""
@ -671,9 +713,6 @@ def getclasstree(classes, unique=0):
return walktree(roots, children, None)
# ------------------------------------------------ argument list extraction
# These constants are from Python's compile.h.
CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 1, 2, 4, 8
Arguments = namedtuple('Arguments', 'args varargs keywords')
def getargs(co):

View File

@ -11,10 +11,10 @@ from test import inspect_fodder2 as mod2
# Functions tested in this suite:
# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
# isbuiltin, isroutine, getmembers, getdoc, getfile, getmodule,
# getsourcefile, getcomments, getsource, getclasstree, getargspec,
# getargvalues, formatargspec, formatargvalues, currentframe, stack, trace
# isdatadescriptor
# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
# currentframe, stack, trace, isdatadescriptor
modfile = mod.__file__
if modfile.endswith(('c', 'o')):
@ -32,23 +32,33 @@ git = mod.StupidGit()
class IsTestBase(unittest.TestCase):
predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
inspect.isframe, inspect.isfunction, inspect.ismethod,
inspect.ismodule, inspect.istraceback])
inspect.ismodule, inspect.istraceback,
inspect.isgenerator, inspect.isgeneratorfunction])
def istest(self, predicate, exp):
obj = eval(exp)
self.failUnless(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
for other in self.predicates - set([predicate]):
if predicate == inspect.isgeneratorfunction and\
other == inspect.isfunction:
continue
self.failIf(other(obj), 'not %s(%s)' % (other.__name__, exp))
def generator_function_example(self):
for i in xrange(2):
yield i
class TestPredicates(IsTestBase):
def test_thirteen(self):
def test_fifteen(self):
count = len(filter(lambda x:x.startswith('is'), dir(inspect)))
# Doc/lib/libinspect.tex claims there are 13 such functions
expected = 13
# This test is here for remember you to update Doc/library/inspect.rst
# which claims there are 15 such functions
expected = 15
err_msg = "There are %d (not %d) is* functions" % (count, expected)
self.assertEqual(count, expected, err_msg)
def test_excluding_predicates(self):
self.istest(inspect.isbuiltin, 'sys.exit')
self.istest(inspect.isbuiltin, '[].append')
@ -62,6 +72,8 @@ class TestPredicates(IsTestBase):
self.istest(inspect.istraceback, 'tb')
self.istest(inspect.isdatadescriptor, '__builtin__.file.closed')
self.istest(inspect.isdatadescriptor, '__builtin__.file.softspace')
self.istest(inspect.isgenerator, '(x for x in xrange(2))')
self.istest(inspect.isgeneratorfunction, 'generator_function_example')
if hasattr(types, 'GetSetDescriptorType'):
self.istest(inspect.isgetsetdescriptor,
'type(tb.tb_frame).f_locals')

View File

@ -414,6 +414,8 @@ Core and builtins
Library
-------
- Issue #1916. Added isgenerator() and isgeneratorfunction() to inspect.py.
- ctypes instances that are not or do not contain pointers can now be
pickled.