blob: aaa15f881a866680932e8b325332047e97517436 [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
Jean-Paul Calderoneb60ee462010-04-10 19:59:28 +0000438
439 def _classify_test(self, newstyle):
440 """Helper for testing that classify_class_attrs finds a bunch of
441 different kinds of attributes on a given class.
442 """
443 if newstyle:
444 base = object
445 else:
446 class base:
447 pass
448
449 class A(base):
450 def s(): pass
451 s = staticmethod(s)
452
453 def c(cls): pass
454 c = classmethod(c)
455
456 def getp(self): pass
457 p = property(getp)
458
459 def m(self): pass
460
461 def m1(self): pass
462
463 datablob = '1'
464
465 attrs = attrs_wo_objs(A)
466 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
467 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
468 self.assertIn(('p', 'property', A), attrs, 'missing property')
469 self.assertIn(('m', 'method', A), attrs, 'missing plain method')
470 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
471 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
472
473 class B(A):
474 def m(self): pass
475
476 attrs = attrs_wo_objs(B)
477 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
478 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
479 self.assertIn(('p', 'property', A), attrs, 'missing property')
480 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
481 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
482 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
483
484
485 class C(A):
486 def m(self): pass
487 def c(self): pass
488
489 attrs = attrs_wo_objs(C)
490 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
491 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
492 self.assertIn(('p', 'property', A), attrs, 'missing property')
493 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
494 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
495 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
496
497 class D(B, C):
498 def m1(self): pass
499
500 attrs = attrs_wo_objs(D)
501 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
502 if newstyle:
503 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
504 else:
505 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
506 self.assertIn(('p', 'property', A), attrs, 'missing property')
507 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
508 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
509 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
510
511
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000512 def test_classify_oldstyle(self):
Jean-Paul Calderoneb60ee462010-04-10 19:59:28 +0000513 """classify_class_attrs finds static methods, class methods,
514 properties, normal methods, and data attributes on an old-style
515 class.
516 """
517 self._classify_test(False)
Tim Peters13b49d32001-09-23 02:00:29 +0000518
519
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000520 def test_classify_newstyle(self):
Jean-Paul Calderoneb60ee462010-04-10 19:59:28 +0000521 """Just like test_classify_oldstyle, but for a new-style class.
522 """
523 self._classify_test(True)
Tim Peters13b49d32001-09-23 02:00:29 +0000524
525
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000526
Benjamin Peterson7e213252010-03-30 17:58:13 +0000527class TestGetcallargsFunctions(unittest.TestCase):
528
529 # tuple parameters are named '.1', '.2', etc.
530 is_tuplename = re.compile(r'^\.\d+$').match
531
532 def assertEqualCallArgs(self, func, call_params_string, locs=None):
533 locs = dict(locs or {}, func=func)
534 r1 = eval('func(%s)' % call_params_string, None, locs)
535 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
536 locs)
537 self.assertEqual(r1, r2)
538
539 def assertEqualException(self, func, call_param_string, locs=None):
540 locs = dict(locs or {}, func=func)
541 try:
542 eval('func(%s)' % call_param_string, None, locs)
543 except Exception, ex1:
544 pass
545 else:
546 self.fail('Exception not raised')
547 try:
548 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
549 locs)
550 except Exception, ex2:
551 pass
552 else:
553 self.fail('Exception not raised')
554 self.assertIs(type(ex1), type(ex2))
555 self.assertEqual(str(ex1), str(ex2))
556
557 def makeCallable(self, signature):
558 """Create a function that returns its locals(), excluding the
559 autogenerated '.1', '.2', etc. tuple param names (if any)."""
Ezio Melottifcc500e2010-03-31 08:33:50 +0000560 with check_py3k_warnings(
561 ("tuple parameter unpacking has been removed", SyntaxWarning),
562 quiet=True):
563 code = ("lambda %s: dict(i for i in locals().items() "
564 "if not is_tuplename(i[0]))")
565 return eval(code % signature, {'is_tuplename' : self.is_tuplename})
Benjamin Peterson7e213252010-03-30 17:58:13 +0000566
567 def test_plain(self):
568 f = self.makeCallable('a, b=1')
569 self.assertEqualCallArgs(f, '2')
570 self.assertEqualCallArgs(f, '2, 3')
571 self.assertEqualCallArgs(f, 'a=2')
572 self.assertEqualCallArgs(f, 'b=3, a=2')
573 self.assertEqualCallArgs(f, '2, b=3')
574 # expand *iterable / **mapping
575 self.assertEqualCallArgs(f, '*(2,)')
576 self.assertEqualCallArgs(f, '*[2]')
577 self.assertEqualCallArgs(f, '*(2, 3)')
578 self.assertEqualCallArgs(f, '*[2, 3]')
579 self.assertEqualCallArgs(f, '**{"a":2}')
580 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
581 self.assertEqualCallArgs(f, '2, **{"b":3}')
582 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
583 # expand UserList / UserDict
584 self.assertEqualCallArgs(f, '*UserList([2])')
585 self.assertEqualCallArgs(f, '*UserList([2, 3])')
586 self.assertEqualCallArgs(f, '**UserDict(a=2)')
587 self.assertEqualCallArgs(f, '2, **UserDict(b=3)')
588 self.assertEqualCallArgs(f, 'b=2, **UserDict(a=3)')
589 # unicode keyword args
590 self.assertEqualCallArgs(f, '**{u"a":2}')
591 self.assertEqualCallArgs(f, 'b=3, **{u"a":2}')
592 self.assertEqualCallArgs(f, '2, **{u"b":3}')
593 self.assertEqualCallArgs(f, '**{u"b":3, u"a":2}')
594
595 def test_varargs(self):
596 f = self.makeCallable('a, b=1, *c')
597 self.assertEqualCallArgs(f, '2')
598 self.assertEqualCallArgs(f, '2, 3')
599 self.assertEqualCallArgs(f, '2, 3, 4')
600 self.assertEqualCallArgs(f, '*(2,3,4)')
601 self.assertEqualCallArgs(f, '2, *[3,4]')
602 self.assertEqualCallArgs(f, '2, 3, *UserList([4])')
603
604 def test_varkw(self):
605 f = self.makeCallable('a, b=1, **c')
606 self.assertEqualCallArgs(f, 'a=2')
607 self.assertEqualCallArgs(f, '2, b=3, c=4')
608 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
609 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
610 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
611 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
612 self.assertEqualCallArgs(f, '**UserDict(a=2, b=3, c=4)')
613 self.assertEqualCallArgs(f, '2, c=4, **UserDict(b=3)')
614 self.assertEqualCallArgs(f, 'b=2, **UserDict(a=3, c=4)')
615 # unicode keyword args
616 self.assertEqualCallArgs(f, 'c=4, **{u"a":2, u"b":3}')
617 self.assertEqualCallArgs(f, '2, c=4, **{u"b":3}')
618 self.assertEqualCallArgs(f, 'b=2, **{u"a":3, u"c":4}')
619
620 def test_tupleargs(self):
621 f = self.makeCallable('(b,c), (d,(e,f))=(0,[1,2])')
622 self.assertEqualCallArgs(f, '(2,3)')
623 self.assertEqualCallArgs(f, '[2,3]')
624 self.assertEqualCallArgs(f, 'UserList([2,3])')
625 self.assertEqualCallArgs(f, '(2,3), (4,(5,6))')
626 self.assertEqualCallArgs(f, '(2,3), (4,[5,6])')
627 self.assertEqualCallArgs(f, '(2,3), [4,UserList([5,6])]')
628
629 def test_multiple_features(self):
630 f = self.makeCallable('a, b=2, (c,(d,e))=(3,[4,5]), *f, **g')
631 self.assertEqualCallArgs(f, '2, 3, (4,[5,6]), 7')
632 self.assertEqualCallArgs(f, '2, 3, *[(4,[5,6]), 7], x=8')
633 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
634 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
635 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
636 self.assertEqualCallArgs(f, 'x=8, *UserList([2, 3, (4,[5,6])]), '
637 '**{"y":9, "z":10}')
638 self.assertEqualCallArgs(f, '2, x=8, *UserList([3, (4,[5,6])]), '
639 '**UserDict(y=9, z=10)')
640
641 def test_errors(self):
642 f0 = self.makeCallable('')
643 f1 = self.makeCallable('a, b')
644 f2 = self.makeCallable('a, b=1')
645 # f0 takes no arguments
646 self.assertEqualException(f0, '1')
647 self.assertEqualException(f0, 'x=1')
648 self.assertEqualException(f0, '1,x=1')
649 # f1 takes exactly 2 arguments
650 self.assertEqualException(f1, '')
651 self.assertEqualException(f1, '1')
652 self.assertEqualException(f1, 'a=2')
653 self.assertEqualException(f1, 'b=3')
654 # f2 takes at least 1 argument
655 self.assertEqualException(f2, '')
656 self.assertEqualException(f2, 'b=3')
657 for f in f1, f2:
658 # f1/f2 takes exactly/at most 2 arguments
659 self.assertEqualException(f, '2, 3, 4')
660 self.assertEqualException(f, '1, 2, 3, a=1')
661 self.assertEqualException(f, '2, 3, 4, c=5')
662 self.assertEqualException(f, '2, 3, 4, a=1, c=5')
663 # f got an unexpected keyword argument
664 self.assertEqualException(f, 'c=2')
665 self.assertEqualException(f, '2, c=3')
666 self.assertEqualException(f, '2, 3, c=4')
667 self.assertEqualException(f, '2, c=4, b=3')
668 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
669 # f got multiple values for keyword argument
670 self.assertEqualException(f, '1, a=2')
671 self.assertEqualException(f, '1, **{"a":2}')
672 self.assertEqualException(f, '1, 2, b=3')
673 # XXX: Python inconsistency
674 # - for functions and bound methods: unexpected keyword 'c'
675 # - for unbound methods: multiple values for keyword 'a'
676 #self.assertEqualException(f, '1, c=3, a=2')
677 f = self.makeCallable('(a,b)=(0,1)')
678 self.assertEqualException(f, '1')
679 self.assertEqualException(f, '[1]')
680 self.assertEqualException(f, '(1,2,3)')
681
682class TestGetcallargsMethods(TestGetcallargsFunctions):
683
684 def setUp(self):
685 class Foo(object):
686 pass
687 self.cls = Foo
688 self.inst = Foo()
689
690 def makeCallable(self, signature):
691 assert 'self' not in signature
692 mk = super(TestGetcallargsMethods, self).makeCallable
693 self.cls.method = mk('self, ' + signature)
694 return self.inst.method
695
696class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
697
698 def makeCallable(self, signature):
699 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
700 return self.cls.method
701
702 def assertEqualCallArgs(self, func, call_params_string, locs=None):
703 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
704 *self._getAssertEqualParams(func, call_params_string, locs))
705
706 def assertEqualException(self, func, call_params_string, locs=None):
707 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
708 *self._getAssertEqualParams(func, call_params_string, locs))
709
710 def _getAssertEqualParams(self, func, call_params_string, locs=None):
711 assert 'inst' not in call_params_string
712 locs = dict(locs or {}, inst=self.inst)
713 return (func, 'inst,' + call_params_string, locs)
714
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000715def test_main():
Benjamin Peterson7e213252010-03-30 17:58:13 +0000716 run_unittest(
717 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
718 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
719 TestGetcallargsFunctions, TestGetcallargsMethods,
720 TestGetcallargsUnboundMethods)
Martin v. Löwis893ffa42003-10-31 15:35:53 +0000721
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000722if __name__ == "__main__":
723 test_main()