Issue #1916. Added isgenerator() and isgeneratorfunction() to
inspect.py. Thanks Javi Mansilla for patch review and corrections.
This commit is contained in:
parent
b169eaa917
commit
759bfc6207
|
@ -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)
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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')
|
||||
|
|
Loading…
Reference in New Issue