blob: 23e12894d72d69ccae5e0a177d30ad27192b595e [file] [log] [blame]
Benjamin Peterson7e213252010-03-30 17:58:13 +00001import re
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002import sys
Barry Warsaw00decd72006-07-27 23:43:15 +00003import types
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004import unittest
5import inspect
Barry Warsaw00decd72006-07-27 23:43:15 +00006import datetime
Benjamin Peterson7e213252010-03-30 17:58:13 +00007from UserList import UserList
8from UserDict import UserDict
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +00009
Florent Xicluna07627882010-03-21 01:14:24 +000010from test.test_support import run_unittest, check_py3k_warnings
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000011
Florent Xicluna07627882010-03-21 01:14:24 +000012with check_py3k_warnings(
13 ("tuple parameter unpacking has been removed", SyntaxWarning),
14 quiet=True):
15 from test import inspect_fodder as mod
16 from test import inspect_fodder2 as mod2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000017
R. David Murray996ba022009-05-13 17:14:11 +000018# C module for test_findsource_binary
R. David Murray87855542009-05-14 16:12:57 +000019import unicodedata
R. David Murray996ba022009-05-13 17:14:11 +000020
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000021# Functions tested in this suite:
22# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Facundo Batista759bfc62008-02-18 03:43:43 +000023# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
24# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
25# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
26# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000027
Nick Coghlana2053472008-12-14 10:54:50 +000028# NOTE: There are some additional tests relating to interaction with
29# zipimport in the test_zipimport_support test module.
30
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000031modfile = mod.__file__
Georg Brandlb2afe852006-06-09 20:43:48 +000032if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000033 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000034
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000035import __builtin__
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000036
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000037try:
Florent Xicluna07627882010-03-21 01:14:24 +000038 1 // 0
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000039except:
40 tb = sys.exc_traceback
41
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000042git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000043
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000044class IsTestBase(unittest.TestCase):
45 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
46 inspect.isframe, inspect.isfunction, inspect.ismethod,
Facundo Batista759bfc62008-02-18 03:43:43 +000047 inspect.ismodule, inspect.istraceback,
48 inspect.isgenerator, inspect.isgeneratorfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000049
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000050 def istest(self, predicate, exp):
51 obj = eval(exp)
Benjamin Peterson5c8da862009-06-30 22:57:08 +000052 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000053
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000054 for other in self.predicates - set([predicate]):
Facundo Batista759bfc62008-02-18 03:43:43 +000055 if predicate == inspect.isgeneratorfunction and\
56 other == inspect.isfunction:
57 continue
Benjamin Peterson5c8da862009-06-30 22:57:08 +000058 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000059
Facundo Batista759bfc62008-02-18 03:43:43 +000060def generator_function_example(self):
61 for i in xrange(2):
62 yield i
63
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000064class TestPredicates(IsTestBase):
Christian Heimes728bee82008-03-03 20:30:29 +000065 def test_sixteen(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000066 count = len(filter(lambda x:x.startswith('is'), dir(inspect)))
Facundo Batista759bfc62008-02-18 03:43:43 +000067 # This test is here for remember you to update Doc/library/inspect.rst
Georg Brandl26bc1772008-03-03 20:39:00 +000068 # which claims there are 16 such functions
Christian Heimes728bee82008-03-03 20:30:29 +000069 expected = 16
Neal Norwitzdf80af72006-07-28 04:22:34 +000070 err_msg = "There are %d (not %d) is* functions" % (count, expected)
71 self.assertEqual(count, expected, err_msg)
Tim Peters5a9fb3c2005-01-07 16:01:32 +000072
Facundo Batista759bfc62008-02-18 03:43:43 +000073
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000074 def test_excluding_predicates(self):
75 self.istest(inspect.isbuiltin, 'sys.exit')
76 self.istest(inspect.isbuiltin, '[].append')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000077 self.istest(inspect.iscode, 'mod.spam.func_code')
78 self.istest(inspect.isframe, 'tb.tb_frame')
79 self.istest(inspect.isfunction, 'mod.spam')
80 self.istest(inspect.ismethod, 'mod.StupidGit.abuse')
81 self.istest(inspect.ismethod, 'git.argue')
82 self.istest(inspect.ismodule, 'mod')
83 self.istest(inspect.istraceback, 'tb')
84 self.istest(inspect.isdatadescriptor, '__builtin__.file.closed')
85 self.istest(inspect.isdatadescriptor, '__builtin__.file.softspace')
Facundo Batista759bfc62008-02-18 03:43:43 +000086 self.istest(inspect.isgenerator, '(x for x in xrange(2))')
87 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Barry Warsaw00decd72006-07-27 23:43:15 +000088 if hasattr(types, 'GetSetDescriptorType'):
89 self.istest(inspect.isgetsetdescriptor,
90 'type(tb.tb_frame).f_locals')
91 else:
Benjamin Peterson5c8da862009-06-30 22:57:08 +000092 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
Barry Warsaw00decd72006-07-27 23:43:15 +000093 if hasattr(types, 'MemberDescriptorType'):
94 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
95 else:
Benjamin Peterson5c8da862009-06-30 22:57:08 +000096 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000097
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000098 def test_isroutine(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +000099 self.assertTrue(inspect.isroutine(mod.spam))
100 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000101
Benjamin Peterson5e5fbb62009-01-17 22:27:54 +0000102 def test_isclass(self):
103 self.istest(inspect.isclass, 'mod.StupidGit')
104 self.assertTrue(inspect.isclass(list))
105
106 class newstyle(object): pass
107 self.assertTrue(inspect.isclass(newstyle))
108
109 class CustomGetattr(object):
110 def __getattr__(self, attr):
111 return None
112 self.assertFalse(inspect.isclass(CustomGetattr()))
113
Amaury Forgeot d'Arcb54447f2009-01-13 23:39:22 +0000114 def test_get_slot_members(self):
115 class C(object):
116 __slots__ = ("a", "b")
117
118 x = C()
119 x.a = 42
120 members = dict(inspect.getmembers(x))
Ezio Melottiaa980582010-01-23 23:04:36 +0000121 self.assertIn('a', members)
122 self.assertNotIn('b', members)
Amaury Forgeot d'Arcb54447f2009-01-13 23:39:22 +0000123
Benjamin Petersonc63457b2009-10-15 03:06:55 +0000124 def test_isabstract(self):
125 from abc import ABCMeta, abstractmethod
126
127 class AbstractClassExample(object):
128 __metaclass__ = ABCMeta
129
130 @abstractmethod
131 def foo(self):
132 pass
133
134 class ClassExample(AbstractClassExample):
135 def foo(self):
136 pass
137
138 a = ClassExample()
139
140 # Test general behaviour.
141 self.assertTrue(inspect.isabstract(AbstractClassExample))
142 self.assertFalse(inspect.isabstract(ClassExample))
143 self.assertFalse(inspect.isabstract(a))
144 self.assertFalse(inspect.isabstract(int))
145 self.assertFalse(inspect.isabstract(5))
146
Amaury Forgeot d'Arcb54447f2009-01-13 23:39:22 +0000147
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000148class TestInterpreterStack(IsTestBase):
149 def __init__(self, *args, **kwargs):
150 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000151
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000152 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000153
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000154 def test_abuse_done(self):
155 self.istest(inspect.istraceback, 'git.ex[2]')
156 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000157
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000158 def test_stack(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000159 self.assertTrue(len(mod.st) >= 5)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000160 self.assertEqual(mod.st[0][1:],
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000161 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000162 self.assertEqual(mod.st[1][1:],
163 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
164 self.assertEqual(mod.st[2][1:],
165 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
166 self.assertEqual(mod.st[3][1:],
167 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000168
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000169 def test_trace(self):
170 self.assertEqual(len(git.tr), 3)
171 self.assertEqual(git.tr[0][1:], (modfile, 43, 'argue',
172 [' spam(a, b, c)\n'], 0))
173 self.assertEqual(git.tr[1][1:], (modfile, 9, 'spam',
174 [' eggs(b + d, c + f)\n'], 0))
175 self.assertEqual(git.tr[2][1:], (modfile, 18, 'eggs',
Mark Dickinsonc68e9f02010-02-03 16:50:14 +0000176 [' q = y // 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000177
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000178 def test_frame(self):
179 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
180 self.assertEqual(args, ['x', 'y'])
181 self.assertEqual(varargs, None)
182 self.assertEqual(varkw, None)
183 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
184 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
185 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000186
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000187 def test_previous_frame(self):
188 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
189 self.assertEqual(args, ['a', 'b', 'c', 'd', ['e', ['f']]])
190 self.assertEqual(varargs, 'g')
191 self.assertEqual(varkw, 'h')
192 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
193 '(a=7, b=8, c=9, d=3, (e=4, (f=5,)), *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000194
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000195class GetSourceBase(unittest.TestCase):
196 # Subclasses must override.
197 fodderFile = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000198
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000199 def __init__(self, *args, **kwargs):
200 unittest.TestCase.__init__(self, *args, **kwargs)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000201
Philip Jenvey6a111022009-05-28 05:58:44 +0000202 with open(inspect.getsourcefile(self.fodderFile)) as fp:
203 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000204
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000205 def sourcerange(self, top, bottom):
206 lines = self.source.split("\n")
207 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000208
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000209 def assertSourceEqual(self, obj, top, bottom):
210 self.assertEqual(inspect.getsource(obj),
211 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000212
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000213class TestRetrievingSourceCode(GetSourceBase):
214 fodderFile = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000215
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000216 def test_getclasses(self):
217 classes = inspect.getmembers(mod, inspect.isclass)
218 self.assertEqual(classes,
219 [('FesteringGob', mod.FesteringGob),
220 ('MalodorousPervert', mod.MalodorousPervert),
221 ('ParrotDroppings', mod.ParrotDroppings),
222 ('StupidGit', mod.StupidGit)])
223 tree = inspect.getclasstree([cls[1] for cls in classes], 1)
224 self.assertEqual(tree,
225 [(mod.ParrotDroppings, ()),
226 (mod.StupidGit, ()),
227 [(mod.MalodorousPervert, (mod.StupidGit,)),
228 [(mod.FesteringGob, (mod.MalodorousPervert,
229 mod.ParrotDroppings))
230 ]
231 ]
232 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000233
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000234 def test_getfunctions(self):
235 functions = inspect.getmembers(mod, inspect.isfunction)
236 self.assertEqual(functions, [('eggs', mod.eggs),
237 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000238
R. David Murrayf28fd242010-02-23 00:24:49 +0000239 @unittest.skipIf(sys.flags.optimize >= 2,
240 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000241 def test_getdoc(self):
242 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
243 self.assertEqual(inspect.getdoc(mod.StupidGit),
244 'A longer,\n\nindented\n\ndocstring.')
245 self.assertEqual(inspect.getdoc(git.abuse),
246 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000247
Georg Brandl7be19aa2008-06-07 15:59:10 +0000248 def test_cleandoc(self):
249 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
250 'An\nindented\ndocstring.')
251
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000252 def test_getcomments(self):
253 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
254 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000255
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000256 def test_getmodule(self):
Nick Coghlanc495c662006-09-07 10:50:34 +0000257 # Check actual module
258 self.assertEqual(inspect.getmodule(mod), mod)
259 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000260 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Nick Coghlanc495c662006-09-07 10:50:34 +0000261 # Check a method (no __module__ attribute, falls back to filename)
262 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
263 # Do it again (check the caching isn't broken)
264 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
265 # Check a builtin
266 self.assertEqual(inspect.getmodule(str), sys.modules["__builtin__"])
267 # Check filename override
268 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000269
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000270 def test_getsource(self):
271 self.assertSourceEqual(git.abuse, 29, 39)
272 self.assertSourceEqual(mod.StupidGit, 21, 46)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000273
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000274 def test_getsourcefile(self):
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000275 self.assertEqual(inspect.getsourcefile(mod.spam), modfile)
276 self.assertEqual(inspect.getsourcefile(git.abuse), modfile)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000277
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000278 def test_getfile(self):
279 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000280
Phillip J. Eby5d86bdb2006-07-10 19:03:29 +0000281 def test_getmodule_recursion(self):
Christian Heimesc756d002007-11-27 21:34:01 +0000282 from types import ModuleType
Phillip J. Eby5d86bdb2006-07-10 19:03:29 +0000283 name = '__inspect_dummy'
Christian Heimesc756d002007-11-27 21:34:01 +0000284 m = sys.modules[name] = ModuleType(name)
Tim Peters722b8832006-07-10 21:11:49 +0000285 m.__file__ = "<string>" # hopefully not a real filename...
Phillip J. Eby5d86bdb2006-07-10 19:03:29 +0000286 m.__loader__ = "dummy" # pretend the filename is understood by a loader
287 exec "def x(): pass" in m.__dict__
288 self.assertEqual(inspect.getsourcefile(m.x.func_code), '<string>')
289 del sys.modules[name]
Phillip J. Eby1a2959c2006-07-20 15:54:16 +0000290 inspect.getmodule(compile('a=10','','single'))
Phillip J. Eby5d86bdb2006-07-10 19:03:29 +0000291
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000292class TestDecorators(GetSourceBase):
293 fodderFile = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000294
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000295 def test_wrapped_decorator(self):
296 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000297
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000298 def test_replacing_decorator(self):
299 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000300
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000301class TestOneliners(GetSourceBase):
302 fodderFile = mod2
303 def test_oneline_lambda(self):
304 # Test inspect.getsource with a one-line lambda function.
305 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000306
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000307 def test_threeline_lambda(self):
308 # Test inspect.getsource with a three-line lambda function,
309 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000310 self.assertSourceEqual(mod2.tll, 28, 30)
311
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000312 def test_twoline_indented_lambda(self):
313 # Test inspect.getsource with a two-line lambda function,
314 # where the second line _is_ indented.
315 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000316
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000317 def test_onelinefunc(self):
318 # Test inspect.getsource with a regular one-line function.
319 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000320
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000321 def test_manyargs(self):
322 # Test inspect.getsource with a regular function where
323 # the arguments are on two lines and _not_ indented and
324 # the body on the second line with the last arguments.
325 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000326
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000327 def test_twolinefunc(self):
328 # Test inspect.getsource with a regular function where
329 # the body is on two lines, following the argument list and
330 # continued on the next line by a \\.
331 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000332
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000333 def test_lambda_in_list(self):
334 # Test inspect.getsource with a one-line lambda function
335 # defined in a list, indented.
336 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000337
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000338 def test_anonymous(self):
339 # Test inspect.getsource with a lambda function defined
340 # as argument to another function.
341 self.assertSourceEqual(mod2.anonymous, 55, 55)
342
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000343class TestBuggyCases(GetSourceBase):
344 fodderFile = mod2
345
346 def test_with_comment(self):
347 self.assertSourceEqual(mod2.with_comment, 58, 59)
348
349 def test_multiline_sig(self):
350 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
351
Armin Rigodd5c0232005-09-25 11:45:45 +0000352 def test_nested_class(self):
353 self.assertSourceEqual(mod2.func69().func71, 71, 72)
354
355 def test_one_liner_followed_by_non_name(self):
356 self.assertSourceEqual(mod2.func77, 77, 77)
357
358 def test_one_liner_dedent_non_name(self):
359 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
360
361 def test_with_comment_instead_of_docstring(self):
362 self.assertSourceEqual(mod2.func88, 88, 90)
363
Georg Brandl2463f8f2006-08-14 21:34:08 +0000364 def test_method_in_dynamic_class(self):
365 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
366
R. David Murray87855542009-05-14 16:12:57 +0000367 @unittest.skipIf(
368 not hasattr(unicodedata, '__file__') or
369 unicodedata.__file__[-4:] in (".pyc", ".pyo"),
370 "unicodedata is not an external binary module")
R. David Murray996ba022009-05-13 17:14:11 +0000371 def test_findsource_binary(self):
R. David Murray87855542009-05-14 16:12:57 +0000372 self.assertRaises(IOError, inspect.getsource, unicodedata)
373 self.assertRaises(IOError, inspect.findsource, unicodedata)
R. David Murray996ba022009-05-13 17:14:11 +0000374
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000375# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000376def attrs_wo_objs(cls):
377 return [t[:3] for t in inspect.classify_class_attrs(cls)]
378
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000379class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000380 def test_classic_mro(self):
381 # Test classic-class method resolution order.
382 class A: pass
383 class B(A): pass
384 class C(A): pass
385 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000386
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000387 expected = (D, B, A, C)
388 got = inspect.getmro(D)
389 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000390
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000391 def test_newstyle_mro(self):
392 # The same w/ new-class MRO.
393 class A(object): pass
394 class B(A): pass
395 class C(A): pass
396 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000397
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000398 expected = (D, B, C, A, object)
399 got = inspect.getmro(D)
400 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000401
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000402 def assertArgSpecEquals(self, routine, args_e, varargs_e = None,
403 varkw_e = None, defaults_e = None,
404 formatted = None):
405 args, varargs, varkw, defaults = inspect.getargspec(routine)
406 self.assertEqual(args, args_e)
407 self.assertEqual(varargs, varargs_e)
408 self.assertEqual(varkw, varkw_e)
409 self.assertEqual(defaults, defaults_e)
410 if formatted is not None:
411 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
412 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000413
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000414 def test_getargspec(self):
415 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted = '(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000416
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000417 self.assertArgSpecEquals(mod.spam,
418 ['a', 'b', 'c', 'd', ['e', ['f']]],
419 'g', 'h', (3, (4, (5,))),
420 '(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000421
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000422 def test_getargspec_method(self):
423 class A(object):
424 def m(self):
425 pass
426 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000427
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000428 def test_getargspec_sublistofone(self):
Florent Xicluna07627882010-03-21 01:14:24 +0000429 with check_py3k_warnings(
430 ("tuple parameter unpacking has been removed", SyntaxWarning),
431 ("parenthesized argument names are invalid", SyntaxWarning)):
432 exec 'def sublistOfOne((foo,)): return 1'
433 self.assertArgSpecEquals(sublistOfOne, [['foo']])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000434
Florent Xicluna07627882010-03-21 01:14:24 +0000435 exec 'def fakeSublistOfOne((foo)): return 1'
436 self.assertArgSpecEquals(fakeSublistOfOne, ['foo'])
Neal Norwitz33b730e2006-03-27 08:58:23 +0000437
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000438 def test_classify_oldstyle(self):
439 class A:
440 def s(): pass
441 s = staticmethod(s)
442
443 def c(cls): pass
444 c = classmethod(c)
445
446 def getp(self): pass
447 p = property(getp)
448
449 def m(self): pass
450
451 def m1(self): pass
452
453 datablob = '1'
454
455 attrs = attrs_wo_objs(A)
Ezio Melottiaa980582010-01-23 23:04:36 +0000456 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
457 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
458 self.assertIn(('p', 'property', A), attrs, 'missing property')
459 self.assertIn(('m', 'method', A), attrs, 'missing plain method')
460 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
461 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000462
463 class B(A):
464 def m(self): pass
465
466 attrs = attrs_wo_objs(B)
Ezio Melottiaa980582010-01-23 23:04:36 +0000467 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
468 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
469 self.assertIn(('p', 'property', A), attrs, 'missing property')
470 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
471 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
472 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Tim Peters13b49d32001-09-23 02:00:29 +0000473
474
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000475 class C(A):
476 def m(self): pass
477 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000478
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000479 attrs = attrs_wo_objs(C)
Ezio Melottiaa980582010-01-23 23:04:36 +0000480 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
481 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
482 self.assertIn(('p', 'property', A), attrs, 'missing property')
483 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
484 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
485 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Tim Peters13b49d32001-09-23 02:00:29 +0000486
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000487 class D(B, C):
488 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000489
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000490 attrs = attrs_wo_objs(D)
Ezio Melottiaa980582010-01-23 23:04:36 +0000491 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
492 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
493 self.assertIn(('p', 'property', A), attrs, 'missing property')
494 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
495 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
496 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Tim Peters13b49d32001-09-23 02:00:29 +0000497
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000498 # Repeat all that, but w/ new-style classes.
499 def test_classify_newstyle(self):
500 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000501
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000502 def s(): pass
503 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000504
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000505 def c(cls): pass
506 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000507
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000508 def getp(self): pass
509 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000510
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000511 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000512
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000513 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000514
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000515 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000516
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000517 attrs = attrs_wo_objs(A)
Ezio Melottiaa980582010-01-23 23:04:36 +0000518 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
519 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
520 self.assertIn(('p', 'property', A), attrs, 'missing property')
521 self.assertIn(('m', 'method', A), attrs, 'missing plain method')
522 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
523 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Tim Peters13b49d32001-09-23 02:00:29 +0000524
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000525 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000526
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000527 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000528
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000529 attrs = attrs_wo_objs(B)
Ezio Melottiaa980582010-01-23 23:04:36 +0000530 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
531 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
532 self.assertIn(('p', 'property', A), attrs, 'missing property')
533 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
534 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
535 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Tim Peters13b49d32001-09-23 02:00:29 +0000536
537
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000538 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000539
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000540 def m(self): pass
541 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000542
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000543 attrs = attrs_wo_objs(C)
Ezio Melottiaa980582010-01-23 23:04:36 +0000544 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
545 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
546 self.assertIn(('p', 'property', A), attrs, 'missing property')
547 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
548 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
549 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Tim Peters13b49d32001-09-23 02:00:29 +0000550
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000551 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000552
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000553 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000554
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000555 attrs = attrs_wo_objs(D)
Ezio Melottiaa980582010-01-23 23:04:36 +0000556 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
557 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
558 self.assertIn(('p', 'property', A), attrs, 'missing property')
559 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
560 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
561 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000562
Benjamin Peterson7e213252010-03-30 17:58:13 +0000563class TestGetcallargsFunctions(unittest.TestCase):
564
565 # tuple parameters are named '.1', '.2', etc.
566 is_tuplename = re.compile(r'^\.\d+$').match
567
568 def assertEqualCallArgs(self, func, call_params_string, locs=None):
569 locs = dict(locs or {}, func=func)
570 r1 = eval('func(%s)' % call_params_string, None, locs)
571 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
572 locs)
573 self.assertEqual(r1, r2)
574
575 def assertEqualException(self, func, call_param_string, locs=None):
576 locs = dict(locs or {}, func=func)
577 try:
578 eval('func(%s)' % call_param_string, None, locs)
579 except Exception, ex1:
580 pass
581 else:
582 self.fail('Exception not raised')
583 try:
584 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
585 locs)
586 except Exception, ex2:
587 pass
588 else:
589 self.fail('Exception not raised')
590 self.assertIs(type(ex1), type(ex2))
591 self.assertEqual(str(ex1), str(ex2))
592
593 def makeCallable(self, signature):
594 """Create a function that returns its locals(), excluding the
595 autogenerated '.1', '.2', etc. tuple param names (if any)."""
Ezio Melottifcc500e2010-03-31 08:33:50 +0000596 with check_py3k_warnings(
597 ("tuple parameter unpacking has been removed", SyntaxWarning),
598 quiet=True):
599 code = ("lambda %s: dict(i for i in locals().items() "
600 "if not is_tuplename(i[0]))")
601 return eval(code % signature, {'is_tuplename' : self.is_tuplename})
Benjamin Peterson7e213252010-03-30 17:58:13 +0000602
603 def test_plain(self):
604 f = self.makeCallable('a, b=1')
605 self.assertEqualCallArgs(f, '2')
606 self.assertEqualCallArgs(f, '2, 3')
607 self.assertEqualCallArgs(f, 'a=2')
608 self.assertEqualCallArgs(f, 'b=3, a=2')
609 self.assertEqualCallArgs(f, '2, b=3')
610 # expand *iterable / **mapping
611 self.assertEqualCallArgs(f, '*(2,)')
612 self.assertEqualCallArgs(f, '*[2]')
613 self.assertEqualCallArgs(f, '*(2, 3)')
614 self.assertEqualCallArgs(f, '*[2, 3]')
615 self.assertEqualCallArgs(f, '**{"a":2}')
616 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
617 self.assertEqualCallArgs(f, '2, **{"b":3}')
618 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
619 # expand UserList / UserDict
620 self.assertEqualCallArgs(f, '*UserList([2])')
621 self.assertEqualCallArgs(f, '*UserList([2, 3])')
622 self.assertEqualCallArgs(f, '**UserDict(a=2)')
623 self.assertEqualCallArgs(f, '2, **UserDict(b=3)')
624 self.assertEqualCallArgs(f, 'b=2, **UserDict(a=3)')
625 # unicode keyword args
626 self.assertEqualCallArgs(f, '**{u"a":2}')
627 self.assertEqualCallArgs(f, 'b=3, **{u"a":2}')
628 self.assertEqualCallArgs(f, '2, **{u"b":3}')
629 self.assertEqualCallArgs(f, '**{u"b":3, u"a":2}')
630
631 def test_varargs(self):
632 f = self.makeCallable('a, b=1, *c')
633 self.assertEqualCallArgs(f, '2')
634 self.assertEqualCallArgs(f, '2, 3')
635 self.assertEqualCallArgs(f, '2, 3, 4')
636 self.assertEqualCallArgs(f, '*(2,3,4)')
637 self.assertEqualCallArgs(f, '2, *[3,4]')
638 self.assertEqualCallArgs(f, '2, 3, *UserList([4])')
639
640 def test_varkw(self):
641 f = self.makeCallable('a, b=1, **c')
642 self.assertEqualCallArgs(f, 'a=2')
643 self.assertEqualCallArgs(f, '2, b=3, c=4')
644 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
645 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
646 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
647 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
648 self.assertEqualCallArgs(f, '**UserDict(a=2, b=3, c=4)')
649 self.assertEqualCallArgs(f, '2, c=4, **UserDict(b=3)')
650 self.assertEqualCallArgs(f, 'b=2, **UserDict(a=3, c=4)')
651 # unicode keyword args
652 self.assertEqualCallArgs(f, 'c=4, **{u"a":2, u"b":3}')
653 self.assertEqualCallArgs(f, '2, c=4, **{u"b":3}')
654 self.assertEqualCallArgs(f, 'b=2, **{u"a":3, u"c":4}')
655
656 def test_tupleargs(self):
657 f = self.makeCallable('(b,c), (d,(e,f))=(0,[1,2])')
658 self.assertEqualCallArgs(f, '(2,3)')
659 self.assertEqualCallArgs(f, '[2,3]')
660 self.assertEqualCallArgs(f, 'UserList([2,3])')
661 self.assertEqualCallArgs(f, '(2,3), (4,(5,6))')
662 self.assertEqualCallArgs(f, '(2,3), (4,[5,6])')
663 self.assertEqualCallArgs(f, '(2,3), [4,UserList([5,6])]')
664
665 def test_multiple_features(self):
666 f = self.makeCallable('a, b=2, (c,(d,e))=(3,[4,5]), *f, **g')
667 self.assertEqualCallArgs(f, '2, 3, (4,[5,6]), 7')
668 self.assertEqualCallArgs(f, '2, 3, *[(4,[5,6]), 7], x=8')
669 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
670 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
671 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
672 self.assertEqualCallArgs(f, 'x=8, *UserList([2, 3, (4,[5,6])]), '
673 '**{"y":9, "z":10}')
674 self.assertEqualCallArgs(f, '2, x=8, *UserList([3, (4,[5,6])]), '
675 '**UserDict(y=9, z=10)')
676
677 def test_errors(self):
678 f0 = self.makeCallable('')
679 f1 = self.makeCallable('a, b')
680 f2 = self.makeCallable('a, b=1')
681 # f0 takes no arguments
682 self.assertEqualException(f0, '1')
683 self.assertEqualException(f0, 'x=1')
684 self.assertEqualException(f0, '1,x=1')
685 # f1 takes exactly 2 arguments
686 self.assertEqualException(f1, '')
687 self.assertEqualException(f1, '1')
688 self.assertEqualException(f1, 'a=2')
689 self.assertEqualException(f1, 'b=3')
690 # f2 takes at least 1 argument
691 self.assertEqualException(f2, '')
692 self.assertEqualException(f2, 'b=3')
693 for f in f1, f2:
694 # f1/f2 takes exactly/at most 2 arguments
695 self.assertEqualException(f, '2, 3, 4')
696 self.assertEqualException(f, '1, 2, 3, a=1')
697 self.assertEqualException(f, '2, 3, 4, c=5')
698 self.assertEqualException(f, '2, 3, 4, a=1, c=5')
699 # f got an unexpected keyword argument
700 self.assertEqualException(f, 'c=2')
701 self.assertEqualException(f, '2, c=3')
702 self.assertEqualException(f, '2, 3, c=4')
703 self.assertEqualException(f, '2, c=4, b=3')
704 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
705 # f got multiple values for keyword argument
706 self.assertEqualException(f, '1, a=2')
707 self.assertEqualException(f, '1, **{"a":2}')
708 self.assertEqualException(f, '1, 2, b=3')
709 # XXX: Python inconsistency
710 # - for functions and bound methods: unexpected keyword 'c'
711 # - for unbound methods: multiple values for keyword 'a'
712 #self.assertEqualException(f, '1, c=3, a=2')
713 f = self.makeCallable('(a,b)=(0,1)')
714 self.assertEqualException(f, '1')
715 self.assertEqualException(f, '[1]')
716 self.assertEqualException(f, '(1,2,3)')
717
718class TestGetcallargsMethods(TestGetcallargsFunctions):
719
720 def setUp(self):
721 class Foo(object):
722 pass
723 self.cls = Foo
724 self.inst = Foo()
725
726 def makeCallable(self, signature):
727 assert 'self' not in signature
728 mk = super(TestGetcallargsMethods, self).makeCallable
729 self.cls.method = mk('self, ' + signature)
730 return self.inst.method
731
732class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
733
734 def makeCallable(self, signature):
735 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
736 return self.cls.method
737
738 def assertEqualCallArgs(self, func, call_params_string, locs=None):
739 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
740 *self._getAssertEqualParams(func, call_params_string, locs))
741
742 def assertEqualException(self, func, call_params_string, locs=None):
743 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
744 *self._getAssertEqualParams(func, call_params_string, locs))
745
746 def _getAssertEqualParams(self, func, call_params_string, locs=None):
747 assert 'inst' not in call_params_string
748 locs = dict(locs or {}, inst=self.inst)
749 return (func, 'inst,' + call_params_string, locs)
750
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000751def test_main():
Benjamin Peterson7e213252010-03-30 17:58:13 +0000752 run_unittest(
753 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
754 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
755 TestGetcallargsFunctions, TestGetcallargsMethods,
756 TestGetcallargsUnboundMethods)
Martin v. Löwis893ffa42003-10-31 15:35:53 +0000757
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000758if __name__ == "__main__":
759 test_main()