blob: cd051c4183b991a423959cbba9d4defa76813bbc [file] [log] [blame]
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001import builtins
Guido van Rossum813b0e52007-05-21 18:11:34 +00002import collections
Larry Hastings5c661892014-01-24 06:17:25 -08003import datetime
Nick Coghlane8c45d62013-07-28 20:00:01 +10004import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +10005import importlib
Larry Hastings5c661892014-01-24 06:17:25 -08006import inspect
7import io
8import linecache
9import os
Christian Heimesa3538eb2007-11-06 11:44:48 +000010from os.path import normcase
Larry Hastings5c661892014-01-24 06:17:25 -080011import _pickle
Yury Selivanova5d63dd2014-03-27 11:31:43 -040012import pickle
Larry Hastings5c661892014-01-24 06:17:25 -080013import re
14import shutil
15import sys
16import types
Yury Selivanovef1e7502014-12-08 16:05:34 -050017import textwrap
Larry Hastings5c661892014-01-24 06:17:25 -080018import unicodedata
19import unittest
Yury Selivanova773de02014-02-21 18:30:53 -050020import unittest.mock
Larry Hastings5c661892014-01-24 06:17:25 -080021
Brett Cannon634a8fc2013-10-02 10:25:42 -040022try:
23 from concurrent.futures import ThreadPoolExecutor
24except ImportError:
25 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000026
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020027from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
Nick Coghlanf9e227e2014-08-17 14:01:19 +100028from test.support import MISSING_C_DOCSTRINGS, cpython_only
Nick Coghlanf94a16b2013-09-22 22:46:49 +100029from test.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000030from test import inspect_fodder as mod
31from test import inspect_fodder2 as mod2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000032
Yury Selivanovef1e7502014-12-08 16:05:34 -050033from test.test_import import _ready_to_import
34
R. David Murray74b89242009-05-13 17:33:03 +000035
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000036# Functions tested in this suite:
37# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000038# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
39# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
40# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
41# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000042
Nick Coghlanf088e5e2008-12-14 11:50:48 +000043# NOTE: There are some additional tests relating to interaction with
44# zipimport in the test_zipimport_support test module.
45
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000046modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000047if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000048 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000049
Christian Heimesa3538eb2007-11-06 11:44:48 +000050# Normalize file names: on Windows, the case of file names of compiled
51# modules depends on the path used to start the python executable.
52modfile = normcase(modfile)
53
54def revise(filename, *args):
55 return (normcase(filename),) + args
56
Georg Brandl1a3284e2007-12-02 09:40:06 +000057import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000058
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000059git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000060
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000061class IsTestBase(unittest.TestCase):
62 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
63 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000064 inspect.ismodule, inspect.istraceback,
65 inspect.isgenerator, inspect.isgeneratorfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000066
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000067 def istest(self, predicate, exp):
68 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000069 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000070
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000071 for other in self.predicates - set([predicate]):
Christian Heimes7131fd92008-02-19 14:21:46 +000072 if predicate == inspect.isgeneratorfunction and\
73 other == inspect.isfunction:
74 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000075 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000076
Christian Heimes7131fd92008-02-19 14:21:46 +000077def generator_function_example(self):
78 for i in range(2):
79 yield i
80
Yury Selivanova5d63dd2014-03-27 11:31:43 -040081
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000082class TestPredicates(IsTestBase):
Christian Heimes227c8002008-03-03 20:34:40 +000083 def test_sixteen(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +000084 count = len([x for x in dir(inspect) if x.startswith('is')])
Christian Heimes7131fd92008-02-19 14:21:46 +000085 # This test is here for remember you to update Doc/library/inspect.rst
Christian Heimes78644762008-03-04 23:39:23 +000086 # which claims there are 16 such functions
Christian Heimes227c8002008-03-03 20:34:40 +000087 expected = 16
Thomas Wouters0e3f5912006-08-11 14:57:12 +000088 err_msg = "There are %d (not %d) is* functions" % (count, expected)
89 self.assertEqual(count, expected, err_msg)
Tim Peters5a9fb3c2005-01-07 16:01:32 +000090
Christian Heimes7131fd92008-02-19 14:21:46 +000091
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000092 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +020093 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000094 self.istest(inspect.isbuiltin, 'sys.exit')
95 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +000096 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +020097 try:
98 1/0
99 except:
100 tb = sys.exc_info()[2]
101 self.istest(inspect.isframe, 'tb.tb_frame')
102 self.istest(inspect.istraceback, 'tb')
103 if hasattr(types, 'GetSetDescriptorType'):
104 self.istest(inspect.isgetsetdescriptor,
105 'type(tb.tb_frame).f_locals')
106 else:
107 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
108 finally:
109 # Clear traceback and all the frames and local variables hanging to it.
110 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000111 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000112 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000113 self.istest(inspect.ismethod, 'git.argue')
114 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000115 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000116 self.istest(inspect.isgenerator, '(x for x in range(2))')
117 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000118 if hasattr(types, 'MemberDescriptorType'):
119 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
120 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000121 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000122
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000123 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000124 self.assertTrue(inspect.isroutine(mod.spam))
125 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000126
Benjamin Petersonc4656002009-01-17 22:41:18 +0000127 def test_isclass(self):
128 self.istest(inspect.isclass, 'mod.StupidGit')
129 self.assertTrue(inspect.isclass(list))
130
131 class CustomGetattr(object):
132 def __getattr__(self, attr):
133 return None
134 self.assertFalse(inspect.isclass(CustomGetattr()))
135
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000136 def test_get_slot_members(self):
137 class C(object):
138 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000139 x = C()
140 x.a = 42
141 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000142 self.assertIn('a', members)
143 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000144
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000145 def test_isabstract(self):
146 from abc import ABCMeta, abstractmethod
147
148 class AbstractClassExample(metaclass=ABCMeta):
149
150 @abstractmethod
151 def foo(self):
152 pass
153
154 class ClassExample(AbstractClassExample):
155 def foo(self):
156 pass
157
158 a = ClassExample()
159
160 # Test general behaviour.
161 self.assertTrue(inspect.isabstract(AbstractClassExample))
162 self.assertFalse(inspect.isabstract(ClassExample))
163 self.assertFalse(inspect.isabstract(a))
164 self.assertFalse(inspect.isabstract(int))
165 self.assertFalse(inspect.isabstract(5))
166
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000167
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000168class TestInterpreterStack(IsTestBase):
169 def __init__(self, *args, **kwargs):
170 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000171
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000172 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000173
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000174 def test_abuse_done(self):
175 self.istest(inspect.istraceback, 'git.ex[2]')
176 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000177
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000178 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000179 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000180 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000181 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000182 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000183 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000184 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000185 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000186 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000187 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400188 # Test named tuple fields
189 record = mod.st[0]
190 self.assertIs(record.frame, mod.fr)
191 self.assertEqual(record.lineno, 16)
192 self.assertEqual(record.filename, mod.__file__)
193 self.assertEqual(record.function, 'eggs')
194 self.assertIn('inspect.stack()', record.code_context[0])
195 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000196
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000197 def test_trace(self):
198 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000199 self.assertEqual(revise(*git.tr[0][1:]),
200 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
201 self.assertEqual(revise(*git.tr[1][1:]),
202 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
203 self.assertEqual(revise(*git.tr[2][1:]),
204 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000205
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000206 def test_frame(self):
207 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
208 self.assertEqual(args, ['x', 'y'])
209 self.assertEqual(varargs, None)
210 self.assertEqual(varkw, None)
211 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
212 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
213 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000214
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000215 def test_previous_frame(self):
216 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000217 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000218 self.assertEqual(varargs, 'g')
219 self.assertEqual(varkw, 'h')
220 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000221 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000222
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000223class GetSourceBase(unittest.TestCase):
224 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000225 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000226
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000227 def __init__(self, *args, **kwargs):
228 unittest.TestCase.__init__(self, *args, **kwargs)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000229
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000230 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000231 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000232
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000233 def sourcerange(self, top, bottom):
234 lines = self.source.split("\n")
235 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000236
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000237 def assertSourceEqual(self, obj, top, bottom):
238 self.assertEqual(inspect.getsource(obj),
239 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000240
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000241class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000242 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000243
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000244 def test_getclasses(self):
245 classes = inspect.getmembers(mod, inspect.isclass)
246 self.assertEqual(classes,
247 [('FesteringGob', mod.FesteringGob),
248 ('MalodorousPervert', mod.MalodorousPervert),
249 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300250 ('StupidGit', mod.StupidGit),
251 ('Tit', mod.MalodorousPervert),
252 ])
253 tree = inspect.getclasstree([cls[1] for cls in classes])
254 self.assertEqual(tree,
255 [(object, ()),
256 [(mod.ParrotDroppings, (object,)),
257 [(mod.FesteringGob, (mod.MalodorousPervert,
258 mod.ParrotDroppings))
259 ],
260 (mod.StupidGit, (object,)),
261 [(mod.MalodorousPervert, (mod.StupidGit,)),
262 [(mod.FesteringGob, (mod.MalodorousPervert,
263 mod.ParrotDroppings))
264 ]
265 ]
266 ]
267 ])
268 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000269 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000270 [(object, ()),
271 [(mod.ParrotDroppings, (object,)),
272 (mod.StupidGit, (object,)),
273 [(mod.MalodorousPervert, (mod.StupidGit,)),
274 [(mod.FesteringGob, (mod.MalodorousPervert,
275 mod.ParrotDroppings))
276 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000277 ]
278 ]
279 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000280
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000281 def test_getfunctions(self):
282 functions = inspect.getmembers(mod, inspect.isfunction)
283 self.assertEqual(functions, [('eggs', mod.eggs),
284 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000285
R. David Murray378c0cf2010-02-24 01:46:21 +0000286 @unittest.skipIf(sys.flags.optimize >= 2,
287 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000288 def test_getdoc(self):
289 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
290 self.assertEqual(inspect.getdoc(mod.StupidGit),
291 'A longer,\n\nindented\n\ndocstring.')
292 self.assertEqual(inspect.getdoc(git.abuse),
293 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000294
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300295 @unittest.skipIf(sys.flags.optimize >= 2,
296 "Docstrings are omitted with -O2 and above")
297 def test_getdoc_inherited(self):
298 self.assertEqual(inspect.getdoc(mod.FesteringGob),
299 'A longer,\n\nindented\n\ndocstring.')
300 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
301 'Another\n\ndocstring\n\ncontaining\n\ntabs')
302 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
303 'Another\n\ndocstring\n\ncontaining\n\ntabs')
304 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
305 'The automatic gainsaying.')
306
307 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
308 def test_finddoc(self):
309 finddoc = inspect._finddoc
310 self.assertEqual(finddoc(int), int.__doc__)
311 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
312 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
313 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
314 self.assertEqual(finddoc(int.real), int.real.__doc__)
315
Georg Brandl0c77a822008-06-10 16:37:50 +0000316 def test_cleandoc(self):
317 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
318 'An\nindented\ndocstring.')
319
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000320 def test_getcomments(self):
321 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
322 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000323
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000324 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000325 # Check actual module
326 self.assertEqual(inspect.getmodule(mod), mod)
327 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000328 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000329 # Check a method (no __module__ attribute, falls back to filename)
330 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
331 # Do it again (check the caching isn't broken)
332 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
333 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000334 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000335 # Check filename override
336 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000337
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000338 def test_getsource(self):
339 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300340 self.assertSourceEqual(mod.StupidGit, 21, 50)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000341
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000342 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000343 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
344 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000345 fn = "_non_existing_filename_used_for_sourcefile_test.py"
346 co = compile("None", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000347 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000348 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200349 try:
350 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
351 finally:
352 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000353
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000354 def test_getfile(self):
355 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000356
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500357 def test_getfile_class_without_module(self):
358 class CM(type):
359 @property
360 def __module__(cls):
361 raise AttributeError
362 class C(metaclass=CM):
363 pass
364 with self.assertRaises(TypeError):
365 inspect.getfile(C)
366
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000367 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000368 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000369 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000370 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000371 m.__file__ = "<string>" # hopefully not a real filename...
372 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000373 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000374 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000375 del sys.modules[name]
376 inspect.getmodule(compile('a=10','','single'))
377
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500378 def test_proceed_with_fake_filename(self):
379 '''doctest monkeypatches linecache to enable inspection'''
380 fn, source = '<test>', 'def x(): pass\n'
381 getlines = linecache.getlines
382 def monkey(filename, module_globals=None):
383 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300384 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500385 else:
386 return getlines(filename, module_globals)
387 linecache.getlines = monkey
388 try:
389 ns = {}
390 exec(compile(source, fn, 'single'), ns)
391 inspect.getsource(ns["x"])
392 finally:
393 linecache.getlines = getlines
394
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000395class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000396 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000397
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000398 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000399 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000400
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000401 def test_replacing_decorator(self):
402 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000403
Yury Selivanov081bbf62014-09-26 17:34:54 -0400404 def test_getsource_unwrap(self):
405 self.assertSourceEqual(mod2.real, 122, 124)
406
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000407class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000408 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000409 def test_oneline_lambda(self):
410 # Test inspect.getsource with a one-line lambda function.
411 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000412
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000413 def test_threeline_lambda(self):
414 # Test inspect.getsource with a three-line lambda function,
415 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000416 self.assertSourceEqual(mod2.tll, 28, 30)
417
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000418 def test_twoline_indented_lambda(self):
419 # Test inspect.getsource with a two-line lambda function,
420 # where the second line _is_ indented.
421 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000422
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000423 def test_onelinefunc(self):
424 # Test inspect.getsource with a regular one-line function.
425 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000426
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000427 def test_manyargs(self):
428 # Test inspect.getsource with a regular function where
429 # the arguments are on two lines and _not_ indented and
430 # the body on the second line with the last arguments.
431 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000432
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000433 def test_twolinefunc(self):
434 # Test inspect.getsource with a regular function where
435 # the body is on two lines, following the argument list and
436 # continued on the next line by a \\.
437 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000438
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000439 def test_lambda_in_list(self):
440 # Test inspect.getsource with a one-line lambda function
441 # defined in a list, indented.
442 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000443
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000444 def test_anonymous(self):
445 # Test inspect.getsource with a lambda function defined
446 # as argument to another function.
447 self.assertSourceEqual(mod2.anonymous, 55, 55)
448
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000449class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000450 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000451
452 def test_with_comment(self):
453 self.assertSourceEqual(mod2.with_comment, 58, 59)
454
455 def test_multiline_sig(self):
456 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
457
Armin Rigodd5c0232005-09-25 11:45:45 +0000458 def test_nested_class(self):
459 self.assertSourceEqual(mod2.func69().func71, 71, 72)
460
461 def test_one_liner_followed_by_non_name(self):
462 self.assertSourceEqual(mod2.func77, 77, 77)
463
464 def test_one_liner_dedent_non_name(self):
465 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
466
467 def test_with_comment_instead_of_docstring(self):
468 self.assertSourceEqual(mod2.func88, 88, 90)
469
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000470 def test_method_in_dynamic_class(self):
471 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
472
R David Murray32562d72014-10-03 11:15:38 -0400473 # This should not skip for CPython, but might on a repackaged python where
474 # unicodedata is not an external module, or on pypy.
475 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
476 unicodedata.__file__.endswith('.py'),
477 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000478 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200479 self.assertRaises(OSError, inspect.getsource, unicodedata)
480 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000481
R. David Murraya1b37402010-06-17 02:04:29 +0000482 def test_findsource_code_in_linecache(self):
483 lines = ["x=1"]
484 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200485 self.assertRaises(OSError, inspect.findsource, co)
486 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000487 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200488 try:
489 self.assertEqual(inspect.findsource(co), (lines,0))
490 self.assertEqual(inspect.getsource(co), lines[0])
491 finally:
492 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000493
Ezio Melotti1b145922013-03-30 05:17:24 +0200494 def test_findsource_without_filename(self):
495 for fname in ['', '<string>']:
496 co = compile('x=1', fname, "exec")
497 self.assertRaises(IOError, inspect.findsource, co)
498 self.assertRaises(IOError, inspect.getsource, co)
499
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000500class TestNoEOL(GetSourceBase):
501 def __init__(self, *args, **kwargs):
502 self.tempdir = TESTFN + '_dir'
503 os.mkdir(self.tempdir)
504 with open(os.path.join(self.tempdir,
505 'inspect_fodder3%spy' % os.extsep), 'w') as f:
506 f.write("class X:\n pass # No EOL")
507 with DirsOnSysPath(self.tempdir):
508 import inspect_fodder3 as mod3
509 self.fodderModule = mod3
510 GetSourceBase.__init__(self, *args, **kwargs)
511
512 def tearDown(self):
513 shutil.rmtree(self.tempdir)
514
515 def test_class(self):
516 self.assertSourceEqual(self.fodderModule.X, 1, 2)
517
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100518
519class _BrokenDataDescriptor(object):
520 """
521 A broken data descriptor. See bug #1785.
522 """
523 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700524 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100525
526 def __set__(*args):
527 raise RuntimeError
528
529 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700530 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100531
532
533class _BrokenMethodDescriptor(object):
534 """
535 A broken method descriptor. See bug #1785.
536 """
537 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700538 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100539
540 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700541 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100542
543
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000544# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000545def attrs_wo_objs(cls):
546 return [t[:3] for t in inspect.classify_class_attrs(cls)]
547
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100548
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000549class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000550 def test_newstyle_mro(self):
551 # The same w/ new-class MRO.
552 class A(object): pass
553 class B(A): pass
554 class C(A): pass
555 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000556
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000557 expected = (D, B, C, A, object)
558 got = inspect.getmro(D)
559 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000560
Christian Heimes3795b532007-11-08 13:48:53 +0000561 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
562 varkw_e=None, defaults_e=None, formatted=None):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000563 args, varargs, varkw, defaults = inspect.getargspec(routine)
564 self.assertEqual(args, args_e)
565 self.assertEqual(varargs, varargs_e)
566 self.assertEqual(varkw, varkw_e)
567 self.assertEqual(defaults, defaults_e)
568 if formatted is not None:
569 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
570 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000571
Christian Heimes3795b532007-11-08 13:48:53 +0000572 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
573 varkw_e=None, defaults_e=None,
574 kwonlyargs_e=[], kwonlydefaults_e=None,
575 ann_e={}, formatted=None):
576 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
577 inspect.getfullargspec(routine)
578 self.assertEqual(args, args_e)
579 self.assertEqual(varargs, varargs_e)
580 self.assertEqual(varkw, varkw_e)
581 self.assertEqual(defaults, defaults_e)
582 self.assertEqual(kwonlyargs, kwonlyargs_e)
583 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
584 self.assertEqual(ann, ann_e)
585 if formatted is not None:
586 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
587 kwonlyargs, kwonlydefaults, ann),
588 formatted)
589
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000590 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000591 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000592
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000593 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000594 ['a', 'b', 'c', 'd', 'e', 'f'],
595 'g', 'h', (3, 4, 5),
596 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000597
Christian Heimes3795b532007-11-08 13:48:53 +0000598 self.assertRaises(ValueError, self.assertArgSpecEquals,
599 mod2.keyworded, [])
600
601 self.assertRaises(ValueError, self.assertArgSpecEquals,
602 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000603 self.assertRaises(ValueError, self.assertArgSpecEquals,
604 mod2.keyword_only_arg, [])
605
Christian Heimes3795b532007-11-08 13:48:53 +0000606
607 def test_getfullargspec(self):
608 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
609 kwonlyargs_e=['arg2'],
610 kwonlydefaults_e={'arg2':1},
611 formatted='(*arg1, arg2=1)')
612
613 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000614 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000615 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000616 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
617 kwonlyargs_e=['arg'],
618 formatted='(*, arg)')
619
Yury Selivanov57d240e2014-02-19 16:27:23 -0500620 def test_argspec_api_ignores_wrapped(self):
621 # Issue 20684: low level introspection API must ignore __wrapped__
622 @functools.wraps(mod.spam)
623 def ham(x, y):
624 pass
625 # Basic check
626 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
627 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
628 self.assertFullArgSpecEquals(functools.partial(ham),
629 ['x', 'y'], formatted='(x, y)')
630 # Other variants
631 def check_method(f):
632 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
633 formatted='(self, x, y)')
634 class C:
635 @functools.wraps(mod.spam)
636 def ham(self, x, y):
637 pass
638 pham = functools.partialmethod(ham)
639 @functools.wraps(mod.spam)
640 def __call__(self, x, y):
641 pass
642 check_method(C())
643 check_method(C.ham)
644 check_method(C().ham)
645 check_method(C.pham)
646 check_method(C().pham)
647
648 class C_new:
649 @functools.wraps(mod.spam)
650 def __new__(self, x, y):
651 pass
652 check_method(C_new)
653
654 class C_init:
655 @functools.wraps(mod.spam)
656 def __init__(self, x, y):
657 pass
658 check_method(C_init)
659
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500660 def test_getfullargspec_signature_attr(self):
661 def test():
662 pass
663 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
664 test.__signature__ = inspect.Signature(parameters=(spam_param,))
665
666 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
667
Yury Selivanov4cb93912014-01-29 11:54:12 -0500668 def test_getfullargspec_signature_annos(self):
669 def test(a:'spam') -> 'ham': pass
670 spec = inspect.getfullargspec(test)
671 self.assertEqual(test.__annotations__, spec.annotations)
672
673 def test(): pass
674 spec = inspect.getfullargspec(test)
675 self.assertEqual(test.__annotations__, spec.annotations)
676
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500677 @unittest.skipIf(MISSING_C_DOCSTRINGS,
678 "Signature information for builtins requires docstrings")
679 def test_getfullargspec_builtin_methods(self):
680 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
681 args_e=['self', 'obj'], formatted='(self, obj)')
682
683 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
684 args_e=['self', 'obj'], formatted='(self, obj)')
685
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500686 self.assertFullArgSpecEquals(
687 os.stat,
688 args_e=['path'],
689 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
690 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
691 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
692
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200693 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500694 @unittest.skipIf(MISSING_C_DOCSTRINGS,
695 "Signature information for builtins requires docstrings")
696 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200697 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500698 builtin = _testcapi.docstring_with_signature_with_defaults
699 spec = inspect.getfullargspec(builtin)
700 self.assertEqual(spec.defaults[0], 'avocado')
701
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200702 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500703 @unittest.skipIf(MISSING_C_DOCSTRINGS,
704 "Signature information for builtins requires docstrings")
705 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200706 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500707 builtin = _testcapi.docstring_no_signature
708 with self.assertRaises(TypeError):
709 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000710
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000711 def test_getargspec_method(self):
712 class A(object):
713 def m(self):
714 pass
715 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000716
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000717 def test_classify_newstyle(self):
718 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000719
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000720 def s(): pass
721 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000722
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000723 def c(cls): pass
724 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000725
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000726 def getp(self): pass
727 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000728
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000729 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000730
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000731 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000732
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000733 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000734
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100735 dd = _BrokenDataDescriptor()
736 md = _BrokenMethodDescriptor()
737
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000738 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500739
740 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
741 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
742
Benjamin Peterson577473f2010-01-19 00:09:57 +0000743 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
744 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
745 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000746 self.assertIn(('m', 'method', A), attrs,
747 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000748 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
749 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100750 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
751 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000752
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000753 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000754
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000755 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000756
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000757 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000758 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
759 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
760 self.assertIn(('p', 'property', A), attrs, 'missing property')
761 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
762 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
763 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100764 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
765 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000766
767
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000768 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000769
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000770 def m(self): pass
771 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000772
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000773 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000774 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
775 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
776 self.assertIn(('p', 'property', A), attrs, 'missing property')
777 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
778 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
779 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100780 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
781 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000782
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000783 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000784
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000785 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000786
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000787 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000788 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
789 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
790 self.assertIn(('p', 'property', A), attrs, 'missing property')
791 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
792 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
793 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100794 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
795 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
796
797 def test_classify_builtin_types(self):
798 # Simple sanity check that all built-in types can have their
799 # attributes classified.
800 for name in dir(__builtins__):
801 builtin = getattr(__builtins__, name)
802 if isinstance(builtin, type):
803 inspect.classify_class_attrs(builtin)
804
Ethan Furman63c141c2013-10-18 00:27:39 -0700805 def test_classify_DynamicClassAttribute(self):
806 class Meta(type):
807 def __getattr__(self, name):
808 if name == 'ham':
809 return 'spam'
810 return super().__getattr__(name)
811 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700812 @types.DynamicClassAttribute
813 def ham(self):
814 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700815 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
816 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700817 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700818 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
819
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700820 def test_classify_metaclass_class_attribute(self):
821 class Meta(type):
822 fish = 'slap'
823 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200824 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700825 class Class(metaclass=Meta):
826 pass
827 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
828 self.assertIn(should_find, inspect.classify_class_attrs(Class))
829
Ethan Furman63c141c2013-10-18 00:27:39 -0700830 def test_classify_VirtualAttribute(self):
831 class Meta(type):
832 def __dir__(cls):
833 return ['__class__', '__module__', '__name__', 'BOOM']
834 def __getattr__(self, name):
835 if name =='BOOM':
836 return 42
837 return super().__getattr(name)
838 class Class(metaclass=Meta):
839 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700840 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700841 self.assertIn(should_find, inspect.classify_class_attrs(Class))
842
843 def test_classify_VirtualAttribute_multi_classes(self):
844 class Meta1(type):
845 def __dir__(cls):
846 return ['__class__', '__module__', '__name__', 'one']
847 def __getattr__(self, name):
848 if name =='one':
849 return 1
850 return super().__getattr__(name)
851 class Meta2(type):
852 def __dir__(cls):
853 return ['__class__', '__module__', '__name__', 'two']
854 def __getattr__(self, name):
855 if name =='two':
856 return 2
857 return super().__getattr__(name)
858 class Meta3(Meta1, Meta2):
859 def __dir__(cls):
860 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
861 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
862 def __getattr__(self, name):
863 if name =='three':
864 return 3
865 return super().__getattr__(name)
866 class Class1(metaclass=Meta1):
867 pass
868 class Class2(Class1, metaclass=Meta3):
869 pass
870
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700871 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
872 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
873 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700874 cca = inspect.classify_class_attrs(Class2)
875 for sf in (should_find1, should_find2, should_find3):
876 self.assertIn(sf, cca)
877
878 def test_classify_class_attrs_with_buggy_dir(self):
879 class M(type):
880 def __dir__(cls):
881 return ['__class__', '__name__', 'missing']
882 class C(metaclass=M):
883 pass
884 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
885 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700886
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100887 def test_getmembers_descriptors(self):
888 class A(object):
889 dd = _BrokenDataDescriptor()
890 md = _BrokenMethodDescriptor()
891
892 def pred_wrapper(pred):
893 # A quick'n'dirty way to discard standard attributes of new-style
894 # classes.
895 class Empty(object):
896 pass
897 def wrapped(x):
898 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
899 return False
900 return pred(x)
901 return wrapped
902
903 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
904 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
905
906 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
907 [('md', A.__dict__['md'])])
908 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
909 [('dd', A.__dict__['dd'])])
910
911 class B(A):
912 pass
913
914 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
915 [('md', A.__dict__['md'])])
916 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
917 [('dd', A.__dict__['dd'])])
918
Antoine Pitrou0c603812012-01-18 17:40:18 +0100919 def test_getmembers_method(self):
920 class B:
921 def f(self):
922 pass
923
924 self.assertIn(('f', B.f), inspect.getmembers(B))
925 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
926 b = B()
927 self.assertIn(('f', b.f), inspect.getmembers(b))
928 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
929
Ethan Furmane03ea372013-09-25 07:14:41 -0700930 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -0700931 class M(type):
932 def __getattr__(cls, name):
933 if name == 'eggs':
934 return 'scrambled'
935 return super().__getattr__(name)
936 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -0700937 @types.DynamicClassAttribute
938 def eggs(self):
939 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -0700940 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
941 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
942
943 def test_getmembers_with_buggy_dir(self):
944 class M(type):
945 def __dir__(cls):
946 return ['__class__', '__name__', 'missing']
947 class C(metaclass=M):
948 pass
949 attrs = [a[0] for a in inspect.getmembers(C)]
950 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700951
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000952
Nick Coghlan2f92e542012-06-23 19:39:55 +1000953_global_ref = object()
954class TestGetClosureVars(unittest.TestCase):
955
956 def test_name_resolution(self):
957 # Basic test of the 4 different resolution mechanisms
958 def f(nonlocal_ref):
959 def g(local_ref):
960 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
961 return g
962 _arg = object()
963 nonlocal_vars = {"nonlocal_ref": _arg}
964 global_vars = {"_global_ref": _global_ref}
965 builtin_vars = {"print": print}
966 unbound_names = {"unbound_ref"}
967 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
968 builtin_vars, unbound_names)
969 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
970
971 def test_generator_closure(self):
972 def f(nonlocal_ref):
973 def g(local_ref):
974 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
975 yield
976 return g
977 _arg = object()
978 nonlocal_vars = {"nonlocal_ref": _arg}
979 global_vars = {"_global_ref": _global_ref}
980 builtin_vars = {"print": print}
981 unbound_names = {"unbound_ref"}
982 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
983 builtin_vars, unbound_names)
984 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
985
986 def test_method_closure(self):
987 class C:
988 def f(self, nonlocal_ref):
989 def g(local_ref):
990 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
991 return g
992 _arg = object()
993 nonlocal_vars = {"nonlocal_ref": _arg}
994 global_vars = {"_global_ref": _global_ref}
995 builtin_vars = {"print": print}
996 unbound_names = {"unbound_ref"}
997 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
998 builtin_vars, unbound_names)
999 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1000
1001 def test_nonlocal_vars(self):
1002 # More complex tests of nonlocal resolution
1003 def _nonlocal_vars(f):
1004 return inspect.getclosurevars(f).nonlocals
1005
1006 def make_adder(x):
1007 def add(y):
1008 return x + y
1009 return add
1010
1011 def curry(func, arg1):
1012 return lambda arg2: func(arg1, arg2)
1013
1014 def less_than(a, b):
1015 return a < b
1016
1017 # The infamous Y combinator.
1018 def Y(le):
1019 def g(f):
1020 return le(lambda x: f(f)(x))
1021 Y.g_ref = g
1022 return g(g)
1023
1024 def check_y_combinator(func):
1025 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1026
1027 inc = make_adder(1)
1028 add_two = make_adder(2)
1029 greater_than_five = curry(less_than, 5)
1030
1031 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1032 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1033 self.assertEqual(_nonlocal_vars(greater_than_five),
1034 {'arg1': 5, 'func': less_than})
1035 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1036 {'x': 3})
1037 Y(check_y_combinator)
1038
1039 def test_getclosurevars_empty(self):
1040 def foo(): pass
1041 _empty = inspect.ClosureVars({}, {}, {}, set())
1042 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1043 self.assertEqual(inspect.getclosurevars(foo), _empty)
1044
1045 def test_getclosurevars_error(self):
1046 class T: pass
1047 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1048 self.assertRaises(TypeError, inspect.getclosurevars, list)
1049 self.assertRaises(TypeError, inspect.getclosurevars, {})
1050
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001051 def _private_globals(self):
1052 code = """def f(): print(path)"""
1053 ns = {}
1054 exec(code, ns)
1055 return ns["f"], ns
1056
1057 def test_builtins_fallback(self):
1058 f, ns = self._private_globals()
1059 ns.pop("__builtins__", None)
1060 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1061 self.assertEqual(inspect.getclosurevars(f), expected)
1062
1063 def test_builtins_as_dict(self):
1064 f, ns = self._private_globals()
1065 ns["__builtins__"] = {"path":1}
1066 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1067 self.assertEqual(inspect.getclosurevars(f), expected)
1068
1069 def test_builtins_as_module(self):
1070 f, ns = self._private_globals()
1071 ns["__builtins__"] = os
1072 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1073 self.assertEqual(inspect.getclosurevars(f), expected)
1074
Nick Coghlan2f92e542012-06-23 19:39:55 +10001075
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001076class TestGetcallargsFunctions(unittest.TestCase):
1077
1078 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1079 locs = dict(locs or {}, func=func)
1080 r1 = eval('func(%s)' % call_params_string, None, locs)
1081 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1082 locs)
1083 self.assertEqual(r1, r2)
1084
1085 def assertEqualException(self, func, call_param_string, locs=None):
1086 locs = dict(locs or {}, func=func)
1087 try:
1088 eval('func(%s)' % call_param_string, None, locs)
1089 except Exception as e:
1090 ex1 = e
1091 else:
1092 self.fail('Exception not raised')
1093 try:
1094 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1095 locs)
1096 except Exception as e:
1097 ex2 = e
1098 else:
1099 self.fail('Exception not raised')
1100 self.assertIs(type(ex1), type(ex2))
1101 self.assertEqual(str(ex1), str(ex2))
1102 del ex1, ex2
1103
1104 def makeCallable(self, signature):
1105 """Create a function that returns its locals()"""
1106 code = "lambda %s: locals()"
1107 return eval(code % signature)
1108
1109 def test_plain(self):
1110 f = self.makeCallable('a, b=1')
1111 self.assertEqualCallArgs(f, '2')
1112 self.assertEqualCallArgs(f, '2, 3')
1113 self.assertEqualCallArgs(f, 'a=2')
1114 self.assertEqualCallArgs(f, 'b=3, a=2')
1115 self.assertEqualCallArgs(f, '2, b=3')
1116 # expand *iterable / **mapping
1117 self.assertEqualCallArgs(f, '*(2,)')
1118 self.assertEqualCallArgs(f, '*[2]')
1119 self.assertEqualCallArgs(f, '*(2, 3)')
1120 self.assertEqualCallArgs(f, '*[2, 3]')
1121 self.assertEqualCallArgs(f, '**{"a":2}')
1122 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1123 self.assertEqualCallArgs(f, '2, **{"b":3}')
1124 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1125 # expand UserList / UserDict
1126 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1127 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1128 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1129 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1130 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1131
1132 def test_varargs(self):
1133 f = self.makeCallable('a, b=1, *c')
1134 self.assertEqualCallArgs(f, '2')
1135 self.assertEqualCallArgs(f, '2, 3')
1136 self.assertEqualCallArgs(f, '2, 3, 4')
1137 self.assertEqualCallArgs(f, '*(2,3,4)')
1138 self.assertEqualCallArgs(f, '2, *[3,4]')
1139 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1140
1141 def test_varkw(self):
1142 f = self.makeCallable('a, b=1, **c')
1143 self.assertEqualCallArgs(f, 'a=2')
1144 self.assertEqualCallArgs(f, '2, b=3, c=4')
1145 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1146 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1147 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1148 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1149 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1150 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1151 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1152
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001153 def test_varkw_only(self):
1154 # issue11256:
1155 f = self.makeCallable('**c')
1156 self.assertEqualCallArgs(f, '')
1157 self.assertEqualCallArgs(f, 'a=1')
1158 self.assertEqualCallArgs(f, 'a=1, b=2')
1159 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1160 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1161 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1162
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001163 def test_keyword_only(self):
1164 f = self.makeCallable('a=3, *, c, d=2')
1165 self.assertEqualCallArgs(f, 'c=3')
1166 self.assertEqualCallArgs(f, 'c=3, a=3')
1167 self.assertEqualCallArgs(f, 'a=2, c=4')
1168 self.assertEqualCallArgs(f, '4, c=4')
1169 self.assertEqualException(f, '')
1170 self.assertEqualException(f, '3')
1171 self.assertEqualException(f, 'a=3')
1172 self.assertEqualException(f, 'd=4')
1173
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001174 f = self.makeCallable('*, c, d=2')
1175 self.assertEqualCallArgs(f, 'c=3')
1176 self.assertEqualCallArgs(f, 'c=3, d=4')
1177 self.assertEqualCallArgs(f, 'd=4, c=3')
1178
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001179 def test_multiple_features(self):
1180 f = self.makeCallable('a, b=2, *f, **g')
1181 self.assertEqualCallArgs(f, '2, 3, 7')
1182 self.assertEqualCallArgs(f, '2, 3, x=8')
1183 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1184 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1185 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1186 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1187 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1188 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1189 '(4,[5,6])]), **collections.UserDict('
1190 'y=9, z=10)')
1191
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001192 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1193 self.assertEqualCallArgs(f, '2, 3, x=8')
1194 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1195 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1196 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1197 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1198 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1199 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1200 '(4,[5,6])]), q=0, **collections.UserDict('
1201 'y=9, z=10)')
1202
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001203 def test_errors(self):
1204 f0 = self.makeCallable('')
1205 f1 = self.makeCallable('a, b')
1206 f2 = self.makeCallable('a, b=1')
1207 # f0 takes no arguments
1208 self.assertEqualException(f0, '1')
1209 self.assertEqualException(f0, 'x=1')
1210 self.assertEqualException(f0, '1,x=1')
1211 # f1 takes exactly 2 arguments
1212 self.assertEqualException(f1, '')
1213 self.assertEqualException(f1, '1')
1214 self.assertEqualException(f1, 'a=2')
1215 self.assertEqualException(f1, 'b=3')
1216 # f2 takes at least 1 argument
1217 self.assertEqualException(f2, '')
1218 self.assertEqualException(f2, 'b=3')
1219 for f in f1, f2:
1220 # f1/f2 takes exactly/at most 2 arguments
1221 self.assertEqualException(f, '2, 3, 4')
1222 self.assertEqualException(f, '1, 2, 3, a=1')
1223 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001224 # XXX: success of this one depends on dict order
1225 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001226 # f got an unexpected keyword argument
1227 self.assertEqualException(f, 'c=2')
1228 self.assertEqualException(f, '2, c=3')
1229 self.assertEqualException(f, '2, 3, c=4')
1230 self.assertEqualException(f, '2, c=4, b=3')
1231 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1232 # f got multiple values for keyword argument
1233 self.assertEqualException(f, '1, a=2')
1234 self.assertEqualException(f, '1, **{"a":2}')
1235 self.assertEqualException(f, '1, 2, b=3')
1236 # XXX: Python inconsistency
1237 # - for functions and bound methods: unexpected keyword 'c'
1238 # - for unbound methods: multiple values for keyword 'a'
1239 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001240 # issue11256:
1241 f3 = self.makeCallable('**c')
1242 self.assertEqualException(f3, '1, 2')
1243 self.assertEqualException(f3, '1, 2, a=1, b=2')
1244 f4 = self.makeCallable('*, a, b=0')
1245 self.assertEqualException(f3, '1, 2')
1246 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001247
Yury Selivanov875df202014-03-27 18:23:03 -04001248 # issue #20816: getcallargs() fails to iterate over non-existent
1249 # kwonlydefaults and raises a wrong TypeError
1250 def f5(*, a): pass
1251 with self.assertRaisesRegex(TypeError,
1252 'missing 1 required keyword-only'):
1253 inspect.getcallargs(f5)
1254
1255
Yury Selivanovdccfa132014-03-27 18:42:52 -04001256 # issue20817:
1257 def f6(a, b, c):
1258 pass
1259 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1260 inspect.getcallargs(f6)
1261
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001262class TestGetcallargsMethods(TestGetcallargsFunctions):
1263
1264 def setUp(self):
1265 class Foo(object):
1266 pass
1267 self.cls = Foo
1268 self.inst = Foo()
1269
1270 def makeCallable(self, signature):
1271 assert 'self' not in signature
1272 mk = super(TestGetcallargsMethods, self).makeCallable
1273 self.cls.method = mk('self, ' + signature)
1274 return self.inst.method
1275
1276class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1277
1278 def makeCallable(self, signature):
1279 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1280 return self.cls.method
1281
1282 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1283 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1284 *self._getAssertEqualParams(func, call_params_string, locs))
1285
1286 def assertEqualException(self, func, call_params_string, locs=None):
1287 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1288 *self._getAssertEqualParams(func, call_params_string, locs))
1289
1290 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1291 assert 'inst' not in call_params_string
1292 locs = dict(locs or {}, inst=self.inst)
1293 return (func, 'inst,' + call_params_string, locs)
1294
Michael Foord95fc51d2010-11-20 15:07:30 +00001295
1296class TestGetattrStatic(unittest.TestCase):
1297
1298 def test_basic(self):
1299 class Thing(object):
1300 x = object()
1301
1302 thing = Thing()
1303 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1304 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1305 with self.assertRaises(AttributeError):
1306 inspect.getattr_static(thing, 'y')
1307
1308 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1309
1310 def test_inherited(self):
1311 class Thing(object):
1312 x = object()
1313 class OtherThing(Thing):
1314 pass
1315
1316 something = OtherThing()
1317 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1318
1319 def test_instance_attr(self):
1320 class Thing(object):
1321 x = 2
1322 def __init__(self, x):
1323 self.x = x
1324 thing = Thing(3)
1325 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1326 del thing.x
1327 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1328
1329 def test_property(self):
1330 class Thing(object):
1331 @property
1332 def x(self):
1333 raise AttributeError("I'm pretending not to exist")
1334 thing = Thing()
1335 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1336
Ezio Melotti75cbd732011-04-28 00:59:29 +03001337 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001338 class descriptor(object):
1339 def __get__(*_):
1340 raise AttributeError("I'm pretending not to exist")
1341 desc = descriptor()
1342 class Thing(object):
1343 x = desc
1344 thing = Thing()
1345 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1346
1347 def test_classAttribute(self):
1348 class Thing(object):
1349 x = object()
1350
1351 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1352
Ethan Furmane03ea372013-09-25 07:14:41 -07001353 def test_classVirtualAttribute(self):
1354 class Thing(object):
1355 @types.DynamicClassAttribute
1356 def x(self):
1357 return self._x
1358 _x = object()
1359
1360 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1361
Michael Foord95fc51d2010-11-20 15:07:30 +00001362 def test_inherited_classattribute(self):
1363 class Thing(object):
1364 x = object()
1365 class OtherThing(Thing):
1366 pass
1367
1368 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1369
1370 def test_slots(self):
1371 class Thing(object):
1372 y = 'bar'
1373 __slots__ = ['x']
1374 def __init__(self):
1375 self.x = 'foo'
1376 thing = Thing()
1377 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1378 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1379
1380 del thing.x
1381 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1382
1383 def test_metaclass(self):
1384 class meta(type):
1385 attr = 'foo'
1386 class Thing(object, metaclass=meta):
1387 pass
1388 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1389
1390 class sub(meta):
1391 pass
1392 class OtherThing(object, metaclass=sub):
1393 x = 3
1394 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1395
1396 class OtherOtherThing(OtherThing):
1397 pass
1398 # this test is odd, but it was added as it exposed a bug
1399 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1400
1401 def test_no_dict_no_slots(self):
1402 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1403 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1404
1405 def test_no_dict_no_slots_instance_member(self):
1406 # returns descriptor
1407 with open(__file__) as handle:
1408 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1409
1410 def test_inherited_slots(self):
1411 # returns descriptor
1412 class Thing(object):
1413 __slots__ = ['x']
1414 def __init__(self):
1415 self.x = 'foo'
1416
1417 class OtherThing(Thing):
1418 pass
1419 # it would be nice if this worked...
1420 # we get the descriptor instead of the instance attribute
1421 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1422
1423 def test_descriptor(self):
1424 class descriptor(object):
1425 def __get__(self, instance, owner):
1426 return 3
1427 class Foo(object):
1428 d = descriptor()
1429
1430 foo = Foo()
1431
1432 # for a non data descriptor we return the instance attribute
1433 foo.__dict__['d'] = 1
1434 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1435
1436 # if the descriptor is a data-desciptor we should return the
1437 # descriptor
1438 descriptor.__set__ = lambda s, i, v: None
1439 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1440
1441
1442 def test_metaclass_with_descriptor(self):
1443 class descriptor(object):
1444 def __get__(self, instance, owner):
1445 return 3
1446 class meta(type):
1447 d = descriptor()
1448 class Thing(object, metaclass=meta):
1449 pass
1450 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1451
1452
Michael Foordcc7ebb82010-11-20 16:20:16 +00001453 def test_class_as_property(self):
1454 class Base(object):
1455 foo = 3
1456
1457 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001458 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001459 @property
1460 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001461 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001462 return object
1463
Michael Foord35184ed2010-11-20 16:58:30 +00001464 instance = Something()
1465 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1466 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001467 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1468
Michael Foorde5162652010-11-20 16:40:44 +00001469 def test_mro_as_property(self):
1470 class Meta(type):
1471 @property
1472 def __mro__(self):
1473 return (object,)
1474
1475 class Base(object):
1476 foo = 3
1477
1478 class Something(Base, metaclass=Meta):
1479 pass
1480
1481 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1482 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1483
Michael Foorddcebe0f2011-03-15 19:20:44 -04001484 def test_dict_as_property(self):
1485 test = self
1486 test.called = False
1487
1488 class Foo(dict):
1489 a = 3
1490 @property
1491 def __dict__(self):
1492 test.called = True
1493 return {}
1494
1495 foo = Foo()
1496 foo.a = 4
1497 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1498 self.assertFalse(test.called)
1499
1500 def test_custom_object_dict(self):
1501 test = self
1502 test.called = False
1503
1504 class Custom(dict):
1505 def get(self, key, default=None):
1506 test.called = True
1507 super().get(key, default)
1508
1509 class Foo(object):
1510 a = 3
1511 foo = Foo()
1512 foo.__dict__ = Custom()
1513 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1514 self.assertFalse(test.called)
1515
1516 def test_metaclass_dict_as_property(self):
1517 class Meta(type):
1518 @property
1519 def __dict__(self):
1520 self.executed = True
1521
1522 class Thing(metaclass=Meta):
1523 executed = False
1524
1525 def __init__(self):
1526 self.spam = 42
1527
1528 instance = Thing()
1529 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1530 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001531
Michael Foorda51623b2011-12-18 22:01:40 +00001532 def test_module(self):
1533 sentinel = object()
1534 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1535 sentinel)
1536
Michael Foord3ba95f82011-12-22 01:13:37 +00001537 def test_metaclass_with_metaclass_with_dict_as_property(self):
1538 class MetaMeta(type):
1539 @property
1540 def __dict__(self):
1541 self.executed = True
1542 return dict(spam=42)
1543
1544 class Meta(type, metaclass=MetaMeta):
1545 executed = False
1546
1547 class Thing(metaclass=Meta):
1548 pass
1549
1550 with self.assertRaises(AttributeError):
1551 inspect.getattr_static(Thing, "spam")
1552 self.assertFalse(Thing.executed)
1553
Nick Coghlane0f04652010-11-21 03:44:04 +00001554class TestGetGeneratorState(unittest.TestCase):
1555
1556 def setUp(self):
1557 def number_generator():
1558 for number in range(5):
1559 yield number
1560 self.generator = number_generator()
1561
1562 def _generatorstate(self):
1563 return inspect.getgeneratorstate(self.generator)
1564
1565 def test_created(self):
1566 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1567
1568 def test_suspended(self):
1569 next(self.generator)
1570 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1571
1572 def test_closed_after_exhaustion(self):
1573 for i in self.generator:
1574 pass
1575 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1576
1577 def test_closed_after_immediate_exception(self):
1578 with self.assertRaises(RuntimeError):
1579 self.generator.throw(RuntimeError)
1580 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1581
1582 def test_running(self):
1583 # As mentioned on issue #10220, checking for the RUNNING state only
1584 # makes sense inside the generator itself.
1585 # The following generator checks for this by using the closure's
1586 # reference to self and the generator state checking helper method
1587 def running_check_generator():
1588 for number in range(5):
1589 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1590 yield number
1591 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1592 self.generator = running_check_generator()
1593 # Running up to the first yield
1594 next(self.generator)
1595 # Running after the first yield
1596 next(self.generator)
1597
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001598 def test_easy_debugging(self):
1599 # repr() and str() of a generator state should contain the state name
1600 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1601 for name in names:
1602 state = getattr(inspect, name)
1603 self.assertIn(name, repr(state))
1604 self.assertIn(name, str(state))
1605
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001606 def test_getgeneratorlocals(self):
1607 def each(lst, a=None):
1608 b=(1, 2, 3)
1609 for v in lst:
1610 if v == 3:
1611 c = 12
1612 yield v
1613
1614 numbers = each([1, 2, 3])
1615 self.assertEqual(inspect.getgeneratorlocals(numbers),
1616 {'a': None, 'lst': [1, 2, 3]})
1617 next(numbers)
1618 self.assertEqual(inspect.getgeneratorlocals(numbers),
1619 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1620 'b': (1, 2, 3)})
1621 next(numbers)
1622 self.assertEqual(inspect.getgeneratorlocals(numbers),
1623 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1624 'b': (1, 2, 3)})
1625 next(numbers)
1626 self.assertEqual(inspect.getgeneratorlocals(numbers),
1627 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1628 'b': (1, 2, 3), 'c': 12})
1629 try:
1630 next(numbers)
1631 except StopIteration:
1632 pass
1633 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1634
1635 def test_getgeneratorlocals_empty(self):
1636 def yield_one():
1637 yield 1
1638 one = yield_one()
1639 self.assertEqual(inspect.getgeneratorlocals(one), {})
1640 try:
1641 next(one)
1642 except StopIteration:
1643 pass
1644 self.assertEqual(inspect.getgeneratorlocals(one), {})
1645
1646 def test_getgeneratorlocals_error(self):
1647 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1648 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1649 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1650 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1651
Nick Coghlane0f04652010-11-21 03:44:04 +00001652
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001653class MySignature(inspect.Signature):
1654 # Top-level to make it picklable;
1655 # used in test_signature_object_pickle
1656 pass
1657
1658class MyParameter(inspect.Parameter):
1659 # Top-level to make it picklable;
1660 # used in test_signature_object_pickle
1661 pass
1662
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001663
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001664
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001665class TestSignatureObject(unittest.TestCase):
1666 @staticmethod
1667 def signature(func):
1668 sig = inspect.signature(func)
1669 return (tuple((param.name,
1670 (... if param.default is param.empty else param.default),
1671 (... if param.annotation is param.empty
1672 else param.annotation),
1673 str(param.kind).lower())
1674 for param in sig.parameters.values()),
1675 (... if sig.return_annotation is sig.empty
1676 else sig.return_annotation))
1677
1678 def test_signature_object(self):
1679 S = inspect.Signature
1680 P = inspect.Parameter
1681
1682 self.assertEqual(str(S()), '()')
1683
Yury Selivanov07a9e452014-01-29 10:58:16 -05001684 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001685 pass
1686 sig = inspect.signature(test)
1687 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001688 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001689 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001690 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001691 args = sig.parameters['args']
1692 ko = sig.parameters['ko']
1693 kwargs = sig.parameters['kwargs']
1694
1695 S((po, pk, args, ko, kwargs))
1696
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001697 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001698 S((pk, po, args, ko, kwargs))
1699
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001700 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001701 S((po, args, pk, ko, kwargs))
1702
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001703 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001704 S((args, po, pk, ko, kwargs))
1705
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001706 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001707 S((po, pk, args, kwargs, ko))
1708
1709 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001710 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001711 S((po, pk, args, kwargs2, ko))
1712
Yury Selivanov07a9e452014-01-29 10:58:16 -05001713 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1714 S((pod, po))
1715
1716 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1717 S((po, pkd, pk))
1718
1719 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1720 S((pkd, pk))
1721
Yury Selivanov374375d2014-03-27 12:41:53 -04001722 self.assertTrue(repr(sig).startswith('<Signature'))
1723 self.assertTrue('"(po, pk' in repr(sig))
1724
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001725 def test_signature_object_pickle(self):
1726 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
1727 foo_partial = functools.partial(foo, a=1)
1728
1729 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001730
1731 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1732 with self.subTest(pickle_ver=ver, subclass=False):
1733 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
1734 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001735
1736 # Test that basic sub-classing works
1737 sig = inspect.signature(foo)
1738 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
1739 myparams = collections.OrderedDict(sig.parameters, a=myparam)
1740 mysig = MySignature().replace(parameters=myparams.values(),
1741 return_annotation=sig.return_annotation)
1742 self.assertTrue(isinstance(mysig, MySignature))
1743 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
1744
1745 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1746 with self.subTest(pickle_ver=ver, subclass=True):
1747 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
1748 self.assertEqual(mysig, sig_pickled)
1749 self.assertTrue(isinstance(sig_pickled, MySignature))
1750 self.assertTrue(isinstance(sig_pickled.parameters['z'],
1751 MyParameter))
1752
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001753 def test_signature_immutability(self):
1754 def test(a):
1755 pass
1756 sig = inspect.signature(test)
1757
1758 with self.assertRaises(AttributeError):
1759 sig.foo = 'bar'
1760
1761 with self.assertRaises(TypeError):
1762 sig.parameters['a'] = None
1763
1764 def test_signature_on_noarg(self):
1765 def test():
1766 pass
1767 self.assertEqual(self.signature(test), ((), ...))
1768
1769 def test_signature_on_wargs(self):
1770 def test(a, b:'foo') -> 123:
1771 pass
1772 self.assertEqual(self.signature(test),
1773 ((('a', ..., ..., "positional_or_keyword"),
1774 ('b', ..., 'foo', "positional_or_keyword")),
1775 123))
1776
1777 def test_signature_on_wkwonly(self):
1778 def test(*, a:float, b:str) -> int:
1779 pass
1780 self.assertEqual(self.signature(test),
1781 ((('a', ..., float, "keyword_only"),
1782 ('b', ..., str, "keyword_only")),
1783 int))
1784
1785 def test_signature_on_complex_args(self):
1786 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1787 pass
1788 self.assertEqual(self.signature(test),
1789 ((('a', ..., ..., "positional_or_keyword"),
1790 ('b', 10, 'foo', "positional_or_keyword"),
1791 ('args', ..., 'bar', "var_positional"),
1792 ('spam', ..., 'baz', "keyword_only"),
1793 ('ham', 123, ..., "keyword_only"),
1794 ('kwargs', ..., int, "var_keyword")),
1795 ...))
1796
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001797 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001798 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1799 "Signature information for builtins requires docstrings")
1800 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001801 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001802
Larry Hastings5c661892014-01-24 06:17:25 -08001803 def test_unbound_method(o):
1804 """Use this to test unbound methods (things that should have a self)"""
1805 signature = inspect.signature(o)
1806 self.assertTrue(isinstance(signature, inspect.Signature))
1807 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1808 return signature
1809
1810 def test_callable(o):
1811 """Use this to test bound methods or normal callables (things that don't expect self)"""
1812 signature = inspect.signature(o)
1813 self.assertTrue(isinstance(signature, inspect.Signature))
1814 if signature.parameters:
1815 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1816 return signature
1817
1818 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001819 def p(name): return signature.parameters[name].default
1820 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001821 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001822 self.assertEqual(p('d'), 3.14)
1823 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001824 self.assertEqual(p('n'), None)
1825 self.assertEqual(p('t'), True)
1826 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001827 self.assertEqual(p('local'), 3)
1828 self.assertEqual(p('sys'), sys.maxsize)
1829 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001830
Larry Hastings5c661892014-01-24 06:17:25 -08001831 test_callable(object)
1832
1833 # normal method
1834 # (PyMethodDescr_Type, "method_descriptor")
1835 test_unbound_method(_pickle.Pickler.dump)
1836 d = _pickle.Pickler(io.StringIO())
1837 test_callable(d.dump)
1838
1839 # static method
1840 test_callable(str.maketrans)
1841 test_callable('abc'.maketrans)
1842
1843 # class method
1844 test_callable(dict.fromkeys)
1845 test_callable({}.fromkeys)
1846
1847 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1848 test_unbound_method(type.__call__)
1849 test_unbound_method(int.__add__)
1850 test_callable((3).__add__)
1851
1852 # _PyMethodWrapper_Type
1853 # support for 'method-wrapper'
1854 test_callable(min.__call__)
1855
Larry Hastings2623c8c2014-02-08 22:15:29 -08001856 # This doesn't work now.
1857 # (We don't have a valid signature for "type" in 3.4)
1858 with self.assertRaisesRegex(ValueError, "no signature found"):
1859 class ThisWorksNow:
1860 __call__ = type
1861 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08001862
Yury Selivanov056e2652014-03-02 12:25:27 -05001863 # Regression test for issue #20786
1864 test_unbound_method(dict.__delitem__)
1865 test_unbound_method(property.__delete__)
1866
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001867 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05001868 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1869 "Signature information for builtins requires docstrings")
1870 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001871 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05001872 func = _testcapi.docstring_with_signature_with_defaults
1873
1874 def decorator(func):
1875 @functools.wraps(func)
1876 def wrapper(*args, **kwargs) -> int:
1877 return func(*args, **kwargs)
1878 return wrapper
1879
1880 decorated_func = decorator(func)
1881
1882 self.assertEqual(inspect.signature(func),
1883 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08001884
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001885 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08001886 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001887 import _testcapi
Larry Hastings5c661892014-01-24 06:17:25 -08001888 with self.assertRaisesRegex(ValueError, 'no signature found for builtin'):
1889 inspect.signature(_testcapi.docstring_no_signature)
1890
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001891 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001892 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001893 inspect.signature(42)
1894
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001895 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001896 inspect.Signature.from_function(42)
1897
Yury Selivanovb77511d2014-01-29 10:46:14 -05001898 def test_signature_from_builtin_errors(self):
1899 with self.assertRaisesRegex(TypeError, 'is not a Python builtin'):
1900 inspect.Signature.from_builtin(42)
1901
Yury Selivanov63da7c72014-01-31 14:48:37 -05001902 def test_signature_from_functionlike_object(self):
1903 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1904 pass
1905
1906 class funclike:
1907 # Has to be callable, and have correct
1908 # __code__, __annotations__, __defaults__, __name__,
1909 # and __kwdefaults__ attributes
1910
1911 def __init__(self, func):
1912 self.__name__ = func.__name__
1913 self.__code__ = func.__code__
1914 self.__annotations__ = func.__annotations__
1915 self.__defaults__ = func.__defaults__
1916 self.__kwdefaults__ = func.__kwdefaults__
1917 self.func = func
1918
1919 def __call__(self, *args, **kwargs):
1920 return self.func(*args, **kwargs)
1921
1922 sig_func = inspect.Signature.from_function(func)
1923
1924 sig_funclike = inspect.Signature.from_function(funclike(func))
1925 self.assertEqual(sig_funclike, sig_func)
1926
1927 sig_funclike = inspect.signature(funclike(func))
1928 self.assertEqual(sig_funclike, sig_func)
1929
1930 # If object is not a duck type of function, then
1931 # signature will try to get a signature for its '__call__'
1932 # method
1933 fl = funclike(func)
1934 del fl.__defaults__
1935 self.assertEqual(self.signature(fl),
1936 ((('args', ..., ..., "var_positional"),
1937 ('kwargs', ..., ..., "var_keyword")),
1938 ...))
1939
Yury Selivanova773de02014-02-21 18:30:53 -05001940 # Test with cython-like builtins:
1941 _orig_isdesc = inspect.ismethoddescriptor
1942 def _isdesc(obj):
1943 if hasattr(obj, '_builtinmock'):
1944 return True
1945 return _orig_isdesc(obj)
1946
1947 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
1948 builtin_func = funclike(func)
1949 # Make sure that our mock setup is working
1950 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
1951 builtin_func._builtinmock = True
1952 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
1953 self.assertEqual(inspect.signature(builtin_func), sig_func)
1954
Yury Selivanov63da7c72014-01-31 14:48:37 -05001955 def test_signature_functionlike_class(self):
1956 # We only want to duck type function-like objects,
1957 # not classes.
1958
1959 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1960 pass
1961
1962 class funclike:
1963 def __init__(self, marker):
1964 pass
1965
1966 __name__ = func.__name__
1967 __code__ = func.__code__
1968 __annotations__ = func.__annotations__
1969 __defaults__ = func.__defaults__
1970 __kwdefaults__ = func.__kwdefaults__
1971
1972 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1973 inspect.Signature.from_function(funclike)
1974
1975 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
1976
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001977 def test_signature_on_method(self):
1978 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05001979 def __init__(*args):
1980 pass
1981 def m1(self, arg1, arg2=1) -> int:
1982 pass
1983 def m2(*args):
1984 pass
1985 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001986 pass
1987
Yury Selivanov62560fb2014-01-28 12:26:24 -05001988 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001989 ((('arg1', ..., ..., "positional_or_keyword"),
1990 ('arg2', 1, ..., "positional_or_keyword")),
1991 int))
1992
Yury Selivanov62560fb2014-01-28 12:26:24 -05001993 self.assertEqual(self.signature(Test().m2),
1994 ((('args', ..., ..., "var_positional"),),
1995 ...))
1996
1997 self.assertEqual(self.signature(Test),
1998 ((('args', ..., ..., "var_positional"),),
1999 ...))
2000
2001 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2002 self.signature(Test())
2003
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002004 def test_signature_on_classmethod(self):
2005 class Test:
2006 @classmethod
2007 def foo(cls, arg1, *, arg2=1):
2008 pass
2009
2010 meth = Test().foo
2011 self.assertEqual(self.signature(meth),
2012 ((('arg1', ..., ..., "positional_or_keyword"),
2013 ('arg2', 1, ..., "keyword_only")),
2014 ...))
2015
2016 meth = Test.foo
2017 self.assertEqual(self.signature(meth),
2018 ((('arg1', ..., ..., "positional_or_keyword"),
2019 ('arg2', 1, ..., "keyword_only")),
2020 ...))
2021
2022 def test_signature_on_staticmethod(self):
2023 class Test:
2024 @staticmethod
2025 def foo(cls, *, arg):
2026 pass
2027
2028 meth = Test().foo
2029 self.assertEqual(self.signature(meth),
2030 ((('cls', ..., ..., "positional_or_keyword"),
2031 ('arg', ..., ..., "keyword_only")),
2032 ...))
2033
2034 meth = Test.foo
2035 self.assertEqual(self.signature(meth),
2036 ((('cls', ..., ..., "positional_or_keyword"),
2037 ('arg', ..., ..., "keyword_only")),
2038 ...))
2039
2040 def test_signature_on_partial(self):
2041 from functools import partial
2042
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002043 Parameter = inspect.Parameter
2044
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002045 def test():
2046 pass
2047
2048 self.assertEqual(self.signature(partial(test)), ((), ...))
2049
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002050 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002051 inspect.signature(partial(test, 1))
2052
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002053 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002054 inspect.signature(partial(test, a=1))
2055
2056 def test(a, b, *, c, d):
2057 pass
2058
2059 self.assertEqual(self.signature(partial(test)),
2060 ((('a', ..., ..., "positional_or_keyword"),
2061 ('b', ..., ..., "positional_or_keyword"),
2062 ('c', ..., ..., "keyword_only"),
2063 ('d', ..., ..., "keyword_only")),
2064 ...))
2065
2066 self.assertEqual(self.signature(partial(test, 1)),
2067 ((('b', ..., ..., "positional_or_keyword"),
2068 ('c', ..., ..., "keyword_only"),
2069 ('d', ..., ..., "keyword_only")),
2070 ...))
2071
2072 self.assertEqual(self.signature(partial(test, 1, c=2)),
2073 ((('b', ..., ..., "positional_or_keyword"),
2074 ('c', 2, ..., "keyword_only"),
2075 ('d', ..., ..., "keyword_only")),
2076 ...))
2077
2078 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2079 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002080 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002081 ('c', 2, ..., "keyword_only"),
2082 ('d', ..., ..., "keyword_only")),
2083 ...))
2084
2085 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002086 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002087 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002088 ('d', ..., ..., "keyword_only")),
2089 ...))
2090
2091 self.assertEqual(self.signature(partial(test, a=1)),
2092 ((('a', 1, ..., "keyword_only"),
2093 ('b', ..., ..., "keyword_only"),
2094 ('c', ..., ..., "keyword_only"),
2095 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002096 ...))
2097
2098 def test(a, *args, b, **kwargs):
2099 pass
2100
2101 self.assertEqual(self.signature(partial(test, 1)),
2102 ((('args', ..., ..., "var_positional"),
2103 ('b', ..., ..., "keyword_only"),
2104 ('kwargs', ..., ..., "var_keyword")),
2105 ...))
2106
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002107 self.assertEqual(self.signature(partial(test, a=1)),
2108 ((('a', 1, ..., "keyword_only"),
2109 ('b', ..., ..., "keyword_only"),
2110 ('kwargs', ..., ..., "var_keyword")),
2111 ...))
2112
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002113 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2114 ((('args', ..., ..., "var_positional"),
2115 ('b', ..., ..., "keyword_only"),
2116 ('kwargs', ..., ..., "var_keyword")),
2117 ...))
2118
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002119 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2120 ((('args', ..., ..., "var_positional"),
2121 ('b', ..., ..., "keyword_only"),
2122 ('kwargs', ..., ..., "var_keyword")),
2123 ...))
2124
2125 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2126 ((('args', ..., ..., "var_positional"),
2127 ('b', 0, ..., "keyword_only"),
2128 ('kwargs', ..., ..., "var_keyword")),
2129 ...))
2130
2131 self.assertEqual(self.signature(partial(test, b=0)),
2132 ((('a', ..., ..., "positional_or_keyword"),
2133 ('args', ..., ..., "var_positional"),
2134 ('b', 0, ..., "keyword_only"),
2135 ('kwargs', ..., ..., "var_keyword")),
2136 ...))
2137
2138 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2139 ((('a', ..., ..., "positional_or_keyword"),
2140 ('args', ..., ..., "var_positional"),
2141 ('b', 0, ..., "keyword_only"),
2142 ('kwargs', ..., ..., "var_keyword")),
2143 ...))
2144
2145 def test(a, b, c:int) -> 42:
2146 pass
2147
2148 sig = test.__signature__ = inspect.signature(test)
2149
2150 self.assertEqual(self.signature(partial(partial(test, 1))),
2151 ((('b', ..., ..., "positional_or_keyword"),
2152 ('c', ..., int, "positional_or_keyword")),
2153 42))
2154
2155 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2156 ((('c', ..., int, "positional_or_keyword"),),
2157 42))
2158
2159 psig = inspect.signature(partial(partial(test, 1), 2))
2160
2161 def foo(a):
2162 return a
2163 _foo = partial(partial(foo, a=10), a=20)
2164 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002165 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002166 ...))
2167 # check that we don't have any side-effects in signature(),
2168 # and the partial object is still functioning
2169 self.assertEqual(_foo(), 20)
2170
2171 def foo(a, b, c):
2172 return a, b, c
2173 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002174
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002175 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002176 ((('b', 30, ..., "keyword_only"),
2177 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002178 ...))
2179 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002180
2181 def foo(a, b, c, *, d):
2182 return a, b, c, d
2183 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2184 self.assertEqual(self.signature(_foo),
2185 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002186 ('b', 10, ..., "keyword_only"),
2187 ('c', 20, ..., "keyword_only"),
2188 ('d', 30, ..., "keyword_only"),
2189 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002190 ...))
2191 ba = inspect.signature(_foo).bind(a=200, b=11)
2192 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2193
2194 def foo(a=1, b=2, c=3):
2195 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002196 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2197
2198 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002199 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002200
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002201 ba = inspect.signature(_foo).bind(11, 12)
2202 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002203
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002204 ba = inspect.signature(_foo).bind(11, b=12)
2205 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002206
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002207 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002208 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2209
2210 _foo = partial(_foo, b=10, c=20)
2211 ba = inspect.signature(_foo).bind(12)
2212 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2213
2214
2215 def foo(a, b, c, d, **kwargs):
2216 pass
2217 sig = inspect.signature(foo)
2218 params = sig.parameters.copy()
2219 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2220 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2221 foo.__signature__ = inspect.Signature(params.values())
2222 sig = inspect.signature(foo)
2223 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2224
2225 self.assertEqual(self.signature(partial(foo, 1)),
2226 ((('b', ..., ..., 'positional_only'),
2227 ('c', ..., ..., 'positional_or_keyword'),
2228 ('d', ..., ..., 'positional_or_keyword'),
2229 ('kwargs', ..., ..., 'var_keyword')),
2230 ...))
2231
2232 self.assertEqual(self.signature(partial(foo, 1, 2)),
2233 ((('c', ..., ..., 'positional_or_keyword'),
2234 ('d', ..., ..., 'positional_or_keyword'),
2235 ('kwargs', ..., ..., 'var_keyword')),
2236 ...))
2237
2238 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2239 ((('d', ..., ..., 'positional_or_keyword'),
2240 ('kwargs', ..., ..., 'var_keyword')),
2241 ...))
2242
2243 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2244 ((('c', 3, ..., 'keyword_only'),
2245 ('d', ..., ..., 'keyword_only'),
2246 ('kwargs', ..., ..., 'var_keyword')),
2247 ...))
2248
2249 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2250 ((('b', ..., ..., 'positional_only'),
2251 ('c', 3, ..., 'keyword_only'),
2252 ('d', ..., ..., 'keyword_only'),
2253 ('kwargs', ..., ..., 'var_keyword')),
2254 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002255
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002256 def test_signature_on_partialmethod(self):
2257 from functools import partialmethod
2258
2259 class Spam:
2260 def test():
2261 pass
2262 ham = partialmethod(test)
2263
2264 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2265 inspect.signature(Spam.ham)
2266
2267 class Spam:
2268 def test(it, a, *, c) -> 'spam':
2269 pass
2270 ham = partialmethod(test, c=1)
2271
2272 self.assertEqual(self.signature(Spam.ham),
2273 ((('it', ..., ..., 'positional_or_keyword'),
2274 ('a', ..., ..., 'positional_or_keyword'),
2275 ('c', 1, ..., 'keyword_only')),
2276 'spam'))
2277
2278 self.assertEqual(self.signature(Spam().ham),
2279 ((('a', ..., ..., 'positional_or_keyword'),
2280 ('c', 1, ..., 'keyword_only')),
2281 'spam'))
2282
Yury Selivanov0486f812014-01-29 12:18:59 -05002283 def test_signature_on_fake_partialmethod(self):
2284 def foo(a): pass
2285 foo._partialmethod = 'spam'
2286 self.assertEqual(str(inspect.signature(foo)), '(a)')
2287
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002288 def test_signature_on_decorated(self):
2289 import functools
2290
2291 def decorator(func):
2292 @functools.wraps(func)
2293 def wrapper(*args, **kwargs) -> int:
2294 return func(*args, **kwargs)
2295 return wrapper
2296
2297 class Foo:
2298 @decorator
2299 def bar(self, a, b):
2300 pass
2301
2302 self.assertEqual(self.signature(Foo.bar),
2303 ((('self', ..., ..., "positional_or_keyword"),
2304 ('a', ..., ..., "positional_or_keyword"),
2305 ('b', ..., ..., "positional_or_keyword")),
2306 ...))
2307
2308 self.assertEqual(self.signature(Foo().bar),
2309 ((('a', ..., ..., "positional_or_keyword"),
2310 ('b', ..., ..., "positional_or_keyword")),
2311 ...))
2312
2313 # Test that we handle method wrappers correctly
2314 def decorator(func):
2315 @functools.wraps(func)
2316 def wrapper(*args, **kwargs) -> int:
2317 return func(42, *args, **kwargs)
2318 sig = inspect.signature(func)
2319 new_params = tuple(sig.parameters.values())[1:]
2320 wrapper.__signature__ = sig.replace(parameters=new_params)
2321 return wrapper
2322
2323 class Foo:
2324 @decorator
2325 def __call__(self, a, b):
2326 pass
2327
2328 self.assertEqual(self.signature(Foo.__call__),
2329 ((('a', ..., ..., "positional_or_keyword"),
2330 ('b', ..., ..., "positional_or_keyword")),
2331 ...))
2332
2333 self.assertEqual(self.signature(Foo().__call__),
2334 ((('b', ..., ..., "positional_or_keyword"),),
2335 ...))
2336
Nick Coghlane8c45d62013-07-28 20:00:01 +10002337 # Test we handle __signature__ partway down the wrapper stack
2338 def wrapped_foo_call():
2339 pass
2340 wrapped_foo_call.__wrapped__ = Foo.__call__
2341
2342 self.assertEqual(self.signature(wrapped_foo_call),
2343 ((('a', ..., ..., "positional_or_keyword"),
2344 ('b', ..., ..., "positional_or_keyword")),
2345 ...))
2346
2347
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002348 def test_signature_on_class(self):
2349 class C:
2350 def __init__(self, a):
2351 pass
2352
2353 self.assertEqual(self.signature(C),
2354 ((('a', ..., ..., "positional_or_keyword"),),
2355 ...))
2356
2357 class CM(type):
2358 def __call__(cls, a):
2359 pass
2360 class C(metaclass=CM):
2361 def __init__(self, b):
2362 pass
2363
2364 self.assertEqual(self.signature(C),
2365 ((('a', ..., ..., "positional_or_keyword"),),
2366 ...))
2367
2368 class CM(type):
2369 def __new__(mcls, name, bases, dct, *, foo=1):
2370 return super().__new__(mcls, name, bases, dct)
2371 class C(metaclass=CM):
2372 def __init__(self, b):
2373 pass
2374
2375 self.assertEqual(self.signature(C),
2376 ((('b', ..., ..., "positional_or_keyword"),),
2377 ...))
2378
2379 self.assertEqual(self.signature(CM),
2380 ((('name', ..., ..., "positional_or_keyword"),
2381 ('bases', ..., ..., "positional_or_keyword"),
2382 ('dct', ..., ..., "positional_or_keyword"),
2383 ('foo', 1, ..., "keyword_only")),
2384 ...))
2385
2386 class CMM(type):
2387 def __new__(mcls, name, bases, dct, *, foo=1):
2388 return super().__new__(mcls, name, bases, dct)
2389 def __call__(cls, nm, bs, dt):
2390 return type(nm, bs, dt)
2391 class CM(type, metaclass=CMM):
2392 def __new__(mcls, name, bases, dct, *, bar=2):
2393 return super().__new__(mcls, name, bases, dct)
2394 class C(metaclass=CM):
2395 def __init__(self, b):
2396 pass
2397
2398 self.assertEqual(self.signature(CMM),
2399 ((('name', ..., ..., "positional_or_keyword"),
2400 ('bases', ..., ..., "positional_or_keyword"),
2401 ('dct', ..., ..., "positional_or_keyword"),
2402 ('foo', 1, ..., "keyword_only")),
2403 ...))
2404
2405 self.assertEqual(self.signature(CM),
2406 ((('nm', ..., ..., "positional_or_keyword"),
2407 ('bs', ..., ..., "positional_or_keyword"),
2408 ('dt', ..., ..., "positional_or_keyword")),
2409 ...))
2410
2411 self.assertEqual(self.signature(C),
2412 ((('b', ..., ..., "positional_or_keyword"),),
2413 ...))
2414
2415 class CM(type):
2416 def __init__(cls, name, bases, dct, *, bar=2):
2417 return super().__init__(name, bases, dct)
2418 class C(metaclass=CM):
2419 def __init__(self, b):
2420 pass
2421
2422 self.assertEqual(self.signature(CM),
2423 ((('name', ..., ..., "positional_or_keyword"),
2424 ('bases', ..., ..., "positional_or_keyword"),
2425 ('dct', ..., ..., "positional_or_keyword"),
2426 ('bar', 2, ..., "keyword_only")),
2427 ...))
2428
Yury Selivanov145dff82014-02-01 13:49:29 -05002429 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2430 "Signature information for builtins requires docstrings")
2431 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002432 # Test classes without user-defined __init__ or __new__
2433 class C: pass
2434 self.assertEqual(str(inspect.signature(C)), '()')
2435 class D(C): pass
2436 self.assertEqual(str(inspect.signature(D)), '()')
2437
2438 # Test meta-classes without user-defined __init__ or __new__
2439 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002440 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002441 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2442 self.assertEqual(inspect.signature(C), None)
2443 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2444 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002445
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002446 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2447 "Signature information for builtins requires docstrings")
2448 def test_signature_on_builtin_class(self):
2449 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2450 '(file, protocol=None, fix_imports=True)')
2451
2452 class P(_pickle.Pickler): pass
2453 class EmptyTrait: pass
2454 class P2(EmptyTrait, P): pass
2455 self.assertEqual(str(inspect.signature(P)),
2456 '(file, protocol=None, fix_imports=True)')
2457 self.assertEqual(str(inspect.signature(P2)),
2458 '(file, protocol=None, fix_imports=True)')
2459
2460 class P3(P2):
2461 def __init__(self, spam):
2462 pass
2463 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2464
2465 class MetaP(type):
2466 def __call__(cls, foo, bar):
2467 pass
2468 class P4(P2, metaclass=MetaP):
2469 pass
2470 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2471
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002472 def test_signature_on_callable_objects(self):
2473 class Foo:
2474 def __call__(self, a):
2475 pass
2476
2477 self.assertEqual(self.signature(Foo()),
2478 ((('a', ..., ..., "positional_or_keyword"),),
2479 ...))
2480
2481 class Spam:
2482 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002483 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002484 inspect.signature(Spam())
2485
2486 class Bar(Spam, Foo):
2487 pass
2488
2489 self.assertEqual(self.signature(Bar()),
2490 ((('a', ..., ..., "positional_or_keyword"),),
2491 ...))
2492
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002493 class Wrapped:
2494 pass
2495 Wrapped.__wrapped__ = lambda a: None
2496 self.assertEqual(self.signature(Wrapped),
2497 ((('a', ..., ..., "positional_or_keyword"),),
2498 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002499 # wrapper loop:
2500 Wrapped.__wrapped__ = Wrapped
2501 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2502 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002503
2504 def test_signature_on_lambdas(self):
2505 self.assertEqual(self.signature((lambda a=10: a)),
2506 ((('a', 10, ..., "positional_or_keyword"),),
2507 ...))
2508
2509 def test_signature_equality(self):
2510 def foo(a, *, b:int) -> float: pass
2511 self.assertNotEqual(inspect.signature(foo), 42)
2512
2513 def bar(a, *, b:int) -> float: pass
2514 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002515 self.assertEqual(
2516 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002517
2518 def bar(a, *, b:int) -> int: pass
2519 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002520 self.assertNotEqual(
2521 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002522
2523 def bar(a, *, b:int): pass
2524 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002525 self.assertNotEqual(
2526 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002527
2528 def bar(a, *, b:int=42) -> float: pass
2529 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002530 self.assertNotEqual(
2531 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002532
2533 def bar(a, *, c) -> float: pass
2534 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002535 self.assertNotEqual(
2536 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002537
2538 def bar(a, b:int) -> float: pass
2539 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002540 self.assertNotEqual(
2541 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002542 def spam(b:int, a) -> float: pass
2543 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002544 self.assertNotEqual(
2545 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002546
2547 def foo(*, a, b, c): pass
2548 def bar(*, c, b, a): pass
2549 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002550 self.assertEqual(
2551 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002552
2553 def foo(*, a=1, b, c): pass
2554 def bar(*, c, b, a=1): pass
2555 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002556 self.assertEqual(
2557 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002558
2559 def foo(pos, *, a=1, b, c): pass
2560 def bar(pos, *, c, b, a=1): pass
2561 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002562 self.assertEqual(
2563 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002564
2565 def foo(pos, *, a, b, c): pass
2566 def bar(pos, *, c, b, a=1): pass
2567 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002568 self.assertNotEqual(
2569 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002570
2571 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2572 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2573 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002574 self.assertEqual(
2575 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002576
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002577 def test_signature_hashable(self):
2578 S = inspect.Signature
2579 P = inspect.Parameter
2580
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002581 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002582 foo_sig = inspect.signature(foo)
2583
2584 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2585
2586 self.assertEqual(hash(foo_sig), hash(manual_sig))
2587 self.assertNotEqual(hash(foo_sig),
2588 hash(manual_sig.replace(return_annotation='spam')))
2589
2590 def bar(a) -> 1: pass
2591 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2592
2593 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002594 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002595 hash(inspect.signature(foo))
2596
2597 def foo(a) -> {}: pass
2598 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2599 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002600
2601 def test_signature_str(self):
2602 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2603 pass
2604 self.assertEqual(str(inspect.signature(foo)),
2605 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2606
2607 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2608 pass
2609 self.assertEqual(str(inspect.signature(foo)),
2610 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2611
2612 def foo():
2613 pass
2614 self.assertEqual(str(inspect.signature(foo)), '()')
2615
2616 def test_signature_str_positional_only(self):
2617 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002618 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002619
2620 def test(a_po, *, b, **kwargs):
2621 return a_po, kwargs
2622
2623 sig = inspect.signature(test)
2624 new_params = list(sig.parameters.values())
2625 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2626 test.__signature__ = sig.replace(parameters=new_params)
2627
2628 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002629 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002630
Yury Selivanov2393dca2014-01-27 15:07:58 -05002631 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2632 '(foo, /)')
2633
2634 self.assertEqual(str(S(parameters=[
2635 P('foo', P.POSITIONAL_ONLY),
2636 P('bar', P.VAR_KEYWORD)])),
2637 '(foo, /, **bar)')
2638
2639 self.assertEqual(str(S(parameters=[
2640 P('foo', P.POSITIONAL_ONLY),
2641 P('bar', P.VAR_POSITIONAL)])),
2642 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002643
2644 def test_signature_replace_anno(self):
2645 def test() -> 42:
2646 pass
2647
2648 sig = inspect.signature(test)
2649 sig = sig.replace(return_annotation=None)
2650 self.assertIs(sig.return_annotation, None)
2651 sig = sig.replace(return_annotation=sig.empty)
2652 self.assertIs(sig.return_annotation, sig.empty)
2653 sig = sig.replace(return_annotation=42)
2654 self.assertEqual(sig.return_annotation, 42)
2655 self.assertEqual(sig, inspect.signature(test))
2656
Yury Selivanov34ce99f2014-02-18 12:49:41 -05002657 def test_signature_on_mangled_parameters(self):
2658 class Spam:
2659 def foo(self, __p1:1=2, *, __p2:2=3):
2660 pass
2661 class Ham(Spam):
2662 pass
2663
2664 self.assertEqual(self.signature(Spam.foo),
2665 ((('self', ..., ..., "positional_or_keyword"),
2666 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2667 ('_Spam__p2', 3, 2, "keyword_only")),
2668 ...))
2669
2670 self.assertEqual(self.signature(Spam.foo),
2671 self.signature(Ham.foo))
2672
Yury Selivanovda396452014-03-27 12:09:24 -04002673 def test_signature_from_callable_python_obj(self):
2674 class MySignature(inspect.Signature): pass
2675 def foo(a, *, b:1): pass
2676 foo_sig = MySignature.from_callable(foo)
2677 self.assertTrue(isinstance(foo_sig, MySignature))
2678
2679 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2680 "Signature information for builtins requires docstrings")
2681 def test_signature_from_callable_builtin_obj(self):
2682 class MySignature(inspect.Signature): pass
2683 sig = MySignature.from_callable(_pickle.Pickler)
2684 self.assertTrue(isinstance(sig, MySignature))
2685
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002686
2687class TestParameterObject(unittest.TestCase):
2688 def test_signature_parameter_kinds(self):
2689 P = inspect.Parameter
2690 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2691 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2692
2693 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2694 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2695
2696 def test_signature_parameter_object(self):
2697 p = inspect.Parameter('foo', default=10,
2698 kind=inspect.Parameter.POSITIONAL_ONLY)
2699 self.assertEqual(p.name, 'foo')
2700 self.assertEqual(p.default, 10)
2701 self.assertIs(p.annotation, p.empty)
2702 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2703
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002704 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002705 inspect.Parameter('foo', default=10, kind='123')
2706
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002707 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002708 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2709
Yury Selivanov2393dca2014-01-27 15:07:58 -05002710 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002711 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2712
Yury Selivanov2393dca2014-01-27 15:07:58 -05002713 with self.assertRaisesRegex(ValueError,
2714 'is not a valid parameter name'):
2715 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2716
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002717 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002718 inspect.Parameter('a', default=42,
2719 kind=inspect.Parameter.VAR_KEYWORD)
2720
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002721 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002722 inspect.Parameter('a', default=42,
2723 kind=inspect.Parameter.VAR_POSITIONAL)
2724
2725 p = inspect.Parameter('a', default=42,
2726 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002727 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002728 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2729
2730 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04002731 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002732
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002733 def test_signature_parameter_hashable(self):
2734 P = inspect.Parameter
2735 foo = P('foo', kind=P.POSITIONAL_ONLY)
2736 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
2737 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
2738 default=42)))
2739 self.assertNotEqual(hash(foo),
2740 hash(foo.replace(kind=P.VAR_POSITIONAL)))
2741
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002742 def test_signature_parameter_equality(self):
2743 P = inspect.Parameter
2744 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2745
2746 self.assertEqual(p, p)
2747 self.assertNotEqual(p, 42)
2748
2749 self.assertEqual(p, P('foo', default=42,
2750 kind=inspect.Parameter.KEYWORD_ONLY))
2751
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002752 def test_signature_parameter_replace(self):
2753 p = inspect.Parameter('foo', default=42,
2754 kind=inspect.Parameter.KEYWORD_ONLY)
2755
2756 self.assertIsNot(p, p.replace())
2757 self.assertEqual(p, p.replace())
2758
2759 p2 = p.replace(annotation=1)
2760 self.assertEqual(p2.annotation, 1)
2761 p2 = p2.replace(annotation=p2.empty)
2762 self.assertEqual(p, p2)
2763
2764 p2 = p2.replace(name='bar')
2765 self.assertEqual(p2.name, 'bar')
2766 self.assertNotEqual(p2, p)
2767
Yury Selivanov2393dca2014-01-27 15:07:58 -05002768 with self.assertRaisesRegex(ValueError,
2769 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002770 p2 = p2.replace(name=p2.empty)
2771
2772 p2 = p2.replace(name='foo', default=None)
2773 self.assertIs(p2.default, None)
2774 self.assertNotEqual(p2, p)
2775
2776 p2 = p2.replace(name='foo', default=p2.empty)
2777 self.assertIs(p2.default, p2.empty)
2778
2779
2780 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2781 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2782 self.assertNotEqual(p2, p)
2783
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002784 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002785 p2 = p2.replace(kind=p2.empty)
2786
2787 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2788 self.assertEqual(p2, p)
2789
2790 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002791 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2792 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002793
2794 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002795 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002796
2797 with self.assertRaises(AttributeError):
2798 p.foo = 'bar'
2799
2800 with self.assertRaises(AttributeError):
2801 p.kind = 123
2802
2803
2804class TestSignatureBind(unittest.TestCase):
2805 @staticmethod
2806 def call(func, *args, **kwargs):
2807 sig = inspect.signature(func)
2808 ba = sig.bind(*args, **kwargs)
2809 return func(*ba.args, **ba.kwargs)
2810
2811 def test_signature_bind_empty(self):
2812 def test():
2813 return 42
2814
2815 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002816 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002817 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002818 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002819 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002820 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002821 self.call(test, spam=1)
2822
2823 def test_signature_bind_var(self):
2824 def test(*args, **kwargs):
2825 return args, kwargs
2826
2827 self.assertEqual(self.call(test), ((), {}))
2828 self.assertEqual(self.call(test, 1), ((1,), {}))
2829 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2830 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2831 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2832 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2833 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2834 ((1, 2), {'foo': 'bar'}))
2835
2836 def test_signature_bind_just_args(self):
2837 def test(a, b, c):
2838 return a, b, c
2839
2840 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2841
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002842 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002843 self.call(test, 1, 2, 3, 4)
2844
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002845 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002846 self.call(test, 1)
2847
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002848 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002849 self.call(test)
2850
2851 def test(a, b, c=10):
2852 return a, b, c
2853 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2854 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2855
2856 def test(a=1, b=2, c=3):
2857 return a, b, c
2858 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2859 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2860 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2861
2862 def test_signature_bind_varargs_order(self):
2863 def test(*args):
2864 return args
2865
2866 self.assertEqual(self.call(test), ())
2867 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2868
2869 def test_signature_bind_args_and_varargs(self):
2870 def test(a, b, c=3, *args):
2871 return a, b, c, args
2872
2873 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2874 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2875 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2876 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2877
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002878 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002879 "multiple values for argument 'c'"):
2880 self.call(test, 1, 2, 3, c=4)
2881
2882 def test_signature_bind_just_kwargs(self):
2883 def test(**kwargs):
2884 return kwargs
2885
2886 self.assertEqual(self.call(test), {})
2887 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2888 {'foo': 'bar', 'spam': 'ham'})
2889
2890 def test_signature_bind_args_and_kwargs(self):
2891 def test(a, b, c=3, **kwargs):
2892 return a, b, c, kwargs
2893
2894 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2895 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2896 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2897 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2898 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2899 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2900 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2901 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2902 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2903 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2904 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2905 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2906 (1, 2, 4, {'foo': 'bar'}))
2907 self.assertEqual(self.call(test, c=5, a=4, b=3),
2908 (4, 3, 5, {}))
2909
2910 def test_signature_bind_kwonly(self):
2911 def test(*, foo):
2912 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002913 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002914 'too many positional arguments'):
2915 self.call(test, 1)
2916 self.assertEqual(self.call(test, foo=1), 1)
2917
2918 def test(a, *, foo=1, bar):
2919 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002920 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002921 "'bar' parameter lacking default value"):
2922 self.call(test, 1)
2923
2924 def test(foo, *, bar):
2925 return foo, bar
2926 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2927 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2928
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002929 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002930 'too many keyword arguments'):
2931 self.call(test, bar=2, foo=1, spam=10)
2932
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002933 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002934 'too many positional arguments'):
2935 self.call(test, 1, 2)
2936
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002937 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002938 'too many positional arguments'):
2939 self.call(test, 1, 2, bar=2)
2940
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002941 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002942 'too many keyword arguments'):
2943 self.call(test, 1, bar=2, spam='ham')
2944
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002945 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002946 "'bar' parameter lacking default value"):
2947 self.call(test, 1)
2948
2949 def test(foo, *, bar, **bin):
2950 return foo, bar, bin
2951 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2952 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2953 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2954 (1, 2, {'spam': 'ham'}))
2955 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2956 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002957 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002958 "'foo' parameter lacking default value"):
2959 self.call(test, spam='ham', bar=2)
2960 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2961 (1, 2, {'bin': 1, 'spam': 10}))
2962
2963 def test_signature_bind_arguments(self):
2964 def test(a, *args, b, z=100, **kwargs):
2965 pass
2966 sig = inspect.signature(test)
2967 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2968 # we won't have 'z' argument in the bound arguments object, as we didn't
2969 # pass it to the 'bind'
2970 self.assertEqual(tuple(ba.arguments.items()),
2971 (('a', 10), ('args', (20,)), ('b', 30),
2972 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2973 self.assertEqual(ba.kwargs,
2974 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2975 self.assertEqual(ba.args, (10, 20))
2976
2977 def test_signature_bind_positional_only(self):
2978 P = inspect.Parameter
2979
2980 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2981 return a_po, b_po, c_po, foo, bar, kwargs
2982
2983 sig = inspect.signature(test)
2984 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2985 for name in ('a_po', 'b_po', 'c_po'):
2986 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2987 new_sig = sig.replace(parameters=new_params.values())
2988 test.__signature__ = new_sig
2989
2990 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2991 (1, 2, 4, 5, 6, {}))
2992
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002993 self.assertEqual(self.call(test, 1, 2),
2994 (1, 2, 3, 42, 50, {}))
2995
2996 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
2997 (1, 2, 3, 4, 5, {}))
2998
2999 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3000 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3001
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003002 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003003 self.call(test, 1, 2, c_po=4)
3004
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003005 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003006 self.call(test, a_po=1, b_po=2)
3007
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003008 def test_signature_bind_with_self_arg(self):
3009 # Issue #17071: one of the parameters is named "self
3010 def test(a, self, b):
3011 pass
3012 sig = inspect.signature(test)
3013 ba = sig.bind(1, 2, 3)
3014 self.assertEqual(ba.args, (1, 2, 3))
3015 ba = sig.bind(1, self=2, b=3)
3016 self.assertEqual(ba.args, (1, 2, 3))
3017
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003018 def test_signature_bind_vararg_name(self):
3019 def test(a, *args):
3020 return a, args
3021 sig = inspect.signature(test)
3022
3023 with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
3024 sig.bind(a=0, args=1)
3025
3026 def test(*args, **kwargs):
3027 return args, kwargs
3028 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3029
3030 sig = inspect.signature(test)
3031 ba = sig.bind(args=1)
3032 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3033
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003034
3035class TestBoundArguments(unittest.TestCase):
3036 def test_signature_bound_arguments_unhashable(self):
3037 def foo(a): pass
3038 ba = inspect.signature(foo).bind(1)
3039
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003040 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003041 hash(ba)
3042
3043 def test_signature_bound_arguments_equality(self):
3044 def foo(a): pass
3045 ba = inspect.signature(foo).bind(1)
3046 self.assertEqual(ba, ba)
3047
3048 ba2 = inspect.signature(foo).bind(1)
3049 self.assertEqual(ba, ba2)
3050
3051 ba3 = inspect.signature(foo).bind(2)
3052 self.assertNotEqual(ba, ba3)
3053 ba3.arguments['a'] = 1
3054 self.assertEqual(ba, ba3)
3055
3056 def bar(b): pass
3057 ba4 = inspect.signature(bar).bind(1)
3058 self.assertNotEqual(ba, ba4)
3059
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003060 def test_signature_bound_arguments_pickle(self):
3061 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3062 sig = inspect.signature(foo)
3063 ba = sig.bind(20, 30, z={})
3064
3065 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3066 with self.subTest(pickle_ver=ver):
3067 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3068 self.assertEqual(ba, ba_pickled)
3069
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003070
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003071class TestSignaturePrivateHelpers(unittest.TestCase):
3072 def test_signature_get_bound_param(self):
3073 getter = inspect._signature_get_bound_param
3074
3075 self.assertEqual(getter('($self)'), 'self')
3076 self.assertEqual(getter('($self, obj)'), 'self')
3077 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3078
Larry Hastings2623c8c2014-02-08 22:15:29 -08003079 def _strip_non_python_syntax(self, input,
3080 clean_signature, self_parameter, last_positional_only):
3081 computed_clean_signature, \
3082 computed_self_parameter, \
3083 computed_last_positional_only = \
3084 inspect._signature_strip_non_python_syntax(input)
3085 self.assertEqual(computed_clean_signature, clean_signature)
3086 self.assertEqual(computed_self_parameter, self_parameter)
3087 self.assertEqual(computed_last_positional_only, last_positional_only)
3088
3089 def test_signature_strip_non_python_syntax(self):
3090 self._strip_non_python_syntax(
3091 "($module, /, path, mode, *, dir_fd=None, " +
3092 "effective_ids=False,\n follow_symlinks=True)",
3093 "(module, path, mode, *, dir_fd=None, " +
3094 "effective_ids=False, follow_symlinks=True)",
3095 0,
3096 0)
3097
3098 self._strip_non_python_syntax(
3099 "($module, word, salt, /)",
3100 "(module, word, salt)",
3101 0,
3102 2)
3103
3104 self._strip_non_python_syntax(
3105 "(x, y=None, z=None, /)",
3106 "(x, y=None, z=None)",
3107 None,
3108 2)
3109
3110 self._strip_non_python_syntax(
3111 "(x, y=None, z=None)",
3112 "(x, y=None, z=None)",
3113 None,
3114 None)
3115
3116 self._strip_non_python_syntax(
3117 "(x,\n y=None,\n z = None )",
3118 "(x, y=None, z=None)",
3119 None,
3120 None)
3121
3122 self._strip_non_python_syntax(
3123 "",
3124 "",
3125 None,
3126 None)
3127
3128 self._strip_non_python_syntax(
3129 None,
3130 None,
3131 None,
3132 None)
3133
Nick Coghlan9c680b02015-04-13 12:54:54 -04003134class TestSignatureDefinitions(unittest.TestCase):
3135 # This test case provides a home for checking that particular APIs
3136 # have signatures available for introspection
3137
3138 @cpython_only
3139 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3140 "Signature information for builtins requires docstrings")
3141 def test_builtins_have_signatures(self):
3142 # This checks all builtin callables in CPython have signatures
3143 # A few have signatures Signature can't yet handle, so we skip those
3144 # since they will have to wait until PEP 457 adds the required
3145 # introspection support to the inspect module
3146 # Some others also haven't been converted yet for various other
3147 # reasons, so we also skip those for the time being, but design
3148 # the test to fail in order to indicate when it needs to be
3149 # updated.
3150 no_signature = set()
3151 # These need PEP 457 groups
3152 needs_groups = {"range", "slice", "dir", "getattr",
3153 "next", "iter", "vars"}
3154 no_signature |= needs_groups
3155 # These need PEP 457 groups or a signature change to accept None
3156 needs_semantic_update = {"round"}
3157 no_signature |= needs_semantic_update
3158 # These need *args support in Argument Clinic
3159 needs_varargs = {"min", "max", "print", "__build_class__"}
3160 no_signature |= needs_varargs
3161 # These simply weren't covered in the initial AC conversion
3162 # for builtin callables
3163 not_converted_yet = {"open", "__import__"}
3164 no_signature |= not_converted_yet
3165 # These builtin types are expected to provide introspection info
3166 types_with_signatures = set()
3167 # Check the signatures we expect to be there
3168 ns = vars(builtins)
3169 for name, obj in sorted(ns.items()):
3170 if not callable(obj):
3171 continue
3172 # The builtin types haven't been converted to AC yet
3173 if isinstance(obj, type) and (name not in types_with_signatures):
3174 # Note that this also skips all the exception types
3175 no_signature.add(name)
3176 if (name in no_signature):
3177 # Not yet converted
3178 continue
3179 with self.subTest(builtin=name):
3180 self.assertIsNotNone(inspect.signature(obj))
3181 # Check callables that haven't been converted don't claim a signature
3182 # This ensures this test will start failing as more signatures are
3183 # added, so the affected items can be moved into the scope of the
3184 # regression test above
3185 for name in no_signature:
3186 with self.subTest(builtin=name):
3187 self.assertIsNone(obj.__text_signature__)
3188
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003189
Nick Coghlane8c45d62013-07-28 20:00:01 +10003190class TestUnwrap(unittest.TestCase):
3191
3192 def test_unwrap_one(self):
3193 def func(a, b):
3194 return a + b
3195 wrapper = functools.lru_cache(maxsize=20)(func)
3196 self.assertIs(inspect.unwrap(wrapper), func)
3197
3198 def test_unwrap_several(self):
3199 def func(a, b):
3200 return a + b
3201 wrapper = func
3202 for __ in range(10):
3203 @functools.wraps(wrapper)
3204 def wrapper():
3205 pass
3206 self.assertIsNot(wrapper.__wrapped__, func)
3207 self.assertIs(inspect.unwrap(wrapper), func)
3208
3209 def test_stop(self):
3210 def func1(a, b):
3211 return a + b
3212 @functools.wraps(func1)
3213 def func2():
3214 pass
3215 @functools.wraps(func2)
3216 def wrapper():
3217 pass
3218 func2.stop_here = 1
3219 unwrapped = inspect.unwrap(wrapper,
3220 stop=(lambda f: hasattr(f, "stop_here")))
3221 self.assertIs(unwrapped, func2)
3222
3223 def test_cycle(self):
3224 def func1(): pass
3225 func1.__wrapped__ = func1
3226 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3227 inspect.unwrap(func1)
3228
3229 def func2(): pass
3230 func2.__wrapped__ = func1
3231 func1.__wrapped__ = func2
3232 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3233 inspect.unwrap(func1)
3234 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3235 inspect.unwrap(func2)
3236
3237 def test_unhashable(self):
3238 def func(): pass
3239 func.__wrapped__ = None
3240 class C:
3241 __hash__ = None
3242 __wrapped__ = func
3243 self.assertIsNone(inspect.unwrap(C()))
3244
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003245class TestMain(unittest.TestCase):
3246 def test_only_source(self):
3247 module = importlib.import_module('unittest')
3248 rc, out, err = assert_python_ok('-m', 'inspect',
3249 'unittest')
3250 lines = out.decode().splitlines()
3251 # ignore the final newline
3252 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3253 self.assertEqual(err, b'')
3254
Yury Selivanov42407ab2014-06-23 10:23:50 -07003255 def test_custom_getattr(self):
3256 def foo():
3257 pass
3258 foo.__signature__ = 42
3259 with self.assertRaises(TypeError):
3260 inspect.signature(foo)
3261
Brett Cannon634a8fc2013-10-02 10:25:42 -04003262 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003263 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003264 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003265 rc, out, err = assert_python_ok('-m', 'inspect',
3266 'concurrent.futures:ThreadPoolExecutor')
3267 lines = out.decode().splitlines()
3268 # ignore the final newline
3269 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003270 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003271 self.assertEqual(err, b'')
3272
3273 def test_builtins(self):
3274 module = importlib.import_module('unittest')
3275 _, out, err = assert_python_failure('-m', 'inspect',
3276 'sys')
3277 lines = err.decode().splitlines()
3278 self.assertEqual(lines, ["Can't get info for builtin modules."])
3279
3280 def test_details(self):
3281 module = importlib.import_module('unittest')
3282 rc, out, err = assert_python_ok('-m', 'inspect',
3283 'unittest', '--details')
3284 output = out.decode()
3285 # Just a quick sanity check on the output
3286 self.assertIn(module.__name__, output)
3287 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02003288 if not sys.flags.optimize:
3289 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003290 self.assertEqual(err, b'')
3291
3292
Yury Selivanovef1e7502014-12-08 16:05:34 -05003293class TestReload(unittest.TestCase):
3294
3295 src_before = textwrap.dedent("""\
3296def foo():
3297 print("Bla")
3298 """)
3299
3300 src_after = textwrap.dedent("""\
3301def foo():
3302 print("Oh no!")
3303 """)
3304
3305 def assertInspectEqual(self, path, source):
3306 inspected_src = inspect.getsource(source)
3307 with open(path) as src:
3308 self.assertEqual(
3309 src.read().splitlines(True),
3310 inspected_src.splitlines(True)
3311 )
3312
3313 def test_getsource_reload(self):
3314 # see issue 1218234
3315 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3316 module = importlib.import_module(name)
3317 self.assertInspectEqual(path, module)
3318 with open(path, 'w') as src:
3319 src.write(self.src_after)
3320 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003321
Nick Coghlane8c45d62013-07-28 20:00:01 +10003322
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003323def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003324 run_unittest(
3325 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3326 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3327 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003328 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003329 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003330 TestBoundArguments, TestSignaturePrivateHelpers,
3331 TestSignatureDefinitions,
3332 TestGetClosureVars, TestUnwrap, TestMain, TestReload
Michael Foord95fc51d2010-11-20 15:07:30 +00003333 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003334
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003335if __name__ == "__main__":
3336 test_main()