blob: 76f2b47401218e8b43329b3ccf216d34ef826c6b [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 Storchaka5cf2b7252015-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 Storchaka5cf2b7252015-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
Zachary Ware8ef887c2015-04-13 18:22:35 -05001867 # Regression test for issue #20586
1868 test_callable(_testcapi.docstring_with_signature_but_no_doc)
1869
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001870 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05001871 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1872 "Signature information for builtins requires docstrings")
1873 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001874 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05001875 func = _testcapi.docstring_with_signature_with_defaults
1876
1877 def decorator(func):
1878 @functools.wraps(func)
1879 def wrapper(*args, **kwargs) -> int:
1880 return func(*args, **kwargs)
1881 return wrapper
1882
1883 decorated_func = decorator(func)
1884
1885 self.assertEqual(inspect.signature(func),
1886 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08001887
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001888 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08001889 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001890 import _testcapi
Larry Hastings5c661892014-01-24 06:17:25 -08001891 with self.assertRaisesRegex(ValueError, 'no signature found for builtin'):
1892 inspect.signature(_testcapi.docstring_no_signature)
1893
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001894 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001895 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001896 inspect.signature(42)
1897
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001898 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001899 inspect.Signature.from_function(42)
1900
Yury Selivanovb77511d2014-01-29 10:46:14 -05001901 def test_signature_from_builtin_errors(self):
1902 with self.assertRaisesRegex(TypeError, 'is not a Python builtin'):
1903 inspect.Signature.from_builtin(42)
1904
Yury Selivanov63da7c72014-01-31 14:48:37 -05001905 def test_signature_from_functionlike_object(self):
1906 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1907 pass
1908
1909 class funclike:
1910 # Has to be callable, and have correct
1911 # __code__, __annotations__, __defaults__, __name__,
1912 # and __kwdefaults__ attributes
1913
1914 def __init__(self, func):
1915 self.__name__ = func.__name__
1916 self.__code__ = func.__code__
1917 self.__annotations__ = func.__annotations__
1918 self.__defaults__ = func.__defaults__
1919 self.__kwdefaults__ = func.__kwdefaults__
1920 self.func = func
1921
1922 def __call__(self, *args, **kwargs):
1923 return self.func(*args, **kwargs)
1924
1925 sig_func = inspect.Signature.from_function(func)
1926
1927 sig_funclike = inspect.Signature.from_function(funclike(func))
1928 self.assertEqual(sig_funclike, sig_func)
1929
1930 sig_funclike = inspect.signature(funclike(func))
1931 self.assertEqual(sig_funclike, sig_func)
1932
1933 # If object is not a duck type of function, then
1934 # signature will try to get a signature for its '__call__'
1935 # method
1936 fl = funclike(func)
1937 del fl.__defaults__
1938 self.assertEqual(self.signature(fl),
1939 ((('args', ..., ..., "var_positional"),
1940 ('kwargs', ..., ..., "var_keyword")),
1941 ...))
1942
Yury Selivanova773de02014-02-21 18:30:53 -05001943 # Test with cython-like builtins:
1944 _orig_isdesc = inspect.ismethoddescriptor
1945 def _isdesc(obj):
1946 if hasattr(obj, '_builtinmock'):
1947 return True
1948 return _orig_isdesc(obj)
1949
1950 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
1951 builtin_func = funclike(func)
1952 # Make sure that our mock setup is working
1953 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
1954 builtin_func._builtinmock = True
1955 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
1956 self.assertEqual(inspect.signature(builtin_func), sig_func)
1957
Yury Selivanov63da7c72014-01-31 14:48:37 -05001958 def test_signature_functionlike_class(self):
1959 # We only want to duck type function-like objects,
1960 # not classes.
1961
1962 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1963 pass
1964
1965 class funclike:
1966 def __init__(self, marker):
1967 pass
1968
1969 __name__ = func.__name__
1970 __code__ = func.__code__
1971 __annotations__ = func.__annotations__
1972 __defaults__ = func.__defaults__
1973 __kwdefaults__ = func.__kwdefaults__
1974
1975 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1976 inspect.Signature.from_function(funclike)
1977
1978 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
1979
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001980 def test_signature_on_method(self):
1981 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05001982 def __init__(*args):
1983 pass
1984 def m1(self, arg1, arg2=1) -> int:
1985 pass
1986 def m2(*args):
1987 pass
1988 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001989 pass
1990
Yury Selivanov62560fb2014-01-28 12:26:24 -05001991 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001992 ((('arg1', ..., ..., "positional_or_keyword"),
1993 ('arg2', 1, ..., "positional_or_keyword")),
1994 int))
1995
Yury Selivanov62560fb2014-01-28 12:26:24 -05001996 self.assertEqual(self.signature(Test().m2),
1997 ((('args', ..., ..., "var_positional"),),
1998 ...))
1999
2000 self.assertEqual(self.signature(Test),
2001 ((('args', ..., ..., "var_positional"),),
2002 ...))
2003
2004 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2005 self.signature(Test())
2006
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002007 def test_signature_on_classmethod(self):
2008 class Test:
2009 @classmethod
2010 def foo(cls, arg1, *, arg2=1):
2011 pass
2012
2013 meth = Test().foo
2014 self.assertEqual(self.signature(meth),
2015 ((('arg1', ..., ..., "positional_or_keyword"),
2016 ('arg2', 1, ..., "keyword_only")),
2017 ...))
2018
2019 meth = Test.foo
2020 self.assertEqual(self.signature(meth),
2021 ((('arg1', ..., ..., "positional_or_keyword"),
2022 ('arg2', 1, ..., "keyword_only")),
2023 ...))
2024
2025 def test_signature_on_staticmethod(self):
2026 class Test:
2027 @staticmethod
2028 def foo(cls, *, arg):
2029 pass
2030
2031 meth = Test().foo
2032 self.assertEqual(self.signature(meth),
2033 ((('cls', ..., ..., "positional_or_keyword"),
2034 ('arg', ..., ..., "keyword_only")),
2035 ...))
2036
2037 meth = Test.foo
2038 self.assertEqual(self.signature(meth),
2039 ((('cls', ..., ..., "positional_or_keyword"),
2040 ('arg', ..., ..., "keyword_only")),
2041 ...))
2042
2043 def test_signature_on_partial(self):
2044 from functools import partial
2045
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002046 Parameter = inspect.Parameter
2047
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002048 def test():
2049 pass
2050
2051 self.assertEqual(self.signature(partial(test)), ((), ...))
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, 1))
2055
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002056 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002057 inspect.signature(partial(test, a=1))
2058
2059 def test(a, b, *, c, d):
2060 pass
2061
2062 self.assertEqual(self.signature(partial(test)),
2063 ((('a', ..., ..., "positional_or_keyword"),
2064 ('b', ..., ..., "positional_or_keyword"),
2065 ('c', ..., ..., "keyword_only"),
2066 ('d', ..., ..., "keyword_only")),
2067 ...))
2068
2069 self.assertEqual(self.signature(partial(test, 1)),
2070 ((('b', ..., ..., "positional_or_keyword"),
2071 ('c', ..., ..., "keyword_only"),
2072 ('d', ..., ..., "keyword_only")),
2073 ...))
2074
2075 self.assertEqual(self.signature(partial(test, 1, c=2)),
2076 ((('b', ..., ..., "positional_or_keyword"),
2077 ('c', 2, ..., "keyword_only"),
2078 ('d', ..., ..., "keyword_only")),
2079 ...))
2080
2081 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2082 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002083 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002084 ('c', 2, ..., "keyword_only"),
2085 ('d', ..., ..., "keyword_only")),
2086 ...))
2087
2088 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002089 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002090 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002091 ('d', ..., ..., "keyword_only")),
2092 ...))
2093
2094 self.assertEqual(self.signature(partial(test, a=1)),
2095 ((('a', 1, ..., "keyword_only"),
2096 ('b', ..., ..., "keyword_only"),
2097 ('c', ..., ..., "keyword_only"),
2098 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002099 ...))
2100
2101 def test(a, *args, b, **kwargs):
2102 pass
2103
2104 self.assertEqual(self.signature(partial(test, 1)),
2105 ((('args', ..., ..., "var_positional"),
2106 ('b', ..., ..., "keyword_only"),
2107 ('kwargs', ..., ..., "var_keyword")),
2108 ...))
2109
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002110 self.assertEqual(self.signature(partial(test, a=1)),
2111 ((('a', 1, ..., "keyword_only"),
2112 ('b', ..., ..., "keyword_only"),
2113 ('kwargs', ..., ..., "var_keyword")),
2114 ...))
2115
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002116 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2117 ((('args', ..., ..., "var_positional"),
2118 ('b', ..., ..., "keyword_only"),
2119 ('kwargs', ..., ..., "var_keyword")),
2120 ...))
2121
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002122 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2123 ((('args', ..., ..., "var_positional"),
2124 ('b', ..., ..., "keyword_only"),
2125 ('kwargs', ..., ..., "var_keyword")),
2126 ...))
2127
2128 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2129 ((('args', ..., ..., "var_positional"),
2130 ('b', 0, ..., "keyword_only"),
2131 ('kwargs', ..., ..., "var_keyword")),
2132 ...))
2133
2134 self.assertEqual(self.signature(partial(test, b=0)),
2135 ((('a', ..., ..., "positional_or_keyword"),
2136 ('args', ..., ..., "var_positional"),
2137 ('b', 0, ..., "keyword_only"),
2138 ('kwargs', ..., ..., "var_keyword")),
2139 ...))
2140
2141 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2142 ((('a', ..., ..., "positional_or_keyword"),
2143 ('args', ..., ..., "var_positional"),
2144 ('b', 0, ..., "keyword_only"),
2145 ('kwargs', ..., ..., "var_keyword")),
2146 ...))
2147
2148 def test(a, b, c:int) -> 42:
2149 pass
2150
2151 sig = test.__signature__ = inspect.signature(test)
2152
2153 self.assertEqual(self.signature(partial(partial(test, 1))),
2154 ((('b', ..., ..., "positional_or_keyword"),
2155 ('c', ..., int, "positional_or_keyword")),
2156 42))
2157
2158 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2159 ((('c', ..., int, "positional_or_keyword"),),
2160 42))
2161
2162 psig = inspect.signature(partial(partial(test, 1), 2))
2163
2164 def foo(a):
2165 return a
2166 _foo = partial(partial(foo, a=10), a=20)
2167 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002168 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002169 ...))
2170 # check that we don't have any side-effects in signature(),
2171 # and the partial object is still functioning
2172 self.assertEqual(_foo(), 20)
2173
2174 def foo(a, b, c):
2175 return a, b, c
2176 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002177
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002178 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002179 ((('b', 30, ..., "keyword_only"),
2180 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002181 ...))
2182 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002183
2184 def foo(a, b, c, *, d):
2185 return a, b, c, d
2186 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2187 self.assertEqual(self.signature(_foo),
2188 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002189 ('b', 10, ..., "keyword_only"),
2190 ('c', 20, ..., "keyword_only"),
2191 ('d', 30, ..., "keyword_only"),
2192 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002193 ...))
2194 ba = inspect.signature(_foo).bind(a=200, b=11)
2195 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2196
2197 def foo(a=1, b=2, c=3):
2198 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002199 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2200
2201 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002202 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002203
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002204 ba = inspect.signature(_foo).bind(11, 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(11, b=12)
2208 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002209
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002210 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002211 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2212
2213 _foo = partial(_foo, b=10, c=20)
2214 ba = inspect.signature(_foo).bind(12)
2215 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2216
2217
2218 def foo(a, b, c, d, **kwargs):
2219 pass
2220 sig = inspect.signature(foo)
2221 params = sig.parameters.copy()
2222 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2223 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2224 foo.__signature__ = inspect.Signature(params.values())
2225 sig = inspect.signature(foo)
2226 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2227
2228 self.assertEqual(self.signature(partial(foo, 1)),
2229 ((('b', ..., ..., 'positional_only'),
2230 ('c', ..., ..., 'positional_or_keyword'),
2231 ('d', ..., ..., 'positional_or_keyword'),
2232 ('kwargs', ..., ..., 'var_keyword')),
2233 ...))
2234
2235 self.assertEqual(self.signature(partial(foo, 1, 2)),
2236 ((('c', ..., ..., 'positional_or_keyword'),
2237 ('d', ..., ..., 'positional_or_keyword'),
2238 ('kwargs', ..., ..., 'var_keyword')),
2239 ...))
2240
2241 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2242 ((('d', ..., ..., 'positional_or_keyword'),
2243 ('kwargs', ..., ..., 'var_keyword')),
2244 ...))
2245
2246 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2247 ((('c', 3, ..., 'keyword_only'),
2248 ('d', ..., ..., 'keyword_only'),
2249 ('kwargs', ..., ..., 'var_keyword')),
2250 ...))
2251
2252 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2253 ((('b', ..., ..., 'positional_only'),
2254 ('c', 3, ..., 'keyword_only'),
2255 ('d', ..., ..., 'keyword_only'),
2256 ('kwargs', ..., ..., 'var_keyword')),
2257 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002258
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002259 def test_signature_on_partialmethod(self):
2260 from functools import partialmethod
2261
2262 class Spam:
2263 def test():
2264 pass
2265 ham = partialmethod(test)
2266
2267 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2268 inspect.signature(Spam.ham)
2269
2270 class Spam:
2271 def test(it, a, *, c) -> 'spam':
2272 pass
2273 ham = partialmethod(test, c=1)
2274
2275 self.assertEqual(self.signature(Spam.ham),
2276 ((('it', ..., ..., 'positional_or_keyword'),
2277 ('a', ..., ..., 'positional_or_keyword'),
2278 ('c', 1, ..., 'keyword_only')),
2279 'spam'))
2280
2281 self.assertEqual(self.signature(Spam().ham),
2282 ((('a', ..., ..., 'positional_or_keyword'),
2283 ('c', 1, ..., 'keyword_only')),
2284 'spam'))
2285
Yury Selivanov0486f812014-01-29 12:18:59 -05002286 def test_signature_on_fake_partialmethod(self):
2287 def foo(a): pass
2288 foo._partialmethod = 'spam'
2289 self.assertEqual(str(inspect.signature(foo)), '(a)')
2290
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002291 def test_signature_on_decorated(self):
2292 import functools
2293
2294 def decorator(func):
2295 @functools.wraps(func)
2296 def wrapper(*args, **kwargs) -> int:
2297 return func(*args, **kwargs)
2298 return wrapper
2299
2300 class Foo:
2301 @decorator
2302 def bar(self, a, b):
2303 pass
2304
2305 self.assertEqual(self.signature(Foo.bar),
2306 ((('self', ..., ..., "positional_or_keyword"),
2307 ('a', ..., ..., "positional_or_keyword"),
2308 ('b', ..., ..., "positional_or_keyword")),
2309 ...))
2310
2311 self.assertEqual(self.signature(Foo().bar),
2312 ((('a', ..., ..., "positional_or_keyword"),
2313 ('b', ..., ..., "positional_or_keyword")),
2314 ...))
2315
2316 # Test that we handle method wrappers correctly
2317 def decorator(func):
2318 @functools.wraps(func)
2319 def wrapper(*args, **kwargs) -> int:
2320 return func(42, *args, **kwargs)
2321 sig = inspect.signature(func)
2322 new_params = tuple(sig.parameters.values())[1:]
2323 wrapper.__signature__ = sig.replace(parameters=new_params)
2324 return wrapper
2325
2326 class Foo:
2327 @decorator
2328 def __call__(self, a, b):
2329 pass
2330
2331 self.assertEqual(self.signature(Foo.__call__),
2332 ((('a', ..., ..., "positional_or_keyword"),
2333 ('b', ..., ..., "positional_or_keyword")),
2334 ...))
2335
2336 self.assertEqual(self.signature(Foo().__call__),
2337 ((('b', ..., ..., "positional_or_keyword"),),
2338 ...))
2339
Nick Coghlane8c45d62013-07-28 20:00:01 +10002340 # Test we handle __signature__ partway down the wrapper stack
2341 def wrapped_foo_call():
2342 pass
2343 wrapped_foo_call.__wrapped__ = Foo.__call__
2344
2345 self.assertEqual(self.signature(wrapped_foo_call),
2346 ((('a', ..., ..., "positional_or_keyword"),
2347 ('b', ..., ..., "positional_or_keyword")),
2348 ...))
2349
2350
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002351 def test_signature_on_class(self):
2352 class C:
2353 def __init__(self, a):
2354 pass
2355
2356 self.assertEqual(self.signature(C),
2357 ((('a', ..., ..., "positional_or_keyword"),),
2358 ...))
2359
2360 class CM(type):
2361 def __call__(cls, a):
2362 pass
2363 class C(metaclass=CM):
2364 def __init__(self, b):
2365 pass
2366
2367 self.assertEqual(self.signature(C),
2368 ((('a', ..., ..., "positional_or_keyword"),),
2369 ...))
2370
2371 class CM(type):
2372 def __new__(mcls, name, bases, dct, *, foo=1):
2373 return super().__new__(mcls, name, bases, dct)
2374 class C(metaclass=CM):
2375 def __init__(self, b):
2376 pass
2377
2378 self.assertEqual(self.signature(C),
2379 ((('b', ..., ..., "positional_or_keyword"),),
2380 ...))
2381
2382 self.assertEqual(self.signature(CM),
2383 ((('name', ..., ..., "positional_or_keyword"),
2384 ('bases', ..., ..., "positional_or_keyword"),
2385 ('dct', ..., ..., "positional_or_keyword"),
2386 ('foo', 1, ..., "keyword_only")),
2387 ...))
2388
2389 class CMM(type):
2390 def __new__(mcls, name, bases, dct, *, foo=1):
2391 return super().__new__(mcls, name, bases, dct)
2392 def __call__(cls, nm, bs, dt):
2393 return type(nm, bs, dt)
2394 class CM(type, metaclass=CMM):
2395 def __new__(mcls, name, bases, dct, *, bar=2):
2396 return super().__new__(mcls, name, bases, dct)
2397 class C(metaclass=CM):
2398 def __init__(self, b):
2399 pass
2400
2401 self.assertEqual(self.signature(CMM),
2402 ((('name', ..., ..., "positional_or_keyword"),
2403 ('bases', ..., ..., "positional_or_keyword"),
2404 ('dct', ..., ..., "positional_or_keyword"),
2405 ('foo', 1, ..., "keyword_only")),
2406 ...))
2407
2408 self.assertEqual(self.signature(CM),
2409 ((('nm', ..., ..., "positional_or_keyword"),
2410 ('bs', ..., ..., "positional_or_keyword"),
2411 ('dt', ..., ..., "positional_or_keyword")),
2412 ...))
2413
2414 self.assertEqual(self.signature(C),
2415 ((('b', ..., ..., "positional_or_keyword"),),
2416 ...))
2417
2418 class CM(type):
2419 def __init__(cls, name, bases, dct, *, bar=2):
2420 return super().__init__(name, bases, dct)
2421 class C(metaclass=CM):
2422 def __init__(self, b):
2423 pass
2424
2425 self.assertEqual(self.signature(CM),
2426 ((('name', ..., ..., "positional_or_keyword"),
2427 ('bases', ..., ..., "positional_or_keyword"),
2428 ('dct', ..., ..., "positional_or_keyword"),
2429 ('bar', 2, ..., "keyword_only")),
2430 ...))
2431
Yury Selivanov145dff82014-02-01 13:49:29 -05002432 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2433 "Signature information for builtins requires docstrings")
2434 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002435 # Test classes without user-defined __init__ or __new__
2436 class C: pass
2437 self.assertEqual(str(inspect.signature(C)), '()')
2438 class D(C): pass
2439 self.assertEqual(str(inspect.signature(D)), '()')
2440
2441 # Test meta-classes without user-defined __init__ or __new__
2442 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002443 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002444 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2445 self.assertEqual(inspect.signature(C), None)
2446 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2447 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002448
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002449 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2450 "Signature information for builtins requires docstrings")
2451 def test_signature_on_builtin_class(self):
2452 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2453 '(file, protocol=None, fix_imports=True)')
2454
2455 class P(_pickle.Pickler): pass
2456 class EmptyTrait: pass
2457 class P2(EmptyTrait, P): pass
2458 self.assertEqual(str(inspect.signature(P)),
2459 '(file, protocol=None, fix_imports=True)')
2460 self.assertEqual(str(inspect.signature(P2)),
2461 '(file, protocol=None, fix_imports=True)')
2462
2463 class P3(P2):
2464 def __init__(self, spam):
2465 pass
2466 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2467
2468 class MetaP(type):
2469 def __call__(cls, foo, bar):
2470 pass
2471 class P4(P2, metaclass=MetaP):
2472 pass
2473 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2474
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002475 def test_signature_on_callable_objects(self):
2476 class Foo:
2477 def __call__(self, a):
2478 pass
2479
2480 self.assertEqual(self.signature(Foo()),
2481 ((('a', ..., ..., "positional_or_keyword"),),
2482 ...))
2483
2484 class Spam:
2485 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002486 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002487 inspect.signature(Spam())
2488
2489 class Bar(Spam, Foo):
2490 pass
2491
2492 self.assertEqual(self.signature(Bar()),
2493 ((('a', ..., ..., "positional_or_keyword"),),
2494 ...))
2495
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002496 class Wrapped:
2497 pass
2498 Wrapped.__wrapped__ = lambda a: None
2499 self.assertEqual(self.signature(Wrapped),
2500 ((('a', ..., ..., "positional_or_keyword"),),
2501 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002502 # wrapper loop:
2503 Wrapped.__wrapped__ = Wrapped
2504 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2505 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002506
2507 def test_signature_on_lambdas(self):
2508 self.assertEqual(self.signature((lambda a=10: a)),
2509 ((('a', 10, ..., "positional_or_keyword"),),
2510 ...))
2511
2512 def test_signature_equality(self):
2513 def foo(a, *, b:int) -> float: pass
2514 self.assertNotEqual(inspect.signature(foo), 42)
2515
2516 def bar(a, *, b:int) -> float: pass
2517 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002518 self.assertEqual(
2519 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002520
2521 def bar(a, *, b:int) -> int: pass
2522 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002523 self.assertNotEqual(
2524 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002525
2526 def bar(a, *, b:int): pass
2527 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002528 self.assertNotEqual(
2529 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002530
2531 def bar(a, *, b:int=42) -> float: pass
2532 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002533 self.assertNotEqual(
2534 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002535
2536 def bar(a, *, c) -> float: pass
2537 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002538 self.assertNotEqual(
2539 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002540
2541 def bar(a, b:int) -> float: pass
2542 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002543 self.assertNotEqual(
2544 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002545 def spam(b:int, a) -> float: pass
2546 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002547 self.assertNotEqual(
2548 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002549
2550 def foo(*, a, b, c): pass
2551 def bar(*, c, b, a): pass
2552 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002553 self.assertEqual(
2554 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002555
2556 def foo(*, a=1, b, c): pass
2557 def bar(*, c, b, a=1): pass
2558 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002559 self.assertEqual(
2560 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002561
2562 def foo(pos, *, a=1, b, c): pass
2563 def bar(pos, *, c, b, a=1): pass
2564 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002565 self.assertEqual(
2566 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002567
2568 def foo(pos, *, a, b, c): pass
2569 def bar(pos, *, c, b, a=1): pass
2570 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002571 self.assertNotEqual(
2572 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002573
2574 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2575 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2576 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002577 self.assertEqual(
2578 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002579
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002580 def test_signature_hashable(self):
2581 S = inspect.Signature
2582 P = inspect.Parameter
2583
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002584 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002585 foo_sig = inspect.signature(foo)
2586
2587 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2588
2589 self.assertEqual(hash(foo_sig), hash(manual_sig))
2590 self.assertNotEqual(hash(foo_sig),
2591 hash(manual_sig.replace(return_annotation='spam')))
2592
2593 def bar(a) -> 1: pass
2594 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2595
2596 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002597 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002598 hash(inspect.signature(foo))
2599
2600 def foo(a) -> {}: pass
2601 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2602 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002603
2604 def test_signature_str(self):
2605 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2606 pass
2607 self.assertEqual(str(inspect.signature(foo)),
2608 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2609
2610 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2611 pass
2612 self.assertEqual(str(inspect.signature(foo)),
2613 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2614
2615 def foo():
2616 pass
2617 self.assertEqual(str(inspect.signature(foo)), '()')
2618
2619 def test_signature_str_positional_only(self):
2620 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002621 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002622
2623 def test(a_po, *, b, **kwargs):
2624 return a_po, kwargs
2625
2626 sig = inspect.signature(test)
2627 new_params = list(sig.parameters.values())
2628 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2629 test.__signature__ = sig.replace(parameters=new_params)
2630
2631 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002632 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002633
Yury Selivanov2393dca2014-01-27 15:07:58 -05002634 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2635 '(foo, /)')
2636
2637 self.assertEqual(str(S(parameters=[
2638 P('foo', P.POSITIONAL_ONLY),
2639 P('bar', P.VAR_KEYWORD)])),
2640 '(foo, /, **bar)')
2641
2642 self.assertEqual(str(S(parameters=[
2643 P('foo', P.POSITIONAL_ONLY),
2644 P('bar', P.VAR_POSITIONAL)])),
2645 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002646
2647 def test_signature_replace_anno(self):
2648 def test() -> 42:
2649 pass
2650
2651 sig = inspect.signature(test)
2652 sig = sig.replace(return_annotation=None)
2653 self.assertIs(sig.return_annotation, None)
2654 sig = sig.replace(return_annotation=sig.empty)
2655 self.assertIs(sig.return_annotation, sig.empty)
2656 sig = sig.replace(return_annotation=42)
2657 self.assertEqual(sig.return_annotation, 42)
2658 self.assertEqual(sig, inspect.signature(test))
2659
Yury Selivanov34ce99f2014-02-18 12:49:41 -05002660 def test_signature_on_mangled_parameters(self):
2661 class Spam:
2662 def foo(self, __p1:1=2, *, __p2:2=3):
2663 pass
2664 class Ham(Spam):
2665 pass
2666
2667 self.assertEqual(self.signature(Spam.foo),
2668 ((('self', ..., ..., "positional_or_keyword"),
2669 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2670 ('_Spam__p2', 3, 2, "keyword_only")),
2671 ...))
2672
2673 self.assertEqual(self.signature(Spam.foo),
2674 self.signature(Ham.foo))
2675
Yury Selivanovda396452014-03-27 12:09:24 -04002676 def test_signature_from_callable_python_obj(self):
2677 class MySignature(inspect.Signature): pass
2678 def foo(a, *, b:1): pass
2679 foo_sig = MySignature.from_callable(foo)
2680 self.assertTrue(isinstance(foo_sig, MySignature))
2681
2682 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2683 "Signature information for builtins requires docstrings")
2684 def test_signature_from_callable_builtin_obj(self):
2685 class MySignature(inspect.Signature): pass
2686 sig = MySignature.from_callable(_pickle.Pickler)
2687 self.assertTrue(isinstance(sig, MySignature))
2688
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002689
2690class TestParameterObject(unittest.TestCase):
2691 def test_signature_parameter_kinds(self):
2692 P = inspect.Parameter
2693 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2694 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2695
2696 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2697 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2698
2699 def test_signature_parameter_object(self):
2700 p = inspect.Parameter('foo', default=10,
2701 kind=inspect.Parameter.POSITIONAL_ONLY)
2702 self.assertEqual(p.name, 'foo')
2703 self.assertEqual(p.default, 10)
2704 self.assertIs(p.annotation, p.empty)
2705 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2706
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002707 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002708 inspect.Parameter('foo', default=10, kind='123')
2709
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002710 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002711 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2712
Yury Selivanov2393dca2014-01-27 15:07:58 -05002713 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002714 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2715
Yury Selivanov2393dca2014-01-27 15:07:58 -05002716 with self.assertRaisesRegex(ValueError,
2717 'is not a valid parameter name'):
2718 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2719
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002720 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002721 inspect.Parameter('a', default=42,
2722 kind=inspect.Parameter.VAR_KEYWORD)
2723
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002724 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002725 inspect.Parameter('a', default=42,
2726 kind=inspect.Parameter.VAR_POSITIONAL)
2727
2728 p = inspect.Parameter('a', default=42,
2729 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002730 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002731 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2732
2733 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04002734 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002735
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002736 def test_signature_parameter_hashable(self):
2737 P = inspect.Parameter
2738 foo = P('foo', kind=P.POSITIONAL_ONLY)
2739 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
2740 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
2741 default=42)))
2742 self.assertNotEqual(hash(foo),
2743 hash(foo.replace(kind=P.VAR_POSITIONAL)))
2744
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002745 def test_signature_parameter_equality(self):
2746 P = inspect.Parameter
2747 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2748
2749 self.assertEqual(p, p)
2750 self.assertNotEqual(p, 42)
2751
2752 self.assertEqual(p, P('foo', default=42,
2753 kind=inspect.Parameter.KEYWORD_ONLY))
2754
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002755 def test_signature_parameter_replace(self):
2756 p = inspect.Parameter('foo', default=42,
2757 kind=inspect.Parameter.KEYWORD_ONLY)
2758
2759 self.assertIsNot(p, p.replace())
2760 self.assertEqual(p, p.replace())
2761
2762 p2 = p.replace(annotation=1)
2763 self.assertEqual(p2.annotation, 1)
2764 p2 = p2.replace(annotation=p2.empty)
2765 self.assertEqual(p, p2)
2766
2767 p2 = p2.replace(name='bar')
2768 self.assertEqual(p2.name, 'bar')
2769 self.assertNotEqual(p2, p)
2770
Yury Selivanov2393dca2014-01-27 15:07:58 -05002771 with self.assertRaisesRegex(ValueError,
2772 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002773 p2 = p2.replace(name=p2.empty)
2774
2775 p2 = p2.replace(name='foo', default=None)
2776 self.assertIs(p2.default, None)
2777 self.assertNotEqual(p2, p)
2778
2779 p2 = p2.replace(name='foo', default=p2.empty)
2780 self.assertIs(p2.default, p2.empty)
2781
2782
2783 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2784 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2785 self.assertNotEqual(p2, p)
2786
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002787 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002788 p2 = p2.replace(kind=p2.empty)
2789
2790 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2791 self.assertEqual(p2, p)
2792
2793 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002794 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2795 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002796
2797 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002798 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002799
2800 with self.assertRaises(AttributeError):
2801 p.foo = 'bar'
2802
2803 with self.assertRaises(AttributeError):
2804 p.kind = 123
2805
2806
2807class TestSignatureBind(unittest.TestCase):
2808 @staticmethod
2809 def call(func, *args, **kwargs):
2810 sig = inspect.signature(func)
2811 ba = sig.bind(*args, **kwargs)
2812 return func(*ba.args, **ba.kwargs)
2813
2814 def test_signature_bind_empty(self):
2815 def test():
2816 return 42
2817
2818 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002819 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002820 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002821 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002822 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002823 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002824 self.call(test, spam=1)
2825
2826 def test_signature_bind_var(self):
2827 def test(*args, **kwargs):
2828 return args, kwargs
2829
2830 self.assertEqual(self.call(test), ((), {}))
2831 self.assertEqual(self.call(test, 1), ((1,), {}))
2832 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2833 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2834 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2835 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2836 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2837 ((1, 2), {'foo': 'bar'}))
2838
2839 def test_signature_bind_just_args(self):
2840 def test(a, b, c):
2841 return a, b, c
2842
2843 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2844
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002845 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002846 self.call(test, 1, 2, 3, 4)
2847
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002848 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002849 self.call(test, 1)
2850
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002851 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002852 self.call(test)
2853
2854 def test(a, b, c=10):
2855 return a, b, c
2856 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2857 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2858
2859 def test(a=1, b=2, c=3):
2860 return a, b, c
2861 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2862 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2863 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2864
2865 def test_signature_bind_varargs_order(self):
2866 def test(*args):
2867 return args
2868
2869 self.assertEqual(self.call(test), ())
2870 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2871
2872 def test_signature_bind_args_and_varargs(self):
2873 def test(a, b, c=3, *args):
2874 return a, b, c, args
2875
2876 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2877 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2878 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2879 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2880
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002881 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002882 "multiple values for argument 'c'"):
2883 self.call(test, 1, 2, 3, c=4)
2884
2885 def test_signature_bind_just_kwargs(self):
2886 def test(**kwargs):
2887 return kwargs
2888
2889 self.assertEqual(self.call(test), {})
2890 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2891 {'foo': 'bar', 'spam': 'ham'})
2892
2893 def test_signature_bind_args_and_kwargs(self):
2894 def test(a, b, c=3, **kwargs):
2895 return a, b, c, kwargs
2896
2897 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2898 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2899 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2900 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2901 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2902 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2903 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2904 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2905 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2906 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2907 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2908 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2909 (1, 2, 4, {'foo': 'bar'}))
2910 self.assertEqual(self.call(test, c=5, a=4, b=3),
2911 (4, 3, 5, {}))
2912
2913 def test_signature_bind_kwonly(self):
2914 def test(*, foo):
2915 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002916 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002917 'too many positional arguments'):
2918 self.call(test, 1)
2919 self.assertEqual(self.call(test, foo=1), 1)
2920
2921 def test(a, *, foo=1, bar):
2922 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002923 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002924 "'bar' parameter lacking default value"):
2925 self.call(test, 1)
2926
2927 def test(foo, *, bar):
2928 return foo, bar
2929 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2930 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2931
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002932 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002933 'too many keyword arguments'):
2934 self.call(test, bar=2, foo=1, spam=10)
2935
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002936 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002937 'too many positional arguments'):
2938 self.call(test, 1, 2)
2939
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002940 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002941 'too many positional arguments'):
2942 self.call(test, 1, 2, bar=2)
2943
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002944 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002945 'too many keyword arguments'):
2946 self.call(test, 1, bar=2, spam='ham')
2947
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002948 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002949 "'bar' parameter lacking default value"):
2950 self.call(test, 1)
2951
2952 def test(foo, *, bar, **bin):
2953 return foo, bar, bin
2954 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2955 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2956 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2957 (1, 2, {'spam': 'ham'}))
2958 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2959 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002960 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002961 "'foo' parameter lacking default value"):
2962 self.call(test, spam='ham', bar=2)
2963 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2964 (1, 2, {'bin': 1, 'spam': 10}))
2965
2966 def test_signature_bind_arguments(self):
2967 def test(a, *args, b, z=100, **kwargs):
2968 pass
2969 sig = inspect.signature(test)
2970 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2971 # we won't have 'z' argument in the bound arguments object, as we didn't
2972 # pass it to the 'bind'
2973 self.assertEqual(tuple(ba.arguments.items()),
2974 (('a', 10), ('args', (20,)), ('b', 30),
2975 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2976 self.assertEqual(ba.kwargs,
2977 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2978 self.assertEqual(ba.args, (10, 20))
2979
2980 def test_signature_bind_positional_only(self):
2981 P = inspect.Parameter
2982
2983 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2984 return a_po, b_po, c_po, foo, bar, kwargs
2985
2986 sig = inspect.signature(test)
2987 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2988 for name in ('a_po', 'b_po', 'c_po'):
2989 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2990 new_sig = sig.replace(parameters=new_params.values())
2991 test.__signature__ = new_sig
2992
2993 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2994 (1, 2, 4, 5, 6, {}))
2995
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002996 self.assertEqual(self.call(test, 1, 2),
2997 (1, 2, 3, 42, 50, {}))
2998
2999 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3000 (1, 2, 3, 4, 5, {}))
3001
3002 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3003 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
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, 1, 2, c_po=4)
3007
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003008 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003009 self.call(test, a_po=1, b_po=2)
3010
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003011 def test_signature_bind_with_self_arg(self):
3012 # Issue #17071: one of the parameters is named "self
3013 def test(a, self, b):
3014 pass
3015 sig = inspect.signature(test)
3016 ba = sig.bind(1, 2, 3)
3017 self.assertEqual(ba.args, (1, 2, 3))
3018 ba = sig.bind(1, self=2, b=3)
3019 self.assertEqual(ba.args, (1, 2, 3))
3020
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003021 def test_signature_bind_vararg_name(self):
3022 def test(a, *args):
3023 return a, args
3024 sig = inspect.signature(test)
3025
3026 with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
3027 sig.bind(a=0, args=1)
3028
3029 def test(*args, **kwargs):
3030 return args, kwargs
3031 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3032
3033 sig = inspect.signature(test)
3034 ba = sig.bind(args=1)
3035 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3036
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003037
3038class TestBoundArguments(unittest.TestCase):
3039 def test_signature_bound_arguments_unhashable(self):
3040 def foo(a): pass
3041 ba = inspect.signature(foo).bind(1)
3042
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003043 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003044 hash(ba)
3045
3046 def test_signature_bound_arguments_equality(self):
3047 def foo(a): pass
3048 ba = inspect.signature(foo).bind(1)
3049 self.assertEqual(ba, ba)
3050
3051 ba2 = inspect.signature(foo).bind(1)
3052 self.assertEqual(ba, ba2)
3053
3054 ba3 = inspect.signature(foo).bind(2)
3055 self.assertNotEqual(ba, ba3)
3056 ba3.arguments['a'] = 1
3057 self.assertEqual(ba, ba3)
3058
3059 def bar(b): pass
3060 ba4 = inspect.signature(bar).bind(1)
3061 self.assertNotEqual(ba, ba4)
3062
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003063 def test_signature_bound_arguments_pickle(self):
3064 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3065 sig = inspect.signature(foo)
3066 ba = sig.bind(20, 30, z={})
3067
3068 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3069 with self.subTest(pickle_ver=ver):
3070 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3071 self.assertEqual(ba, ba_pickled)
3072
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003073
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003074class TestSignaturePrivateHelpers(unittest.TestCase):
3075 def test_signature_get_bound_param(self):
3076 getter = inspect._signature_get_bound_param
3077
3078 self.assertEqual(getter('($self)'), 'self')
3079 self.assertEqual(getter('($self, obj)'), 'self')
3080 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3081
Larry Hastings2623c8c2014-02-08 22:15:29 -08003082 def _strip_non_python_syntax(self, input,
3083 clean_signature, self_parameter, last_positional_only):
3084 computed_clean_signature, \
3085 computed_self_parameter, \
3086 computed_last_positional_only = \
3087 inspect._signature_strip_non_python_syntax(input)
3088 self.assertEqual(computed_clean_signature, clean_signature)
3089 self.assertEqual(computed_self_parameter, self_parameter)
3090 self.assertEqual(computed_last_positional_only, last_positional_only)
3091
3092 def test_signature_strip_non_python_syntax(self):
3093 self._strip_non_python_syntax(
3094 "($module, /, path, mode, *, dir_fd=None, " +
3095 "effective_ids=False,\n follow_symlinks=True)",
3096 "(module, path, mode, *, dir_fd=None, " +
3097 "effective_ids=False, follow_symlinks=True)",
3098 0,
3099 0)
3100
3101 self._strip_non_python_syntax(
3102 "($module, word, salt, /)",
3103 "(module, word, salt)",
3104 0,
3105 2)
3106
3107 self._strip_non_python_syntax(
3108 "(x, y=None, z=None, /)",
3109 "(x, y=None, z=None)",
3110 None,
3111 2)
3112
3113 self._strip_non_python_syntax(
3114 "(x, y=None, z=None)",
3115 "(x, y=None, z=None)",
3116 None,
3117 None)
3118
3119 self._strip_non_python_syntax(
3120 "(x,\n y=None,\n z = None )",
3121 "(x, y=None, z=None)",
3122 None,
3123 None)
3124
3125 self._strip_non_python_syntax(
3126 "",
3127 "",
3128 None,
3129 None)
3130
3131 self._strip_non_python_syntax(
3132 None,
3133 None,
3134 None,
3135 None)
3136
Nick Coghlan9c680b02015-04-13 12:54:54 -04003137class TestSignatureDefinitions(unittest.TestCase):
3138 # This test case provides a home for checking that particular APIs
3139 # have signatures available for introspection
3140
3141 @cpython_only
3142 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3143 "Signature information for builtins requires docstrings")
3144 def test_builtins_have_signatures(self):
3145 # This checks all builtin callables in CPython have signatures
3146 # A few have signatures Signature can't yet handle, so we skip those
3147 # since they will have to wait until PEP 457 adds the required
3148 # introspection support to the inspect module
3149 # Some others also haven't been converted yet for various other
3150 # reasons, so we also skip those for the time being, but design
3151 # the test to fail in order to indicate when it needs to be
3152 # updated.
3153 no_signature = set()
3154 # These need PEP 457 groups
3155 needs_groups = {"range", "slice", "dir", "getattr",
3156 "next", "iter", "vars"}
3157 no_signature |= needs_groups
3158 # These need PEP 457 groups or a signature change to accept None
3159 needs_semantic_update = {"round"}
3160 no_signature |= needs_semantic_update
3161 # These need *args support in Argument Clinic
3162 needs_varargs = {"min", "max", "print", "__build_class__"}
3163 no_signature |= needs_varargs
3164 # These simply weren't covered in the initial AC conversion
3165 # for builtin callables
3166 not_converted_yet = {"open", "__import__"}
3167 no_signature |= not_converted_yet
3168 # These builtin types are expected to provide introspection info
3169 types_with_signatures = set()
3170 # Check the signatures we expect to be there
3171 ns = vars(builtins)
3172 for name, obj in sorted(ns.items()):
3173 if not callable(obj):
3174 continue
3175 # The builtin types haven't been converted to AC yet
3176 if isinstance(obj, type) and (name not in types_with_signatures):
3177 # Note that this also skips all the exception types
3178 no_signature.add(name)
3179 if (name in no_signature):
3180 # Not yet converted
3181 continue
3182 with self.subTest(builtin=name):
3183 self.assertIsNotNone(inspect.signature(obj))
3184 # Check callables that haven't been converted don't claim a signature
3185 # This ensures this test will start failing as more signatures are
3186 # added, so the affected items can be moved into the scope of the
3187 # regression test above
3188 for name in no_signature:
3189 with self.subTest(builtin=name):
3190 self.assertIsNone(obj.__text_signature__)
3191
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003192
Nick Coghlane8c45d62013-07-28 20:00:01 +10003193class TestUnwrap(unittest.TestCase):
3194
3195 def test_unwrap_one(self):
3196 def func(a, b):
3197 return a + b
3198 wrapper = functools.lru_cache(maxsize=20)(func)
3199 self.assertIs(inspect.unwrap(wrapper), func)
3200
3201 def test_unwrap_several(self):
3202 def func(a, b):
3203 return a + b
3204 wrapper = func
3205 for __ in range(10):
3206 @functools.wraps(wrapper)
3207 def wrapper():
3208 pass
3209 self.assertIsNot(wrapper.__wrapped__, func)
3210 self.assertIs(inspect.unwrap(wrapper), func)
3211
3212 def test_stop(self):
3213 def func1(a, b):
3214 return a + b
3215 @functools.wraps(func1)
3216 def func2():
3217 pass
3218 @functools.wraps(func2)
3219 def wrapper():
3220 pass
3221 func2.stop_here = 1
3222 unwrapped = inspect.unwrap(wrapper,
3223 stop=(lambda f: hasattr(f, "stop_here")))
3224 self.assertIs(unwrapped, func2)
3225
3226 def test_cycle(self):
3227 def func1(): pass
3228 func1.__wrapped__ = func1
3229 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3230 inspect.unwrap(func1)
3231
3232 def func2(): pass
3233 func2.__wrapped__ = func1
3234 func1.__wrapped__ = func2
3235 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3236 inspect.unwrap(func1)
3237 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3238 inspect.unwrap(func2)
3239
3240 def test_unhashable(self):
3241 def func(): pass
3242 func.__wrapped__ = None
3243 class C:
3244 __hash__ = None
3245 __wrapped__ = func
3246 self.assertIsNone(inspect.unwrap(C()))
3247
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003248class TestMain(unittest.TestCase):
3249 def test_only_source(self):
3250 module = importlib.import_module('unittest')
3251 rc, out, err = assert_python_ok('-m', 'inspect',
3252 'unittest')
3253 lines = out.decode().splitlines()
3254 # ignore the final newline
3255 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3256 self.assertEqual(err, b'')
3257
Yury Selivanov42407ab2014-06-23 10:23:50 -07003258 def test_custom_getattr(self):
3259 def foo():
3260 pass
3261 foo.__signature__ = 42
3262 with self.assertRaises(TypeError):
3263 inspect.signature(foo)
3264
Brett Cannon634a8fc2013-10-02 10:25:42 -04003265 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003266 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003267 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003268 rc, out, err = assert_python_ok('-m', 'inspect',
3269 'concurrent.futures:ThreadPoolExecutor')
3270 lines = out.decode().splitlines()
3271 # ignore the final newline
3272 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003273 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003274 self.assertEqual(err, b'')
3275
3276 def test_builtins(self):
3277 module = importlib.import_module('unittest')
3278 _, out, err = assert_python_failure('-m', 'inspect',
3279 'sys')
3280 lines = err.decode().splitlines()
3281 self.assertEqual(lines, ["Can't get info for builtin modules."])
3282
3283 def test_details(self):
3284 module = importlib.import_module('unittest')
3285 rc, out, err = assert_python_ok('-m', 'inspect',
3286 'unittest', '--details')
3287 output = out.decode()
3288 # Just a quick sanity check on the output
3289 self.assertIn(module.__name__, output)
3290 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02003291 if not sys.flags.optimize:
3292 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003293 self.assertEqual(err, b'')
3294
3295
Yury Selivanovef1e7502014-12-08 16:05:34 -05003296class TestReload(unittest.TestCase):
3297
3298 src_before = textwrap.dedent("""\
3299def foo():
3300 print("Bla")
3301 """)
3302
3303 src_after = textwrap.dedent("""\
3304def foo():
3305 print("Oh no!")
3306 """)
3307
3308 def assertInspectEqual(self, path, source):
3309 inspected_src = inspect.getsource(source)
3310 with open(path) as src:
3311 self.assertEqual(
3312 src.read().splitlines(True),
3313 inspected_src.splitlines(True)
3314 )
3315
3316 def test_getsource_reload(self):
3317 # see issue 1218234
3318 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3319 module = importlib.import_module(name)
3320 self.assertInspectEqual(path, module)
3321 with open(path, 'w') as src:
3322 src.write(self.src_after)
3323 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003324
Nick Coghlane8c45d62013-07-28 20:00:01 +10003325
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003326def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003327 run_unittest(
3328 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3329 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3330 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003331 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003332 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003333 TestBoundArguments, TestSignaturePrivateHelpers,
3334 TestSignatureDefinitions,
3335 TestGetClosureVars, TestUnwrap, TestMain, TestReload
Michael Foord95fc51d2010-11-20 15:07:30 +00003336 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003337
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003338if __name__ == "__main__":
3339 test_main()