|
From: <pj...@us...> - 2011-03-17 22:18:44
|
Revision: 7242
http://jython.svn.sourceforge.net/jython/?rev=7242&view=rev
Author: pjenvey
Date: 2011-03-17 22:18:37 +0000 (Thu, 17 Mar 2011)
Log Message:
-----------
update inspect/test_inspect to 2.6
we now pass test_inspect's test_getargspec_method and all of its
test_excluding_predicates
Modified Paths:
--------------
trunk/jython/Lib/inspect.py
trunk/jython/Lib/test/test_inspect.py
Modified: trunk/jython/Lib/inspect.py
===================================================================
--- trunk/jython/Lib/inspect.py 2011-03-16 05:44:13 UTC (rev 7241)
+++ trunk/jython/Lib/inspect.py 2011-03-17 22:18:37 UTC (rev 7242)
@@ -7,8 +7,9 @@
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,12 +29,27 @@
__author__ = 'Ka-Ping Yee <pi...@lf...>'
__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
_jython = sys.platform.startswith('java')
if _jython:
_ReflectedFunctionType = type(os.listdir)
+# These constants are from Include/code.h.
+CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 0x1, 0x2, 0x4, 0x8
+CO_NESTED, CO_GENERATOR, CO_NOFREE = 0x10, 0x20, 0x40
+# See Include/object.h
+TPFLAGS_IS_ABSTRACT = 1 << 20
+
# ----------------------------------------------------------- type-checking
def ismodule(object):
"""Return true if the object is a module.
@@ -139,6 +155,32 @@
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."""
+ return bool((isfunction(object) or ismethod(object)) and
+ object.func_code.co_flags & CO_GENERATOR)
+
+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.
@@ -202,6 +244,10 @@
or ismethoddescriptor(object)
or (_jython and isinstance(object, _ReflectedFunctionType)))
+def isabstract(object):
+ """Return true if the object is an abstract base class (ABC)."""
+ return isinstance(object, type) and object.__flags__ & TPFLAGS_IS_ABSTRACT
+
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."""
@@ -213,6 +259,8 @@
results.sort()
return results
+Attribute = namedtuple('Attribute', 'name kind defining_class object')
+
def classify_class_attrs(cls):
"""Return list of attribute-descriptor tuples.
@@ -279,7 +327,7 @@
else:
kind = "data"
- result.append((name, kind, homecls, obj))
+ result.append(Attribute(name, kind, homecls, obj))
return result
@@ -374,15 +422,18 @@
raise TypeError('arg is not a module, class, method, '
'function, traceback, frame, or code object')
+ModuleInfo = namedtuple('ModuleInfo', 'name suffix mode module_type')
+
def getmoduleinfo(path):
"""Get the module name, suffix, mode, and module type for a given file."""
filename = os.path.basename(path)
- suffixes = map(lambda (suffix, mode, mtype):
- (-len(suffix), suffix, mode, mtype), imp.get_suffixes())
+ suffixes = map(lambda info:
+ (-len(info[0]), info[0], info[1], info[2]),
+ imp.get_suffixes())
suffixes.sort() # try longest suffixes first, in case they overlap
for neglen, suffix, mode, mtype in suffixes:
if filename[neglen:] == suffix:
- return filename[:neglen], suffix, mode, mtype
+ return ModuleInfo(filename[:neglen], suffix, mode, mtype)
def getmodulename(path):
"""Return the module name for a given file, or None."""
@@ -581,7 +632,9 @@
self.passline = False
self.last = 1
- def tokeneater(self, type, token, (srow, scol), (erow, ecol), line):
+ def tokeneater(self, type, token, srow_scol, erow_ecol, line):
+ srow, scol = srow_scol
+ erow, ecol = erow_ecol
if not self.started:
# look for the first "def", "class" or "lambda"
if token in ("def", "class", "lambda"):
@@ -679,8 +732,7 @@
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):
"""Get information about the arguments accepted by a code object.
@@ -742,8 +794,10 @@
varkw = None
if co.co_flags & CO_VARKEYWORDS:
varkw = co.co_varnames[nargs]
- return args, varargs, varkw
+ return Arguments(args, varargs, varkw)
+ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults')
+
def getargspec(func):
"""Get the names and default values of a function's arguments.
@@ -758,8 +812,10 @@
if not isfunction(func):
raise TypeError('arg is not a Python function')
args, varargs, varkw = getargs(func.func_code)
- return args, varargs, varkw, func.func_defaults
+ return ArgSpec(args, varargs, varkw, func.func_defaults)
+ArgInfo = namedtuple('ArgInfo', 'args varargs keywords locals')
+
def getargvalues(frame):
"""Get information about arguments passed into a particular frame.
@@ -768,7 +824,7 @@
'varargs' and 'varkw' are the names of the * and ** arguments or None.
'locals' is the locals dictionary of the given frame."""
args, varargs, varkw = getargs(frame.f_code)
- return args, varargs, varkw, frame.f_locals
+ return ArgInfo(args, varargs, varkw, frame.f_locals)
def joinseq(seq):
if len(seq) == 1:
@@ -834,6 +890,9 @@
return '(' + string.join(specs, ', ') + ')'
# -------------------------------------------------- stack frame extraction
+
+Traceback = namedtuple('Traceback', 'filename lineno function code_context index')
+
def getframeinfo(frame, context=1):
"""Get information about a frame or traceback object.
@@ -865,7 +924,7 @@
else:
lines = index = None
- return (filename, lineno, frame.f_code.co_name, lines, index)
+ return Traceback(filename, lineno, frame.f_code.co_name, lines, index)
def getlineno(frame):
"""Get the line number from a frame object, allowing for optimization."""
@@ -894,7 +953,10 @@
tb = tb.tb_next
return framelist
-currentframe = sys._getframe
+if hasattr(sys, '_getframe'):
+ currentframe = sys._getframe
+else:
+ currentframe = lambda _=None: None
def stack(context=1):
"""Return a list of records for the stack above the caller's frame."""
Modified: trunk/jython/Lib/test/test_inspect.py
===================================================================
--- trunk/jython/Lib/test/test_inspect.py 2011-03-16 05:44:13 UTC (rev 7241)
+++ trunk/jython/Lib/test/test_inspect.py 2011-03-17 22:18:37 UTC (rev 7242)
@@ -4,19 +4,24 @@
import inspect
import datetime
-from test.test_support import TESTFN, run_unittest, is_jython
+from test.test_support import is_jython, run_unittest, _check_py3k_warnings
-from test import inspect_fodder as mod
-from test import inspect_fodder2 as mod2
-from test import test_support
+with _check_py3k_warnings(
+ ("tuple parameter unpacking has been removed", SyntaxWarning),
+ quiet=True):
+ from test import inspect_fodder as mod
+ 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
+# NOTE: There are some additional tests relating to interaction with
+# zipimport in the test_zipimport_support test module.
+
modfile = mod.__file__
if modfile.endswith(('c', 'o')):
modfile = modfile[:-1]
@@ -26,7 +31,7 @@
import __builtin__
try:
- 1/0
+ 1 // 0
except:
tb = sys.exc_traceback
@@ -44,27 +49,37 @@
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_sixteen(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 16 such functions
+ expected = 16
err_msg = "There are %d (not %d) is* functions" % (count, expected)
self.assertEqual(count, expected, err_msg)
+
def test_excluding_predicates(self):
- #XXX: Jython's PySystemState needs more work before this
- #will be doable.
- if not test_support.is_jython:
+ # XXX: Jython's PySystemState needs more work before this will
+ # be doable.
+ if not is_jython:
self.istest(inspect.isbuiltin, 'sys.exit')
self.istest(inspect.isbuiltin, '[].append')
self.istest(inspect.isclass, 'mod.StupidGit')
@@ -77,11 +92,12 @@
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')
- #XXX: This detail of PyFrames is not yet supported in Jython
- elif not test_support.is_jython:
+ else:
self.failIf(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
if hasattr(types, 'MemberDescriptorType'):
self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
@@ -120,7 +136,7 @@
self.assertEqual(git.tr[1][1:], (modfile, 9, 'spam',
[' eggs(b + d, c + f)\n'], 0))
self.assertEqual(git.tr[2][1:], (modfile, 18, 'eggs',
- [' q = y / 0\n'], 0))
+ [' q = y // 0\n'], 0))
def test_frame(self):
args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
@@ -194,6 +210,10 @@
self.assertEqual(inspect.getdoc(git.abuse),
'Another\n\ndocstring\n\ncontaining\n\ntabs')
+ def test_cleandoc(self):
+ self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
+ 'An\nindented\ndocstring.')
+
def test_getcomments(self):
self.assertEqual(inspect.getcomments(mod), '# line 1\n')
self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
@@ -224,9 +244,9 @@
self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
def test_getmodule_recursion(self):
- from new import module
+ from types import ModuleType
name = '__inspect_dummy'
- m = sys.modules[name] = module(name)
+ m = sys.modules[name] = ModuleType(name)
m.__file__ = "<string>" # hopefully not a real filename...
m.__loader__ = "dummy" # pretend the filename is understood by a loader
exec "def x(): pass" in m.__dict__
@@ -357,7 +377,6 @@
'g', 'h', (3, (4, (5,))),
'(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h)')
- @na_for_jython
def test_getargspec_method(self):
class A(object):
def m(self):
@@ -366,11 +385,14 @@
@na_for_jython
def test_getargspec_sublistofone(self):
- def sublistOfOne((foo,)): return 1
- self.assertArgSpecEquals(sublistOfOne, [['foo']])
+ with _check_py3k_warnings(
+ ("tuple parameter unpacking has been removed", SyntaxWarning),
+ ("parenthesized argument names are invalid", SyntaxWarning)):
+ exec 'def sublistOfOne((foo,)): return 1'
+ self.assertArgSpecEquals(sublistOfOne, [['foo']])
- def fakeSublistOfOne((foo)): return 1
- self.assertArgSpecEquals(fakeSublistOfOne, ['foo'])
+ exec 'def fakeSublistOfOne((foo)): return 1'
+ self.assertArgSpecEquals(fakeSublistOfOne, ['foo'])
def test_classify_oldstyle(self):
class A:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|