mirror of
https://github.com/python/cpython.git
synced 2025-11-02 19:12:55 +00:00
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
4 changed files with 104 additions and 15 deletions
|
|
@ -28,7 +28,7 @@ Types and members
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
The :func:`getmembers` function retrieves the members of an object such as a
|
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`.
|
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
|
They also help you determine when you can expect to find the following special
|
||||||
attributes:
|
attributes:
|
||||||
|
|
@ -81,6 +81,35 @@ attributes:
|
||||||
+-----------+-----------------+---------------------------+-------+
|
+-----------+-----------------+---------------------------+-------+
|
||||||
| | func_name | (same as __name__) | |
|
| | 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 | |
|
| traceback | tb_frame | frame object at this | |
|
||||||
| | | level | |
|
| | | level | |
|
||||||
+-----------+-----------------+---------------------------+-------+
|
+-----------+-----------------+---------------------------+-------+
|
||||||
|
|
@ -246,6 +275,13 @@ Note:
|
||||||
|
|
||||||
Return true if the object is a Python function or unnamed (:term:`lambda`) function.
|
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)
|
.. 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:
|
Here are some of the useful functions provided by this module:
|
||||||
|
|
||||||
ismodule(), isclass(), ismethod(), isfunction(), istraceback(),
|
ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(),
|
||||||
isframe(), iscode(), isbuiltin(), isroutine() - check object types
|
isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(),
|
||||||
|
isroutine() - check object types
|
||||||
getmembers() - get members of an object that satisfy a given condition
|
getmembers() - get members of an object that satisfy a given condition
|
||||||
|
|
||||||
getfile(), getsourcefile(), getsource() - find an object's source code
|
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>'
|
__author__ = 'Ka-Ping Yee <ping@lfw.org>'
|
||||||
__date__ = '1 Jan 2001'
|
__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 operator import attrgetter
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
from compiler.consts import (CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS,
|
||||||
|
CO_VARKEYWORDS, CO_GENERATOR)
|
||||||
|
|
||||||
# ----------------------------------------------------------- type-checking
|
# ----------------------------------------------------------- type-checking
|
||||||
def ismodule(object):
|
def ismodule(object):
|
||||||
|
|
@ -137,6 +148,33 @@ def isfunction(object):
|
||||||
func_name (same as __name__)"""
|
func_name (same as __name__)"""
|
||||||
return isinstance(object, types.FunctionType)
|
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):
|
def istraceback(object):
|
||||||
"""Return true if the object is a traceback.
|
"""Return true if the object is a traceback.
|
||||||
|
|
||||||
|
|
@ -199,6 +237,10 @@ def isroutine(object):
|
||||||
or ismethod(object)
|
or ismethod(object)
|
||||||
or ismethoddescriptor(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):
|
def getmembers(object, predicate=None):
|
||||||
"""Return all members of an object as (name, value) pairs sorted by name.
|
"""Return all members of an object as (name, value) pairs sorted by name.
|
||||||
Optionally, only return members that satisfy a given predicate."""
|
Optionally, only return members that satisfy a given predicate."""
|
||||||
|
|
@ -671,9 +713,6 @@ def getclasstree(classes, unique=0):
|
||||||
return walktree(roots, children, None)
|
return walktree(roots, children, None)
|
||||||
|
|
||||||
# ------------------------------------------------ argument list extraction
|
# ------------------------------------------------ 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')
|
Arguments = namedtuple('Arguments', 'args varargs keywords')
|
||||||
|
|
||||||
def getargs(co):
|
def getargs(co):
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,10 @@ from test import inspect_fodder2 as mod2
|
||||||
|
|
||||||
# Functions tested in this suite:
|
# Functions tested in this suite:
|
||||||
# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
|
# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
|
||||||
# isbuiltin, isroutine, getmembers, getdoc, getfile, getmodule,
|
# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
|
||||||
# getsourcefile, getcomments, getsource, getclasstree, getargspec,
|
# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
|
||||||
# getargvalues, formatargspec, formatargvalues, currentframe, stack, trace
|
# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
|
||||||
# isdatadescriptor
|
# currentframe, stack, trace, isdatadescriptor
|
||||||
|
|
||||||
modfile = mod.__file__
|
modfile = mod.__file__
|
||||||
if modfile.endswith(('c', 'o')):
|
if modfile.endswith(('c', 'o')):
|
||||||
|
|
@ -32,23 +32,33 @@ git = mod.StupidGit()
|
||||||
class IsTestBase(unittest.TestCase):
|
class IsTestBase(unittest.TestCase):
|
||||||
predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
|
predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
|
||||||
inspect.isframe, inspect.isfunction, inspect.ismethod,
|
inspect.isframe, inspect.isfunction, inspect.ismethod,
|
||||||
inspect.ismodule, inspect.istraceback])
|
inspect.ismodule, inspect.istraceback,
|
||||||
|
inspect.isgenerator, inspect.isgeneratorfunction])
|
||||||
|
|
||||||
def istest(self, predicate, exp):
|
def istest(self, predicate, exp):
|
||||||
obj = eval(exp)
|
obj = eval(exp)
|
||||||
self.failUnless(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
|
self.failUnless(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
|
||||||
|
|
||||||
for other in self.predicates - set([predicate]):
|
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))
|
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):
|
class TestPredicates(IsTestBase):
|
||||||
def test_thirteen(self):
|
def test_fifteen(self):
|
||||||
count = len(filter(lambda x:x.startswith('is'), dir(inspect)))
|
count = len(filter(lambda x:x.startswith('is'), dir(inspect)))
|
||||||
# Doc/lib/libinspect.tex claims there are 13 such functions
|
# This test is here for remember you to update Doc/library/inspect.rst
|
||||||
expected = 13
|
# which claims there are 15 such functions
|
||||||
|
expected = 15
|
||||||
err_msg = "There are %d (not %d) is* functions" % (count, expected)
|
err_msg = "There are %d (not %d) is* functions" % (count, expected)
|
||||||
self.assertEqual(count, expected, err_msg)
|
self.assertEqual(count, expected, err_msg)
|
||||||
|
|
||||||
|
|
||||||
def test_excluding_predicates(self):
|
def test_excluding_predicates(self):
|
||||||
self.istest(inspect.isbuiltin, 'sys.exit')
|
self.istest(inspect.isbuiltin, 'sys.exit')
|
||||||
self.istest(inspect.isbuiltin, '[].append')
|
self.istest(inspect.isbuiltin, '[].append')
|
||||||
|
|
@ -62,6 +72,8 @@ class TestPredicates(IsTestBase):
|
||||||
self.istest(inspect.istraceback, 'tb')
|
self.istest(inspect.istraceback, 'tb')
|
||||||
self.istest(inspect.isdatadescriptor, '__builtin__.file.closed')
|
self.istest(inspect.isdatadescriptor, '__builtin__.file.closed')
|
||||||
self.istest(inspect.isdatadescriptor, '__builtin__.file.softspace')
|
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'):
|
if hasattr(types, 'GetSetDescriptorType'):
|
||||||
self.istest(inspect.isgetsetdescriptor,
|
self.istest(inspect.isgetsetdescriptor,
|
||||||
'type(tb.tb_frame).f_locals')
|
'type(tb.tb_frame).f_locals')
|
||||||
|
|
|
||||||
|
|
@ -414,6 +414,8 @@ Core and builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #1916. Added isgenerator() and isgeneratorfunction() to inspect.py.
|
||||||
|
|
||||||
- ctypes instances that are not or do not contain pointers can now be
|
- ctypes instances that are not or do not contain pointers can now be
|
||||||
pickled.
|
pickled.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue