diff options
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/inspect.py | 51 | ||||
-rw-r--r-- | Lib/test/test_inspect.py | 28 |
2 files changed, 65 insertions, 14 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py index 8ae50fc246..42f2c310bb 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -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): diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 0537d7ebd6..33bcfb4f79 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -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') |