blob: 520bf0e60832f3f8215ffa2ebfeddf530b972527 [file] [log] [blame]
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001import re
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002import sys
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003import types
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004import unittest
5import inspect
R. David Murraya1b37402010-06-17 02:04:29 +00006import linecache
Thomas Wouters0e3f5912006-08-11 14:57:12 +00007import datetime
Guido van Rossum813b0e52007-05-21 18:11:34 +00008import collections
Alexander Belopolskyf546e702010-12-02 00:10:11 +00009import os
10import shutil
Nick Coghlane8c45d62013-07-28 20:00:01 +100011import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +100012import importlib
Christian Heimesa3538eb2007-11-06 11:44:48 +000013from os.path import normcase
Brett Cannon634a8fc2013-10-02 10:25:42 -040014try:
15 from concurrent.futures import ThreadPoolExecutor
16except ImportError:
17 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000018
Alexander Belopolskyf546e702010-12-02 00:10:11 +000019from test.support import run_unittest, TESTFN, DirsOnSysPath
Larry Hastingsfcafe432013-11-23 17:35:48 -080020from test.support import MISSING_C_DOCSTRINGS
Nick Coghlanf94a16b2013-09-22 22:46:49 +100021from test.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000022from test import inspect_fodder as mod
23from test import inspect_fodder2 as mod2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000024
R. David Murray74b89242009-05-13 17:33:03 +000025# C module for test_findsource_binary
R. David Murrayb5655772009-05-14 16:17:50 +000026import unicodedata
R. David Murray74b89242009-05-13 17:33:03 +000027
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000028# Functions tested in this suite:
29# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000030# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
31# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
32# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
33# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000034
Nick Coghlanf088e5e2008-12-14 11:50:48 +000035# NOTE: There are some additional tests relating to interaction with
36# zipimport in the test_zipimport_support test module.
37
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000038modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000039if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000040 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000041
Christian Heimesa3538eb2007-11-06 11:44:48 +000042# Normalize file names: on Windows, the case of file names of compiled
43# modules depends on the path used to start the python executable.
44modfile = normcase(modfile)
45
46def revise(filename, *args):
47 return (normcase(filename),) + args
48
Georg Brandl1a3284e2007-12-02 09:40:06 +000049import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000050
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000051git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000052
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000053class IsTestBase(unittest.TestCase):
54 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
55 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000056 inspect.ismodule, inspect.istraceback,
57 inspect.isgenerator, inspect.isgeneratorfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000058
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000059 def istest(self, predicate, exp):
60 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000061 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000062
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000063 for other in self.predicates - set([predicate]):
Christian Heimes7131fd92008-02-19 14:21:46 +000064 if predicate == inspect.isgeneratorfunction and\
65 other == inspect.isfunction:
66 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000067 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000068
Christian Heimes7131fd92008-02-19 14:21:46 +000069def generator_function_example(self):
70 for i in range(2):
71 yield i
72
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000073class TestPredicates(IsTestBase):
Christian Heimes227c8002008-03-03 20:34:40 +000074 def test_sixteen(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +000075 count = len([x for x in dir(inspect) if x.startswith('is')])
Christian Heimes7131fd92008-02-19 14:21:46 +000076 # This test is here for remember you to update Doc/library/inspect.rst
Christian Heimes78644762008-03-04 23:39:23 +000077 # which claims there are 16 such functions
Christian Heimes227c8002008-03-03 20:34:40 +000078 expected = 16
Thomas Wouters0e3f5912006-08-11 14:57:12 +000079 err_msg = "There are %d (not %d) is* functions" % (count, expected)
80 self.assertEqual(count, expected, err_msg)
Tim Peters5a9fb3c2005-01-07 16:01:32 +000081
Christian Heimes7131fd92008-02-19 14:21:46 +000082
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000083 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +020084 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000085 self.istest(inspect.isbuiltin, 'sys.exit')
86 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +000087 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +020088 try:
89 1/0
90 except:
91 tb = sys.exc_info()[2]
92 self.istest(inspect.isframe, 'tb.tb_frame')
93 self.istest(inspect.istraceback, 'tb')
94 if hasattr(types, 'GetSetDescriptorType'):
95 self.istest(inspect.isgetsetdescriptor,
96 'type(tb.tb_frame).f_locals')
97 else:
98 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
99 finally:
100 # Clear traceback and all the frames and local variables hanging to it.
101 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000102 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000103 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000104 self.istest(inspect.ismethod, 'git.argue')
105 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000106 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000107 self.istest(inspect.isgenerator, '(x for x in range(2))')
108 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000109 if hasattr(types, 'MemberDescriptorType'):
110 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
111 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000112 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000113
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000114 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000115 self.assertTrue(inspect.isroutine(mod.spam))
116 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000117
Benjamin Petersonc4656002009-01-17 22:41:18 +0000118 def test_isclass(self):
119 self.istest(inspect.isclass, 'mod.StupidGit')
120 self.assertTrue(inspect.isclass(list))
121
122 class CustomGetattr(object):
123 def __getattr__(self, attr):
124 return None
125 self.assertFalse(inspect.isclass(CustomGetattr()))
126
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000127 def test_get_slot_members(self):
128 class C(object):
129 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000130 x = C()
131 x.a = 42
132 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000133 self.assertIn('a', members)
134 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000135
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000136 def test_isabstract(self):
137 from abc import ABCMeta, abstractmethod
138
139 class AbstractClassExample(metaclass=ABCMeta):
140
141 @abstractmethod
142 def foo(self):
143 pass
144
145 class ClassExample(AbstractClassExample):
146 def foo(self):
147 pass
148
149 a = ClassExample()
150
151 # Test general behaviour.
152 self.assertTrue(inspect.isabstract(AbstractClassExample))
153 self.assertFalse(inspect.isabstract(ClassExample))
154 self.assertFalse(inspect.isabstract(a))
155 self.assertFalse(inspect.isabstract(int))
156 self.assertFalse(inspect.isabstract(5))
157
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000158
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000159class TestInterpreterStack(IsTestBase):
160 def __init__(self, *args, **kwargs):
161 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000162
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000163 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000164
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000165 def test_abuse_done(self):
166 self.istest(inspect.istraceback, 'git.ex[2]')
167 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000168
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000169 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000170 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000171 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000172 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000173 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000174 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000175 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000176 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000177 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000178 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000179
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000180 def test_trace(self):
181 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000182 self.assertEqual(revise(*git.tr[0][1:]),
183 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
184 self.assertEqual(revise(*git.tr[1][1:]),
185 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
186 self.assertEqual(revise(*git.tr[2][1:]),
187 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000188
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000189 def test_frame(self):
190 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
191 self.assertEqual(args, ['x', 'y'])
192 self.assertEqual(varargs, None)
193 self.assertEqual(varkw, None)
194 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
195 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
196 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000197
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000198 def test_previous_frame(self):
199 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000200 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000201 self.assertEqual(varargs, 'g')
202 self.assertEqual(varkw, 'h')
203 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000204 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000205
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000206class GetSourceBase(unittest.TestCase):
207 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000208 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000209
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000210 def __init__(self, *args, **kwargs):
211 unittest.TestCase.__init__(self, *args, **kwargs)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000212
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000213 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000214 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000215
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000216 def sourcerange(self, top, bottom):
217 lines = self.source.split("\n")
218 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000219
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000220 def assertSourceEqual(self, obj, top, bottom):
221 self.assertEqual(inspect.getsource(obj),
222 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000223
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000224class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000225 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000226
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000227 def test_getclasses(self):
228 classes = inspect.getmembers(mod, inspect.isclass)
229 self.assertEqual(classes,
230 [('FesteringGob', mod.FesteringGob),
231 ('MalodorousPervert', mod.MalodorousPervert),
232 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300233 ('StupidGit', mod.StupidGit),
234 ('Tit', mod.MalodorousPervert),
235 ])
236 tree = inspect.getclasstree([cls[1] for cls in classes])
237 self.assertEqual(tree,
238 [(object, ()),
239 [(mod.ParrotDroppings, (object,)),
240 [(mod.FesteringGob, (mod.MalodorousPervert,
241 mod.ParrotDroppings))
242 ],
243 (mod.StupidGit, (object,)),
244 [(mod.MalodorousPervert, (mod.StupidGit,)),
245 [(mod.FesteringGob, (mod.MalodorousPervert,
246 mod.ParrotDroppings))
247 ]
248 ]
249 ]
250 ])
251 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000252 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000253 [(object, ()),
254 [(mod.ParrotDroppings, (object,)),
255 (mod.StupidGit, (object,)),
256 [(mod.MalodorousPervert, (mod.StupidGit,)),
257 [(mod.FesteringGob, (mod.MalodorousPervert,
258 mod.ParrotDroppings))
259 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000260 ]
261 ]
262 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000263
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000264 def test_getfunctions(self):
265 functions = inspect.getmembers(mod, inspect.isfunction)
266 self.assertEqual(functions, [('eggs', mod.eggs),
267 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000268
R. David Murray378c0cf2010-02-24 01:46:21 +0000269 @unittest.skipIf(sys.flags.optimize >= 2,
270 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000271 def test_getdoc(self):
272 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
273 self.assertEqual(inspect.getdoc(mod.StupidGit),
274 'A longer,\n\nindented\n\ndocstring.')
275 self.assertEqual(inspect.getdoc(git.abuse),
276 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000277
Georg Brandl0c77a822008-06-10 16:37:50 +0000278 def test_cleandoc(self):
279 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
280 'An\nindented\ndocstring.')
281
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000282 def test_getcomments(self):
283 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
284 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000285
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000286 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000287 # Check actual module
288 self.assertEqual(inspect.getmodule(mod), mod)
289 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000290 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000291 # Check a method (no __module__ attribute, falls back to filename)
292 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
293 # Do it again (check the caching isn't broken)
294 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
295 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000296 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000297 # Check filename override
298 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000299
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000300 def test_getsource(self):
301 self.assertSourceEqual(git.abuse, 29, 39)
302 self.assertSourceEqual(mod.StupidGit, 21, 46)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000303
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000304 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000305 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
306 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000307 fn = "_non_existing_filename_used_for_sourcefile_test.py"
308 co = compile("None", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000309 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000310 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200311 try:
312 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
313 finally:
314 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000315
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000316 def test_getfile(self):
317 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000318
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000319 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000320 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000321 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000322 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000323 m.__file__ = "<string>" # hopefully not a real filename...
324 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000325 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000326 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000327 del sys.modules[name]
328 inspect.getmodule(compile('a=10','','single'))
329
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500330 def test_proceed_with_fake_filename(self):
331 '''doctest monkeypatches linecache to enable inspection'''
332 fn, source = '<test>', 'def x(): pass\n'
333 getlines = linecache.getlines
334 def monkey(filename, module_globals=None):
335 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300336 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500337 else:
338 return getlines(filename, module_globals)
339 linecache.getlines = monkey
340 try:
341 ns = {}
342 exec(compile(source, fn, 'single'), ns)
343 inspect.getsource(ns["x"])
344 finally:
345 linecache.getlines = getlines
346
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000347class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000348 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000349
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000350 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000351 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000352
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000353 def test_replacing_decorator(self):
354 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000355
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000356class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000357 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000358 def test_oneline_lambda(self):
359 # Test inspect.getsource with a one-line lambda function.
360 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000361
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000362 def test_threeline_lambda(self):
363 # Test inspect.getsource with a three-line lambda function,
364 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000365 self.assertSourceEqual(mod2.tll, 28, 30)
366
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000367 def test_twoline_indented_lambda(self):
368 # Test inspect.getsource with a two-line lambda function,
369 # where the second line _is_ indented.
370 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000371
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000372 def test_onelinefunc(self):
373 # Test inspect.getsource with a regular one-line function.
374 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000375
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000376 def test_manyargs(self):
377 # Test inspect.getsource with a regular function where
378 # the arguments are on two lines and _not_ indented and
379 # the body on the second line with the last arguments.
380 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000381
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000382 def test_twolinefunc(self):
383 # Test inspect.getsource with a regular function where
384 # the body is on two lines, following the argument list and
385 # continued on the next line by a \\.
386 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000387
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000388 def test_lambda_in_list(self):
389 # Test inspect.getsource with a one-line lambda function
390 # defined in a list, indented.
391 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000392
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000393 def test_anonymous(self):
394 # Test inspect.getsource with a lambda function defined
395 # as argument to another function.
396 self.assertSourceEqual(mod2.anonymous, 55, 55)
397
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000398class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000399 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000400
401 def test_with_comment(self):
402 self.assertSourceEqual(mod2.with_comment, 58, 59)
403
404 def test_multiline_sig(self):
405 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
406
Armin Rigodd5c0232005-09-25 11:45:45 +0000407 def test_nested_class(self):
408 self.assertSourceEqual(mod2.func69().func71, 71, 72)
409
410 def test_one_liner_followed_by_non_name(self):
411 self.assertSourceEqual(mod2.func77, 77, 77)
412
413 def test_one_liner_dedent_non_name(self):
414 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
415
416 def test_with_comment_instead_of_docstring(self):
417 self.assertSourceEqual(mod2.func88, 88, 90)
418
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000419 def test_method_in_dynamic_class(self):
420 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
421
R. David Murrayb5655772009-05-14 16:17:50 +0000422 @unittest.skipIf(
423 not hasattr(unicodedata, '__file__') or
424 unicodedata.__file__[-4:] in (".pyc", ".pyo"),
425 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000426 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200427 self.assertRaises(OSError, inspect.getsource, unicodedata)
428 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000429
R. David Murraya1b37402010-06-17 02:04:29 +0000430 def test_findsource_code_in_linecache(self):
431 lines = ["x=1"]
432 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200433 self.assertRaises(OSError, inspect.findsource, co)
434 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000435 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200436 try:
437 self.assertEqual(inspect.findsource(co), (lines,0))
438 self.assertEqual(inspect.getsource(co), lines[0])
439 finally:
440 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000441
Ezio Melotti1b145922013-03-30 05:17:24 +0200442 def test_findsource_without_filename(self):
443 for fname in ['', '<string>']:
444 co = compile('x=1', fname, "exec")
445 self.assertRaises(IOError, inspect.findsource, co)
446 self.assertRaises(IOError, inspect.getsource, co)
447
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000448class TestNoEOL(GetSourceBase):
449 def __init__(self, *args, **kwargs):
450 self.tempdir = TESTFN + '_dir'
451 os.mkdir(self.tempdir)
452 with open(os.path.join(self.tempdir,
453 'inspect_fodder3%spy' % os.extsep), 'w') as f:
454 f.write("class X:\n pass # No EOL")
455 with DirsOnSysPath(self.tempdir):
456 import inspect_fodder3 as mod3
457 self.fodderModule = mod3
458 GetSourceBase.__init__(self, *args, **kwargs)
459
460 def tearDown(self):
461 shutil.rmtree(self.tempdir)
462
463 def test_class(self):
464 self.assertSourceEqual(self.fodderModule.X, 1, 2)
465
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100466
467class _BrokenDataDescriptor(object):
468 """
469 A broken data descriptor. See bug #1785.
470 """
471 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700472 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100473
474 def __set__(*args):
475 raise RuntimeError
476
477 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700478 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100479
480
481class _BrokenMethodDescriptor(object):
482 """
483 A broken method descriptor. See bug #1785.
484 """
485 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700486 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100487
488 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700489 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100490
491
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000492# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000493def attrs_wo_objs(cls):
494 return [t[:3] for t in inspect.classify_class_attrs(cls)]
495
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100496
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000497class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000498 def test_newstyle_mro(self):
499 # The same w/ new-class MRO.
500 class A(object): pass
501 class B(A): pass
502 class C(A): pass
503 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000504
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000505 expected = (D, B, C, A, object)
506 got = inspect.getmro(D)
507 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000508
Christian Heimes3795b532007-11-08 13:48:53 +0000509 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
510 varkw_e=None, defaults_e=None, formatted=None):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000511 args, varargs, varkw, defaults = inspect.getargspec(routine)
512 self.assertEqual(args, args_e)
513 self.assertEqual(varargs, varargs_e)
514 self.assertEqual(varkw, varkw_e)
515 self.assertEqual(defaults, defaults_e)
516 if formatted is not None:
517 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
518 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000519
Christian Heimes3795b532007-11-08 13:48:53 +0000520 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
521 varkw_e=None, defaults_e=None,
522 kwonlyargs_e=[], kwonlydefaults_e=None,
523 ann_e={}, formatted=None):
524 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
525 inspect.getfullargspec(routine)
526 self.assertEqual(args, args_e)
527 self.assertEqual(varargs, varargs_e)
528 self.assertEqual(varkw, varkw_e)
529 self.assertEqual(defaults, defaults_e)
530 self.assertEqual(kwonlyargs, kwonlyargs_e)
531 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
532 self.assertEqual(ann, ann_e)
533 if formatted is not None:
534 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
535 kwonlyargs, kwonlydefaults, ann),
536 formatted)
537
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000538 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000539 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000540
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000541 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000542 ['a', 'b', 'c', 'd', 'e', 'f'],
543 'g', 'h', (3, 4, 5),
544 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000545
Christian Heimes3795b532007-11-08 13:48:53 +0000546 self.assertRaises(ValueError, self.assertArgSpecEquals,
547 mod2.keyworded, [])
548
549 self.assertRaises(ValueError, self.assertArgSpecEquals,
550 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000551 self.assertRaises(ValueError, self.assertArgSpecEquals,
552 mod2.keyword_only_arg, [])
553
Christian Heimes3795b532007-11-08 13:48:53 +0000554
555 def test_getfullargspec(self):
556 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
557 kwonlyargs_e=['arg2'],
558 kwonlydefaults_e={'arg2':1},
559 formatted='(*arg1, arg2=1)')
560
561 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000562 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000563 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000564 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
565 kwonlyargs_e=['arg'],
566 formatted='(*, arg)')
567
Christian Heimes3795b532007-11-08 13:48:53 +0000568
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000569 def test_getargspec_method(self):
570 class A(object):
571 def m(self):
572 pass
573 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000574
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000575 def test_classify_newstyle(self):
576 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000577
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000578 def s(): pass
579 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000580
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000581 def c(cls): pass
582 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000583
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000584 def getp(self): pass
585 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000586
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000587 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000588
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000589 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000590
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000591 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000592
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100593 dd = _BrokenDataDescriptor()
594 md = _BrokenMethodDescriptor()
595
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000596 attrs = attrs_wo_objs(A)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000597 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
598 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
599 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000600 self.assertIn(('m', 'method', A), attrs,
601 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000602 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
603 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100604 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
605 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000606
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000607 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000608
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000609 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000610
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000611 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000612 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
613 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
614 self.assertIn(('p', 'property', A), attrs, 'missing property')
615 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
616 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
617 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100618 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
619 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000620
621
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000622 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000623
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000624 def m(self): pass
625 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000626
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000627 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000628 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
629 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
630 self.assertIn(('p', 'property', A), attrs, 'missing property')
631 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
632 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
633 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100634 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
635 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000636
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000637 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000638
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000639 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000640
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000641 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000642 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
643 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
644 self.assertIn(('p', 'property', A), attrs, 'missing property')
645 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
646 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
647 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100648 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
649 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
650
651 def test_classify_builtin_types(self):
652 # Simple sanity check that all built-in types can have their
653 # attributes classified.
654 for name in dir(__builtins__):
655 builtin = getattr(__builtins__, name)
656 if isinstance(builtin, type):
657 inspect.classify_class_attrs(builtin)
658
Ethan Furman63c141c2013-10-18 00:27:39 -0700659 def test_classify_DynamicClassAttribute(self):
660 class Meta(type):
661 def __getattr__(self, name):
662 if name == 'ham':
663 return 'spam'
664 return super().__getattr__(name)
665 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700666 @types.DynamicClassAttribute
667 def ham(self):
668 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700669 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
670 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700671 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700672 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
673
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700674 def test_classify_metaclass_class_attribute(self):
675 class Meta(type):
676 fish = 'slap'
677 def __dir__(self):
678 return ['__class__', '__modules__', '__name__', 'fish']
679 class Class(metaclass=Meta):
680 pass
681 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
682 self.assertIn(should_find, inspect.classify_class_attrs(Class))
683
Ethan Furman63c141c2013-10-18 00:27:39 -0700684 def test_classify_VirtualAttribute(self):
685 class Meta(type):
686 def __dir__(cls):
687 return ['__class__', '__module__', '__name__', 'BOOM']
688 def __getattr__(self, name):
689 if name =='BOOM':
690 return 42
691 return super().__getattr(name)
692 class Class(metaclass=Meta):
693 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700694 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700695 self.assertIn(should_find, inspect.classify_class_attrs(Class))
696
697 def test_classify_VirtualAttribute_multi_classes(self):
698 class Meta1(type):
699 def __dir__(cls):
700 return ['__class__', '__module__', '__name__', 'one']
701 def __getattr__(self, name):
702 if name =='one':
703 return 1
704 return super().__getattr__(name)
705 class Meta2(type):
706 def __dir__(cls):
707 return ['__class__', '__module__', '__name__', 'two']
708 def __getattr__(self, name):
709 if name =='two':
710 return 2
711 return super().__getattr__(name)
712 class Meta3(Meta1, Meta2):
713 def __dir__(cls):
714 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
715 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
716 def __getattr__(self, name):
717 if name =='three':
718 return 3
719 return super().__getattr__(name)
720 class Class1(metaclass=Meta1):
721 pass
722 class Class2(Class1, metaclass=Meta3):
723 pass
724
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700725 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
726 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
727 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700728 cca = inspect.classify_class_attrs(Class2)
729 for sf in (should_find1, should_find2, should_find3):
730 self.assertIn(sf, cca)
731
732 def test_classify_class_attrs_with_buggy_dir(self):
733 class M(type):
734 def __dir__(cls):
735 return ['__class__', '__name__', 'missing']
736 class C(metaclass=M):
737 pass
738 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
739 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700740
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100741 def test_getmembers_descriptors(self):
742 class A(object):
743 dd = _BrokenDataDescriptor()
744 md = _BrokenMethodDescriptor()
745
746 def pred_wrapper(pred):
747 # A quick'n'dirty way to discard standard attributes of new-style
748 # classes.
749 class Empty(object):
750 pass
751 def wrapped(x):
752 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
753 return False
754 return pred(x)
755 return wrapped
756
757 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
758 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
759
760 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
761 [('md', A.__dict__['md'])])
762 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
763 [('dd', A.__dict__['dd'])])
764
765 class B(A):
766 pass
767
768 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
769 [('md', A.__dict__['md'])])
770 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
771 [('dd', A.__dict__['dd'])])
772
Antoine Pitrou0c603812012-01-18 17:40:18 +0100773 def test_getmembers_method(self):
774 class B:
775 def f(self):
776 pass
777
778 self.assertIn(('f', B.f), inspect.getmembers(B))
779 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
780 b = B()
781 self.assertIn(('f', b.f), inspect.getmembers(b))
782 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
783
Ethan Furmane03ea372013-09-25 07:14:41 -0700784 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -0700785 class M(type):
786 def __getattr__(cls, name):
787 if name == 'eggs':
788 return 'scrambled'
789 return super().__getattr__(name)
790 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -0700791 @types.DynamicClassAttribute
792 def eggs(self):
793 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -0700794 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
795 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
796
797 def test_getmembers_with_buggy_dir(self):
798 class M(type):
799 def __dir__(cls):
800 return ['__class__', '__name__', 'missing']
801 class C(metaclass=M):
802 pass
803 attrs = [a[0] for a in inspect.getmembers(C)]
804 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700805
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000806
Nick Coghlan2f92e542012-06-23 19:39:55 +1000807_global_ref = object()
808class TestGetClosureVars(unittest.TestCase):
809
810 def test_name_resolution(self):
811 # Basic test of the 4 different resolution mechanisms
812 def f(nonlocal_ref):
813 def g(local_ref):
814 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
815 return g
816 _arg = object()
817 nonlocal_vars = {"nonlocal_ref": _arg}
818 global_vars = {"_global_ref": _global_ref}
819 builtin_vars = {"print": print}
820 unbound_names = {"unbound_ref"}
821 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
822 builtin_vars, unbound_names)
823 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
824
825 def test_generator_closure(self):
826 def f(nonlocal_ref):
827 def g(local_ref):
828 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
829 yield
830 return g
831 _arg = object()
832 nonlocal_vars = {"nonlocal_ref": _arg}
833 global_vars = {"_global_ref": _global_ref}
834 builtin_vars = {"print": print}
835 unbound_names = {"unbound_ref"}
836 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
837 builtin_vars, unbound_names)
838 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
839
840 def test_method_closure(self):
841 class C:
842 def f(self, nonlocal_ref):
843 def g(local_ref):
844 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
845 return g
846 _arg = object()
847 nonlocal_vars = {"nonlocal_ref": _arg}
848 global_vars = {"_global_ref": _global_ref}
849 builtin_vars = {"print": print}
850 unbound_names = {"unbound_ref"}
851 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
852 builtin_vars, unbound_names)
853 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
854
855 def test_nonlocal_vars(self):
856 # More complex tests of nonlocal resolution
857 def _nonlocal_vars(f):
858 return inspect.getclosurevars(f).nonlocals
859
860 def make_adder(x):
861 def add(y):
862 return x + y
863 return add
864
865 def curry(func, arg1):
866 return lambda arg2: func(arg1, arg2)
867
868 def less_than(a, b):
869 return a < b
870
871 # The infamous Y combinator.
872 def Y(le):
873 def g(f):
874 return le(lambda x: f(f)(x))
875 Y.g_ref = g
876 return g(g)
877
878 def check_y_combinator(func):
879 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
880
881 inc = make_adder(1)
882 add_two = make_adder(2)
883 greater_than_five = curry(less_than, 5)
884
885 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
886 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
887 self.assertEqual(_nonlocal_vars(greater_than_five),
888 {'arg1': 5, 'func': less_than})
889 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
890 {'x': 3})
891 Y(check_y_combinator)
892
893 def test_getclosurevars_empty(self):
894 def foo(): pass
895 _empty = inspect.ClosureVars({}, {}, {}, set())
896 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
897 self.assertEqual(inspect.getclosurevars(foo), _empty)
898
899 def test_getclosurevars_error(self):
900 class T: pass
901 self.assertRaises(TypeError, inspect.getclosurevars, 1)
902 self.assertRaises(TypeError, inspect.getclosurevars, list)
903 self.assertRaises(TypeError, inspect.getclosurevars, {})
904
Nick Coghlan6c6e2542012-06-23 20:07:39 +1000905 def _private_globals(self):
906 code = """def f(): print(path)"""
907 ns = {}
908 exec(code, ns)
909 return ns["f"], ns
910
911 def test_builtins_fallback(self):
912 f, ns = self._private_globals()
913 ns.pop("__builtins__", None)
914 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
915 self.assertEqual(inspect.getclosurevars(f), expected)
916
917 def test_builtins_as_dict(self):
918 f, ns = self._private_globals()
919 ns["__builtins__"] = {"path":1}
920 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
921 self.assertEqual(inspect.getclosurevars(f), expected)
922
923 def test_builtins_as_module(self):
924 f, ns = self._private_globals()
925 ns["__builtins__"] = os
926 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
927 self.assertEqual(inspect.getclosurevars(f), expected)
928
Nick Coghlan2f92e542012-06-23 19:39:55 +1000929
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000930class TestGetcallargsFunctions(unittest.TestCase):
931
932 def assertEqualCallArgs(self, func, call_params_string, locs=None):
933 locs = dict(locs or {}, func=func)
934 r1 = eval('func(%s)' % call_params_string, None, locs)
935 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
936 locs)
937 self.assertEqual(r1, r2)
938
939 def assertEqualException(self, func, call_param_string, locs=None):
940 locs = dict(locs or {}, func=func)
941 try:
942 eval('func(%s)' % call_param_string, None, locs)
943 except Exception as e:
944 ex1 = e
945 else:
946 self.fail('Exception not raised')
947 try:
948 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
949 locs)
950 except Exception as e:
951 ex2 = e
952 else:
953 self.fail('Exception not raised')
954 self.assertIs(type(ex1), type(ex2))
955 self.assertEqual(str(ex1), str(ex2))
956 del ex1, ex2
957
958 def makeCallable(self, signature):
959 """Create a function that returns its locals()"""
960 code = "lambda %s: locals()"
961 return eval(code % signature)
962
963 def test_plain(self):
964 f = self.makeCallable('a, b=1')
965 self.assertEqualCallArgs(f, '2')
966 self.assertEqualCallArgs(f, '2, 3')
967 self.assertEqualCallArgs(f, 'a=2')
968 self.assertEqualCallArgs(f, 'b=3, a=2')
969 self.assertEqualCallArgs(f, '2, b=3')
970 # expand *iterable / **mapping
971 self.assertEqualCallArgs(f, '*(2,)')
972 self.assertEqualCallArgs(f, '*[2]')
973 self.assertEqualCallArgs(f, '*(2, 3)')
974 self.assertEqualCallArgs(f, '*[2, 3]')
975 self.assertEqualCallArgs(f, '**{"a":2}')
976 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
977 self.assertEqualCallArgs(f, '2, **{"b":3}')
978 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
979 # expand UserList / UserDict
980 self.assertEqualCallArgs(f, '*collections.UserList([2])')
981 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
982 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
983 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
984 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
985
986 def test_varargs(self):
987 f = self.makeCallable('a, b=1, *c')
988 self.assertEqualCallArgs(f, '2')
989 self.assertEqualCallArgs(f, '2, 3')
990 self.assertEqualCallArgs(f, '2, 3, 4')
991 self.assertEqualCallArgs(f, '*(2,3,4)')
992 self.assertEqualCallArgs(f, '2, *[3,4]')
993 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
994
995 def test_varkw(self):
996 f = self.makeCallable('a, b=1, **c')
997 self.assertEqualCallArgs(f, 'a=2')
998 self.assertEqualCallArgs(f, '2, b=3, c=4')
999 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1000 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1001 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1002 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1003 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1004 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1005 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1006
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001007 def test_varkw_only(self):
1008 # issue11256:
1009 f = self.makeCallable('**c')
1010 self.assertEqualCallArgs(f, '')
1011 self.assertEqualCallArgs(f, 'a=1')
1012 self.assertEqualCallArgs(f, 'a=1, b=2')
1013 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1014 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1015 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1016
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001017 def test_keyword_only(self):
1018 f = self.makeCallable('a=3, *, c, d=2')
1019 self.assertEqualCallArgs(f, 'c=3')
1020 self.assertEqualCallArgs(f, 'c=3, a=3')
1021 self.assertEqualCallArgs(f, 'a=2, c=4')
1022 self.assertEqualCallArgs(f, '4, c=4')
1023 self.assertEqualException(f, '')
1024 self.assertEqualException(f, '3')
1025 self.assertEqualException(f, 'a=3')
1026 self.assertEqualException(f, 'd=4')
1027
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001028 f = self.makeCallable('*, c, d=2')
1029 self.assertEqualCallArgs(f, 'c=3')
1030 self.assertEqualCallArgs(f, 'c=3, d=4')
1031 self.assertEqualCallArgs(f, 'd=4, c=3')
1032
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001033 def test_multiple_features(self):
1034 f = self.makeCallable('a, b=2, *f, **g')
1035 self.assertEqualCallArgs(f, '2, 3, 7')
1036 self.assertEqualCallArgs(f, '2, 3, x=8')
1037 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1038 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1039 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1040 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1041 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1042 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1043 '(4,[5,6])]), **collections.UserDict('
1044 'y=9, z=10)')
1045
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001046 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1047 self.assertEqualCallArgs(f, '2, 3, x=8')
1048 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1049 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1050 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1051 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1052 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1053 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1054 '(4,[5,6])]), q=0, **collections.UserDict('
1055 'y=9, z=10)')
1056
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001057 def test_errors(self):
1058 f0 = self.makeCallable('')
1059 f1 = self.makeCallable('a, b')
1060 f2 = self.makeCallable('a, b=1')
1061 # f0 takes no arguments
1062 self.assertEqualException(f0, '1')
1063 self.assertEqualException(f0, 'x=1')
1064 self.assertEqualException(f0, '1,x=1')
1065 # f1 takes exactly 2 arguments
1066 self.assertEqualException(f1, '')
1067 self.assertEqualException(f1, '1')
1068 self.assertEqualException(f1, 'a=2')
1069 self.assertEqualException(f1, 'b=3')
1070 # f2 takes at least 1 argument
1071 self.assertEqualException(f2, '')
1072 self.assertEqualException(f2, 'b=3')
1073 for f in f1, f2:
1074 # f1/f2 takes exactly/at most 2 arguments
1075 self.assertEqualException(f, '2, 3, 4')
1076 self.assertEqualException(f, '1, 2, 3, a=1')
1077 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001078 # XXX: success of this one depends on dict order
1079 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001080 # f got an unexpected keyword argument
1081 self.assertEqualException(f, 'c=2')
1082 self.assertEqualException(f, '2, c=3')
1083 self.assertEqualException(f, '2, 3, c=4')
1084 self.assertEqualException(f, '2, c=4, b=3')
1085 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1086 # f got multiple values for keyword argument
1087 self.assertEqualException(f, '1, a=2')
1088 self.assertEqualException(f, '1, **{"a":2}')
1089 self.assertEqualException(f, '1, 2, b=3')
1090 # XXX: Python inconsistency
1091 # - for functions and bound methods: unexpected keyword 'c'
1092 # - for unbound methods: multiple values for keyword 'a'
1093 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001094 # issue11256:
1095 f3 = self.makeCallable('**c')
1096 self.assertEqualException(f3, '1, 2')
1097 self.assertEqualException(f3, '1, 2, a=1, b=2')
1098 f4 = self.makeCallable('*, a, b=0')
1099 self.assertEqualException(f3, '1, 2')
1100 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001101
1102class TestGetcallargsMethods(TestGetcallargsFunctions):
1103
1104 def setUp(self):
1105 class Foo(object):
1106 pass
1107 self.cls = Foo
1108 self.inst = Foo()
1109
1110 def makeCallable(self, signature):
1111 assert 'self' not in signature
1112 mk = super(TestGetcallargsMethods, self).makeCallable
1113 self.cls.method = mk('self, ' + signature)
1114 return self.inst.method
1115
1116class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1117
1118 def makeCallable(self, signature):
1119 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1120 return self.cls.method
1121
1122 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1123 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1124 *self._getAssertEqualParams(func, call_params_string, locs))
1125
1126 def assertEqualException(self, func, call_params_string, locs=None):
1127 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1128 *self._getAssertEqualParams(func, call_params_string, locs))
1129
1130 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1131 assert 'inst' not in call_params_string
1132 locs = dict(locs or {}, inst=self.inst)
1133 return (func, 'inst,' + call_params_string, locs)
1134
Michael Foord95fc51d2010-11-20 15:07:30 +00001135
1136class TestGetattrStatic(unittest.TestCase):
1137
1138 def test_basic(self):
1139 class Thing(object):
1140 x = object()
1141
1142 thing = Thing()
1143 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1144 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1145 with self.assertRaises(AttributeError):
1146 inspect.getattr_static(thing, 'y')
1147
1148 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1149
1150 def test_inherited(self):
1151 class Thing(object):
1152 x = object()
1153 class OtherThing(Thing):
1154 pass
1155
1156 something = OtherThing()
1157 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1158
1159 def test_instance_attr(self):
1160 class Thing(object):
1161 x = 2
1162 def __init__(self, x):
1163 self.x = x
1164 thing = Thing(3)
1165 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1166 del thing.x
1167 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1168
1169 def test_property(self):
1170 class Thing(object):
1171 @property
1172 def x(self):
1173 raise AttributeError("I'm pretending not to exist")
1174 thing = Thing()
1175 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1176
Ezio Melotti75cbd732011-04-28 00:59:29 +03001177 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001178 class descriptor(object):
1179 def __get__(*_):
1180 raise AttributeError("I'm pretending not to exist")
1181 desc = descriptor()
1182 class Thing(object):
1183 x = desc
1184 thing = Thing()
1185 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1186
1187 def test_classAttribute(self):
1188 class Thing(object):
1189 x = object()
1190
1191 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1192
Ethan Furmane03ea372013-09-25 07:14:41 -07001193 def test_classVirtualAttribute(self):
1194 class Thing(object):
1195 @types.DynamicClassAttribute
1196 def x(self):
1197 return self._x
1198 _x = object()
1199
1200 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1201
Michael Foord95fc51d2010-11-20 15:07:30 +00001202 def test_inherited_classattribute(self):
1203 class Thing(object):
1204 x = object()
1205 class OtherThing(Thing):
1206 pass
1207
1208 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1209
1210 def test_slots(self):
1211 class Thing(object):
1212 y = 'bar'
1213 __slots__ = ['x']
1214 def __init__(self):
1215 self.x = 'foo'
1216 thing = Thing()
1217 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1218 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1219
1220 del thing.x
1221 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1222
1223 def test_metaclass(self):
1224 class meta(type):
1225 attr = 'foo'
1226 class Thing(object, metaclass=meta):
1227 pass
1228 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1229
1230 class sub(meta):
1231 pass
1232 class OtherThing(object, metaclass=sub):
1233 x = 3
1234 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1235
1236 class OtherOtherThing(OtherThing):
1237 pass
1238 # this test is odd, but it was added as it exposed a bug
1239 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1240
1241 def test_no_dict_no_slots(self):
1242 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1243 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1244
1245 def test_no_dict_no_slots_instance_member(self):
1246 # returns descriptor
1247 with open(__file__) as handle:
1248 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1249
1250 def test_inherited_slots(self):
1251 # returns descriptor
1252 class Thing(object):
1253 __slots__ = ['x']
1254 def __init__(self):
1255 self.x = 'foo'
1256
1257 class OtherThing(Thing):
1258 pass
1259 # it would be nice if this worked...
1260 # we get the descriptor instead of the instance attribute
1261 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1262
1263 def test_descriptor(self):
1264 class descriptor(object):
1265 def __get__(self, instance, owner):
1266 return 3
1267 class Foo(object):
1268 d = descriptor()
1269
1270 foo = Foo()
1271
1272 # for a non data descriptor we return the instance attribute
1273 foo.__dict__['d'] = 1
1274 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1275
1276 # if the descriptor is a data-desciptor we should return the
1277 # descriptor
1278 descriptor.__set__ = lambda s, i, v: None
1279 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1280
1281
1282 def test_metaclass_with_descriptor(self):
1283 class descriptor(object):
1284 def __get__(self, instance, owner):
1285 return 3
1286 class meta(type):
1287 d = descriptor()
1288 class Thing(object, metaclass=meta):
1289 pass
1290 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1291
1292
Michael Foordcc7ebb82010-11-20 16:20:16 +00001293 def test_class_as_property(self):
1294 class Base(object):
1295 foo = 3
1296
1297 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001298 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001299 @property
1300 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001301 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001302 return object
1303
Michael Foord35184ed2010-11-20 16:58:30 +00001304 instance = Something()
1305 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1306 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001307 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1308
Michael Foorde5162652010-11-20 16:40:44 +00001309 def test_mro_as_property(self):
1310 class Meta(type):
1311 @property
1312 def __mro__(self):
1313 return (object,)
1314
1315 class Base(object):
1316 foo = 3
1317
1318 class Something(Base, metaclass=Meta):
1319 pass
1320
1321 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1322 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1323
Michael Foorddcebe0f2011-03-15 19:20:44 -04001324 def test_dict_as_property(self):
1325 test = self
1326 test.called = False
1327
1328 class Foo(dict):
1329 a = 3
1330 @property
1331 def __dict__(self):
1332 test.called = True
1333 return {}
1334
1335 foo = Foo()
1336 foo.a = 4
1337 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1338 self.assertFalse(test.called)
1339
1340 def test_custom_object_dict(self):
1341 test = self
1342 test.called = False
1343
1344 class Custom(dict):
1345 def get(self, key, default=None):
1346 test.called = True
1347 super().get(key, default)
1348
1349 class Foo(object):
1350 a = 3
1351 foo = Foo()
1352 foo.__dict__ = Custom()
1353 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1354 self.assertFalse(test.called)
1355
1356 def test_metaclass_dict_as_property(self):
1357 class Meta(type):
1358 @property
1359 def __dict__(self):
1360 self.executed = True
1361
1362 class Thing(metaclass=Meta):
1363 executed = False
1364
1365 def __init__(self):
1366 self.spam = 42
1367
1368 instance = Thing()
1369 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1370 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001371
Michael Foorda51623b2011-12-18 22:01:40 +00001372 def test_module(self):
1373 sentinel = object()
1374 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1375 sentinel)
1376
Michael Foord3ba95f82011-12-22 01:13:37 +00001377 def test_metaclass_with_metaclass_with_dict_as_property(self):
1378 class MetaMeta(type):
1379 @property
1380 def __dict__(self):
1381 self.executed = True
1382 return dict(spam=42)
1383
1384 class Meta(type, metaclass=MetaMeta):
1385 executed = False
1386
1387 class Thing(metaclass=Meta):
1388 pass
1389
1390 with self.assertRaises(AttributeError):
1391 inspect.getattr_static(Thing, "spam")
1392 self.assertFalse(Thing.executed)
1393
Nick Coghlane0f04652010-11-21 03:44:04 +00001394class TestGetGeneratorState(unittest.TestCase):
1395
1396 def setUp(self):
1397 def number_generator():
1398 for number in range(5):
1399 yield number
1400 self.generator = number_generator()
1401
1402 def _generatorstate(self):
1403 return inspect.getgeneratorstate(self.generator)
1404
1405 def test_created(self):
1406 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1407
1408 def test_suspended(self):
1409 next(self.generator)
1410 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1411
1412 def test_closed_after_exhaustion(self):
1413 for i in self.generator:
1414 pass
1415 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1416
1417 def test_closed_after_immediate_exception(self):
1418 with self.assertRaises(RuntimeError):
1419 self.generator.throw(RuntimeError)
1420 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1421
1422 def test_running(self):
1423 # As mentioned on issue #10220, checking for the RUNNING state only
1424 # makes sense inside the generator itself.
1425 # The following generator checks for this by using the closure's
1426 # reference to self and the generator state checking helper method
1427 def running_check_generator():
1428 for number in range(5):
1429 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1430 yield number
1431 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1432 self.generator = running_check_generator()
1433 # Running up to the first yield
1434 next(self.generator)
1435 # Running after the first yield
1436 next(self.generator)
1437
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001438 def test_easy_debugging(self):
1439 # repr() and str() of a generator state should contain the state name
1440 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1441 for name in names:
1442 state = getattr(inspect, name)
1443 self.assertIn(name, repr(state))
1444 self.assertIn(name, str(state))
1445
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001446 def test_getgeneratorlocals(self):
1447 def each(lst, a=None):
1448 b=(1, 2, 3)
1449 for v in lst:
1450 if v == 3:
1451 c = 12
1452 yield v
1453
1454 numbers = each([1, 2, 3])
1455 self.assertEqual(inspect.getgeneratorlocals(numbers),
1456 {'a': None, 'lst': [1, 2, 3]})
1457 next(numbers)
1458 self.assertEqual(inspect.getgeneratorlocals(numbers),
1459 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1460 'b': (1, 2, 3)})
1461 next(numbers)
1462 self.assertEqual(inspect.getgeneratorlocals(numbers),
1463 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1464 'b': (1, 2, 3)})
1465 next(numbers)
1466 self.assertEqual(inspect.getgeneratorlocals(numbers),
1467 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1468 'b': (1, 2, 3), 'c': 12})
1469 try:
1470 next(numbers)
1471 except StopIteration:
1472 pass
1473 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1474
1475 def test_getgeneratorlocals_empty(self):
1476 def yield_one():
1477 yield 1
1478 one = yield_one()
1479 self.assertEqual(inspect.getgeneratorlocals(one), {})
1480 try:
1481 next(one)
1482 except StopIteration:
1483 pass
1484 self.assertEqual(inspect.getgeneratorlocals(one), {})
1485
1486 def test_getgeneratorlocals_error(self):
1487 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1488 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1489 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1490 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1491
Nick Coghlane0f04652010-11-21 03:44:04 +00001492
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001493class TestSignatureObject(unittest.TestCase):
1494 @staticmethod
1495 def signature(func):
1496 sig = inspect.signature(func)
1497 return (tuple((param.name,
1498 (... if param.default is param.empty else param.default),
1499 (... if param.annotation is param.empty
1500 else param.annotation),
1501 str(param.kind).lower())
1502 for param in sig.parameters.values()),
1503 (... if sig.return_annotation is sig.empty
1504 else sig.return_annotation))
1505
1506 def test_signature_object(self):
1507 S = inspect.Signature
1508 P = inspect.Parameter
1509
1510 self.assertEqual(str(S()), '()')
1511
1512 def test(po, pk, *args, ko, **kwargs):
1513 pass
1514 sig = inspect.signature(test)
1515 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
1516 pk = sig.parameters['pk']
1517 args = sig.parameters['args']
1518 ko = sig.parameters['ko']
1519 kwargs = sig.parameters['kwargs']
1520
1521 S((po, pk, args, ko, kwargs))
1522
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001523 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001524 S((pk, po, args, ko, kwargs))
1525
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001526 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001527 S((po, args, pk, ko, kwargs))
1528
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001529 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001530 S((args, po, pk, ko, kwargs))
1531
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001532 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001533 S((po, pk, args, kwargs, ko))
1534
1535 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001536 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001537 S((po, pk, args, kwargs2, ko))
1538
1539 def test_signature_immutability(self):
1540 def test(a):
1541 pass
1542 sig = inspect.signature(test)
1543
1544 with self.assertRaises(AttributeError):
1545 sig.foo = 'bar'
1546
1547 with self.assertRaises(TypeError):
1548 sig.parameters['a'] = None
1549
1550 def test_signature_on_noarg(self):
1551 def test():
1552 pass
1553 self.assertEqual(self.signature(test), ((), ...))
1554
1555 def test_signature_on_wargs(self):
1556 def test(a, b:'foo') -> 123:
1557 pass
1558 self.assertEqual(self.signature(test),
1559 ((('a', ..., ..., "positional_or_keyword"),
1560 ('b', ..., 'foo', "positional_or_keyword")),
1561 123))
1562
1563 def test_signature_on_wkwonly(self):
1564 def test(*, a:float, b:str) -> int:
1565 pass
1566 self.assertEqual(self.signature(test),
1567 ((('a', ..., float, "keyword_only"),
1568 ('b', ..., str, "keyword_only")),
1569 int))
1570
1571 def test_signature_on_complex_args(self):
1572 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1573 pass
1574 self.assertEqual(self.signature(test),
1575 ((('a', ..., ..., "positional_or_keyword"),
1576 ('b', 10, 'foo', "positional_or_keyword"),
1577 ('args', ..., 'bar', "var_positional"),
1578 ('spam', ..., 'baz', "keyword_only"),
1579 ('ham', 123, ..., "keyword_only"),
1580 ('kwargs', ..., int, "var_keyword")),
1581 ...))
1582
Larry Hastingsfcafe432013-11-23 17:35:48 -08001583 def test_signature_on_unsupported_builtins(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001584 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001585 inspect.signature(type)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001586 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001587 # support for 'wrapper_descriptor'
1588 inspect.signature(type.__call__)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001589 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001590 # support for 'method-wrapper'
1591 inspect.signature(min.__call__)
Larry Hastingsfcafe432013-11-23 17:35:48 -08001592
1593 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1594 "Signature information for builtins requires docstrings")
1595 def test_signature_on_builtins(self):
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001596 self.assertEqual(inspect.signature(min), None)
1597 signature = inspect.signature(os.stat)
1598 self.assertTrue(isinstance(signature, inspect.Signature))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001599
1600 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001601 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001602 inspect.signature(42)
1603
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001604 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001605 inspect.Signature.from_function(42)
1606
1607 def test_signature_on_method(self):
1608 class Test:
1609 def foo(self, arg1, arg2=1) -> int:
1610 pass
1611
1612 meth = Test().foo
1613
1614 self.assertEqual(self.signature(meth),
1615 ((('arg1', ..., ..., "positional_or_keyword"),
1616 ('arg2', 1, ..., "positional_or_keyword")),
1617 int))
1618
1619 def test_signature_on_classmethod(self):
1620 class Test:
1621 @classmethod
1622 def foo(cls, arg1, *, arg2=1):
1623 pass
1624
1625 meth = Test().foo
1626 self.assertEqual(self.signature(meth),
1627 ((('arg1', ..., ..., "positional_or_keyword"),
1628 ('arg2', 1, ..., "keyword_only")),
1629 ...))
1630
1631 meth = Test.foo
1632 self.assertEqual(self.signature(meth),
1633 ((('arg1', ..., ..., "positional_or_keyword"),
1634 ('arg2', 1, ..., "keyword_only")),
1635 ...))
1636
1637 def test_signature_on_staticmethod(self):
1638 class Test:
1639 @staticmethod
1640 def foo(cls, *, arg):
1641 pass
1642
1643 meth = Test().foo
1644 self.assertEqual(self.signature(meth),
1645 ((('cls', ..., ..., "positional_or_keyword"),
1646 ('arg', ..., ..., "keyword_only")),
1647 ...))
1648
1649 meth = Test.foo
1650 self.assertEqual(self.signature(meth),
1651 ((('cls', ..., ..., "positional_or_keyword"),
1652 ('arg', ..., ..., "keyword_only")),
1653 ...))
1654
1655 def test_signature_on_partial(self):
1656 from functools import partial
1657
1658 def test():
1659 pass
1660
1661 self.assertEqual(self.signature(partial(test)), ((), ...))
1662
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001663 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001664 inspect.signature(partial(test, 1))
1665
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001666 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001667 inspect.signature(partial(test, a=1))
1668
1669 def test(a, b, *, c, d):
1670 pass
1671
1672 self.assertEqual(self.signature(partial(test)),
1673 ((('a', ..., ..., "positional_or_keyword"),
1674 ('b', ..., ..., "positional_or_keyword"),
1675 ('c', ..., ..., "keyword_only"),
1676 ('d', ..., ..., "keyword_only")),
1677 ...))
1678
1679 self.assertEqual(self.signature(partial(test, 1)),
1680 ((('b', ..., ..., "positional_or_keyword"),
1681 ('c', ..., ..., "keyword_only"),
1682 ('d', ..., ..., "keyword_only")),
1683 ...))
1684
1685 self.assertEqual(self.signature(partial(test, 1, c=2)),
1686 ((('b', ..., ..., "positional_or_keyword"),
1687 ('c', 2, ..., "keyword_only"),
1688 ('d', ..., ..., "keyword_only")),
1689 ...))
1690
1691 self.assertEqual(self.signature(partial(test, b=1, c=2)),
1692 ((('a', ..., ..., "positional_or_keyword"),
1693 ('b', 1, ..., "positional_or_keyword"),
1694 ('c', 2, ..., "keyword_only"),
1695 ('d', ..., ..., "keyword_only")),
1696 ...))
1697
1698 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
1699 ((('b', 1, ..., "positional_or_keyword"),
1700 ('c', 2, ..., "keyword_only"),
1701 ('d', ..., ..., "keyword_only"),),
1702 ...))
1703
1704 def test(a, *args, b, **kwargs):
1705 pass
1706
1707 self.assertEqual(self.signature(partial(test, 1)),
1708 ((('args', ..., ..., "var_positional"),
1709 ('b', ..., ..., "keyword_only"),
1710 ('kwargs', ..., ..., "var_keyword")),
1711 ...))
1712
1713 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
1714 ((('args', ..., ..., "var_positional"),
1715 ('b', ..., ..., "keyword_only"),
1716 ('kwargs', ..., ..., "var_keyword")),
1717 ...))
1718
1719
1720 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
1721 ((('args', ..., ..., "var_positional"),
1722 ('b', ..., ..., "keyword_only"),
1723 ('kwargs', ..., ..., "var_keyword")),
1724 ...))
1725
1726 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
1727 ((('args', ..., ..., "var_positional"),
1728 ('b', 0, ..., "keyword_only"),
1729 ('kwargs', ..., ..., "var_keyword")),
1730 ...))
1731
1732 self.assertEqual(self.signature(partial(test, b=0)),
1733 ((('a', ..., ..., "positional_or_keyword"),
1734 ('args', ..., ..., "var_positional"),
1735 ('b', 0, ..., "keyword_only"),
1736 ('kwargs', ..., ..., "var_keyword")),
1737 ...))
1738
1739 self.assertEqual(self.signature(partial(test, b=0, test=1)),
1740 ((('a', ..., ..., "positional_or_keyword"),
1741 ('args', ..., ..., "var_positional"),
1742 ('b', 0, ..., "keyword_only"),
1743 ('kwargs', ..., ..., "var_keyword")),
1744 ...))
1745
1746 def test(a, b, c:int) -> 42:
1747 pass
1748
1749 sig = test.__signature__ = inspect.signature(test)
1750
1751 self.assertEqual(self.signature(partial(partial(test, 1))),
1752 ((('b', ..., ..., "positional_or_keyword"),
1753 ('c', ..., int, "positional_or_keyword")),
1754 42))
1755
1756 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
1757 ((('c', ..., int, "positional_or_keyword"),),
1758 42))
1759
1760 psig = inspect.signature(partial(partial(test, 1), 2))
1761
1762 def foo(a):
1763 return a
1764 _foo = partial(partial(foo, a=10), a=20)
1765 self.assertEqual(self.signature(_foo),
1766 ((('a', 20, ..., "positional_or_keyword"),),
1767 ...))
1768 # check that we don't have any side-effects in signature(),
1769 # and the partial object is still functioning
1770 self.assertEqual(_foo(), 20)
1771
1772 def foo(a, b, c):
1773 return a, b, c
1774 _foo = partial(partial(foo, 1, b=20), b=30)
1775 self.assertEqual(self.signature(_foo),
1776 ((('b', 30, ..., "positional_or_keyword"),
1777 ('c', ..., ..., "positional_or_keyword")),
1778 ...))
1779 self.assertEqual(_foo(c=10), (1, 30, 10))
1780 _foo = partial(_foo, 2) # now 'b' has two values -
1781 # positional and keyword
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001782 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001783 inspect.signature(_foo)
1784
1785 def foo(a, b, c, *, d):
1786 return a, b, c, d
1787 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
1788 self.assertEqual(self.signature(_foo),
1789 ((('a', ..., ..., "positional_or_keyword"),
1790 ('b', 10, ..., "positional_or_keyword"),
1791 ('c', 20, ..., "positional_or_keyword"),
1792 ('d', 30, ..., "keyword_only")),
1793 ...))
1794 ba = inspect.signature(_foo).bind(a=200, b=11)
1795 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
1796
1797 def foo(a=1, b=2, c=3):
1798 return a, b, c
1799 _foo = partial(foo, a=10, c=13)
1800 ba = inspect.signature(_foo).bind(11)
1801 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
1802 ba = inspect.signature(_foo).bind(11, 12)
1803 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
1804 ba = inspect.signature(_foo).bind(11, b=12)
1805 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
1806 ba = inspect.signature(_foo).bind(b=12)
1807 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
1808 _foo = partial(_foo, b=10)
1809 ba = inspect.signature(_foo).bind(12, 14)
1810 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
1811
1812 def test_signature_on_decorated(self):
1813 import functools
1814
1815 def decorator(func):
1816 @functools.wraps(func)
1817 def wrapper(*args, **kwargs) -> int:
1818 return func(*args, **kwargs)
1819 return wrapper
1820
1821 class Foo:
1822 @decorator
1823 def bar(self, a, b):
1824 pass
1825
1826 self.assertEqual(self.signature(Foo.bar),
1827 ((('self', ..., ..., "positional_or_keyword"),
1828 ('a', ..., ..., "positional_or_keyword"),
1829 ('b', ..., ..., "positional_or_keyword")),
1830 ...))
1831
1832 self.assertEqual(self.signature(Foo().bar),
1833 ((('a', ..., ..., "positional_or_keyword"),
1834 ('b', ..., ..., "positional_or_keyword")),
1835 ...))
1836
1837 # Test that we handle method wrappers correctly
1838 def decorator(func):
1839 @functools.wraps(func)
1840 def wrapper(*args, **kwargs) -> int:
1841 return func(42, *args, **kwargs)
1842 sig = inspect.signature(func)
1843 new_params = tuple(sig.parameters.values())[1:]
1844 wrapper.__signature__ = sig.replace(parameters=new_params)
1845 return wrapper
1846
1847 class Foo:
1848 @decorator
1849 def __call__(self, a, b):
1850 pass
1851
1852 self.assertEqual(self.signature(Foo.__call__),
1853 ((('a', ..., ..., "positional_or_keyword"),
1854 ('b', ..., ..., "positional_or_keyword")),
1855 ...))
1856
1857 self.assertEqual(self.signature(Foo().__call__),
1858 ((('b', ..., ..., "positional_or_keyword"),),
1859 ...))
1860
Nick Coghlane8c45d62013-07-28 20:00:01 +10001861 # Test we handle __signature__ partway down the wrapper stack
1862 def wrapped_foo_call():
1863 pass
1864 wrapped_foo_call.__wrapped__ = Foo.__call__
1865
1866 self.assertEqual(self.signature(wrapped_foo_call),
1867 ((('a', ..., ..., "positional_or_keyword"),
1868 ('b', ..., ..., "positional_or_keyword")),
1869 ...))
1870
1871
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001872 def test_signature_on_class(self):
1873 class C:
1874 def __init__(self, a):
1875 pass
1876
1877 self.assertEqual(self.signature(C),
1878 ((('a', ..., ..., "positional_or_keyword"),),
1879 ...))
1880
1881 class CM(type):
1882 def __call__(cls, a):
1883 pass
1884 class C(metaclass=CM):
1885 def __init__(self, b):
1886 pass
1887
1888 self.assertEqual(self.signature(C),
1889 ((('a', ..., ..., "positional_or_keyword"),),
1890 ...))
1891
1892 class CM(type):
1893 def __new__(mcls, name, bases, dct, *, foo=1):
1894 return super().__new__(mcls, name, bases, dct)
1895 class C(metaclass=CM):
1896 def __init__(self, b):
1897 pass
1898
1899 self.assertEqual(self.signature(C),
1900 ((('b', ..., ..., "positional_or_keyword"),),
1901 ...))
1902
1903 self.assertEqual(self.signature(CM),
1904 ((('name', ..., ..., "positional_or_keyword"),
1905 ('bases', ..., ..., "positional_or_keyword"),
1906 ('dct', ..., ..., "positional_or_keyword"),
1907 ('foo', 1, ..., "keyword_only")),
1908 ...))
1909
1910 class CMM(type):
1911 def __new__(mcls, name, bases, dct, *, foo=1):
1912 return super().__new__(mcls, name, bases, dct)
1913 def __call__(cls, nm, bs, dt):
1914 return type(nm, bs, dt)
1915 class CM(type, metaclass=CMM):
1916 def __new__(mcls, name, bases, dct, *, bar=2):
1917 return super().__new__(mcls, name, bases, dct)
1918 class C(metaclass=CM):
1919 def __init__(self, b):
1920 pass
1921
1922 self.assertEqual(self.signature(CMM),
1923 ((('name', ..., ..., "positional_or_keyword"),
1924 ('bases', ..., ..., "positional_or_keyword"),
1925 ('dct', ..., ..., "positional_or_keyword"),
1926 ('foo', 1, ..., "keyword_only")),
1927 ...))
1928
1929 self.assertEqual(self.signature(CM),
1930 ((('nm', ..., ..., "positional_or_keyword"),
1931 ('bs', ..., ..., "positional_or_keyword"),
1932 ('dt', ..., ..., "positional_or_keyword")),
1933 ...))
1934
1935 self.assertEqual(self.signature(C),
1936 ((('b', ..., ..., "positional_or_keyword"),),
1937 ...))
1938
1939 class CM(type):
1940 def __init__(cls, name, bases, dct, *, bar=2):
1941 return super().__init__(name, bases, dct)
1942 class C(metaclass=CM):
1943 def __init__(self, b):
1944 pass
1945
1946 self.assertEqual(self.signature(CM),
1947 ((('name', ..., ..., "positional_or_keyword"),
1948 ('bases', ..., ..., "positional_or_keyword"),
1949 ('dct', ..., ..., "positional_or_keyword"),
1950 ('bar', 2, ..., "keyword_only")),
1951 ...))
1952
1953 def test_signature_on_callable_objects(self):
1954 class Foo:
1955 def __call__(self, a):
1956 pass
1957
1958 self.assertEqual(self.signature(Foo()),
1959 ((('a', ..., ..., "positional_or_keyword"),),
1960 ...))
1961
1962 class Spam:
1963 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001964 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001965 inspect.signature(Spam())
1966
1967 class Bar(Spam, Foo):
1968 pass
1969
1970 self.assertEqual(self.signature(Bar()),
1971 ((('a', ..., ..., "positional_or_keyword"),),
1972 ...))
1973
1974 class ToFail:
1975 __call__ = type
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001976 with self.assertRaisesRegex(ValueError, "not supported by signature"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001977 inspect.signature(ToFail())
1978
1979
1980 class Wrapped:
1981 pass
1982 Wrapped.__wrapped__ = lambda a: None
1983 self.assertEqual(self.signature(Wrapped),
1984 ((('a', ..., ..., "positional_or_keyword"),),
1985 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10001986 # wrapper loop:
1987 Wrapped.__wrapped__ = Wrapped
1988 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
1989 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001990
1991 def test_signature_on_lambdas(self):
1992 self.assertEqual(self.signature((lambda a=10: a)),
1993 ((('a', 10, ..., "positional_or_keyword"),),
1994 ...))
1995
1996 def test_signature_equality(self):
1997 def foo(a, *, b:int) -> float: pass
1998 self.assertNotEqual(inspect.signature(foo), 42)
1999
2000 def bar(a, *, b:int) -> float: pass
2001 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2002
2003 def bar(a, *, b:int) -> int: pass
2004 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2005
2006 def bar(a, *, b:int): pass
2007 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2008
2009 def bar(a, *, b:int=42) -> float: pass
2010 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2011
2012 def bar(a, *, c) -> float: pass
2013 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2014
2015 def bar(a, b:int) -> float: pass
2016 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2017 def spam(b:int, a) -> float: pass
2018 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
2019
2020 def foo(*, a, b, c): pass
2021 def bar(*, c, b, a): pass
2022 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2023
2024 def foo(*, a=1, b, c): pass
2025 def bar(*, c, b, a=1): pass
2026 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2027
2028 def foo(pos, *, a=1, b, c): pass
2029 def bar(pos, *, c, b, a=1): pass
2030 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2031
2032 def foo(pos, *, a, b, c): pass
2033 def bar(pos, *, c, b, a=1): pass
2034 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2035
2036 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2037 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2038 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2039
2040 def test_signature_unhashable(self):
2041 def foo(a): pass
2042 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002043 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002044 hash(sig)
2045
2046 def test_signature_str(self):
2047 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2048 pass
2049 self.assertEqual(str(inspect.signature(foo)),
2050 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2051
2052 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2053 pass
2054 self.assertEqual(str(inspect.signature(foo)),
2055 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2056
2057 def foo():
2058 pass
2059 self.assertEqual(str(inspect.signature(foo)), '()')
2060
2061 def test_signature_str_positional_only(self):
2062 P = inspect.Parameter
2063
2064 def test(a_po, *, b, **kwargs):
2065 return a_po, kwargs
2066
2067 sig = inspect.signature(test)
2068 new_params = list(sig.parameters.values())
2069 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2070 test.__signature__ = sig.replace(parameters=new_params)
2071
2072 self.assertEqual(str(inspect.signature(test)),
2073 '(<a_po>, *, b, **kwargs)')
2074
2075 sig = inspect.signature(test)
2076 new_params = list(sig.parameters.values())
2077 new_params[0] = new_params[0].replace(name=None)
2078 test.__signature__ = sig.replace(parameters=new_params)
2079 self.assertEqual(str(inspect.signature(test)),
2080 '(<0>, *, b, **kwargs)')
2081
2082 def test_signature_replace_anno(self):
2083 def test() -> 42:
2084 pass
2085
2086 sig = inspect.signature(test)
2087 sig = sig.replace(return_annotation=None)
2088 self.assertIs(sig.return_annotation, None)
2089 sig = sig.replace(return_annotation=sig.empty)
2090 self.assertIs(sig.return_annotation, sig.empty)
2091 sig = sig.replace(return_annotation=42)
2092 self.assertEqual(sig.return_annotation, 42)
2093 self.assertEqual(sig, inspect.signature(test))
2094
2095
2096class TestParameterObject(unittest.TestCase):
2097 def test_signature_parameter_kinds(self):
2098 P = inspect.Parameter
2099 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2100 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2101
2102 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2103 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2104
2105 def test_signature_parameter_object(self):
2106 p = inspect.Parameter('foo', default=10,
2107 kind=inspect.Parameter.POSITIONAL_ONLY)
2108 self.assertEqual(p.name, 'foo')
2109 self.assertEqual(p.default, 10)
2110 self.assertIs(p.annotation, p.empty)
2111 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2112
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002113 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002114 inspect.Parameter('foo', default=10, kind='123')
2115
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002116 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002117 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2118
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002119 with self.assertRaisesRegex(ValueError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002120 'non-positional-only parameter'):
2121 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2122
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002123 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002124 inspect.Parameter('a', default=42,
2125 kind=inspect.Parameter.VAR_KEYWORD)
2126
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002127 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002128 inspect.Parameter('a', default=42,
2129 kind=inspect.Parameter.VAR_POSITIONAL)
2130
2131 p = inspect.Parameter('a', default=42,
2132 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002133 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002134 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2135
2136 self.assertTrue(repr(p).startswith('<Parameter'))
2137
2138 def test_signature_parameter_equality(self):
2139 P = inspect.Parameter
2140 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2141
2142 self.assertEqual(p, p)
2143 self.assertNotEqual(p, 42)
2144
2145 self.assertEqual(p, P('foo', default=42,
2146 kind=inspect.Parameter.KEYWORD_ONLY))
2147
2148 def test_signature_parameter_unhashable(self):
2149 p = inspect.Parameter('foo', default=42,
2150 kind=inspect.Parameter.KEYWORD_ONLY)
2151
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002152 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002153 hash(p)
2154
2155 def test_signature_parameter_replace(self):
2156 p = inspect.Parameter('foo', default=42,
2157 kind=inspect.Parameter.KEYWORD_ONLY)
2158
2159 self.assertIsNot(p, p.replace())
2160 self.assertEqual(p, p.replace())
2161
2162 p2 = p.replace(annotation=1)
2163 self.assertEqual(p2.annotation, 1)
2164 p2 = p2.replace(annotation=p2.empty)
2165 self.assertEqual(p, p2)
2166
2167 p2 = p2.replace(name='bar')
2168 self.assertEqual(p2.name, 'bar')
2169 self.assertNotEqual(p2, p)
2170
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002171 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002172 p2 = p2.replace(name=p2.empty)
2173
2174 p2 = p2.replace(name='foo', default=None)
2175 self.assertIs(p2.default, None)
2176 self.assertNotEqual(p2, p)
2177
2178 p2 = p2.replace(name='foo', default=p2.empty)
2179 self.assertIs(p2.default, p2.empty)
2180
2181
2182 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2183 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2184 self.assertNotEqual(p2, p)
2185
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002186 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002187 p2 = p2.replace(kind=p2.empty)
2188
2189 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2190 self.assertEqual(p2, p)
2191
2192 def test_signature_parameter_positional_only(self):
2193 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
2194 self.assertEqual(str(p), '<>')
2195
2196 p = p.replace(name='1')
2197 self.assertEqual(str(p), '<1>')
2198
2199 def test_signature_parameter_immutability(self):
2200 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
2201
2202 with self.assertRaises(AttributeError):
2203 p.foo = 'bar'
2204
2205 with self.assertRaises(AttributeError):
2206 p.kind = 123
2207
2208
2209class TestSignatureBind(unittest.TestCase):
2210 @staticmethod
2211 def call(func, *args, **kwargs):
2212 sig = inspect.signature(func)
2213 ba = sig.bind(*args, **kwargs)
2214 return func(*ba.args, **ba.kwargs)
2215
2216 def test_signature_bind_empty(self):
2217 def test():
2218 return 42
2219
2220 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002221 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002222 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002223 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002224 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002225 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002226 self.call(test, spam=1)
2227
2228 def test_signature_bind_var(self):
2229 def test(*args, **kwargs):
2230 return args, kwargs
2231
2232 self.assertEqual(self.call(test), ((), {}))
2233 self.assertEqual(self.call(test, 1), ((1,), {}))
2234 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2235 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2236 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2237 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2238 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2239 ((1, 2), {'foo': 'bar'}))
2240
2241 def test_signature_bind_just_args(self):
2242 def test(a, b, c):
2243 return a, b, c
2244
2245 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2246
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002247 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002248 self.call(test, 1, 2, 3, 4)
2249
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002250 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002251 self.call(test, 1)
2252
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002253 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002254 self.call(test)
2255
2256 def test(a, b, c=10):
2257 return a, b, c
2258 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2259 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2260
2261 def test(a=1, b=2, c=3):
2262 return a, b, c
2263 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2264 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2265 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2266
2267 def test_signature_bind_varargs_order(self):
2268 def test(*args):
2269 return args
2270
2271 self.assertEqual(self.call(test), ())
2272 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2273
2274 def test_signature_bind_args_and_varargs(self):
2275 def test(a, b, c=3, *args):
2276 return a, b, c, args
2277
2278 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2279 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2280 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2281 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2282
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002283 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002284 "multiple values for argument 'c'"):
2285 self.call(test, 1, 2, 3, c=4)
2286
2287 def test_signature_bind_just_kwargs(self):
2288 def test(**kwargs):
2289 return kwargs
2290
2291 self.assertEqual(self.call(test), {})
2292 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2293 {'foo': 'bar', 'spam': 'ham'})
2294
2295 def test_signature_bind_args_and_kwargs(self):
2296 def test(a, b, c=3, **kwargs):
2297 return a, b, c, kwargs
2298
2299 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2300 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2301 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2302 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2303 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2304 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2305 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2306 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2307 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2308 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2309 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2310 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2311 (1, 2, 4, {'foo': 'bar'}))
2312 self.assertEqual(self.call(test, c=5, a=4, b=3),
2313 (4, 3, 5, {}))
2314
2315 def test_signature_bind_kwonly(self):
2316 def test(*, foo):
2317 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002318 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002319 'too many positional arguments'):
2320 self.call(test, 1)
2321 self.assertEqual(self.call(test, foo=1), 1)
2322
2323 def test(a, *, foo=1, bar):
2324 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002325 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002326 "'bar' parameter lacking default value"):
2327 self.call(test, 1)
2328
2329 def test(foo, *, bar):
2330 return foo, bar
2331 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2332 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2333
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002334 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002335 'too many keyword arguments'):
2336 self.call(test, bar=2, foo=1, spam=10)
2337
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002338 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002339 'too many positional arguments'):
2340 self.call(test, 1, 2)
2341
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002342 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002343 'too many positional arguments'):
2344 self.call(test, 1, 2, bar=2)
2345
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002346 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002347 'too many keyword arguments'):
2348 self.call(test, 1, bar=2, spam='ham')
2349
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002350 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002351 "'bar' parameter lacking default value"):
2352 self.call(test, 1)
2353
2354 def test(foo, *, bar, **bin):
2355 return foo, bar, bin
2356 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2357 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2358 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2359 (1, 2, {'spam': 'ham'}))
2360 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2361 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002362 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002363 "'foo' parameter lacking default value"):
2364 self.call(test, spam='ham', bar=2)
2365 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2366 (1, 2, {'bin': 1, 'spam': 10}))
2367
2368 def test_signature_bind_arguments(self):
2369 def test(a, *args, b, z=100, **kwargs):
2370 pass
2371 sig = inspect.signature(test)
2372 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2373 # we won't have 'z' argument in the bound arguments object, as we didn't
2374 # pass it to the 'bind'
2375 self.assertEqual(tuple(ba.arguments.items()),
2376 (('a', 10), ('args', (20,)), ('b', 30),
2377 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2378 self.assertEqual(ba.kwargs,
2379 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2380 self.assertEqual(ba.args, (10, 20))
2381
2382 def test_signature_bind_positional_only(self):
2383 P = inspect.Parameter
2384
2385 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2386 return a_po, b_po, c_po, foo, bar, kwargs
2387
2388 sig = inspect.signature(test)
2389 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2390 for name in ('a_po', 'b_po', 'c_po'):
2391 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2392 new_sig = sig.replace(parameters=new_params.values())
2393 test.__signature__ = new_sig
2394
2395 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2396 (1, 2, 4, 5, 6, {}))
2397
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002398 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002399 self.call(test, 1, 2, c_po=4)
2400
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002401 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002402 self.call(test, a_po=1, b_po=2)
2403
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002404 def test_signature_bind_with_self_arg(self):
2405 # Issue #17071: one of the parameters is named "self
2406 def test(a, self, b):
2407 pass
2408 sig = inspect.signature(test)
2409 ba = sig.bind(1, 2, 3)
2410 self.assertEqual(ba.args, (1, 2, 3))
2411 ba = sig.bind(1, self=2, b=3)
2412 self.assertEqual(ba.args, (1, 2, 3))
2413
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002414
2415class TestBoundArguments(unittest.TestCase):
2416 def test_signature_bound_arguments_unhashable(self):
2417 def foo(a): pass
2418 ba = inspect.signature(foo).bind(1)
2419
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002420 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002421 hash(ba)
2422
2423 def test_signature_bound_arguments_equality(self):
2424 def foo(a): pass
2425 ba = inspect.signature(foo).bind(1)
2426 self.assertEqual(ba, ba)
2427
2428 ba2 = inspect.signature(foo).bind(1)
2429 self.assertEqual(ba, ba2)
2430
2431 ba3 = inspect.signature(foo).bind(2)
2432 self.assertNotEqual(ba, ba3)
2433 ba3.arguments['a'] = 1
2434 self.assertEqual(ba, ba3)
2435
2436 def bar(b): pass
2437 ba4 = inspect.signature(bar).bind(1)
2438 self.assertNotEqual(ba, ba4)
2439
2440
Nick Coghlane8c45d62013-07-28 20:00:01 +10002441class TestUnwrap(unittest.TestCase):
2442
2443 def test_unwrap_one(self):
2444 def func(a, b):
2445 return a + b
2446 wrapper = functools.lru_cache(maxsize=20)(func)
2447 self.assertIs(inspect.unwrap(wrapper), func)
2448
2449 def test_unwrap_several(self):
2450 def func(a, b):
2451 return a + b
2452 wrapper = func
2453 for __ in range(10):
2454 @functools.wraps(wrapper)
2455 def wrapper():
2456 pass
2457 self.assertIsNot(wrapper.__wrapped__, func)
2458 self.assertIs(inspect.unwrap(wrapper), func)
2459
2460 def test_stop(self):
2461 def func1(a, b):
2462 return a + b
2463 @functools.wraps(func1)
2464 def func2():
2465 pass
2466 @functools.wraps(func2)
2467 def wrapper():
2468 pass
2469 func2.stop_here = 1
2470 unwrapped = inspect.unwrap(wrapper,
2471 stop=(lambda f: hasattr(f, "stop_here")))
2472 self.assertIs(unwrapped, func2)
2473
2474 def test_cycle(self):
2475 def func1(): pass
2476 func1.__wrapped__ = func1
2477 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2478 inspect.unwrap(func1)
2479
2480 def func2(): pass
2481 func2.__wrapped__ = func1
2482 func1.__wrapped__ = func2
2483 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2484 inspect.unwrap(func1)
2485 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2486 inspect.unwrap(func2)
2487
2488 def test_unhashable(self):
2489 def func(): pass
2490 func.__wrapped__ = None
2491 class C:
2492 __hash__ = None
2493 __wrapped__ = func
2494 self.assertIsNone(inspect.unwrap(C()))
2495
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002496class TestMain(unittest.TestCase):
2497 def test_only_source(self):
2498 module = importlib.import_module('unittest')
2499 rc, out, err = assert_python_ok('-m', 'inspect',
2500 'unittest')
2501 lines = out.decode().splitlines()
2502 # ignore the final newline
2503 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
2504 self.assertEqual(err, b'')
2505
Brett Cannon634a8fc2013-10-02 10:25:42 -04002506 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04002507 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002508 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002509 rc, out, err = assert_python_ok('-m', 'inspect',
2510 'concurrent.futures:ThreadPoolExecutor')
2511 lines = out.decode().splitlines()
2512 # ignore the final newline
2513 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04002514 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002515 self.assertEqual(err, b'')
2516
2517 def test_builtins(self):
2518 module = importlib.import_module('unittest')
2519 _, out, err = assert_python_failure('-m', 'inspect',
2520 'sys')
2521 lines = err.decode().splitlines()
2522 self.assertEqual(lines, ["Can't get info for builtin modules."])
2523
2524 def test_details(self):
2525 module = importlib.import_module('unittest')
2526 rc, out, err = assert_python_ok('-m', 'inspect',
2527 'unittest', '--details')
2528 output = out.decode()
2529 # Just a quick sanity check on the output
2530 self.assertIn(module.__name__, output)
2531 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02002532 if not sys.flags.optimize:
2533 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002534 self.assertEqual(err, b'')
2535
2536
2537
Nick Coghlane8c45d62013-07-28 20:00:01 +10002538
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002539def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00002540 run_unittest(
2541 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
2542 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
2543 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00002544 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002545 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002546 TestBoundArguments, TestGetClosureVars, TestUnwrap, TestMain
Michael Foord95fc51d2010-11-20 15:07:30 +00002547 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00002548
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002549if __name__ == "__main__":
2550 test_main()