def spam(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h):
fr = inspect.currentframe()
def abuse(self, a, b, c): # a comment
def argue(self, a, b, c):
self.tr = inspect.trace()
class MalodorousPervert(StupidGit):
class FesteringGob(MalodorousPervert, ParrotDroppings):
# 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
from test
.test_support
import TestFailed
, TESTFN
import sys
, imp
, os
, string
def test(assertion
, message
, *args
):
raise TestFailed
, message
% args
# Note that load_source creates file TESTFN+'c' or TESTFN+'o'.
mod
= imp
.load_source('testmod', TESTFN
)
files_to_clean_up
= [TESTFN
, TESTFN
+ 'c', TESTFN
+ 'o']
test(func(obj
), '%s(%s)' % (func
.__name
__, exp
))
for other
in [inspect
.isbuiltin
, inspect
.isclass
, inspect
.iscode
,
inspect
.isframe
, inspect
.isfunction
, inspect
.ismethod
,
inspect
.ismodule
, inspect
.istraceback
]:
test(not other(obj
), 'not %s(%s)' % (other
.__name
__, exp
))
istest(inspect
.isbuiltin
, 'sys.exit')
istest(inspect
.isbuiltin
, '[].append')
istest(inspect
.isclass
, 'mod.StupidGit')
istest(inspect
.iscode
, 'mod.spam.func_code')
istest(inspect
.isframe
, 'tb.tb_frame')
istest(inspect
.isfunction
, 'mod.spam')
istest(inspect
.ismethod
, 'mod.StupidGit.abuse')
istest(inspect
.ismethod
, 'git.argue')
istest(inspect
.ismodule
, 'mod')
istest(inspect
.istraceback
, 'tb')
istest(inspect
.isdatadescriptor
, '__builtin__.file.closed')
istest(inspect
.isdatadescriptor
, '__builtin__.file.softspace')
test(inspect
.isroutine(mod
.spam
), 'isroutine(mod.spam)')
test(inspect
.isroutine([].count
), 'isroutine([].count)')
classes
= inspect
.getmembers(mod
, inspect
.isclass
)
[('FesteringGob', mod
.FesteringGob
),
('MalodorousPervert', mod
.MalodorousPervert
),
('ParrotDroppings', mod
.ParrotDroppings
),
('StupidGit', mod
.StupidGit
)], 'class list')
tree
= inspect
.getclasstree(map(lambda x
: x
[1], classes
), 1)
[(mod
.ParrotDroppings
, ()),
[(mod
.MalodorousPervert
, (mod
.StupidGit
,)),
[(mod
.FesteringGob
, (mod
.MalodorousPervert
, mod
.ParrotDroppings
))
functions
= inspect
.getmembers(mod
, inspect
.isfunction
)
test(functions
== [('eggs', mod
.eggs
), ('spam', mod
.spam
)], 'function list')
test(inspect
.getdoc(mod
) == 'A module docstring.', 'getdoc(mod)')
test(inspect
.getcomments(mod
) == '# line 1\n', 'getcomments(mod)')
test(inspect
.getmodule(mod
.StupidGit
) == mod
, 'getmodule(mod.StupidGit)')
test(inspect
.getfile(mod
.StupidGit
) == TESTFN
, 'getfile(mod.StupidGit)')
test(inspect
.getsourcefile(mod
.spam
) == TESTFN
, 'getsourcefile(mod.spam)')
test(inspect
.getsourcefile(git
.abuse
) == TESTFN
, 'getsourcefile(git.abuse)')
def sourcerange(top
, bottom
):
lines
= string
.split(source
, '\n')
return string
.join(lines
[top
-1:bottom
], '\n') + '\n'
test(inspect
.getsource(git
.abuse
) == sourcerange(29, 39),
test(inspect
.getsource(mod
.StupidGit
) == sourcerange(21, 46),
'getsource(mod.StupidGit)')
test(inspect
.getdoc(mod
.StupidGit
) ==
'A longer,\n\nindented\n\ndocstring.', 'getdoc(mod.StupidGit)')
test(inspect
.getdoc(git
.abuse
) ==
'Another\n\ndocstring\n\ncontaining\n\ntabs', 'getdoc(git.abuse)')
test(inspect
.getcomments(mod
.StupidGit
) == '# line 20\n',
'getcomments(mod.StupidGit)')
istest(inspect
.istraceback
, 'git.ex[2]')
istest(inspect
.isframe
, 'mod.fr')
test(len(git
.tr
) == 3, 'trace() length')
test(git
.tr
[0][1:] == (TESTFN
, 43, 'argue',
[' spam(a, b, c)\n'], 0),
test(git
.tr
[1][1:] == (TESTFN
, 9, 'spam', [' eggs(b + d, c + f)\n'], 0),
test(git
.tr
[2][1:] == (TESTFN
, 18, 'eggs', [' q = y / 0\n'], 0),
test(len(mod
.st
) >= 5, 'stack() length')
(TESTFN
, 16, 'eggs', [' st = inspect.stack()\n'], 0),
(TESTFN
, 9, 'spam', [' eggs(b + d, c + f)\n'], 0),
(TESTFN
, 43, 'argue', [' spam(a, b, c)\n'], 0),
(TESTFN
, 39, 'abuse', [' self.argue(a, b, c)\n'], 0),
args
, varargs
, varkw
, locals = inspect
.getargvalues(mod
.fr
)
test(args
== ['x', 'y'], 'mod.fr args')
test(varargs
== None, 'mod.fr varargs')
test(varkw
== None, 'mod.fr varkw')
test(locals == {'x': 11, 'p': 11, 'y': 14}, 'mod.fr locals')
test(inspect
.formatargvalues(args
, varargs
, varkw
, locals) ==
'(x=11, y=14)', 'mod.fr formatted argvalues')
args
, varargs
, varkw
, locals = inspect
.getargvalues(mod
.fr
.f_back
)
test(args
== ['a', 'b', 'c', 'd', ['e', ['f']]], 'mod.fr.f_back args')
test(varargs
== 'g', 'mod.fr.f_back varargs')
test(varkw
== 'h', 'mod.fr.f_back varkw')
test(inspect
.formatargvalues(args
, varargs
, varkw
, locals) ==
'(a=7, b=8, c=9, d=3, (e=4, (f=5,)), *g=(), **h={})',
'mod.fr.f_back formatted argvalues')
for fname
in files_to_clean_up
:
# Test for decorators as well.
# two decorators, one with argument
file = open(TESTFN
+ "2", "w")
files_to_clean_up
= [TESTFN
+ "2", TESTFN
+ '2c', TESTFN
+ '2o']
mod2
= imp
.load_source("testmod3", TESTFN
+ "2")
test(inspect
.getsource(mod2
.wrapped
) == sourcerange(13, 16),
"inspect.getsource(mod.wrapped)")
test(inspect
.getsource(mod2
.gone
) == sourcerange(8, 9),
"inspect.getsource(mod.gone)")
for fname
in files_to_clean_up
:
# Test classic-class method resolution order.
test(expected
== got
, "expected %r mro, got %r", expected
, got
)
# The same w/ new-class MRO.
expected
= (D
, B
, C
, A
, object)
test(expected
== got
, "expected %r mro, got %r", expected
, got
)
# Test classify_class_attrs.
return [t
[:3] for t
in inspect
.classify_class_attrs(cls
)]
test(('s', 'static method', A
) in attrs
, 'missing static method')
test(('c', 'class method', A
) in attrs
, 'missing class method')
test(('p', 'property', A
) in attrs
, 'missing property')
test(('m', 'method', A
) in attrs
, 'missing plain method')
test(('m1', 'method', A
) in attrs
, 'missing plain method')
test(('datablob', 'data', A
) in attrs
, 'missing data')
test(('s', 'static method', A
) in attrs
, 'missing static method')
test(('c', 'class method', A
) in attrs
, 'missing class method')
test(('p', 'property', A
) in attrs
, 'missing property')
test(('m', 'method', B
) in attrs
, 'missing plain method')
test(('m1', 'method', A
) in attrs
, 'missing plain method')
test(('datablob', 'data', A
) in attrs
, 'missing data')
test(('s', 'static method', A
) in attrs
, 'missing static method')
test(('c', 'method', C
) in attrs
, 'missing plain method')
test(('p', 'property', A
) in attrs
, 'missing property')
test(('m', 'method', C
) in attrs
, 'missing plain method')
test(('m1', 'method', A
) in attrs
, 'missing plain method')
test(('datablob', 'data', A
) in attrs
, 'missing data')
test(('s', 'static method', A
) in attrs
, 'missing static method')
test(('c', 'class method', A
) in attrs
, 'missing class method')
test(('p', 'property', A
) in attrs
, 'missing property')
test(('m', 'method', B
) in attrs
, 'missing plain method')
test(('m1', 'method', D
) in attrs
, 'missing plain method')
test(('datablob', 'data', A
) in attrs
, 'missing data')
# Repeat all that, but w/ new-style classes.
test(('s', 'static method', A
) in attrs
, 'missing static method')
test(('c', 'class method', A
) in attrs
, 'missing class method')
test(('p', 'property', A
) in attrs
, 'missing property')
test(('m', 'method', A
) in attrs
, 'missing plain method')
test(('m1', 'method', A
) in attrs
, 'missing plain method')
test(('datablob', 'data', A
) in attrs
, 'missing data')
test(('s', 'static method', A
) in attrs
, 'missing static method')
test(('c', 'class method', A
) in attrs
, 'missing class method')
test(('p', 'property', A
) in attrs
, 'missing property')
test(('m', 'method', B
) in attrs
, 'missing plain method')
test(('m1', 'method', A
) in attrs
, 'missing plain method')
test(('datablob', 'data', A
) in attrs
, 'missing data')
test(('s', 'static method', A
) in attrs
, 'missing static method')
test(('c', 'method', C
) in attrs
, 'missing plain method')
test(('p', 'property', A
) in attrs
, 'missing property')
test(('m', 'method', C
) in attrs
, 'missing plain method')
test(('m1', 'method', A
) in attrs
, 'missing plain method')
test(('datablob', 'data', A
) in attrs
, 'missing data')
test(('s', 'static method', A
) in attrs
, 'missing static method')
test(('c', 'method', C
) in attrs
, 'missing plain method')
test(('p', 'property', A
) in attrs
, 'missing property')
test(('m', 'method', B
) in attrs
, 'missing plain method')
test(('m1', 'method', D
) in attrs
, 'missing plain method')
test(('datablob', 'data', A
) in attrs
, 'missing data')
args
, varargs
, varkw
, defaults
= inspect
.getargspec(mod
.eggs
)
test(args
== ['x', 'y'], 'mod.eggs args')
test(varargs
== None, 'mod.eggs varargs')
test(varkw
== None, 'mod.eggs varkw')
test(defaults
== None, 'mod.eggs defaults')
test(inspect
.formatargspec(args
, varargs
, varkw
, defaults
) ==
'(x, y)', 'mod.eggs formatted argspec')
args
, varargs
, varkw
, defaults
= inspect
.getargspec(mod
.spam
)
test(args
== ['a', 'b', 'c', 'd', ['e', ['f']]], 'mod.spam args')
test(varargs
== 'g', 'mod.spam varargs')
test(varkw
== 'h', 'mod.spam varkw')
test(defaults
== (3, (4, (5,))), 'mod.spam defaults')
test(inspect
.formatargspec(args
, varargs
, varkw
, defaults
) ==
'(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h)',
'mod.spam formatted argspec')
args
, varargs
, varkw
, defaults
= inspect
.getargspec(A
.m
)
test(args
== ['self'], 'A.m args')
test(varargs
is None, 'A.m varargs')
test(varkw
is None, 'A.m varkw')
test(defaults
is None, 'A.m defaults')
# Doc/lib/libinspect.tex claims there are 11 such functions
count
= len(filter(lambda x
:x
.startswith('is'), dir(inspect
)))
test(count
== 11, "There are %d (not 11) is* functions", count
)
def sublistOfOne((foo
)): return 1
args
, varargs
, varkw
, defaults
= inspect
.getargspec(sublistOfOne
)
test(args
== [['foo']], 'sublistOfOne args')
test(varargs
is None, 'sublistOfOne varargs')
test(varkw
is None, 'sublistOfOne varkw')
test(defaults
is None, 'sublistOfOn defaults')