blob: 0dc74512a259a09750df9a2879944edf2fc107cb [file] [log] [blame]
Guido van Rossum813b0e52007-05-21 18:11:34 +00001import collections
Larry Hastings5c661892014-01-24 06:17:25 -08002import datetime
Nick Coghlane8c45d62013-07-28 20:00:01 +10003import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004import importlib
Larry Hastings5c661892014-01-24 06:17:25 -08005import inspect
6import io
7import linecache
8import os
Christian Heimesa3538eb2007-11-06 11:44:48 +00009from os.path import normcase
Larry Hastings5c661892014-01-24 06:17:25 -080010import _pickle
11import re
12import shutil
13import sys
14import types
15import unicodedata
16import unittest
Yury Selivanov8dfb4572014-02-21 18:30:53 -050017import unittest.mock
Larry Hastings5c661892014-01-24 06:17:25 -080018
Brett Cannon634a8fc2013-10-02 10:25:42 -040019try:
20 from concurrent.futures import ThreadPoolExecutor
21except ImportError:
22 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000023
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020024from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -080025from test.support import MISSING_C_DOCSTRINGS
Nick Coghlanf94a16b2013-09-22 22:46:49 +100026from test.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000027from test import inspect_fodder as mod
28from test import inspect_fodder2 as mod2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000029
R. David Murray74b89242009-05-13 17:33:03 +000030
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000031# Functions tested in this suite:
32# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000033# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
34# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
35# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
36# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000037
Nick Coghlanf088e5e2008-12-14 11:50:48 +000038# NOTE: There are some additional tests relating to interaction with
39# zipimport in the test_zipimport_support test module.
40
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000041modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000042if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000043 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000044
Christian Heimesa3538eb2007-11-06 11:44:48 +000045# Normalize file names: on Windows, the case of file names of compiled
46# modules depends on the path used to start the python executable.
47modfile = normcase(modfile)
48
49def revise(filename, *args):
50 return (normcase(filename),) + args
51
Georg Brandl1a3284e2007-12-02 09:40:06 +000052import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000053
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000054git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000055
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000056class IsTestBase(unittest.TestCase):
57 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
58 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000059 inspect.ismodule, inspect.istraceback,
60 inspect.isgenerator, inspect.isgeneratorfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000061
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000062 def istest(self, predicate, exp):
63 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000064 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000065
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000066 for other in self.predicates - set([predicate]):
Christian Heimes7131fd92008-02-19 14:21:46 +000067 if predicate == inspect.isgeneratorfunction and\
68 other == inspect.isfunction:
69 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000070 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000071
Christian Heimes7131fd92008-02-19 14:21:46 +000072def generator_function_example(self):
73 for i in range(2):
74 yield i
75
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000076class TestPredicates(IsTestBase):
Christian Heimes227c8002008-03-03 20:34:40 +000077 def test_sixteen(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +000078 count = len([x for x in dir(inspect) if x.startswith('is')])
Christian Heimes7131fd92008-02-19 14:21:46 +000079 # This test is here for remember you to update Doc/library/inspect.rst
Christian Heimes78644762008-03-04 23:39:23 +000080 # which claims there are 16 such functions
Christian Heimes227c8002008-03-03 20:34:40 +000081 expected = 16
Thomas Wouters0e3f5912006-08-11 14:57:12 +000082 err_msg = "There are %d (not %d) is* functions" % (count, expected)
83 self.assertEqual(count, expected, err_msg)
Tim Peters5a9fb3c2005-01-07 16:01:32 +000084
Christian Heimes7131fd92008-02-19 14:21:46 +000085
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000086 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +020087 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000088 self.istest(inspect.isbuiltin, 'sys.exit')
89 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +000090 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +020091 try:
92 1/0
93 except:
94 tb = sys.exc_info()[2]
95 self.istest(inspect.isframe, 'tb.tb_frame')
96 self.istest(inspect.istraceback, 'tb')
97 if hasattr(types, 'GetSetDescriptorType'):
98 self.istest(inspect.isgetsetdescriptor,
99 'type(tb.tb_frame).f_locals')
100 else:
101 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
102 finally:
103 # Clear traceback and all the frames and local variables hanging to it.
104 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000105 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000106 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000107 self.istest(inspect.ismethod, 'git.argue')
108 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000109 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000110 self.istest(inspect.isgenerator, '(x for x in range(2))')
111 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000112 if hasattr(types, 'MemberDescriptorType'):
113 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
114 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000115 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000116
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000117 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000118 self.assertTrue(inspect.isroutine(mod.spam))
119 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000120
Benjamin Petersonc4656002009-01-17 22:41:18 +0000121 def test_isclass(self):
122 self.istest(inspect.isclass, 'mod.StupidGit')
123 self.assertTrue(inspect.isclass(list))
124
125 class CustomGetattr(object):
126 def __getattr__(self, attr):
127 return None
128 self.assertFalse(inspect.isclass(CustomGetattr()))
129
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000130 def test_get_slot_members(self):
131 class C(object):
132 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000133 x = C()
134 x.a = 42
135 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000136 self.assertIn('a', members)
137 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000138
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000139 def test_isabstract(self):
140 from abc import ABCMeta, abstractmethod
141
142 class AbstractClassExample(metaclass=ABCMeta):
143
144 @abstractmethod
145 def foo(self):
146 pass
147
148 class ClassExample(AbstractClassExample):
149 def foo(self):
150 pass
151
152 a = ClassExample()
153
154 # Test general behaviour.
155 self.assertTrue(inspect.isabstract(AbstractClassExample))
156 self.assertFalse(inspect.isabstract(ClassExample))
157 self.assertFalse(inspect.isabstract(a))
158 self.assertFalse(inspect.isabstract(int))
159 self.assertFalse(inspect.isabstract(5))
160
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000161
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000162class TestInterpreterStack(IsTestBase):
163 def __init__(self, *args, **kwargs):
164 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000165
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000166 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000167
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000168 def test_abuse_done(self):
169 self.istest(inspect.istraceback, 'git.ex[2]')
170 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000171
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000172 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000173 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000174 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000175 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000176 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000177 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000178 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000179 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000180 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000181 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000182
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000183 def test_trace(self):
184 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000185 self.assertEqual(revise(*git.tr[0][1:]),
186 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
187 self.assertEqual(revise(*git.tr[1][1:]),
188 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
189 self.assertEqual(revise(*git.tr[2][1:]),
190 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000191
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000192 def test_frame(self):
193 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
194 self.assertEqual(args, ['x', 'y'])
195 self.assertEqual(varargs, None)
196 self.assertEqual(varkw, None)
197 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
198 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
199 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000200
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000201 def test_previous_frame(self):
202 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000203 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000204 self.assertEqual(varargs, 'g')
205 self.assertEqual(varkw, 'h')
206 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000207 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000208
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000209class GetSourceBase(unittest.TestCase):
210 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000211 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000212
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000213 def __init__(self, *args, **kwargs):
214 unittest.TestCase.__init__(self, *args, **kwargs)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000215
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000216 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000217 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000218
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000219 def sourcerange(self, top, bottom):
220 lines = self.source.split("\n")
221 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000222
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000223 def assertSourceEqual(self, obj, top, bottom):
224 self.assertEqual(inspect.getsource(obj),
225 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000226
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000227class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000228 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000229
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000230 def test_getclasses(self):
231 classes = inspect.getmembers(mod, inspect.isclass)
232 self.assertEqual(classes,
233 [('FesteringGob', mod.FesteringGob),
234 ('MalodorousPervert', mod.MalodorousPervert),
235 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300236 ('StupidGit', mod.StupidGit),
237 ('Tit', mod.MalodorousPervert),
238 ])
239 tree = inspect.getclasstree([cls[1] for cls in classes])
240 self.assertEqual(tree,
241 [(object, ()),
242 [(mod.ParrotDroppings, (object,)),
243 [(mod.FesteringGob, (mod.MalodorousPervert,
244 mod.ParrotDroppings))
245 ],
246 (mod.StupidGit, (object,)),
247 [(mod.MalodorousPervert, (mod.StupidGit,)),
248 [(mod.FesteringGob, (mod.MalodorousPervert,
249 mod.ParrotDroppings))
250 ]
251 ]
252 ]
253 ])
254 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000255 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000256 [(object, ()),
257 [(mod.ParrotDroppings, (object,)),
258 (mod.StupidGit, (object,)),
259 [(mod.MalodorousPervert, (mod.StupidGit,)),
260 [(mod.FesteringGob, (mod.MalodorousPervert,
261 mod.ParrotDroppings))
262 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000263 ]
264 ]
265 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000266
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000267 def test_getfunctions(self):
268 functions = inspect.getmembers(mod, inspect.isfunction)
269 self.assertEqual(functions, [('eggs', mod.eggs),
270 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000271
R. David Murray378c0cf2010-02-24 01:46:21 +0000272 @unittest.skipIf(sys.flags.optimize >= 2,
273 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000274 def test_getdoc(self):
275 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
276 self.assertEqual(inspect.getdoc(mod.StupidGit),
277 'A longer,\n\nindented\n\ndocstring.')
278 self.assertEqual(inspect.getdoc(git.abuse),
279 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000280
Georg Brandl0c77a822008-06-10 16:37:50 +0000281 def test_cleandoc(self):
282 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
283 'An\nindented\ndocstring.')
284
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000285 def test_getcomments(self):
286 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
287 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000288
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000289 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000290 # Check actual module
291 self.assertEqual(inspect.getmodule(mod), mod)
292 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000293 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000294 # Check a method (no __module__ attribute, falls back to filename)
295 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
296 # Do it again (check the caching isn't broken)
297 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
298 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000299 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000300 # Check filename override
301 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000302
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000303 def test_getsource(self):
304 self.assertSourceEqual(git.abuse, 29, 39)
305 self.assertSourceEqual(mod.StupidGit, 21, 46)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000306
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000307 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000308 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
309 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000310 fn = "_non_existing_filename_used_for_sourcefile_test.py"
311 co = compile("None", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000312 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000313 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200314 try:
315 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
316 finally:
317 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000318
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000319 def test_getfile(self):
320 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000321
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500322 def test_getfile_class_without_module(self):
323 class CM(type):
324 @property
325 def __module__(cls):
326 raise AttributeError
327 class C(metaclass=CM):
328 pass
329 with self.assertRaises(TypeError):
330 inspect.getfile(C)
331
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000332 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000333 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000334 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000335 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000336 m.__file__ = "<string>" # hopefully not a real filename...
337 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000338 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000339 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000340 del sys.modules[name]
341 inspect.getmodule(compile('a=10','','single'))
342
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500343 def test_proceed_with_fake_filename(self):
344 '''doctest monkeypatches linecache to enable inspection'''
345 fn, source = '<test>', 'def x(): pass\n'
346 getlines = linecache.getlines
347 def monkey(filename, module_globals=None):
348 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300349 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500350 else:
351 return getlines(filename, module_globals)
352 linecache.getlines = monkey
353 try:
354 ns = {}
355 exec(compile(source, fn, 'single'), ns)
356 inspect.getsource(ns["x"])
357 finally:
358 linecache.getlines = getlines
359
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000360class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000361 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000362
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000363 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000364 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000365
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000366 def test_replacing_decorator(self):
367 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000368
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000369class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000370 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000371 def test_oneline_lambda(self):
372 # Test inspect.getsource with a one-line lambda function.
373 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000374
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000375 def test_threeline_lambda(self):
376 # Test inspect.getsource with a three-line lambda function,
377 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000378 self.assertSourceEqual(mod2.tll, 28, 30)
379
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000380 def test_twoline_indented_lambda(self):
381 # Test inspect.getsource with a two-line lambda function,
382 # where the second line _is_ indented.
383 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000384
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000385 def test_onelinefunc(self):
386 # Test inspect.getsource with a regular one-line function.
387 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000388
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000389 def test_manyargs(self):
390 # Test inspect.getsource with a regular function where
391 # the arguments are on two lines and _not_ indented and
392 # the body on the second line with the last arguments.
393 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000394
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000395 def test_twolinefunc(self):
396 # Test inspect.getsource with a regular function where
397 # the body is on two lines, following the argument list and
398 # continued on the next line by a \\.
399 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000400
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000401 def test_lambda_in_list(self):
402 # Test inspect.getsource with a one-line lambda function
403 # defined in a list, indented.
404 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000405
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000406 def test_anonymous(self):
407 # Test inspect.getsource with a lambda function defined
408 # as argument to another function.
409 self.assertSourceEqual(mod2.anonymous, 55, 55)
410
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000411class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000412 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000413
414 def test_with_comment(self):
415 self.assertSourceEqual(mod2.with_comment, 58, 59)
416
417 def test_multiline_sig(self):
418 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
419
Armin Rigodd5c0232005-09-25 11:45:45 +0000420 def test_nested_class(self):
421 self.assertSourceEqual(mod2.func69().func71, 71, 72)
422
423 def test_one_liner_followed_by_non_name(self):
424 self.assertSourceEqual(mod2.func77, 77, 77)
425
426 def test_one_liner_dedent_non_name(self):
427 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
428
429 def test_with_comment_instead_of_docstring(self):
430 self.assertSourceEqual(mod2.func88, 88, 90)
431
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000432 def test_method_in_dynamic_class(self):
433 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
434
R. David Murrayb5655772009-05-14 16:17:50 +0000435 @unittest.skipIf(
436 not hasattr(unicodedata, '__file__') or
437 unicodedata.__file__[-4:] in (".pyc", ".pyo"),
438 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000439 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200440 self.assertRaises(OSError, inspect.getsource, unicodedata)
441 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000442
R. David Murraya1b37402010-06-17 02:04:29 +0000443 def test_findsource_code_in_linecache(self):
444 lines = ["x=1"]
445 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200446 self.assertRaises(OSError, inspect.findsource, co)
447 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000448 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200449 try:
450 self.assertEqual(inspect.findsource(co), (lines,0))
451 self.assertEqual(inspect.getsource(co), lines[0])
452 finally:
453 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000454
Ezio Melotti1b145922013-03-30 05:17:24 +0200455 def test_findsource_without_filename(self):
456 for fname in ['', '<string>']:
457 co = compile('x=1', fname, "exec")
458 self.assertRaises(IOError, inspect.findsource, co)
459 self.assertRaises(IOError, inspect.getsource, co)
460
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000461class TestNoEOL(GetSourceBase):
462 def __init__(self, *args, **kwargs):
463 self.tempdir = TESTFN + '_dir'
464 os.mkdir(self.tempdir)
465 with open(os.path.join(self.tempdir,
466 'inspect_fodder3%spy' % os.extsep), 'w') as f:
467 f.write("class X:\n pass # No EOL")
468 with DirsOnSysPath(self.tempdir):
469 import inspect_fodder3 as mod3
470 self.fodderModule = mod3
471 GetSourceBase.__init__(self, *args, **kwargs)
472
473 def tearDown(self):
474 shutil.rmtree(self.tempdir)
475
476 def test_class(self):
477 self.assertSourceEqual(self.fodderModule.X, 1, 2)
478
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100479
480class _BrokenDataDescriptor(object):
481 """
482 A broken data descriptor. See bug #1785.
483 """
484 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700485 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100486
487 def __set__(*args):
488 raise RuntimeError
489
490 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700491 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100492
493
494class _BrokenMethodDescriptor(object):
495 """
496 A broken method descriptor. See bug #1785.
497 """
498 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700499 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100500
501 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700502 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100503
504
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000505# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000506def attrs_wo_objs(cls):
507 return [t[:3] for t in inspect.classify_class_attrs(cls)]
508
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100509
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000510class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000511 def test_newstyle_mro(self):
512 # The same w/ new-class MRO.
513 class A(object): pass
514 class B(A): pass
515 class C(A): pass
516 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000517
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000518 expected = (D, B, C, A, object)
519 got = inspect.getmro(D)
520 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000521
Christian Heimes3795b532007-11-08 13:48:53 +0000522 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
523 varkw_e=None, defaults_e=None, formatted=None):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000524 args, varargs, varkw, defaults = inspect.getargspec(routine)
525 self.assertEqual(args, args_e)
526 self.assertEqual(varargs, varargs_e)
527 self.assertEqual(varkw, varkw_e)
528 self.assertEqual(defaults, defaults_e)
529 if formatted is not None:
530 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
531 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000532
Christian Heimes3795b532007-11-08 13:48:53 +0000533 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
534 varkw_e=None, defaults_e=None,
535 kwonlyargs_e=[], kwonlydefaults_e=None,
536 ann_e={}, formatted=None):
537 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
538 inspect.getfullargspec(routine)
539 self.assertEqual(args, args_e)
540 self.assertEqual(varargs, varargs_e)
541 self.assertEqual(varkw, varkw_e)
542 self.assertEqual(defaults, defaults_e)
543 self.assertEqual(kwonlyargs, kwonlyargs_e)
544 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
545 self.assertEqual(ann, ann_e)
546 if formatted is not None:
547 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
548 kwonlyargs, kwonlydefaults, ann),
549 formatted)
550
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000551 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000552 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000553
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000554 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000555 ['a', 'b', 'c', 'd', 'e', 'f'],
556 'g', 'h', (3, 4, 5),
557 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000558
Christian Heimes3795b532007-11-08 13:48:53 +0000559 self.assertRaises(ValueError, self.assertArgSpecEquals,
560 mod2.keyworded, [])
561
562 self.assertRaises(ValueError, self.assertArgSpecEquals,
563 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000564 self.assertRaises(ValueError, self.assertArgSpecEquals,
565 mod2.keyword_only_arg, [])
566
Christian Heimes3795b532007-11-08 13:48:53 +0000567
568 def test_getfullargspec(self):
569 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
570 kwonlyargs_e=['arg2'],
571 kwonlydefaults_e={'arg2':1},
572 formatted='(*arg1, arg2=1)')
573
574 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000575 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000576 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000577 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
578 kwonlyargs_e=['arg'],
579 formatted='(*, arg)')
580
Yury Selivanovff385b82014-02-19 16:27:23 -0500581 def test_argspec_api_ignores_wrapped(self):
582 # Issue 20684: low level introspection API must ignore __wrapped__
583 @functools.wraps(mod.spam)
584 def ham(x, y):
585 pass
586 # Basic check
587 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
588 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
589 self.assertFullArgSpecEquals(functools.partial(ham),
590 ['x', 'y'], formatted='(x, y)')
591 # Other variants
592 def check_method(f):
593 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
594 formatted='(self, x, y)')
595 class C:
596 @functools.wraps(mod.spam)
597 def ham(self, x, y):
598 pass
599 pham = functools.partialmethod(ham)
600 @functools.wraps(mod.spam)
601 def __call__(self, x, y):
602 pass
603 check_method(C())
604 check_method(C.ham)
605 check_method(C().ham)
606 check_method(C.pham)
607 check_method(C().pham)
608
609 class C_new:
610 @functools.wraps(mod.spam)
611 def __new__(self, x, y):
612 pass
613 check_method(C_new)
614
615 class C_init:
616 @functools.wraps(mod.spam)
617 def __init__(self, x, y):
618 pass
619 check_method(C_init)
620
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500621 def test_getfullargspec_signature_attr(self):
622 def test():
623 pass
624 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
625 test.__signature__ = inspect.Signature(parameters=(spam_param,))
626
627 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
628
Yury Selivanov4cb93912014-01-29 11:54:12 -0500629 def test_getfullargspec_signature_annos(self):
630 def test(a:'spam') -> 'ham': pass
631 spec = inspect.getfullargspec(test)
632 self.assertEqual(test.__annotations__, spec.annotations)
633
634 def test(): pass
635 spec = inspect.getfullargspec(test)
636 self.assertEqual(test.__annotations__, spec.annotations)
637
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500638 @unittest.skipIf(MISSING_C_DOCSTRINGS,
639 "Signature information for builtins requires docstrings")
640 def test_getfullargspec_builtin_methods(self):
641 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
642 args_e=['self', 'obj'], formatted='(self, obj)')
643
644 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
645 args_e=['self', 'obj'], formatted='(self, obj)')
646
Yury Selivanovd224b6a2014-02-21 01:32:42 -0500647 self.assertFullArgSpecEquals(
648 os.stat,
649 args_e=['path'],
650 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
651 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
652 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
653
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200654 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500655 @unittest.skipIf(MISSING_C_DOCSTRINGS,
656 "Signature information for builtins requires docstrings")
657 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200658 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500659 builtin = _testcapi.docstring_with_signature_with_defaults
660 spec = inspect.getfullargspec(builtin)
661 self.assertEqual(spec.defaults[0], 'avocado')
662
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200663 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500664 @unittest.skipIf(MISSING_C_DOCSTRINGS,
665 "Signature information for builtins requires docstrings")
666 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200667 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500668 builtin = _testcapi.docstring_no_signature
669 with self.assertRaises(TypeError):
670 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000671
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000672 def test_getargspec_method(self):
673 class A(object):
674 def m(self):
675 pass
676 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000677
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000678 def test_classify_newstyle(self):
679 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000680
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000681 def s(): pass
682 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000683
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000684 def c(cls): pass
685 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000686
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000687 def getp(self): pass
688 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000689
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000690 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000691
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000692 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000693
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000694 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000695
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100696 dd = _BrokenDataDescriptor()
697 md = _BrokenMethodDescriptor()
698
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000699 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500700
701 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
702 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
703
Benjamin Peterson577473f2010-01-19 00:09:57 +0000704 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
705 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
706 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000707 self.assertIn(('m', 'method', A), attrs,
708 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000709 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
710 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100711 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
712 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000713
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000714 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000715
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000716 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000717
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000718 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000719 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
720 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
721 self.assertIn(('p', 'property', A), attrs, 'missing property')
722 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
723 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
724 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100725 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
726 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000727
728
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000729 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000730
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000731 def m(self): pass
732 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000733
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000734 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000735 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
736 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
737 self.assertIn(('p', 'property', A), attrs, 'missing property')
738 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
739 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
740 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100741 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
742 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000743
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000744 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000745
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000746 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000747
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000748 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000749 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
750 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
751 self.assertIn(('p', 'property', A), attrs, 'missing property')
752 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
753 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
754 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100755 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
756 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
757
758 def test_classify_builtin_types(self):
759 # Simple sanity check that all built-in types can have their
760 # attributes classified.
761 for name in dir(__builtins__):
762 builtin = getattr(__builtins__, name)
763 if isinstance(builtin, type):
764 inspect.classify_class_attrs(builtin)
765
Ethan Furman63c141c2013-10-18 00:27:39 -0700766 def test_classify_DynamicClassAttribute(self):
767 class Meta(type):
768 def __getattr__(self, name):
769 if name == 'ham':
770 return 'spam'
771 return super().__getattr__(name)
772 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700773 @types.DynamicClassAttribute
774 def ham(self):
775 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700776 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
777 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700778 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700779 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
780
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700781 def test_classify_metaclass_class_attribute(self):
782 class Meta(type):
783 fish = 'slap'
784 def __dir__(self):
785 return ['__class__', '__modules__', '__name__', 'fish']
786 class Class(metaclass=Meta):
787 pass
788 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
789 self.assertIn(should_find, inspect.classify_class_attrs(Class))
790
Ethan Furman63c141c2013-10-18 00:27:39 -0700791 def test_classify_VirtualAttribute(self):
792 class Meta(type):
793 def __dir__(cls):
794 return ['__class__', '__module__', '__name__', 'BOOM']
795 def __getattr__(self, name):
796 if name =='BOOM':
797 return 42
798 return super().__getattr(name)
799 class Class(metaclass=Meta):
800 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700801 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700802 self.assertIn(should_find, inspect.classify_class_attrs(Class))
803
804 def test_classify_VirtualAttribute_multi_classes(self):
805 class Meta1(type):
806 def __dir__(cls):
807 return ['__class__', '__module__', '__name__', 'one']
808 def __getattr__(self, name):
809 if name =='one':
810 return 1
811 return super().__getattr__(name)
812 class Meta2(type):
813 def __dir__(cls):
814 return ['__class__', '__module__', '__name__', 'two']
815 def __getattr__(self, name):
816 if name =='two':
817 return 2
818 return super().__getattr__(name)
819 class Meta3(Meta1, Meta2):
820 def __dir__(cls):
821 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
822 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
823 def __getattr__(self, name):
824 if name =='three':
825 return 3
826 return super().__getattr__(name)
827 class Class1(metaclass=Meta1):
828 pass
829 class Class2(Class1, metaclass=Meta3):
830 pass
831
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700832 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
833 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
834 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700835 cca = inspect.classify_class_attrs(Class2)
836 for sf in (should_find1, should_find2, should_find3):
837 self.assertIn(sf, cca)
838
839 def test_classify_class_attrs_with_buggy_dir(self):
840 class M(type):
841 def __dir__(cls):
842 return ['__class__', '__name__', 'missing']
843 class C(metaclass=M):
844 pass
845 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
846 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700847
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100848 def test_getmembers_descriptors(self):
849 class A(object):
850 dd = _BrokenDataDescriptor()
851 md = _BrokenMethodDescriptor()
852
853 def pred_wrapper(pred):
854 # A quick'n'dirty way to discard standard attributes of new-style
855 # classes.
856 class Empty(object):
857 pass
858 def wrapped(x):
859 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
860 return False
861 return pred(x)
862 return wrapped
863
864 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
865 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
866
867 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
868 [('md', A.__dict__['md'])])
869 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
870 [('dd', A.__dict__['dd'])])
871
872 class B(A):
873 pass
874
875 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
876 [('md', A.__dict__['md'])])
877 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
878 [('dd', A.__dict__['dd'])])
879
Antoine Pitrou0c603812012-01-18 17:40:18 +0100880 def test_getmembers_method(self):
881 class B:
882 def f(self):
883 pass
884
885 self.assertIn(('f', B.f), inspect.getmembers(B))
886 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
887 b = B()
888 self.assertIn(('f', b.f), inspect.getmembers(b))
889 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
890
Ethan Furmane03ea372013-09-25 07:14:41 -0700891 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -0700892 class M(type):
893 def __getattr__(cls, name):
894 if name == 'eggs':
895 return 'scrambled'
896 return super().__getattr__(name)
897 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -0700898 @types.DynamicClassAttribute
899 def eggs(self):
900 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -0700901 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
902 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
903
904 def test_getmembers_with_buggy_dir(self):
905 class M(type):
906 def __dir__(cls):
907 return ['__class__', '__name__', 'missing']
908 class C(metaclass=M):
909 pass
910 attrs = [a[0] for a in inspect.getmembers(C)]
911 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700912
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000913
Nick Coghlan2f92e542012-06-23 19:39:55 +1000914_global_ref = object()
915class TestGetClosureVars(unittest.TestCase):
916
917 def test_name_resolution(self):
918 # Basic test of the 4 different resolution mechanisms
919 def f(nonlocal_ref):
920 def g(local_ref):
921 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
922 return g
923 _arg = object()
924 nonlocal_vars = {"nonlocal_ref": _arg}
925 global_vars = {"_global_ref": _global_ref}
926 builtin_vars = {"print": print}
927 unbound_names = {"unbound_ref"}
928 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
929 builtin_vars, unbound_names)
930 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
931
932 def test_generator_closure(self):
933 def f(nonlocal_ref):
934 def g(local_ref):
935 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
936 yield
937 return g
938 _arg = object()
939 nonlocal_vars = {"nonlocal_ref": _arg}
940 global_vars = {"_global_ref": _global_ref}
941 builtin_vars = {"print": print}
942 unbound_names = {"unbound_ref"}
943 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
944 builtin_vars, unbound_names)
945 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
946
947 def test_method_closure(self):
948 class C:
949 def f(self, nonlocal_ref):
950 def g(local_ref):
951 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
952 return g
953 _arg = object()
954 nonlocal_vars = {"nonlocal_ref": _arg}
955 global_vars = {"_global_ref": _global_ref}
956 builtin_vars = {"print": print}
957 unbound_names = {"unbound_ref"}
958 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
959 builtin_vars, unbound_names)
960 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
961
962 def test_nonlocal_vars(self):
963 # More complex tests of nonlocal resolution
964 def _nonlocal_vars(f):
965 return inspect.getclosurevars(f).nonlocals
966
967 def make_adder(x):
968 def add(y):
969 return x + y
970 return add
971
972 def curry(func, arg1):
973 return lambda arg2: func(arg1, arg2)
974
975 def less_than(a, b):
976 return a < b
977
978 # The infamous Y combinator.
979 def Y(le):
980 def g(f):
981 return le(lambda x: f(f)(x))
982 Y.g_ref = g
983 return g(g)
984
985 def check_y_combinator(func):
986 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
987
988 inc = make_adder(1)
989 add_two = make_adder(2)
990 greater_than_five = curry(less_than, 5)
991
992 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
993 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
994 self.assertEqual(_nonlocal_vars(greater_than_five),
995 {'arg1': 5, 'func': less_than})
996 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
997 {'x': 3})
998 Y(check_y_combinator)
999
1000 def test_getclosurevars_empty(self):
1001 def foo(): pass
1002 _empty = inspect.ClosureVars({}, {}, {}, set())
1003 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1004 self.assertEqual(inspect.getclosurevars(foo), _empty)
1005
1006 def test_getclosurevars_error(self):
1007 class T: pass
1008 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1009 self.assertRaises(TypeError, inspect.getclosurevars, list)
1010 self.assertRaises(TypeError, inspect.getclosurevars, {})
1011
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001012 def _private_globals(self):
1013 code = """def f(): print(path)"""
1014 ns = {}
1015 exec(code, ns)
1016 return ns["f"], ns
1017
1018 def test_builtins_fallback(self):
1019 f, ns = self._private_globals()
1020 ns.pop("__builtins__", None)
1021 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1022 self.assertEqual(inspect.getclosurevars(f), expected)
1023
1024 def test_builtins_as_dict(self):
1025 f, ns = self._private_globals()
1026 ns["__builtins__"] = {"path":1}
1027 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1028 self.assertEqual(inspect.getclosurevars(f), expected)
1029
1030 def test_builtins_as_module(self):
1031 f, ns = self._private_globals()
1032 ns["__builtins__"] = os
1033 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1034 self.assertEqual(inspect.getclosurevars(f), expected)
1035
Nick Coghlan2f92e542012-06-23 19:39:55 +10001036
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001037class TestGetcallargsFunctions(unittest.TestCase):
1038
1039 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1040 locs = dict(locs or {}, func=func)
1041 r1 = eval('func(%s)' % call_params_string, None, locs)
1042 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1043 locs)
1044 self.assertEqual(r1, r2)
1045
1046 def assertEqualException(self, func, call_param_string, locs=None):
1047 locs = dict(locs or {}, func=func)
1048 try:
1049 eval('func(%s)' % call_param_string, None, locs)
1050 except Exception as e:
1051 ex1 = e
1052 else:
1053 self.fail('Exception not raised')
1054 try:
1055 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1056 locs)
1057 except Exception as e:
1058 ex2 = e
1059 else:
1060 self.fail('Exception not raised')
1061 self.assertIs(type(ex1), type(ex2))
1062 self.assertEqual(str(ex1), str(ex2))
1063 del ex1, ex2
1064
1065 def makeCallable(self, signature):
1066 """Create a function that returns its locals()"""
1067 code = "lambda %s: locals()"
1068 return eval(code % signature)
1069
1070 def test_plain(self):
1071 f = self.makeCallable('a, b=1')
1072 self.assertEqualCallArgs(f, '2')
1073 self.assertEqualCallArgs(f, '2, 3')
1074 self.assertEqualCallArgs(f, 'a=2')
1075 self.assertEqualCallArgs(f, 'b=3, a=2')
1076 self.assertEqualCallArgs(f, '2, b=3')
1077 # expand *iterable / **mapping
1078 self.assertEqualCallArgs(f, '*(2,)')
1079 self.assertEqualCallArgs(f, '*[2]')
1080 self.assertEqualCallArgs(f, '*(2, 3)')
1081 self.assertEqualCallArgs(f, '*[2, 3]')
1082 self.assertEqualCallArgs(f, '**{"a":2}')
1083 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1084 self.assertEqualCallArgs(f, '2, **{"b":3}')
1085 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1086 # expand UserList / UserDict
1087 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1088 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1089 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1090 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1091 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1092
1093 def test_varargs(self):
1094 f = self.makeCallable('a, b=1, *c')
1095 self.assertEqualCallArgs(f, '2')
1096 self.assertEqualCallArgs(f, '2, 3')
1097 self.assertEqualCallArgs(f, '2, 3, 4')
1098 self.assertEqualCallArgs(f, '*(2,3,4)')
1099 self.assertEqualCallArgs(f, '2, *[3,4]')
1100 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1101
1102 def test_varkw(self):
1103 f = self.makeCallable('a, b=1, **c')
1104 self.assertEqualCallArgs(f, 'a=2')
1105 self.assertEqualCallArgs(f, '2, b=3, c=4')
1106 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1107 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1108 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1109 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1110 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1111 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1112 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1113
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001114 def test_varkw_only(self):
1115 # issue11256:
1116 f = self.makeCallable('**c')
1117 self.assertEqualCallArgs(f, '')
1118 self.assertEqualCallArgs(f, 'a=1')
1119 self.assertEqualCallArgs(f, 'a=1, b=2')
1120 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1121 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1122 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1123
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001124 def test_keyword_only(self):
1125 f = self.makeCallable('a=3, *, c, d=2')
1126 self.assertEqualCallArgs(f, 'c=3')
1127 self.assertEqualCallArgs(f, 'c=3, a=3')
1128 self.assertEqualCallArgs(f, 'a=2, c=4')
1129 self.assertEqualCallArgs(f, '4, c=4')
1130 self.assertEqualException(f, '')
1131 self.assertEqualException(f, '3')
1132 self.assertEqualException(f, 'a=3')
1133 self.assertEqualException(f, 'd=4')
1134
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001135 f = self.makeCallable('*, c, d=2')
1136 self.assertEqualCallArgs(f, 'c=3')
1137 self.assertEqualCallArgs(f, 'c=3, d=4')
1138 self.assertEqualCallArgs(f, 'd=4, c=3')
1139
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001140 def test_multiple_features(self):
1141 f = self.makeCallable('a, b=2, *f, **g')
1142 self.assertEqualCallArgs(f, '2, 3, 7')
1143 self.assertEqualCallArgs(f, '2, 3, x=8')
1144 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1145 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1146 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1147 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1148 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1149 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1150 '(4,[5,6])]), **collections.UserDict('
1151 'y=9, z=10)')
1152
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001153 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1154 self.assertEqualCallArgs(f, '2, 3, x=8')
1155 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1156 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1157 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1158 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1159 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1160 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1161 '(4,[5,6])]), q=0, **collections.UserDict('
1162 'y=9, z=10)')
1163
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001164 def test_errors(self):
1165 f0 = self.makeCallable('')
1166 f1 = self.makeCallable('a, b')
1167 f2 = self.makeCallable('a, b=1')
1168 # f0 takes no arguments
1169 self.assertEqualException(f0, '1')
1170 self.assertEqualException(f0, 'x=1')
1171 self.assertEqualException(f0, '1,x=1')
1172 # f1 takes exactly 2 arguments
1173 self.assertEqualException(f1, '')
1174 self.assertEqualException(f1, '1')
1175 self.assertEqualException(f1, 'a=2')
1176 self.assertEqualException(f1, 'b=3')
1177 # f2 takes at least 1 argument
1178 self.assertEqualException(f2, '')
1179 self.assertEqualException(f2, 'b=3')
1180 for f in f1, f2:
1181 # f1/f2 takes exactly/at most 2 arguments
1182 self.assertEqualException(f, '2, 3, 4')
1183 self.assertEqualException(f, '1, 2, 3, a=1')
1184 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001185 # XXX: success of this one depends on dict order
1186 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001187 # f got an unexpected keyword argument
1188 self.assertEqualException(f, 'c=2')
1189 self.assertEqualException(f, '2, c=3')
1190 self.assertEqualException(f, '2, 3, c=4')
1191 self.assertEqualException(f, '2, c=4, b=3')
1192 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1193 # f got multiple values for keyword argument
1194 self.assertEqualException(f, '1, a=2')
1195 self.assertEqualException(f, '1, **{"a":2}')
1196 self.assertEqualException(f, '1, 2, b=3')
1197 # XXX: Python inconsistency
1198 # - for functions and bound methods: unexpected keyword 'c'
1199 # - for unbound methods: multiple values for keyword 'a'
1200 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001201 # issue11256:
1202 f3 = self.makeCallable('**c')
1203 self.assertEqualException(f3, '1, 2')
1204 self.assertEqualException(f3, '1, 2, a=1, b=2')
1205 f4 = self.makeCallable('*, a, b=0')
1206 self.assertEqualException(f3, '1, 2')
1207 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001208
1209class TestGetcallargsMethods(TestGetcallargsFunctions):
1210
1211 def setUp(self):
1212 class Foo(object):
1213 pass
1214 self.cls = Foo
1215 self.inst = Foo()
1216
1217 def makeCallable(self, signature):
1218 assert 'self' not in signature
1219 mk = super(TestGetcallargsMethods, self).makeCallable
1220 self.cls.method = mk('self, ' + signature)
1221 return self.inst.method
1222
1223class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1224
1225 def makeCallable(self, signature):
1226 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1227 return self.cls.method
1228
1229 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1230 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1231 *self._getAssertEqualParams(func, call_params_string, locs))
1232
1233 def assertEqualException(self, func, call_params_string, locs=None):
1234 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1235 *self._getAssertEqualParams(func, call_params_string, locs))
1236
1237 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1238 assert 'inst' not in call_params_string
1239 locs = dict(locs or {}, inst=self.inst)
1240 return (func, 'inst,' + call_params_string, locs)
1241
Michael Foord95fc51d2010-11-20 15:07:30 +00001242
1243class TestGetattrStatic(unittest.TestCase):
1244
1245 def test_basic(self):
1246 class Thing(object):
1247 x = object()
1248
1249 thing = Thing()
1250 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1251 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1252 with self.assertRaises(AttributeError):
1253 inspect.getattr_static(thing, 'y')
1254
1255 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1256
1257 def test_inherited(self):
1258 class Thing(object):
1259 x = object()
1260 class OtherThing(Thing):
1261 pass
1262
1263 something = OtherThing()
1264 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1265
1266 def test_instance_attr(self):
1267 class Thing(object):
1268 x = 2
1269 def __init__(self, x):
1270 self.x = x
1271 thing = Thing(3)
1272 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1273 del thing.x
1274 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1275
1276 def test_property(self):
1277 class Thing(object):
1278 @property
1279 def x(self):
1280 raise AttributeError("I'm pretending not to exist")
1281 thing = Thing()
1282 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1283
Ezio Melotti75cbd732011-04-28 00:59:29 +03001284 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001285 class descriptor(object):
1286 def __get__(*_):
1287 raise AttributeError("I'm pretending not to exist")
1288 desc = descriptor()
1289 class Thing(object):
1290 x = desc
1291 thing = Thing()
1292 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1293
1294 def test_classAttribute(self):
1295 class Thing(object):
1296 x = object()
1297
1298 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1299
Ethan Furmane03ea372013-09-25 07:14:41 -07001300 def test_classVirtualAttribute(self):
1301 class Thing(object):
1302 @types.DynamicClassAttribute
1303 def x(self):
1304 return self._x
1305 _x = object()
1306
1307 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1308
Michael Foord95fc51d2010-11-20 15:07:30 +00001309 def test_inherited_classattribute(self):
1310 class Thing(object):
1311 x = object()
1312 class OtherThing(Thing):
1313 pass
1314
1315 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1316
1317 def test_slots(self):
1318 class Thing(object):
1319 y = 'bar'
1320 __slots__ = ['x']
1321 def __init__(self):
1322 self.x = 'foo'
1323 thing = Thing()
1324 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1325 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1326
1327 del thing.x
1328 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1329
1330 def test_metaclass(self):
1331 class meta(type):
1332 attr = 'foo'
1333 class Thing(object, metaclass=meta):
1334 pass
1335 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1336
1337 class sub(meta):
1338 pass
1339 class OtherThing(object, metaclass=sub):
1340 x = 3
1341 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1342
1343 class OtherOtherThing(OtherThing):
1344 pass
1345 # this test is odd, but it was added as it exposed a bug
1346 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1347
1348 def test_no_dict_no_slots(self):
1349 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1350 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1351
1352 def test_no_dict_no_slots_instance_member(self):
1353 # returns descriptor
1354 with open(__file__) as handle:
1355 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1356
1357 def test_inherited_slots(self):
1358 # returns descriptor
1359 class Thing(object):
1360 __slots__ = ['x']
1361 def __init__(self):
1362 self.x = 'foo'
1363
1364 class OtherThing(Thing):
1365 pass
1366 # it would be nice if this worked...
1367 # we get the descriptor instead of the instance attribute
1368 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1369
1370 def test_descriptor(self):
1371 class descriptor(object):
1372 def __get__(self, instance, owner):
1373 return 3
1374 class Foo(object):
1375 d = descriptor()
1376
1377 foo = Foo()
1378
1379 # for a non data descriptor we return the instance attribute
1380 foo.__dict__['d'] = 1
1381 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1382
1383 # if the descriptor is a data-desciptor we should return the
1384 # descriptor
1385 descriptor.__set__ = lambda s, i, v: None
1386 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1387
1388
1389 def test_metaclass_with_descriptor(self):
1390 class descriptor(object):
1391 def __get__(self, instance, owner):
1392 return 3
1393 class meta(type):
1394 d = descriptor()
1395 class Thing(object, metaclass=meta):
1396 pass
1397 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1398
1399
Michael Foordcc7ebb82010-11-20 16:20:16 +00001400 def test_class_as_property(self):
1401 class Base(object):
1402 foo = 3
1403
1404 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001405 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001406 @property
1407 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001408 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001409 return object
1410
Michael Foord35184ed2010-11-20 16:58:30 +00001411 instance = Something()
1412 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1413 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001414 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1415
Michael Foorde5162652010-11-20 16:40:44 +00001416 def test_mro_as_property(self):
1417 class Meta(type):
1418 @property
1419 def __mro__(self):
1420 return (object,)
1421
1422 class Base(object):
1423 foo = 3
1424
1425 class Something(Base, metaclass=Meta):
1426 pass
1427
1428 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1429 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1430
Michael Foorddcebe0f2011-03-15 19:20:44 -04001431 def test_dict_as_property(self):
1432 test = self
1433 test.called = False
1434
1435 class Foo(dict):
1436 a = 3
1437 @property
1438 def __dict__(self):
1439 test.called = True
1440 return {}
1441
1442 foo = Foo()
1443 foo.a = 4
1444 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1445 self.assertFalse(test.called)
1446
1447 def test_custom_object_dict(self):
1448 test = self
1449 test.called = False
1450
1451 class Custom(dict):
1452 def get(self, key, default=None):
1453 test.called = True
1454 super().get(key, default)
1455
1456 class Foo(object):
1457 a = 3
1458 foo = Foo()
1459 foo.__dict__ = Custom()
1460 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1461 self.assertFalse(test.called)
1462
1463 def test_metaclass_dict_as_property(self):
1464 class Meta(type):
1465 @property
1466 def __dict__(self):
1467 self.executed = True
1468
1469 class Thing(metaclass=Meta):
1470 executed = False
1471
1472 def __init__(self):
1473 self.spam = 42
1474
1475 instance = Thing()
1476 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1477 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001478
Michael Foorda51623b2011-12-18 22:01:40 +00001479 def test_module(self):
1480 sentinel = object()
1481 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1482 sentinel)
1483
Michael Foord3ba95f82011-12-22 01:13:37 +00001484 def test_metaclass_with_metaclass_with_dict_as_property(self):
1485 class MetaMeta(type):
1486 @property
1487 def __dict__(self):
1488 self.executed = True
1489 return dict(spam=42)
1490
1491 class Meta(type, metaclass=MetaMeta):
1492 executed = False
1493
1494 class Thing(metaclass=Meta):
1495 pass
1496
1497 with self.assertRaises(AttributeError):
1498 inspect.getattr_static(Thing, "spam")
1499 self.assertFalse(Thing.executed)
1500
Nick Coghlane0f04652010-11-21 03:44:04 +00001501class TestGetGeneratorState(unittest.TestCase):
1502
1503 def setUp(self):
1504 def number_generator():
1505 for number in range(5):
1506 yield number
1507 self.generator = number_generator()
1508
1509 def _generatorstate(self):
1510 return inspect.getgeneratorstate(self.generator)
1511
1512 def test_created(self):
1513 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1514
1515 def test_suspended(self):
1516 next(self.generator)
1517 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1518
1519 def test_closed_after_exhaustion(self):
1520 for i in self.generator:
1521 pass
1522 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1523
1524 def test_closed_after_immediate_exception(self):
1525 with self.assertRaises(RuntimeError):
1526 self.generator.throw(RuntimeError)
1527 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1528
1529 def test_running(self):
1530 # As mentioned on issue #10220, checking for the RUNNING state only
1531 # makes sense inside the generator itself.
1532 # The following generator checks for this by using the closure's
1533 # reference to self and the generator state checking helper method
1534 def running_check_generator():
1535 for number in range(5):
1536 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1537 yield number
1538 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1539 self.generator = running_check_generator()
1540 # Running up to the first yield
1541 next(self.generator)
1542 # Running after the first yield
1543 next(self.generator)
1544
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001545 def test_easy_debugging(self):
1546 # repr() and str() of a generator state should contain the state name
1547 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1548 for name in names:
1549 state = getattr(inspect, name)
1550 self.assertIn(name, repr(state))
1551 self.assertIn(name, str(state))
1552
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001553 def test_getgeneratorlocals(self):
1554 def each(lst, a=None):
1555 b=(1, 2, 3)
1556 for v in lst:
1557 if v == 3:
1558 c = 12
1559 yield v
1560
1561 numbers = each([1, 2, 3])
1562 self.assertEqual(inspect.getgeneratorlocals(numbers),
1563 {'a': None, 'lst': [1, 2, 3]})
1564 next(numbers)
1565 self.assertEqual(inspect.getgeneratorlocals(numbers),
1566 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1567 'b': (1, 2, 3)})
1568 next(numbers)
1569 self.assertEqual(inspect.getgeneratorlocals(numbers),
1570 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1571 'b': (1, 2, 3)})
1572 next(numbers)
1573 self.assertEqual(inspect.getgeneratorlocals(numbers),
1574 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1575 'b': (1, 2, 3), 'c': 12})
1576 try:
1577 next(numbers)
1578 except StopIteration:
1579 pass
1580 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1581
1582 def test_getgeneratorlocals_empty(self):
1583 def yield_one():
1584 yield 1
1585 one = yield_one()
1586 self.assertEqual(inspect.getgeneratorlocals(one), {})
1587 try:
1588 next(one)
1589 except StopIteration:
1590 pass
1591 self.assertEqual(inspect.getgeneratorlocals(one), {})
1592
1593 def test_getgeneratorlocals_error(self):
1594 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1595 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1596 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1597 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1598
Nick Coghlane0f04652010-11-21 03:44:04 +00001599
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001600class TestSignatureObject(unittest.TestCase):
1601 @staticmethod
1602 def signature(func):
1603 sig = inspect.signature(func)
1604 return (tuple((param.name,
1605 (... if param.default is param.empty else param.default),
1606 (... if param.annotation is param.empty
1607 else param.annotation),
1608 str(param.kind).lower())
1609 for param in sig.parameters.values()),
1610 (... if sig.return_annotation is sig.empty
1611 else sig.return_annotation))
1612
1613 def test_signature_object(self):
1614 S = inspect.Signature
1615 P = inspect.Parameter
1616
1617 self.assertEqual(str(S()), '()')
1618
Yury Selivanov07a9e452014-01-29 10:58:16 -05001619 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001620 pass
1621 sig = inspect.signature(test)
1622 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001623 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001624 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001625 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001626 args = sig.parameters['args']
1627 ko = sig.parameters['ko']
1628 kwargs = sig.parameters['kwargs']
1629
1630 S((po, pk, args, ko, kwargs))
1631
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001632 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001633 S((pk, po, args, ko, kwargs))
1634
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001635 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001636 S((po, args, pk, ko, kwargs))
1637
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001638 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001639 S((args, po, pk, ko, kwargs))
1640
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001641 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001642 S((po, pk, args, kwargs, ko))
1643
1644 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001645 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001646 S((po, pk, args, kwargs2, ko))
1647
Yury Selivanov07a9e452014-01-29 10:58:16 -05001648 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1649 S((pod, po))
1650
1651 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1652 S((po, pkd, pk))
1653
1654 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1655 S((pkd, pk))
1656
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001657 def test_signature_immutability(self):
1658 def test(a):
1659 pass
1660 sig = inspect.signature(test)
1661
1662 with self.assertRaises(AttributeError):
1663 sig.foo = 'bar'
1664
1665 with self.assertRaises(TypeError):
1666 sig.parameters['a'] = None
1667
1668 def test_signature_on_noarg(self):
1669 def test():
1670 pass
1671 self.assertEqual(self.signature(test), ((), ...))
1672
1673 def test_signature_on_wargs(self):
1674 def test(a, b:'foo') -> 123:
1675 pass
1676 self.assertEqual(self.signature(test),
1677 ((('a', ..., ..., "positional_or_keyword"),
1678 ('b', ..., 'foo', "positional_or_keyword")),
1679 123))
1680
1681 def test_signature_on_wkwonly(self):
1682 def test(*, a:float, b:str) -> int:
1683 pass
1684 self.assertEqual(self.signature(test),
1685 ((('a', ..., float, "keyword_only"),
1686 ('b', ..., str, "keyword_only")),
1687 int))
1688
1689 def test_signature_on_complex_args(self):
1690 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1691 pass
1692 self.assertEqual(self.signature(test),
1693 ((('a', ..., ..., "positional_or_keyword"),
1694 ('b', 10, 'foo', "positional_or_keyword"),
1695 ('args', ..., 'bar', "var_positional"),
1696 ('spam', ..., 'baz', "keyword_only"),
1697 ('ham', 123, ..., "keyword_only"),
1698 ('kwargs', ..., int, "var_keyword")),
1699 ...))
1700
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001701 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001702 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1703 "Signature information for builtins requires docstrings")
1704 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001705 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001706
Larry Hastings5c661892014-01-24 06:17:25 -08001707 def test_unbound_method(o):
1708 """Use this to test unbound methods (things that should have a self)"""
1709 signature = inspect.signature(o)
1710 self.assertTrue(isinstance(signature, inspect.Signature))
1711 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1712 return signature
1713
1714 def test_callable(o):
1715 """Use this to test bound methods or normal callables (things that don't expect self)"""
1716 signature = inspect.signature(o)
1717 self.assertTrue(isinstance(signature, inspect.Signature))
1718 if signature.parameters:
1719 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1720 return signature
1721
1722 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001723 def p(name): return signature.parameters[name].default
1724 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001725 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001726 self.assertEqual(p('d'), 3.14)
1727 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001728 self.assertEqual(p('n'), None)
1729 self.assertEqual(p('t'), True)
1730 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001731 self.assertEqual(p('local'), 3)
1732 self.assertEqual(p('sys'), sys.maxsize)
1733 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001734
Larry Hastings5c661892014-01-24 06:17:25 -08001735 test_callable(object)
1736
1737 # normal method
1738 # (PyMethodDescr_Type, "method_descriptor")
1739 test_unbound_method(_pickle.Pickler.dump)
1740 d = _pickle.Pickler(io.StringIO())
1741 test_callable(d.dump)
1742
1743 # static method
1744 test_callable(str.maketrans)
1745 test_callable('abc'.maketrans)
1746
1747 # class method
1748 test_callable(dict.fromkeys)
1749 test_callable({}.fromkeys)
1750
1751 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1752 test_unbound_method(type.__call__)
1753 test_unbound_method(int.__add__)
1754 test_callable((3).__add__)
1755
1756 # _PyMethodWrapper_Type
1757 # support for 'method-wrapper'
1758 test_callable(min.__call__)
1759
Larry Hastings2623c8c2014-02-08 22:15:29 -08001760 # This doesn't work now.
1761 # (We don't have a valid signature for "type" in 3.4)
1762 with self.assertRaisesRegex(ValueError, "no signature found"):
1763 class ThisWorksNow:
1764 __call__ = type
1765 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08001766
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001767 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05001768 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1769 "Signature information for builtins requires docstrings")
1770 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001771 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05001772 func = _testcapi.docstring_with_signature_with_defaults
1773
1774 def decorator(func):
1775 @functools.wraps(func)
1776 def wrapper(*args, **kwargs) -> int:
1777 return func(*args, **kwargs)
1778 return wrapper
1779
1780 decorated_func = decorator(func)
1781
1782 self.assertEqual(inspect.signature(func),
1783 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08001784
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001785 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08001786 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001787 import _testcapi
Larry Hastings5c661892014-01-24 06:17:25 -08001788 with self.assertRaisesRegex(ValueError, 'no signature found for builtin'):
1789 inspect.signature(_testcapi.docstring_no_signature)
1790
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001791 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001792 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001793 inspect.signature(42)
1794
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001795 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001796 inspect.Signature.from_function(42)
1797
Yury Selivanovb77511d2014-01-29 10:46:14 -05001798 def test_signature_from_builtin_errors(self):
1799 with self.assertRaisesRegex(TypeError, 'is not a Python builtin'):
1800 inspect.Signature.from_builtin(42)
1801
Yury Selivanov63da7c72014-01-31 14:48:37 -05001802 def test_signature_from_functionlike_object(self):
1803 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1804 pass
1805
1806 class funclike:
1807 # Has to be callable, and have correct
1808 # __code__, __annotations__, __defaults__, __name__,
1809 # and __kwdefaults__ attributes
1810
1811 def __init__(self, func):
1812 self.__name__ = func.__name__
1813 self.__code__ = func.__code__
1814 self.__annotations__ = func.__annotations__
1815 self.__defaults__ = func.__defaults__
1816 self.__kwdefaults__ = func.__kwdefaults__
1817 self.func = func
1818
1819 def __call__(self, *args, **kwargs):
1820 return self.func(*args, **kwargs)
1821
1822 sig_func = inspect.Signature.from_function(func)
1823
1824 sig_funclike = inspect.Signature.from_function(funclike(func))
1825 self.assertEqual(sig_funclike, sig_func)
1826
1827 sig_funclike = inspect.signature(funclike(func))
1828 self.assertEqual(sig_funclike, sig_func)
1829
1830 # If object is not a duck type of function, then
1831 # signature will try to get a signature for its '__call__'
1832 # method
1833 fl = funclike(func)
1834 del fl.__defaults__
1835 self.assertEqual(self.signature(fl),
1836 ((('args', ..., ..., "var_positional"),
1837 ('kwargs', ..., ..., "var_keyword")),
1838 ...))
1839
Yury Selivanov8dfb4572014-02-21 18:30:53 -05001840 # Test with cython-like builtins:
1841 _orig_isdesc = inspect.ismethoddescriptor
1842 def _isdesc(obj):
1843 if hasattr(obj, '_builtinmock'):
1844 return True
1845 return _orig_isdesc(obj)
1846
1847 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
1848 builtin_func = funclike(func)
1849 # Make sure that our mock setup is working
1850 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
1851 builtin_func._builtinmock = True
1852 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
1853 self.assertEqual(inspect.signature(builtin_func), sig_func)
1854
Yury Selivanov63da7c72014-01-31 14:48:37 -05001855 def test_signature_functionlike_class(self):
1856 # We only want to duck type function-like objects,
1857 # not classes.
1858
1859 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1860 pass
1861
1862 class funclike:
1863 def __init__(self, marker):
1864 pass
1865
1866 __name__ = func.__name__
1867 __code__ = func.__code__
1868 __annotations__ = func.__annotations__
1869 __defaults__ = func.__defaults__
1870 __kwdefaults__ = func.__kwdefaults__
1871
1872 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1873 inspect.Signature.from_function(funclike)
1874
1875 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
1876
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001877 def test_signature_on_method(self):
1878 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05001879 def __init__(*args):
1880 pass
1881 def m1(self, arg1, arg2=1) -> int:
1882 pass
1883 def m2(*args):
1884 pass
1885 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001886 pass
1887
Yury Selivanov62560fb2014-01-28 12:26:24 -05001888 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001889 ((('arg1', ..., ..., "positional_or_keyword"),
1890 ('arg2', 1, ..., "positional_or_keyword")),
1891 int))
1892
Yury Selivanov62560fb2014-01-28 12:26:24 -05001893 self.assertEqual(self.signature(Test().m2),
1894 ((('args', ..., ..., "var_positional"),),
1895 ...))
1896
1897 self.assertEqual(self.signature(Test),
1898 ((('args', ..., ..., "var_positional"),),
1899 ...))
1900
1901 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
1902 self.signature(Test())
1903
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001904 def test_signature_on_classmethod(self):
1905 class Test:
1906 @classmethod
1907 def foo(cls, arg1, *, arg2=1):
1908 pass
1909
1910 meth = Test().foo
1911 self.assertEqual(self.signature(meth),
1912 ((('arg1', ..., ..., "positional_or_keyword"),
1913 ('arg2', 1, ..., "keyword_only")),
1914 ...))
1915
1916 meth = Test.foo
1917 self.assertEqual(self.signature(meth),
1918 ((('arg1', ..., ..., "positional_or_keyword"),
1919 ('arg2', 1, ..., "keyword_only")),
1920 ...))
1921
1922 def test_signature_on_staticmethod(self):
1923 class Test:
1924 @staticmethod
1925 def foo(cls, *, arg):
1926 pass
1927
1928 meth = Test().foo
1929 self.assertEqual(self.signature(meth),
1930 ((('cls', ..., ..., "positional_or_keyword"),
1931 ('arg', ..., ..., "keyword_only")),
1932 ...))
1933
1934 meth = Test.foo
1935 self.assertEqual(self.signature(meth),
1936 ((('cls', ..., ..., "positional_or_keyword"),
1937 ('arg', ..., ..., "keyword_only")),
1938 ...))
1939
1940 def test_signature_on_partial(self):
1941 from functools import partial
1942
1943 def test():
1944 pass
1945
1946 self.assertEqual(self.signature(partial(test)), ((), ...))
1947
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001948 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001949 inspect.signature(partial(test, 1))
1950
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001951 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001952 inspect.signature(partial(test, a=1))
1953
1954 def test(a, b, *, c, d):
1955 pass
1956
1957 self.assertEqual(self.signature(partial(test)),
1958 ((('a', ..., ..., "positional_or_keyword"),
1959 ('b', ..., ..., "positional_or_keyword"),
1960 ('c', ..., ..., "keyword_only"),
1961 ('d', ..., ..., "keyword_only")),
1962 ...))
1963
1964 self.assertEqual(self.signature(partial(test, 1)),
1965 ((('b', ..., ..., "positional_or_keyword"),
1966 ('c', ..., ..., "keyword_only"),
1967 ('d', ..., ..., "keyword_only")),
1968 ...))
1969
1970 self.assertEqual(self.signature(partial(test, 1, c=2)),
1971 ((('b', ..., ..., "positional_or_keyword"),
1972 ('c', 2, ..., "keyword_only"),
1973 ('d', ..., ..., "keyword_only")),
1974 ...))
1975
1976 self.assertEqual(self.signature(partial(test, b=1, c=2)),
1977 ((('a', ..., ..., "positional_or_keyword"),
1978 ('b', 1, ..., "positional_or_keyword"),
1979 ('c', 2, ..., "keyword_only"),
1980 ('d', ..., ..., "keyword_only")),
1981 ...))
1982
1983 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
1984 ((('b', 1, ..., "positional_or_keyword"),
1985 ('c', 2, ..., "keyword_only"),
1986 ('d', ..., ..., "keyword_only"),),
1987 ...))
1988
1989 def test(a, *args, b, **kwargs):
1990 pass
1991
1992 self.assertEqual(self.signature(partial(test, 1)),
1993 ((('args', ..., ..., "var_positional"),
1994 ('b', ..., ..., "keyword_only"),
1995 ('kwargs', ..., ..., "var_keyword")),
1996 ...))
1997
1998 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
1999 ((('args', ..., ..., "var_positional"),
2000 ('b', ..., ..., "keyword_only"),
2001 ('kwargs', ..., ..., "var_keyword")),
2002 ...))
2003
2004
2005 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2006 ((('args', ..., ..., "var_positional"),
2007 ('b', ..., ..., "keyword_only"),
2008 ('kwargs', ..., ..., "var_keyword")),
2009 ...))
2010
2011 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2012 ((('args', ..., ..., "var_positional"),
2013 ('b', 0, ..., "keyword_only"),
2014 ('kwargs', ..., ..., "var_keyword")),
2015 ...))
2016
2017 self.assertEqual(self.signature(partial(test, b=0)),
2018 ((('a', ..., ..., "positional_or_keyword"),
2019 ('args', ..., ..., "var_positional"),
2020 ('b', 0, ..., "keyword_only"),
2021 ('kwargs', ..., ..., "var_keyword")),
2022 ...))
2023
2024 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2025 ((('a', ..., ..., "positional_or_keyword"),
2026 ('args', ..., ..., "var_positional"),
2027 ('b', 0, ..., "keyword_only"),
2028 ('kwargs', ..., ..., "var_keyword")),
2029 ...))
2030
2031 def test(a, b, c:int) -> 42:
2032 pass
2033
2034 sig = test.__signature__ = inspect.signature(test)
2035
2036 self.assertEqual(self.signature(partial(partial(test, 1))),
2037 ((('b', ..., ..., "positional_or_keyword"),
2038 ('c', ..., int, "positional_or_keyword")),
2039 42))
2040
2041 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2042 ((('c', ..., int, "positional_or_keyword"),),
2043 42))
2044
2045 psig = inspect.signature(partial(partial(test, 1), 2))
2046
2047 def foo(a):
2048 return a
2049 _foo = partial(partial(foo, a=10), a=20)
2050 self.assertEqual(self.signature(_foo),
2051 ((('a', 20, ..., "positional_or_keyword"),),
2052 ...))
2053 # check that we don't have any side-effects in signature(),
2054 # and the partial object is still functioning
2055 self.assertEqual(_foo(), 20)
2056
2057 def foo(a, b, c):
2058 return a, b, c
2059 _foo = partial(partial(foo, 1, b=20), b=30)
2060 self.assertEqual(self.signature(_foo),
2061 ((('b', 30, ..., "positional_or_keyword"),
2062 ('c', ..., ..., "positional_or_keyword")),
2063 ...))
2064 self.assertEqual(_foo(c=10), (1, 30, 10))
2065 _foo = partial(_foo, 2) # now 'b' has two values -
2066 # positional and keyword
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002067 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002068 inspect.signature(_foo)
2069
2070 def foo(a, b, c, *, d):
2071 return a, b, c, d
2072 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2073 self.assertEqual(self.signature(_foo),
2074 ((('a', ..., ..., "positional_or_keyword"),
2075 ('b', 10, ..., "positional_or_keyword"),
2076 ('c', 20, ..., "positional_or_keyword"),
2077 ('d', 30, ..., "keyword_only")),
2078 ...))
2079 ba = inspect.signature(_foo).bind(a=200, b=11)
2080 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2081
2082 def foo(a=1, b=2, c=3):
2083 return a, b, c
2084 _foo = partial(foo, a=10, c=13)
2085 ba = inspect.signature(_foo).bind(11)
2086 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
2087 ba = inspect.signature(_foo).bind(11, 12)
2088 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
2089 ba = inspect.signature(_foo).bind(11, b=12)
2090 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
2091 ba = inspect.signature(_foo).bind(b=12)
2092 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
2093 _foo = partial(_foo, b=10)
2094 ba = inspect.signature(_foo).bind(12, 14)
2095 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
2096
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002097 def test_signature_on_partialmethod(self):
2098 from functools import partialmethod
2099
2100 class Spam:
2101 def test():
2102 pass
2103 ham = partialmethod(test)
2104
2105 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2106 inspect.signature(Spam.ham)
2107
2108 class Spam:
2109 def test(it, a, *, c) -> 'spam':
2110 pass
2111 ham = partialmethod(test, c=1)
2112
2113 self.assertEqual(self.signature(Spam.ham),
2114 ((('it', ..., ..., 'positional_or_keyword'),
2115 ('a', ..., ..., 'positional_or_keyword'),
2116 ('c', 1, ..., 'keyword_only')),
2117 'spam'))
2118
2119 self.assertEqual(self.signature(Spam().ham),
2120 ((('a', ..., ..., 'positional_or_keyword'),
2121 ('c', 1, ..., 'keyword_only')),
2122 'spam'))
2123
Yury Selivanov0486f812014-01-29 12:18:59 -05002124 def test_signature_on_fake_partialmethod(self):
2125 def foo(a): pass
2126 foo._partialmethod = 'spam'
2127 self.assertEqual(str(inspect.signature(foo)), '(a)')
2128
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002129 def test_signature_on_decorated(self):
2130 import functools
2131
2132 def decorator(func):
2133 @functools.wraps(func)
2134 def wrapper(*args, **kwargs) -> int:
2135 return func(*args, **kwargs)
2136 return wrapper
2137
2138 class Foo:
2139 @decorator
2140 def bar(self, a, b):
2141 pass
2142
2143 self.assertEqual(self.signature(Foo.bar),
2144 ((('self', ..., ..., "positional_or_keyword"),
2145 ('a', ..., ..., "positional_or_keyword"),
2146 ('b', ..., ..., "positional_or_keyword")),
2147 ...))
2148
2149 self.assertEqual(self.signature(Foo().bar),
2150 ((('a', ..., ..., "positional_or_keyword"),
2151 ('b', ..., ..., "positional_or_keyword")),
2152 ...))
2153
2154 # Test that we handle method wrappers correctly
2155 def decorator(func):
2156 @functools.wraps(func)
2157 def wrapper(*args, **kwargs) -> int:
2158 return func(42, *args, **kwargs)
2159 sig = inspect.signature(func)
2160 new_params = tuple(sig.parameters.values())[1:]
2161 wrapper.__signature__ = sig.replace(parameters=new_params)
2162 return wrapper
2163
2164 class Foo:
2165 @decorator
2166 def __call__(self, a, b):
2167 pass
2168
2169 self.assertEqual(self.signature(Foo.__call__),
2170 ((('a', ..., ..., "positional_or_keyword"),
2171 ('b', ..., ..., "positional_or_keyword")),
2172 ...))
2173
2174 self.assertEqual(self.signature(Foo().__call__),
2175 ((('b', ..., ..., "positional_or_keyword"),),
2176 ...))
2177
Nick Coghlane8c45d62013-07-28 20:00:01 +10002178 # Test we handle __signature__ partway down the wrapper stack
2179 def wrapped_foo_call():
2180 pass
2181 wrapped_foo_call.__wrapped__ = Foo.__call__
2182
2183 self.assertEqual(self.signature(wrapped_foo_call),
2184 ((('a', ..., ..., "positional_or_keyword"),
2185 ('b', ..., ..., "positional_or_keyword")),
2186 ...))
2187
2188
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002189 def test_signature_on_class(self):
2190 class C:
2191 def __init__(self, a):
2192 pass
2193
2194 self.assertEqual(self.signature(C),
2195 ((('a', ..., ..., "positional_or_keyword"),),
2196 ...))
2197
2198 class CM(type):
2199 def __call__(cls, a):
2200 pass
2201 class C(metaclass=CM):
2202 def __init__(self, b):
2203 pass
2204
2205 self.assertEqual(self.signature(C),
2206 ((('a', ..., ..., "positional_or_keyword"),),
2207 ...))
2208
2209 class CM(type):
2210 def __new__(mcls, name, bases, dct, *, foo=1):
2211 return super().__new__(mcls, name, bases, dct)
2212 class C(metaclass=CM):
2213 def __init__(self, b):
2214 pass
2215
2216 self.assertEqual(self.signature(C),
2217 ((('b', ..., ..., "positional_or_keyword"),),
2218 ...))
2219
2220 self.assertEqual(self.signature(CM),
2221 ((('name', ..., ..., "positional_or_keyword"),
2222 ('bases', ..., ..., "positional_or_keyword"),
2223 ('dct', ..., ..., "positional_or_keyword"),
2224 ('foo', 1, ..., "keyword_only")),
2225 ...))
2226
2227 class CMM(type):
2228 def __new__(mcls, name, bases, dct, *, foo=1):
2229 return super().__new__(mcls, name, bases, dct)
2230 def __call__(cls, nm, bs, dt):
2231 return type(nm, bs, dt)
2232 class CM(type, metaclass=CMM):
2233 def __new__(mcls, name, bases, dct, *, bar=2):
2234 return super().__new__(mcls, name, bases, dct)
2235 class C(metaclass=CM):
2236 def __init__(self, b):
2237 pass
2238
2239 self.assertEqual(self.signature(CMM),
2240 ((('name', ..., ..., "positional_or_keyword"),
2241 ('bases', ..., ..., "positional_or_keyword"),
2242 ('dct', ..., ..., "positional_or_keyword"),
2243 ('foo', 1, ..., "keyword_only")),
2244 ...))
2245
2246 self.assertEqual(self.signature(CM),
2247 ((('nm', ..., ..., "positional_or_keyword"),
2248 ('bs', ..., ..., "positional_or_keyword"),
2249 ('dt', ..., ..., "positional_or_keyword")),
2250 ...))
2251
2252 self.assertEqual(self.signature(C),
2253 ((('b', ..., ..., "positional_or_keyword"),),
2254 ...))
2255
2256 class CM(type):
2257 def __init__(cls, name, bases, dct, *, bar=2):
2258 return super().__init__(name, bases, dct)
2259 class C(metaclass=CM):
2260 def __init__(self, b):
2261 pass
2262
2263 self.assertEqual(self.signature(CM),
2264 ((('name', ..., ..., "positional_or_keyword"),
2265 ('bases', ..., ..., "positional_or_keyword"),
2266 ('dct', ..., ..., "positional_or_keyword"),
2267 ('bar', 2, ..., "keyword_only")),
2268 ...))
2269
Yury Selivanov145dff82014-02-01 13:49:29 -05002270 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2271 "Signature information for builtins requires docstrings")
2272 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002273 # Test classes without user-defined __init__ or __new__
2274 class C: pass
2275 self.assertEqual(str(inspect.signature(C)), '()')
2276 class D(C): pass
2277 self.assertEqual(str(inspect.signature(D)), '()')
2278
2279 # Test meta-classes without user-defined __init__ or __new__
2280 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002281 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002282 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2283 self.assertEqual(inspect.signature(C), None)
2284 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2285 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002286
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002287 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2288 "Signature information for builtins requires docstrings")
2289 def test_signature_on_builtin_class(self):
2290 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2291 '(file, protocol=None, fix_imports=True)')
2292
2293 class P(_pickle.Pickler): pass
2294 class EmptyTrait: pass
2295 class P2(EmptyTrait, P): pass
2296 self.assertEqual(str(inspect.signature(P)),
2297 '(file, protocol=None, fix_imports=True)')
2298 self.assertEqual(str(inspect.signature(P2)),
2299 '(file, protocol=None, fix_imports=True)')
2300
2301 class P3(P2):
2302 def __init__(self, spam):
2303 pass
2304 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2305
2306 class MetaP(type):
2307 def __call__(cls, foo, bar):
2308 pass
2309 class P4(P2, metaclass=MetaP):
2310 pass
2311 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2312
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002313 def test_signature_on_callable_objects(self):
2314 class Foo:
2315 def __call__(self, a):
2316 pass
2317
2318 self.assertEqual(self.signature(Foo()),
2319 ((('a', ..., ..., "positional_or_keyword"),),
2320 ...))
2321
2322 class Spam:
2323 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002324 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002325 inspect.signature(Spam())
2326
2327 class Bar(Spam, Foo):
2328 pass
2329
2330 self.assertEqual(self.signature(Bar()),
2331 ((('a', ..., ..., "positional_or_keyword"),),
2332 ...))
2333
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002334 class Wrapped:
2335 pass
2336 Wrapped.__wrapped__ = lambda a: None
2337 self.assertEqual(self.signature(Wrapped),
2338 ((('a', ..., ..., "positional_or_keyword"),),
2339 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002340 # wrapper loop:
2341 Wrapped.__wrapped__ = Wrapped
2342 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2343 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002344
2345 def test_signature_on_lambdas(self):
2346 self.assertEqual(self.signature((lambda a=10: a)),
2347 ((('a', 10, ..., "positional_or_keyword"),),
2348 ...))
2349
2350 def test_signature_equality(self):
2351 def foo(a, *, b:int) -> float: pass
2352 self.assertNotEqual(inspect.signature(foo), 42)
2353
2354 def bar(a, *, b:int) -> float: pass
2355 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2356
2357 def bar(a, *, b:int) -> int: pass
2358 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2359
2360 def bar(a, *, b:int): pass
2361 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2362
2363 def bar(a, *, b:int=42) -> float: pass
2364 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2365
2366 def bar(a, *, c) -> float: pass
2367 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2368
2369 def bar(a, b:int) -> float: pass
2370 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2371 def spam(b:int, a) -> float: pass
2372 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
2373
2374 def foo(*, a, b, c): pass
2375 def bar(*, c, b, a): pass
2376 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2377
2378 def foo(*, a=1, b, c): pass
2379 def bar(*, c, b, a=1): pass
2380 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2381
2382 def foo(pos, *, a=1, b, c): pass
2383 def bar(pos, *, c, b, a=1): pass
2384 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2385
2386 def foo(pos, *, a, b, c): pass
2387 def bar(pos, *, c, b, a=1): pass
2388 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2389
2390 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2391 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2392 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2393
2394 def test_signature_unhashable(self):
2395 def foo(a): pass
2396 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002397 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002398 hash(sig)
2399
2400 def test_signature_str(self):
2401 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2402 pass
2403 self.assertEqual(str(inspect.signature(foo)),
2404 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2405
2406 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2407 pass
2408 self.assertEqual(str(inspect.signature(foo)),
2409 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2410
2411 def foo():
2412 pass
2413 self.assertEqual(str(inspect.signature(foo)), '()')
2414
2415 def test_signature_str_positional_only(self):
2416 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002417 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002418
2419 def test(a_po, *, b, **kwargs):
2420 return a_po, kwargs
2421
2422 sig = inspect.signature(test)
2423 new_params = list(sig.parameters.values())
2424 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2425 test.__signature__ = sig.replace(parameters=new_params)
2426
2427 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002428 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002429
Yury Selivanov2393dca2014-01-27 15:07:58 -05002430 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2431 '(foo, /)')
2432
2433 self.assertEqual(str(S(parameters=[
2434 P('foo', P.POSITIONAL_ONLY),
2435 P('bar', P.VAR_KEYWORD)])),
2436 '(foo, /, **bar)')
2437
2438 self.assertEqual(str(S(parameters=[
2439 P('foo', P.POSITIONAL_ONLY),
2440 P('bar', P.VAR_POSITIONAL)])),
2441 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002442
2443 def test_signature_replace_anno(self):
2444 def test() -> 42:
2445 pass
2446
2447 sig = inspect.signature(test)
2448 sig = sig.replace(return_annotation=None)
2449 self.assertIs(sig.return_annotation, None)
2450 sig = sig.replace(return_annotation=sig.empty)
2451 self.assertIs(sig.return_annotation, sig.empty)
2452 sig = sig.replace(return_annotation=42)
2453 self.assertEqual(sig.return_annotation, 42)
2454 self.assertEqual(sig, inspect.signature(test))
2455
Yury Selivanov026019f2014-02-18 12:49:41 -05002456 def test_signature_on_mangled_parameters(self):
2457 class Spam:
2458 def foo(self, __p1:1=2, *, __p2:2=3):
2459 pass
2460 class Ham(Spam):
2461 pass
2462
2463 self.assertEqual(self.signature(Spam.foo),
2464 ((('self', ..., ..., "positional_or_keyword"),
2465 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2466 ('_Spam__p2', 3, 2, "keyword_only")),
2467 ...))
2468
2469 self.assertEqual(self.signature(Spam.foo),
2470 self.signature(Ham.foo))
2471
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002472
2473class TestParameterObject(unittest.TestCase):
2474 def test_signature_parameter_kinds(self):
2475 P = inspect.Parameter
2476 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2477 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2478
2479 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2480 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2481
2482 def test_signature_parameter_object(self):
2483 p = inspect.Parameter('foo', default=10,
2484 kind=inspect.Parameter.POSITIONAL_ONLY)
2485 self.assertEqual(p.name, 'foo')
2486 self.assertEqual(p.default, 10)
2487 self.assertIs(p.annotation, p.empty)
2488 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2489
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002490 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002491 inspect.Parameter('foo', default=10, kind='123')
2492
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002493 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002494 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2495
Yury Selivanov2393dca2014-01-27 15:07:58 -05002496 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002497 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2498
Yury Selivanov2393dca2014-01-27 15:07:58 -05002499 with self.assertRaisesRegex(ValueError,
2500 'is not a valid parameter name'):
2501 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2502
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002503 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002504 inspect.Parameter('a', default=42,
2505 kind=inspect.Parameter.VAR_KEYWORD)
2506
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002507 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002508 inspect.Parameter('a', default=42,
2509 kind=inspect.Parameter.VAR_POSITIONAL)
2510
2511 p = inspect.Parameter('a', default=42,
2512 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002513 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002514 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2515
2516 self.assertTrue(repr(p).startswith('<Parameter'))
2517
2518 def test_signature_parameter_equality(self):
2519 P = inspect.Parameter
2520 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2521
2522 self.assertEqual(p, p)
2523 self.assertNotEqual(p, 42)
2524
2525 self.assertEqual(p, P('foo', default=42,
2526 kind=inspect.Parameter.KEYWORD_ONLY))
2527
2528 def test_signature_parameter_unhashable(self):
2529 p = inspect.Parameter('foo', default=42,
2530 kind=inspect.Parameter.KEYWORD_ONLY)
2531
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002532 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002533 hash(p)
2534
2535 def test_signature_parameter_replace(self):
2536 p = inspect.Parameter('foo', default=42,
2537 kind=inspect.Parameter.KEYWORD_ONLY)
2538
2539 self.assertIsNot(p, p.replace())
2540 self.assertEqual(p, p.replace())
2541
2542 p2 = p.replace(annotation=1)
2543 self.assertEqual(p2.annotation, 1)
2544 p2 = p2.replace(annotation=p2.empty)
2545 self.assertEqual(p, p2)
2546
2547 p2 = p2.replace(name='bar')
2548 self.assertEqual(p2.name, 'bar')
2549 self.assertNotEqual(p2, p)
2550
Yury Selivanov2393dca2014-01-27 15:07:58 -05002551 with self.assertRaisesRegex(ValueError,
2552 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002553 p2 = p2.replace(name=p2.empty)
2554
2555 p2 = p2.replace(name='foo', default=None)
2556 self.assertIs(p2.default, None)
2557 self.assertNotEqual(p2, p)
2558
2559 p2 = p2.replace(name='foo', default=p2.empty)
2560 self.assertIs(p2.default, p2.empty)
2561
2562
2563 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2564 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2565 self.assertNotEqual(p2, p)
2566
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002567 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002568 p2 = p2.replace(kind=p2.empty)
2569
2570 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2571 self.assertEqual(p2, p)
2572
2573 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002574 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2575 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002576
2577 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002578 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002579
2580 with self.assertRaises(AttributeError):
2581 p.foo = 'bar'
2582
2583 with self.assertRaises(AttributeError):
2584 p.kind = 123
2585
2586
2587class TestSignatureBind(unittest.TestCase):
2588 @staticmethod
2589 def call(func, *args, **kwargs):
2590 sig = inspect.signature(func)
2591 ba = sig.bind(*args, **kwargs)
2592 return func(*ba.args, **ba.kwargs)
2593
2594 def test_signature_bind_empty(self):
2595 def test():
2596 return 42
2597
2598 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002599 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002600 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002601 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002602 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002603 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002604 self.call(test, spam=1)
2605
2606 def test_signature_bind_var(self):
2607 def test(*args, **kwargs):
2608 return args, kwargs
2609
2610 self.assertEqual(self.call(test), ((), {}))
2611 self.assertEqual(self.call(test, 1), ((1,), {}))
2612 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2613 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2614 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2615 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2616 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2617 ((1, 2), {'foo': 'bar'}))
2618
2619 def test_signature_bind_just_args(self):
2620 def test(a, b, c):
2621 return a, b, c
2622
2623 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2624
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002625 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002626 self.call(test, 1, 2, 3, 4)
2627
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002628 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002629 self.call(test, 1)
2630
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002631 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002632 self.call(test)
2633
2634 def test(a, b, c=10):
2635 return a, b, c
2636 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2637 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2638
2639 def test(a=1, b=2, c=3):
2640 return a, b, c
2641 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2642 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2643 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2644
2645 def test_signature_bind_varargs_order(self):
2646 def test(*args):
2647 return args
2648
2649 self.assertEqual(self.call(test), ())
2650 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2651
2652 def test_signature_bind_args_and_varargs(self):
2653 def test(a, b, c=3, *args):
2654 return a, b, c, args
2655
2656 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2657 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2658 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2659 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2660
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002661 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002662 "multiple values for argument 'c'"):
2663 self.call(test, 1, 2, 3, c=4)
2664
2665 def test_signature_bind_just_kwargs(self):
2666 def test(**kwargs):
2667 return kwargs
2668
2669 self.assertEqual(self.call(test), {})
2670 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2671 {'foo': 'bar', 'spam': 'ham'})
2672
2673 def test_signature_bind_args_and_kwargs(self):
2674 def test(a, b, c=3, **kwargs):
2675 return a, b, c, kwargs
2676
2677 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2678 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2679 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2680 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2681 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2682 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2683 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2684 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2685 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2686 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2687 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2688 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2689 (1, 2, 4, {'foo': 'bar'}))
2690 self.assertEqual(self.call(test, c=5, a=4, b=3),
2691 (4, 3, 5, {}))
2692
2693 def test_signature_bind_kwonly(self):
2694 def test(*, foo):
2695 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002696 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002697 'too many positional arguments'):
2698 self.call(test, 1)
2699 self.assertEqual(self.call(test, foo=1), 1)
2700
2701 def test(a, *, foo=1, bar):
2702 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002703 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002704 "'bar' parameter lacking default value"):
2705 self.call(test, 1)
2706
2707 def test(foo, *, bar):
2708 return foo, bar
2709 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2710 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2711
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002712 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002713 'too many keyword arguments'):
2714 self.call(test, bar=2, foo=1, spam=10)
2715
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002716 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002717 'too many positional arguments'):
2718 self.call(test, 1, 2)
2719
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002720 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002721 'too many positional arguments'):
2722 self.call(test, 1, 2, bar=2)
2723
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002724 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002725 'too many keyword arguments'):
2726 self.call(test, 1, bar=2, spam='ham')
2727
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002728 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002729 "'bar' parameter lacking default value"):
2730 self.call(test, 1)
2731
2732 def test(foo, *, bar, **bin):
2733 return foo, bar, bin
2734 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2735 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2736 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2737 (1, 2, {'spam': 'ham'}))
2738 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2739 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002740 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002741 "'foo' parameter lacking default value"):
2742 self.call(test, spam='ham', bar=2)
2743 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2744 (1, 2, {'bin': 1, 'spam': 10}))
2745
2746 def test_signature_bind_arguments(self):
2747 def test(a, *args, b, z=100, **kwargs):
2748 pass
2749 sig = inspect.signature(test)
2750 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2751 # we won't have 'z' argument in the bound arguments object, as we didn't
2752 # pass it to the 'bind'
2753 self.assertEqual(tuple(ba.arguments.items()),
2754 (('a', 10), ('args', (20,)), ('b', 30),
2755 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2756 self.assertEqual(ba.kwargs,
2757 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2758 self.assertEqual(ba.args, (10, 20))
2759
2760 def test_signature_bind_positional_only(self):
2761 P = inspect.Parameter
2762
2763 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2764 return a_po, b_po, c_po, foo, bar, kwargs
2765
2766 sig = inspect.signature(test)
2767 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2768 for name in ('a_po', 'b_po', 'c_po'):
2769 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2770 new_sig = sig.replace(parameters=new_params.values())
2771 test.__signature__ = new_sig
2772
2773 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2774 (1, 2, 4, 5, 6, {}))
2775
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002776 self.assertEqual(self.call(test, 1, 2),
2777 (1, 2, 3, 42, 50, {}))
2778
2779 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
2780 (1, 2, 3, 4, 5, {}))
2781
2782 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
2783 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
2784
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002785 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002786 self.call(test, 1, 2, c_po=4)
2787
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002788 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002789 self.call(test, a_po=1, b_po=2)
2790
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002791 def test_signature_bind_with_self_arg(self):
2792 # Issue #17071: one of the parameters is named "self
2793 def test(a, self, b):
2794 pass
2795 sig = inspect.signature(test)
2796 ba = sig.bind(1, 2, 3)
2797 self.assertEqual(ba.args, (1, 2, 3))
2798 ba = sig.bind(1, self=2, b=3)
2799 self.assertEqual(ba.args, (1, 2, 3))
2800
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002801 def test_signature_bind_vararg_name(self):
2802 def test(a, *args):
2803 return a, args
2804 sig = inspect.signature(test)
2805
2806 with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
2807 sig.bind(a=0, args=1)
2808
2809 def test(*args, **kwargs):
2810 return args, kwargs
2811 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
2812
2813 sig = inspect.signature(test)
2814 ba = sig.bind(args=1)
2815 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
2816
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002817
2818class TestBoundArguments(unittest.TestCase):
2819 def test_signature_bound_arguments_unhashable(self):
2820 def foo(a): pass
2821 ba = inspect.signature(foo).bind(1)
2822
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002823 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002824 hash(ba)
2825
2826 def test_signature_bound_arguments_equality(self):
2827 def foo(a): pass
2828 ba = inspect.signature(foo).bind(1)
2829 self.assertEqual(ba, ba)
2830
2831 ba2 = inspect.signature(foo).bind(1)
2832 self.assertEqual(ba, ba2)
2833
2834 ba3 = inspect.signature(foo).bind(2)
2835 self.assertNotEqual(ba, ba3)
2836 ba3.arguments['a'] = 1
2837 self.assertEqual(ba, ba3)
2838
2839 def bar(b): pass
2840 ba4 = inspect.signature(bar).bind(1)
2841 self.assertNotEqual(ba, ba4)
2842
2843
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002844class TestSignaturePrivateHelpers(unittest.TestCase):
2845 def test_signature_get_bound_param(self):
2846 getter = inspect._signature_get_bound_param
2847
2848 self.assertEqual(getter('($self)'), 'self')
2849 self.assertEqual(getter('($self, obj)'), 'self')
2850 self.assertEqual(getter('($cls, /, obj)'), 'cls')
2851
Larry Hastings2623c8c2014-02-08 22:15:29 -08002852 def _strip_non_python_syntax(self, input,
2853 clean_signature, self_parameter, last_positional_only):
2854 computed_clean_signature, \
2855 computed_self_parameter, \
2856 computed_last_positional_only = \
2857 inspect._signature_strip_non_python_syntax(input)
2858 self.assertEqual(computed_clean_signature, clean_signature)
2859 self.assertEqual(computed_self_parameter, self_parameter)
2860 self.assertEqual(computed_last_positional_only, last_positional_only)
2861
2862 def test_signature_strip_non_python_syntax(self):
2863 self._strip_non_python_syntax(
2864 "($module, /, path, mode, *, dir_fd=None, " +
2865 "effective_ids=False,\n follow_symlinks=True)",
2866 "(module, path, mode, *, dir_fd=None, " +
2867 "effective_ids=False, follow_symlinks=True)",
2868 0,
2869 0)
2870
2871 self._strip_non_python_syntax(
2872 "($module, word, salt, /)",
2873 "(module, word, salt)",
2874 0,
2875 2)
2876
2877 self._strip_non_python_syntax(
2878 "(x, y=None, z=None, /)",
2879 "(x, y=None, z=None)",
2880 None,
2881 2)
2882
2883 self._strip_non_python_syntax(
2884 "(x, y=None, z=None)",
2885 "(x, y=None, z=None)",
2886 None,
2887 None)
2888
2889 self._strip_non_python_syntax(
2890 "(x,\n y=None,\n z = None )",
2891 "(x, y=None, z=None)",
2892 None,
2893 None)
2894
2895 self._strip_non_python_syntax(
2896 "",
2897 "",
2898 None,
2899 None)
2900
2901 self._strip_non_python_syntax(
2902 None,
2903 None,
2904 None,
2905 None)
2906
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002907
Nick Coghlane8c45d62013-07-28 20:00:01 +10002908class TestUnwrap(unittest.TestCase):
2909
2910 def test_unwrap_one(self):
2911 def func(a, b):
2912 return a + b
2913 wrapper = functools.lru_cache(maxsize=20)(func)
2914 self.assertIs(inspect.unwrap(wrapper), func)
2915
2916 def test_unwrap_several(self):
2917 def func(a, b):
2918 return a + b
2919 wrapper = func
2920 for __ in range(10):
2921 @functools.wraps(wrapper)
2922 def wrapper():
2923 pass
2924 self.assertIsNot(wrapper.__wrapped__, func)
2925 self.assertIs(inspect.unwrap(wrapper), func)
2926
2927 def test_stop(self):
2928 def func1(a, b):
2929 return a + b
2930 @functools.wraps(func1)
2931 def func2():
2932 pass
2933 @functools.wraps(func2)
2934 def wrapper():
2935 pass
2936 func2.stop_here = 1
2937 unwrapped = inspect.unwrap(wrapper,
2938 stop=(lambda f: hasattr(f, "stop_here")))
2939 self.assertIs(unwrapped, func2)
2940
2941 def test_cycle(self):
2942 def func1(): pass
2943 func1.__wrapped__ = func1
2944 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2945 inspect.unwrap(func1)
2946
2947 def func2(): pass
2948 func2.__wrapped__ = func1
2949 func1.__wrapped__ = func2
2950 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2951 inspect.unwrap(func1)
2952 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2953 inspect.unwrap(func2)
2954
2955 def test_unhashable(self):
2956 def func(): pass
2957 func.__wrapped__ = None
2958 class C:
2959 __hash__ = None
2960 __wrapped__ = func
2961 self.assertIsNone(inspect.unwrap(C()))
2962
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002963class TestMain(unittest.TestCase):
2964 def test_only_source(self):
2965 module = importlib.import_module('unittest')
2966 rc, out, err = assert_python_ok('-m', 'inspect',
2967 'unittest')
2968 lines = out.decode().splitlines()
2969 # ignore the final newline
2970 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
2971 self.assertEqual(err, b'')
2972
Brett Cannon634a8fc2013-10-02 10:25:42 -04002973 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04002974 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002975 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002976 rc, out, err = assert_python_ok('-m', 'inspect',
2977 'concurrent.futures:ThreadPoolExecutor')
2978 lines = out.decode().splitlines()
2979 # ignore the final newline
2980 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04002981 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002982 self.assertEqual(err, b'')
2983
2984 def test_builtins(self):
2985 module = importlib.import_module('unittest')
2986 _, out, err = assert_python_failure('-m', 'inspect',
2987 'sys')
2988 lines = err.decode().splitlines()
2989 self.assertEqual(lines, ["Can't get info for builtin modules."])
2990
2991 def test_details(self):
2992 module = importlib.import_module('unittest')
2993 rc, out, err = assert_python_ok('-m', 'inspect',
2994 'unittest', '--details')
2995 output = out.decode()
2996 # Just a quick sanity check on the output
2997 self.assertIn(module.__name__, output)
2998 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02002999 if not sys.flags.optimize:
3000 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003001 self.assertEqual(err, b'')
3002
3003
3004
Nick Coghlane8c45d62013-07-28 20:00:01 +10003005
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003006def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003007 run_unittest(
3008 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3009 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3010 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003011 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003012 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003013 TestBoundArguments, TestSignaturePrivateHelpers, TestGetClosureVars,
3014 TestUnwrap, TestMain
Michael Foord95fc51d2010-11-20 15:07:30 +00003015 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003016
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003017if __name__ == "__main__":
3018 test_main()