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