blob: 38367f3ff64299f8828b9bae822abc384d0639f4 [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
Yury Selivanov2542b662014-03-27 18:42:52 -04001217 # issue20817:
1218 def f6(a, b, c):
1219 pass
1220 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1221 inspect.getcallargs(f6)
1222
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001223class TestGetcallargsMethods(TestGetcallargsFunctions):
1224
1225 def setUp(self):
1226 class Foo(object):
1227 pass
1228 self.cls = Foo
1229 self.inst = Foo()
1230
1231 def makeCallable(self, signature):
1232 assert 'self' not in signature
1233 mk = super(TestGetcallargsMethods, self).makeCallable
1234 self.cls.method = mk('self, ' + signature)
1235 return self.inst.method
1236
1237class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1238
1239 def makeCallable(self, signature):
1240 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1241 return self.cls.method
1242
1243 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1244 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1245 *self._getAssertEqualParams(func, call_params_string, locs))
1246
1247 def assertEqualException(self, func, call_params_string, locs=None):
1248 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1249 *self._getAssertEqualParams(func, call_params_string, locs))
1250
1251 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1252 assert 'inst' not in call_params_string
1253 locs = dict(locs or {}, inst=self.inst)
1254 return (func, 'inst,' + call_params_string, locs)
1255
Michael Foord95fc51d2010-11-20 15:07:30 +00001256
1257class TestGetattrStatic(unittest.TestCase):
1258
1259 def test_basic(self):
1260 class Thing(object):
1261 x = object()
1262
1263 thing = Thing()
1264 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1265 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1266 with self.assertRaises(AttributeError):
1267 inspect.getattr_static(thing, 'y')
1268
1269 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1270
1271 def test_inherited(self):
1272 class Thing(object):
1273 x = object()
1274 class OtherThing(Thing):
1275 pass
1276
1277 something = OtherThing()
1278 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1279
1280 def test_instance_attr(self):
1281 class Thing(object):
1282 x = 2
1283 def __init__(self, x):
1284 self.x = x
1285 thing = Thing(3)
1286 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1287 del thing.x
1288 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1289
1290 def test_property(self):
1291 class Thing(object):
1292 @property
1293 def x(self):
1294 raise AttributeError("I'm pretending not to exist")
1295 thing = Thing()
1296 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1297
Ezio Melotti75cbd732011-04-28 00:59:29 +03001298 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001299 class descriptor(object):
1300 def __get__(*_):
1301 raise AttributeError("I'm pretending not to exist")
1302 desc = descriptor()
1303 class Thing(object):
1304 x = desc
1305 thing = Thing()
1306 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1307
1308 def test_classAttribute(self):
1309 class Thing(object):
1310 x = object()
1311
1312 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1313
Ethan Furmane03ea372013-09-25 07:14:41 -07001314 def test_classVirtualAttribute(self):
1315 class Thing(object):
1316 @types.DynamicClassAttribute
1317 def x(self):
1318 return self._x
1319 _x = object()
1320
1321 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1322
Michael Foord95fc51d2010-11-20 15:07:30 +00001323 def test_inherited_classattribute(self):
1324 class Thing(object):
1325 x = object()
1326 class OtherThing(Thing):
1327 pass
1328
1329 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1330
1331 def test_slots(self):
1332 class Thing(object):
1333 y = 'bar'
1334 __slots__ = ['x']
1335 def __init__(self):
1336 self.x = 'foo'
1337 thing = Thing()
1338 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1339 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1340
1341 del thing.x
1342 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1343
1344 def test_metaclass(self):
1345 class meta(type):
1346 attr = 'foo'
1347 class Thing(object, metaclass=meta):
1348 pass
1349 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1350
1351 class sub(meta):
1352 pass
1353 class OtherThing(object, metaclass=sub):
1354 x = 3
1355 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1356
1357 class OtherOtherThing(OtherThing):
1358 pass
1359 # this test is odd, but it was added as it exposed a bug
1360 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1361
1362 def test_no_dict_no_slots(self):
1363 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1364 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1365
1366 def test_no_dict_no_slots_instance_member(self):
1367 # returns descriptor
1368 with open(__file__) as handle:
1369 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1370
1371 def test_inherited_slots(self):
1372 # returns descriptor
1373 class Thing(object):
1374 __slots__ = ['x']
1375 def __init__(self):
1376 self.x = 'foo'
1377
1378 class OtherThing(Thing):
1379 pass
1380 # it would be nice if this worked...
1381 # we get the descriptor instead of the instance attribute
1382 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1383
1384 def test_descriptor(self):
1385 class descriptor(object):
1386 def __get__(self, instance, owner):
1387 return 3
1388 class Foo(object):
1389 d = descriptor()
1390
1391 foo = Foo()
1392
1393 # for a non data descriptor we return the instance attribute
1394 foo.__dict__['d'] = 1
1395 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1396
1397 # if the descriptor is a data-desciptor we should return the
1398 # descriptor
1399 descriptor.__set__ = lambda s, i, v: None
1400 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1401
1402
1403 def test_metaclass_with_descriptor(self):
1404 class descriptor(object):
1405 def __get__(self, instance, owner):
1406 return 3
1407 class meta(type):
1408 d = descriptor()
1409 class Thing(object, metaclass=meta):
1410 pass
1411 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1412
1413
Michael Foordcc7ebb82010-11-20 16:20:16 +00001414 def test_class_as_property(self):
1415 class Base(object):
1416 foo = 3
1417
1418 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001419 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001420 @property
1421 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001422 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001423 return object
1424
Michael Foord35184ed2010-11-20 16:58:30 +00001425 instance = Something()
1426 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1427 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001428 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1429
Michael Foorde5162652010-11-20 16:40:44 +00001430 def test_mro_as_property(self):
1431 class Meta(type):
1432 @property
1433 def __mro__(self):
1434 return (object,)
1435
1436 class Base(object):
1437 foo = 3
1438
1439 class Something(Base, metaclass=Meta):
1440 pass
1441
1442 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1443 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1444
Michael Foorddcebe0f2011-03-15 19:20:44 -04001445 def test_dict_as_property(self):
1446 test = self
1447 test.called = False
1448
1449 class Foo(dict):
1450 a = 3
1451 @property
1452 def __dict__(self):
1453 test.called = True
1454 return {}
1455
1456 foo = Foo()
1457 foo.a = 4
1458 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1459 self.assertFalse(test.called)
1460
1461 def test_custom_object_dict(self):
1462 test = self
1463 test.called = False
1464
1465 class Custom(dict):
1466 def get(self, key, default=None):
1467 test.called = True
1468 super().get(key, default)
1469
1470 class Foo(object):
1471 a = 3
1472 foo = Foo()
1473 foo.__dict__ = Custom()
1474 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1475 self.assertFalse(test.called)
1476
1477 def test_metaclass_dict_as_property(self):
1478 class Meta(type):
1479 @property
1480 def __dict__(self):
1481 self.executed = True
1482
1483 class Thing(metaclass=Meta):
1484 executed = False
1485
1486 def __init__(self):
1487 self.spam = 42
1488
1489 instance = Thing()
1490 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1491 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001492
Michael Foorda51623b2011-12-18 22:01:40 +00001493 def test_module(self):
1494 sentinel = object()
1495 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1496 sentinel)
1497
Michael Foord3ba95f82011-12-22 01:13:37 +00001498 def test_metaclass_with_metaclass_with_dict_as_property(self):
1499 class MetaMeta(type):
1500 @property
1501 def __dict__(self):
1502 self.executed = True
1503 return dict(spam=42)
1504
1505 class Meta(type, metaclass=MetaMeta):
1506 executed = False
1507
1508 class Thing(metaclass=Meta):
1509 pass
1510
1511 with self.assertRaises(AttributeError):
1512 inspect.getattr_static(Thing, "spam")
1513 self.assertFalse(Thing.executed)
1514
Nick Coghlane0f04652010-11-21 03:44:04 +00001515class TestGetGeneratorState(unittest.TestCase):
1516
1517 def setUp(self):
1518 def number_generator():
1519 for number in range(5):
1520 yield number
1521 self.generator = number_generator()
1522
1523 def _generatorstate(self):
1524 return inspect.getgeneratorstate(self.generator)
1525
1526 def test_created(self):
1527 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1528
1529 def test_suspended(self):
1530 next(self.generator)
1531 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1532
1533 def test_closed_after_exhaustion(self):
1534 for i in self.generator:
1535 pass
1536 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1537
1538 def test_closed_after_immediate_exception(self):
1539 with self.assertRaises(RuntimeError):
1540 self.generator.throw(RuntimeError)
1541 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1542
1543 def test_running(self):
1544 # As mentioned on issue #10220, checking for the RUNNING state only
1545 # makes sense inside the generator itself.
1546 # The following generator checks for this by using the closure's
1547 # reference to self and the generator state checking helper method
1548 def running_check_generator():
1549 for number in range(5):
1550 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1551 yield number
1552 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1553 self.generator = running_check_generator()
1554 # Running up to the first yield
1555 next(self.generator)
1556 # Running after the first yield
1557 next(self.generator)
1558
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001559 def test_easy_debugging(self):
1560 # repr() and str() of a generator state should contain the state name
1561 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1562 for name in names:
1563 state = getattr(inspect, name)
1564 self.assertIn(name, repr(state))
1565 self.assertIn(name, str(state))
1566
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001567 def test_getgeneratorlocals(self):
1568 def each(lst, a=None):
1569 b=(1, 2, 3)
1570 for v in lst:
1571 if v == 3:
1572 c = 12
1573 yield v
1574
1575 numbers = each([1, 2, 3])
1576 self.assertEqual(inspect.getgeneratorlocals(numbers),
1577 {'a': None, 'lst': [1, 2, 3]})
1578 next(numbers)
1579 self.assertEqual(inspect.getgeneratorlocals(numbers),
1580 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1581 'b': (1, 2, 3)})
1582 next(numbers)
1583 self.assertEqual(inspect.getgeneratorlocals(numbers),
1584 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1585 'b': (1, 2, 3)})
1586 next(numbers)
1587 self.assertEqual(inspect.getgeneratorlocals(numbers),
1588 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1589 'b': (1, 2, 3), 'c': 12})
1590 try:
1591 next(numbers)
1592 except StopIteration:
1593 pass
1594 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1595
1596 def test_getgeneratorlocals_empty(self):
1597 def yield_one():
1598 yield 1
1599 one = yield_one()
1600 self.assertEqual(inspect.getgeneratorlocals(one), {})
1601 try:
1602 next(one)
1603 except StopIteration:
1604 pass
1605 self.assertEqual(inspect.getgeneratorlocals(one), {})
1606
1607 def test_getgeneratorlocals_error(self):
1608 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1609 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1610 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1611 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1612
Nick Coghlane0f04652010-11-21 03:44:04 +00001613
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001614class TestSignatureObject(unittest.TestCase):
1615 @staticmethod
1616 def signature(func):
1617 sig = inspect.signature(func)
1618 return (tuple((param.name,
1619 (... if param.default is param.empty else param.default),
1620 (... if param.annotation is param.empty
1621 else param.annotation),
1622 str(param.kind).lower())
1623 for param in sig.parameters.values()),
1624 (... if sig.return_annotation is sig.empty
1625 else sig.return_annotation))
1626
1627 def test_signature_object(self):
1628 S = inspect.Signature
1629 P = inspect.Parameter
1630
1631 self.assertEqual(str(S()), '()')
1632
Yury Selivanov07a9e452014-01-29 10:58:16 -05001633 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001634 pass
1635 sig = inspect.signature(test)
1636 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001637 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001638 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001639 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001640 args = sig.parameters['args']
1641 ko = sig.parameters['ko']
1642 kwargs = sig.parameters['kwargs']
1643
1644 S((po, pk, args, 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((pk, po, args, 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, args, pk, ko, kwargs))
1651
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001652 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001653 S((args, po, pk, ko, kwargs))
1654
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001655 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001656 S((po, pk, args, kwargs, ko))
1657
1658 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001659 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001660 S((po, pk, args, kwargs2, ko))
1661
Yury Selivanov07a9e452014-01-29 10:58:16 -05001662 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1663 S((pod, po))
1664
1665 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1666 S((po, pkd, pk))
1667
1668 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1669 S((pkd, pk))
1670
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001671 def test_signature_immutability(self):
1672 def test(a):
1673 pass
1674 sig = inspect.signature(test)
1675
1676 with self.assertRaises(AttributeError):
1677 sig.foo = 'bar'
1678
1679 with self.assertRaises(TypeError):
1680 sig.parameters['a'] = None
1681
1682 def test_signature_on_noarg(self):
1683 def test():
1684 pass
1685 self.assertEqual(self.signature(test), ((), ...))
1686
1687 def test_signature_on_wargs(self):
1688 def test(a, b:'foo') -> 123:
1689 pass
1690 self.assertEqual(self.signature(test),
1691 ((('a', ..., ..., "positional_or_keyword"),
1692 ('b', ..., 'foo', "positional_or_keyword")),
1693 123))
1694
1695 def test_signature_on_wkwonly(self):
1696 def test(*, a:float, b:str) -> int:
1697 pass
1698 self.assertEqual(self.signature(test),
1699 ((('a', ..., float, "keyword_only"),
1700 ('b', ..., str, "keyword_only")),
1701 int))
1702
1703 def test_signature_on_complex_args(self):
1704 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1705 pass
1706 self.assertEqual(self.signature(test),
1707 ((('a', ..., ..., "positional_or_keyword"),
1708 ('b', 10, 'foo', "positional_or_keyword"),
1709 ('args', ..., 'bar', "var_positional"),
1710 ('spam', ..., 'baz', "keyword_only"),
1711 ('ham', 123, ..., "keyword_only"),
1712 ('kwargs', ..., int, "var_keyword")),
1713 ...))
1714
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001715 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001716 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1717 "Signature information for builtins requires docstrings")
1718 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001719 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001720
Larry Hastings5c661892014-01-24 06:17:25 -08001721 def test_unbound_method(o):
1722 """Use this to test unbound methods (things that should have a self)"""
1723 signature = inspect.signature(o)
1724 self.assertTrue(isinstance(signature, inspect.Signature))
1725 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1726 return signature
1727
1728 def test_callable(o):
1729 """Use this to test bound methods or normal callables (things that don't expect self)"""
1730 signature = inspect.signature(o)
1731 self.assertTrue(isinstance(signature, inspect.Signature))
1732 if signature.parameters:
1733 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1734 return signature
1735
1736 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001737 def p(name): return signature.parameters[name].default
1738 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001739 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001740 self.assertEqual(p('d'), 3.14)
1741 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001742 self.assertEqual(p('n'), None)
1743 self.assertEqual(p('t'), True)
1744 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001745 self.assertEqual(p('local'), 3)
1746 self.assertEqual(p('sys'), sys.maxsize)
1747 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001748
Larry Hastings5c661892014-01-24 06:17:25 -08001749 test_callable(object)
1750
1751 # normal method
1752 # (PyMethodDescr_Type, "method_descriptor")
1753 test_unbound_method(_pickle.Pickler.dump)
1754 d = _pickle.Pickler(io.StringIO())
1755 test_callable(d.dump)
1756
1757 # static method
1758 test_callable(str.maketrans)
1759 test_callable('abc'.maketrans)
1760
1761 # class method
1762 test_callable(dict.fromkeys)
1763 test_callable({}.fromkeys)
1764
1765 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1766 test_unbound_method(type.__call__)
1767 test_unbound_method(int.__add__)
1768 test_callable((3).__add__)
1769
1770 # _PyMethodWrapper_Type
1771 # support for 'method-wrapper'
1772 test_callable(min.__call__)
1773
Larry Hastings2623c8c2014-02-08 22:15:29 -08001774 # This doesn't work now.
1775 # (We don't have a valid signature for "type" in 3.4)
1776 with self.assertRaisesRegex(ValueError, "no signature found"):
1777 class ThisWorksNow:
1778 __call__ = type
1779 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08001780
Yury Selivanovd930d852014-03-02 12:25:27 -05001781 # Regression test for issue #20786
1782 test_unbound_method(dict.__delitem__)
1783 test_unbound_method(property.__delete__)
1784
1785
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001786 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05001787 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1788 "Signature information for builtins requires docstrings")
1789 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001790 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05001791 func = _testcapi.docstring_with_signature_with_defaults
1792
1793 def decorator(func):
1794 @functools.wraps(func)
1795 def wrapper(*args, **kwargs) -> int:
1796 return func(*args, **kwargs)
1797 return wrapper
1798
1799 decorated_func = decorator(func)
1800
1801 self.assertEqual(inspect.signature(func),
1802 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08001803
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001804 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08001805 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001806 import _testcapi
Larry Hastings5c661892014-01-24 06:17:25 -08001807 with self.assertRaisesRegex(ValueError, 'no signature found for builtin'):
1808 inspect.signature(_testcapi.docstring_no_signature)
1809
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001810 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001811 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001812 inspect.signature(42)
1813
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001814 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001815 inspect.Signature.from_function(42)
1816
Yury Selivanovb77511d2014-01-29 10:46:14 -05001817 def test_signature_from_builtin_errors(self):
1818 with self.assertRaisesRegex(TypeError, 'is not a Python builtin'):
1819 inspect.Signature.from_builtin(42)
1820
Yury Selivanov63da7c72014-01-31 14:48:37 -05001821 def test_signature_from_functionlike_object(self):
1822 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1823 pass
1824
1825 class funclike:
1826 # Has to be callable, and have correct
1827 # __code__, __annotations__, __defaults__, __name__,
1828 # and __kwdefaults__ attributes
1829
1830 def __init__(self, func):
1831 self.__name__ = func.__name__
1832 self.__code__ = func.__code__
1833 self.__annotations__ = func.__annotations__
1834 self.__defaults__ = func.__defaults__
1835 self.__kwdefaults__ = func.__kwdefaults__
1836 self.func = func
1837
1838 def __call__(self, *args, **kwargs):
1839 return self.func(*args, **kwargs)
1840
1841 sig_func = inspect.Signature.from_function(func)
1842
1843 sig_funclike = inspect.Signature.from_function(funclike(func))
1844 self.assertEqual(sig_funclike, sig_func)
1845
1846 sig_funclike = inspect.signature(funclike(func))
1847 self.assertEqual(sig_funclike, sig_func)
1848
1849 # If object is not a duck type of function, then
1850 # signature will try to get a signature for its '__call__'
1851 # method
1852 fl = funclike(func)
1853 del fl.__defaults__
1854 self.assertEqual(self.signature(fl),
1855 ((('args', ..., ..., "var_positional"),
1856 ('kwargs', ..., ..., "var_keyword")),
1857 ...))
1858
Yury Selivanov8dfb4572014-02-21 18:30:53 -05001859 # Test with cython-like builtins:
1860 _orig_isdesc = inspect.ismethoddescriptor
1861 def _isdesc(obj):
1862 if hasattr(obj, '_builtinmock'):
1863 return True
1864 return _orig_isdesc(obj)
1865
1866 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
1867 builtin_func = funclike(func)
1868 # Make sure that our mock setup is working
1869 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
1870 builtin_func._builtinmock = True
1871 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
1872 self.assertEqual(inspect.signature(builtin_func), sig_func)
1873
Yury Selivanov63da7c72014-01-31 14:48:37 -05001874 def test_signature_functionlike_class(self):
1875 # We only want to duck type function-like objects,
1876 # not classes.
1877
1878 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1879 pass
1880
1881 class funclike:
1882 def __init__(self, marker):
1883 pass
1884
1885 __name__ = func.__name__
1886 __code__ = func.__code__
1887 __annotations__ = func.__annotations__
1888 __defaults__ = func.__defaults__
1889 __kwdefaults__ = func.__kwdefaults__
1890
1891 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1892 inspect.Signature.from_function(funclike)
1893
1894 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
1895
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001896 def test_signature_on_method(self):
1897 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05001898 def __init__(*args):
1899 pass
1900 def m1(self, arg1, arg2=1) -> int:
1901 pass
1902 def m2(*args):
1903 pass
1904 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001905 pass
1906
Yury Selivanov62560fb2014-01-28 12:26:24 -05001907 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001908 ((('arg1', ..., ..., "positional_or_keyword"),
1909 ('arg2', 1, ..., "positional_or_keyword")),
1910 int))
1911
Yury Selivanov62560fb2014-01-28 12:26:24 -05001912 self.assertEqual(self.signature(Test().m2),
1913 ((('args', ..., ..., "var_positional"),),
1914 ...))
1915
1916 self.assertEqual(self.signature(Test),
1917 ((('args', ..., ..., "var_positional"),),
1918 ...))
1919
1920 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
1921 self.signature(Test())
1922
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001923 def test_signature_on_classmethod(self):
1924 class Test:
1925 @classmethod
1926 def foo(cls, arg1, *, arg2=1):
1927 pass
1928
1929 meth = Test().foo
1930 self.assertEqual(self.signature(meth),
1931 ((('arg1', ..., ..., "positional_or_keyword"),
1932 ('arg2', 1, ..., "keyword_only")),
1933 ...))
1934
1935 meth = Test.foo
1936 self.assertEqual(self.signature(meth),
1937 ((('arg1', ..., ..., "positional_or_keyword"),
1938 ('arg2', 1, ..., "keyword_only")),
1939 ...))
1940
1941 def test_signature_on_staticmethod(self):
1942 class Test:
1943 @staticmethod
1944 def foo(cls, *, arg):
1945 pass
1946
1947 meth = Test().foo
1948 self.assertEqual(self.signature(meth),
1949 ((('cls', ..., ..., "positional_or_keyword"),
1950 ('arg', ..., ..., "keyword_only")),
1951 ...))
1952
1953 meth = Test.foo
1954 self.assertEqual(self.signature(meth),
1955 ((('cls', ..., ..., "positional_or_keyword"),
1956 ('arg', ..., ..., "keyword_only")),
1957 ...))
1958
1959 def test_signature_on_partial(self):
1960 from functools import partial
1961
1962 def test():
1963 pass
1964
1965 self.assertEqual(self.signature(partial(test)), ((), ...))
1966
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001967 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001968 inspect.signature(partial(test, 1))
1969
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001970 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001971 inspect.signature(partial(test, a=1))
1972
1973 def test(a, b, *, c, d):
1974 pass
1975
1976 self.assertEqual(self.signature(partial(test)),
1977 ((('a', ..., ..., "positional_or_keyword"),
1978 ('b', ..., ..., "positional_or_keyword"),
1979 ('c', ..., ..., "keyword_only"),
1980 ('d', ..., ..., "keyword_only")),
1981 ...))
1982
1983 self.assertEqual(self.signature(partial(test, 1)),
1984 ((('b', ..., ..., "positional_or_keyword"),
1985 ('c', ..., ..., "keyword_only"),
1986 ('d', ..., ..., "keyword_only")),
1987 ...))
1988
1989 self.assertEqual(self.signature(partial(test, 1, c=2)),
1990 ((('b', ..., ..., "positional_or_keyword"),
1991 ('c', 2, ..., "keyword_only"),
1992 ('d', ..., ..., "keyword_only")),
1993 ...))
1994
1995 self.assertEqual(self.signature(partial(test, b=1, c=2)),
1996 ((('a', ..., ..., "positional_or_keyword"),
1997 ('b', 1, ..., "positional_or_keyword"),
1998 ('c', 2, ..., "keyword_only"),
1999 ('d', ..., ..., "keyword_only")),
2000 ...))
2001
2002 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
2003 ((('b', 1, ..., "positional_or_keyword"),
2004 ('c', 2, ..., "keyword_only"),
2005 ('d', ..., ..., "keyword_only"),),
2006 ...))
2007
2008 def test(a, *args, b, **kwargs):
2009 pass
2010
2011 self.assertEqual(self.signature(partial(test, 1)),
2012 ((('args', ..., ..., "var_positional"),
2013 ('b', ..., ..., "keyword_only"),
2014 ('kwargs', ..., ..., "var_keyword")),
2015 ...))
2016
2017 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2018 ((('args', ..., ..., "var_positional"),
2019 ('b', ..., ..., "keyword_only"),
2020 ('kwargs', ..., ..., "var_keyword")),
2021 ...))
2022
2023
2024 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2025 ((('args', ..., ..., "var_positional"),
2026 ('b', ..., ..., "keyword_only"),
2027 ('kwargs', ..., ..., "var_keyword")),
2028 ...))
2029
2030 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2031 ((('args', ..., ..., "var_positional"),
2032 ('b', 0, ..., "keyword_only"),
2033 ('kwargs', ..., ..., "var_keyword")),
2034 ...))
2035
2036 self.assertEqual(self.signature(partial(test, b=0)),
2037 ((('a', ..., ..., "positional_or_keyword"),
2038 ('args', ..., ..., "var_positional"),
2039 ('b', 0, ..., "keyword_only"),
2040 ('kwargs', ..., ..., "var_keyword")),
2041 ...))
2042
2043 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2044 ((('a', ..., ..., "positional_or_keyword"),
2045 ('args', ..., ..., "var_positional"),
2046 ('b', 0, ..., "keyword_only"),
2047 ('kwargs', ..., ..., "var_keyword")),
2048 ...))
2049
2050 def test(a, b, c:int) -> 42:
2051 pass
2052
2053 sig = test.__signature__ = inspect.signature(test)
2054
2055 self.assertEqual(self.signature(partial(partial(test, 1))),
2056 ((('b', ..., ..., "positional_or_keyword"),
2057 ('c', ..., int, "positional_or_keyword")),
2058 42))
2059
2060 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2061 ((('c', ..., int, "positional_or_keyword"),),
2062 42))
2063
2064 psig = inspect.signature(partial(partial(test, 1), 2))
2065
2066 def foo(a):
2067 return a
2068 _foo = partial(partial(foo, a=10), a=20)
2069 self.assertEqual(self.signature(_foo),
2070 ((('a', 20, ..., "positional_or_keyword"),),
2071 ...))
2072 # check that we don't have any side-effects in signature(),
2073 # and the partial object is still functioning
2074 self.assertEqual(_foo(), 20)
2075
2076 def foo(a, b, c):
2077 return a, b, c
2078 _foo = partial(partial(foo, 1, b=20), b=30)
2079 self.assertEqual(self.signature(_foo),
2080 ((('b', 30, ..., "positional_or_keyword"),
2081 ('c', ..., ..., "positional_or_keyword")),
2082 ...))
2083 self.assertEqual(_foo(c=10), (1, 30, 10))
2084 _foo = partial(_foo, 2) # now 'b' has two values -
2085 # positional and keyword
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002086 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002087 inspect.signature(_foo)
2088
2089 def foo(a, b, c, *, d):
2090 return a, b, c, d
2091 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2092 self.assertEqual(self.signature(_foo),
2093 ((('a', ..., ..., "positional_or_keyword"),
2094 ('b', 10, ..., "positional_or_keyword"),
2095 ('c', 20, ..., "positional_or_keyword"),
2096 ('d', 30, ..., "keyword_only")),
2097 ...))
2098 ba = inspect.signature(_foo).bind(a=200, b=11)
2099 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2100
2101 def foo(a=1, b=2, c=3):
2102 return a, b, c
2103 _foo = partial(foo, a=10, c=13)
2104 ba = inspect.signature(_foo).bind(11)
2105 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
2106 ba = inspect.signature(_foo).bind(11, 12)
2107 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
2108 ba = inspect.signature(_foo).bind(11, b=12)
2109 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
2110 ba = inspect.signature(_foo).bind(b=12)
2111 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
2112 _foo = partial(_foo, b=10)
2113 ba = inspect.signature(_foo).bind(12, 14)
2114 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
2115
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002116 def test_signature_on_partialmethod(self):
2117 from functools import partialmethod
2118
2119 class Spam:
2120 def test():
2121 pass
2122 ham = partialmethod(test)
2123
2124 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2125 inspect.signature(Spam.ham)
2126
2127 class Spam:
2128 def test(it, a, *, c) -> 'spam':
2129 pass
2130 ham = partialmethod(test, c=1)
2131
2132 self.assertEqual(self.signature(Spam.ham),
2133 ((('it', ..., ..., 'positional_or_keyword'),
2134 ('a', ..., ..., 'positional_or_keyword'),
2135 ('c', 1, ..., 'keyword_only')),
2136 'spam'))
2137
2138 self.assertEqual(self.signature(Spam().ham),
2139 ((('a', ..., ..., 'positional_or_keyword'),
2140 ('c', 1, ..., 'keyword_only')),
2141 'spam'))
2142
Yury Selivanov0486f812014-01-29 12:18:59 -05002143 def test_signature_on_fake_partialmethod(self):
2144 def foo(a): pass
2145 foo._partialmethod = 'spam'
2146 self.assertEqual(str(inspect.signature(foo)), '(a)')
2147
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002148 def test_signature_on_decorated(self):
2149 import functools
2150
2151 def decorator(func):
2152 @functools.wraps(func)
2153 def wrapper(*args, **kwargs) -> int:
2154 return func(*args, **kwargs)
2155 return wrapper
2156
2157 class Foo:
2158 @decorator
2159 def bar(self, a, b):
2160 pass
2161
2162 self.assertEqual(self.signature(Foo.bar),
2163 ((('self', ..., ..., "positional_or_keyword"),
2164 ('a', ..., ..., "positional_or_keyword"),
2165 ('b', ..., ..., "positional_or_keyword")),
2166 ...))
2167
2168 self.assertEqual(self.signature(Foo().bar),
2169 ((('a', ..., ..., "positional_or_keyword"),
2170 ('b', ..., ..., "positional_or_keyword")),
2171 ...))
2172
2173 # Test that we handle method wrappers correctly
2174 def decorator(func):
2175 @functools.wraps(func)
2176 def wrapper(*args, **kwargs) -> int:
2177 return func(42, *args, **kwargs)
2178 sig = inspect.signature(func)
2179 new_params = tuple(sig.parameters.values())[1:]
2180 wrapper.__signature__ = sig.replace(parameters=new_params)
2181 return wrapper
2182
2183 class Foo:
2184 @decorator
2185 def __call__(self, a, b):
2186 pass
2187
2188 self.assertEqual(self.signature(Foo.__call__),
2189 ((('a', ..., ..., "positional_or_keyword"),
2190 ('b', ..., ..., "positional_or_keyword")),
2191 ...))
2192
2193 self.assertEqual(self.signature(Foo().__call__),
2194 ((('b', ..., ..., "positional_or_keyword"),),
2195 ...))
2196
Nick Coghlane8c45d62013-07-28 20:00:01 +10002197 # Test we handle __signature__ partway down the wrapper stack
2198 def wrapped_foo_call():
2199 pass
2200 wrapped_foo_call.__wrapped__ = Foo.__call__
2201
2202 self.assertEqual(self.signature(wrapped_foo_call),
2203 ((('a', ..., ..., "positional_or_keyword"),
2204 ('b', ..., ..., "positional_or_keyword")),
2205 ...))
2206
2207
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002208 def test_signature_on_class(self):
2209 class C:
2210 def __init__(self, a):
2211 pass
2212
2213 self.assertEqual(self.signature(C),
2214 ((('a', ..., ..., "positional_or_keyword"),),
2215 ...))
2216
2217 class CM(type):
2218 def __call__(cls, a):
2219 pass
2220 class C(metaclass=CM):
2221 def __init__(self, b):
2222 pass
2223
2224 self.assertEqual(self.signature(C),
2225 ((('a', ..., ..., "positional_or_keyword"),),
2226 ...))
2227
2228 class CM(type):
2229 def __new__(mcls, name, bases, dct, *, foo=1):
2230 return super().__new__(mcls, name, bases, dct)
2231 class C(metaclass=CM):
2232 def __init__(self, b):
2233 pass
2234
2235 self.assertEqual(self.signature(C),
2236 ((('b', ..., ..., "positional_or_keyword"),),
2237 ...))
2238
2239 self.assertEqual(self.signature(CM),
2240 ((('name', ..., ..., "positional_or_keyword"),
2241 ('bases', ..., ..., "positional_or_keyword"),
2242 ('dct', ..., ..., "positional_or_keyword"),
2243 ('foo', 1, ..., "keyword_only")),
2244 ...))
2245
2246 class CMM(type):
2247 def __new__(mcls, name, bases, dct, *, foo=1):
2248 return super().__new__(mcls, name, bases, dct)
2249 def __call__(cls, nm, bs, dt):
2250 return type(nm, bs, dt)
2251 class CM(type, metaclass=CMM):
2252 def __new__(mcls, name, bases, dct, *, bar=2):
2253 return super().__new__(mcls, name, bases, dct)
2254 class C(metaclass=CM):
2255 def __init__(self, b):
2256 pass
2257
2258 self.assertEqual(self.signature(CMM),
2259 ((('name', ..., ..., "positional_or_keyword"),
2260 ('bases', ..., ..., "positional_or_keyword"),
2261 ('dct', ..., ..., "positional_or_keyword"),
2262 ('foo', 1, ..., "keyword_only")),
2263 ...))
2264
2265 self.assertEqual(self.signature(CM),
2266 ((('nm', ..., ..., "positional_or_keyword"),
2267 ('bs', ..., ..., "positional_or_keyword"),
2268 ('dt', ..., ..., "positional_or_keyword")),
2269 ...))
2270
2271 self.assertEqual(self.signature(C),
2272 ((('b', ..., ..., "positional_or_keyword"),),
2273 ...))
2274
2275 class CM(type):
2276 def __init__(cls, name, bases, dct, *, bar=2):
2277 return super().__init__(name, bases, dct)
2278 class C(metaclass=CM):
2279 def __init__(self, b):
2280 pass
2281
2282 self.assertEqual(self.signature(CM),
2283 ((('name', ..., ..., "positional_or_keyword"),
2284 ('bases', ..., ..., "positional_or_keyword"),
2285 ('dct', ..., ..., "positional_or_keyword"),
2286 ('bar', 2, ..., "keyword_only")),
2287 ...))
2288
Yury Selivanov145dff82014-02-01 13:49:29 -05002289 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2290 "Signature information for builtins requires docstrings")
2291 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002292 # Test classes without user-defined __init__ or __new__
2293 class C: pass
2294 self.assertEqual(str(inspect.signature(C)), '()')
2295 class D(C): pass
2296 self.assertEqual(str(inspect.signature(D)), '()')
2297
2298 # Test meta-classes without user-defined __init__ or __new__
2299 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002300 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002301 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2302 self.assertEqual(inspect.signature(C), None)
2303 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2304 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002305
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002306 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2307 "Signature information for builtins requires docstrings")
2308 def test_signature_on_builtin_class(self):
2309 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2310 '(file, protocol=None, fix_imports=True)')
2311
2312 class P(_pickle.Pickler): pass
2313 class EmptyTrait: pass
2314 class P2(EmptyTrait, P): pass
2315 self.assertEqual(str(inspect.signature(P)),
2316 '(file, protocol=None, fix_imports=True)')
2317 self.assertEqual(str(inspect.signature(P2)),
2318 '(file, protocol=None, fix_imports=True)')
2319
2320 class P3(P2):
2321 def __init__(self, spam):
2322 pass
2323 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2324
2325 class MetaP(type):
2326 def __call__(cls, foo, bar):
2327 pass
2328 class P4(P2, metaclass=MetaP):
2329 pass
2330 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2331
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002332 def test_signature_on_callable_objects(self):
2333 class Foo:
2334 def __call__(self, a):
2335 pass
2336
2337 self.assertEqual(self.signature(Foo()),
2338 ((('a', ..., ..., "positional_or_keyword"),),
2339 ...))
2340
2341 class Spam:
2342 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002343 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002344 inspect.signature(Spam())
2345
2346 class Bar(Spam, Foo):
2347 pass
2348
2349 self.assertEqual(self.signature(Bar()),
2350 ((('a', ..., ..., "positional_or_keyword"),),
2351 ...))
2352
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002353 class Wrapped:
2354 pass
2355 Wrapped.__wrapped__ = lambda a: None
2356 self.assertEqual(self.signature(Wrapped),
2357 ((('a', ..., ..., "positional_or_keyword"),),
2358 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002359 # wrapper loop:
2360 Wrapped.__wrapped__ = Wrapped
2361 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2362 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002363
2364 def test_signature_on_lambdas(self):
2365 self.assertEqual(self.signature((lambda a=10: a)),
2366 ((('a', 10, ..., "positional_or_keyword"),),
2367 ...))
2368
2369 def test_signature_equality(self):
2370 def foo(a, *, b:int) -> float: pass
2371 self.assertNotEqual(inspect.signature(foo), 42)
2372
2373 def bar(a, *, b:int) -> float: pass
2374 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2375
2376 def bar(a, *, b:int) -> int: pass
2377 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2378
2379 def bar(a, *, b:int): pass
2380 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2381
2382 def bar(a, *, b:int=42) -> float: pass
2383 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2384
2385 def bar(a, *, c) -> float: pass
2386 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2387
2388 def bar(a, b:int) -> float: pass
2389 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2390 def spam(b:int, a) -> float: pass
2391 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
2392
2393 def foo(*, a, b, c): pass
2394 def bar(*, c, b, a): pass
2395 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2396
2397 def foo(*, a=1, b, c): pass
2398 def bar(*, c, b, a=1): pass
2399 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2400
2401 def foo(pos, *, a=1, b, c): pass
2402 def bar(pos, *, c, b, a=1): pass
2403 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2404
2405 def foo(pos, *, a, b, c): pass
2406 def bar(pos, *, c, b, a=1): pass
2407 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2408
2409 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2410 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2411 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2412
2413 def test_signature_unhashable(self):
2414 def foo(a): pass
2415 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002416 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002417 hash(sig)
2418
2419 def test_signature_str(self):
2420 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2421 pass
2422 self.assertEqual(str(inspect.signature(foo)),
2423 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2424
2425 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2426 pass
2427 self.assertEqual(str(inspect.signature(foo)),
2428 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2429
2430 def foo():
2431 pass
2432 self.assertEqual(str(inspect.signature(foo)), '()')
2433
2434 def test_signature_str_positional_only(self):
2435 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002436 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002437
2438 def test(a_po, *, b, **kwargs):
2439 return a_po, kwargs
2440
2441 sig = inspect.signature(test)
2442 new_params = list(sig.parameters.values())
2443 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2444 test.__signature__ = sig.replace(parameters=new_params)
2445
2446 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002447 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002448
Yury Selivanov2393dca2014-01-27 15:07:58 -05002449 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2450 '(foo, /)')
2451
2452 self.assertEqual(str(S(parameters=[
2453 P('foo', P.POSITIONAL_ONLY),
2454 P('bar', P.VAR_KEYWORD)])),
2455 '(foo, /, **bar)')
2456
2457 self.assertEqual(str(S(parameters=[
2458 P('foo', P.POSITIONAL_ONLY),
2459 P('bar', P.VAR_POSITIONAL)])),
2460 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002461
2462 def test_signature_replace_anno(self):
2463 def test() -> 42:
2464 pass
2465
2466 sig = inspect.signature(test)
2467 sig = sig.replace(return_annotation=None)
2468 self.assertIs(sig.return_annotation, None)
2469 sig = sig.replace(return_annotation=sig.empty)
2470 self.assertIs(sig.return_annotation, sig.empty)
2471 sig = sig.replace(return_annotation=42)
2472 self.assertEqual(sig.return_annotation, 42)
2473 self.assertEqual(sig, inspect.signature(test))
2474
Yury Selivanov026019f2014-02-18 12:49:41 -05002475 def test_signature_on_mangled_parameters(self):
2476 class Spam:
2477 def foo(self, __p1:1=2, *, __p2:2=3):
2478 pass
2479 class Ham(Spam):
2480 pass
2481
2482 self.assertEqual(self.signature(Spam.foo),
2483 ((('self', ..., ..., "positional_or_keyword"),
2484 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2485 ('_Spam__p2', 3, 2, "keyword_only")),
2486 ...))
2487
2488 self.assertEqual(self.signature(Spam.foo),
2489 self.signature(Ham.foo))
2490
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002491
2492class TestParameterObject(unittest.TestCase):
2493 def test_signature_parameter_kinds(self):
2494 P = inspect.Parameter
2495 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2496 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2497
2498 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2499 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2500
2501 def test_signature_parameter_object(self):
2502 p = inspect.Parameter('foo', default=10,
2503 kind=inspect.Parameter.POSITIONAL_ONLY)
2504 self.assertEqual(p.name, 'foo')
2505 self.assertEqual(p.default, 10)
2506 self.assertIs(p.annotation, p.empty)
2507 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2508
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002509 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002510 inspect.Parameter('foo', default=10, kind='123')
2511
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002512 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002513 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2514
Yury Selivanov2393dca2014-01-27 15:07:58 -05002515 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002516 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2517
Yury Selivanov2393dca2014-01-27 15:07:58 -05002518 with self.assertRaisesRegex(ValueError,
2519 'is not a valid parameter name'):
2520 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2521
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002522 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002523 inspect.Parameter('a', default=42,
2524 kind=inspect.Parameter.VAR_KEYWORD)
2525
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002526 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002527 inspect.Parameter('a', default=42,
2528 kind=inspect.Parameter.VAR_POSITIONAL)
2529
2530 p = inspect.Parameter('a', default=42,
2531 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002532 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002533 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2534
2535 self.assertTrue(repr(p).startswith('<Parameter'))
2536
2537 def test_signature_parameter_equality(self):
2538 P = inspect.Parameter
2539 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2540
2541 self.assertEqual(p, p)
2542 self.assertNotEqual(p, 42)
2543
2544 self.assertEqual(p, P('foo', default=42,
2545 kind=inspect.Parameter.KEYWORD_ONLY))
2546
2547 def test_signature_parameter_unhashable(self):
2548 p = inspect.Parameter('foo', default=42,
2549 kind=inspect.Parameter.KEYWORD_ONLY)
2550
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002551 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002552 hash(p)
2553
2554 def test_signature_parameter_replace(self):
2555 p = inspect.Parameter('foo', default=42,
2556 kind=inspect.Parameter.KEYWORD_ONLY)
2557
2558 self.assertIsNot(p, p.replace())
2559 self.assertEqual(p, p.replace())
2560
2561 p2 = p.replace(annotation=1)
2562 self.assertEqual(p2.annotation, 1)
2563 p2 = p2.replace(annotation=p2.empty)
2564 self.assertEqual(p, p2)
2565
2566 p2 = p2.replace(name='bar')
2567 self.assertEqual(p2.name, 'bar')
2568 self.assertNotEqual(p2, p)
2569
Yury Selivanov2393dca2014-01-27 15:07:58 -05002570 with self.assertRaisesRegex(ValueError,
2571 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002572 p2 = p2.replace(name=p2.empty)
2573
2574 p2 = p2.replace(name='foo', default=None)
2575 self.assertIs(p2.default, None)
2576 self.assertNotEqual(p2, p)
2577
2578 p2 = p2.replace(name='foo', default=p2.empty)
2579 self.assertIs(p2.default, p2.empty)
2580
2581
2582 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2583 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2584 self.assertNotEqual(p2, p)
2585
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002586 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002587 p2 = p2.replace(kind=p2.empty)
2588
2589 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2590 self.assertEqual(p2, p)
2591
2592 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002593 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2594 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002595
2596 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002597 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002598
2599 with self.assertRaises(AttributeError):
2600 p.foo = 'bar'
2601
2602 with self.assertRaises(AttributeError):
2603 p.kind = 123
2604
2605
2606class TestSignatureBind(unittest.TestCase):
2607 @staticmethod
2608 def call(func, *args, **kwargs):
2609 sig = inspect.signature(func)
2610 ba = sig.bind(*args, **kwargs)
2611 return func(*ba.args, **ba.kwargs)
2612
2613 def test_signature_bind_empty(self):
2614 def test():
2615 return 42
2616
2617 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002618 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002619 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002620 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002621 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002622 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002623 self.call(test, spam=1)
2624
2625 def test_signature_bind_var(self):
2626 def test(*args, **kwargs):
2627 return args, kwargs
2628
2629 self.assertEqual(self.call(test), ((), {}))
2630 self.assertEqual(self.call(test, 1), ((1,), {}))
2631 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2632 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2633 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2634 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2635 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2636 ((1, 2), {'foo': 'bar'}))
2637
2638 def test_signature_bind_just_args(self):
2639 def test(a, b, c):
2640 return a, b, c
2641
2642 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2643
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002644 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002645 self.call(test, 1, 2, 3, 4)
2646
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002647 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002648 self.call(test, 1)
2649
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002650 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002651 self.call(test)
2652
2653 def test(a, b, c=10):
2654 return a, b, c
2655 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2656 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2657
2658 def test(a=1, b=2, c=3):
2659 return a, b, c
2660 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2661 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2662 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2663
2664 def test_signature_bind_varargs_order(self):
2665 def test(*args):
2666 return args
2667
2668 self.assertEqual(self.call(test), ())
2669 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2670
2671 def test_signature_bind_args_and_varargs(self):
2672 def test(a, b, c=3, *args):
2673 return a, b, c, args
2674
2675 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2676 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2677 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2678 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2679
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002680 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002681 "multiple values for argument 'c'"):
2682 self.call(test, 1, 2, 3, c=4)
2683
2684 def test_signature_bind_just_kwargs(self):
2685 def test(**kwargs):
2686 return kwargs
2687
2688 self.assertEqual(self.call(test), {})
2689 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2690 {'foo': 'bar', 'spam': 'ham'})
2691
2692 def test_signature_bind_args_and_kwargs(self):
2693 def test(a, b, c=3, **kwargs):
2694 return a, b, c, kwargs
2695
2696 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2697 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2698 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2699 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2700 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2701 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2702 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2703 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2704 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2705 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2706 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2707 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2708 (1, 2, 4, {'foo': 'bar'}))
2709 self.assertEqual(self.call(test, c=5, a=4, b=3),
2710 (4, 3, 5, {}))
2711
2712 def test_signature_bind_kwonly(self):
2713 def test(*, foo):
2714 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002715 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002716 'too many positional arguments'):
2717 self.call(test, 1)
2718 self.assertEqual(self.call(test, foo=1), 1)
2719
2720 def test(a, *, foo=1, bar):
2721 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002722 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002723 "'bar' parameter lacking default value"):
2724 self.call(test, 1)
2725
2726 def test(foo, *, bar):
2727 return foo, bar
2728 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2729 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2730
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002731 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002732 'too many keyword arguments'):
2733 self.call(test, bar=2, foo=1, spam=10)
2734
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002735 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002736 'too many positional arguments'):
2737 self.call(test, 1, 2)
2738
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002739 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002740 'too many positional arguments'):
2741 self.call(test, 1, 2, bar=2)
2742
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002743 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002744 'too many keyword arguments'):
2745 self.call(test, 1, bar=2, spam='ham')
2746
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002747 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002748 "'bar' parameter lacking default value"):
2749 self.call(test, 1)
2750
2751 def test(foo, *, bar, **bin):
2752 return foo, bar, bin
2753 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2754 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2755 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2756 (1, 2, {'spam': 'ham'}))
2757 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2758 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002759 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002760 "'foo' parameter lacking default value"):
2761 self.call(test, spam='ham', bar=2)
2762 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2763 (1, 2, {'bin': 1, 'spam': 10}))
2764
2765 def test_signature_bind_arguments(self):
2766 def test(a, *args, b, z=100, **kwargs):
2767 pass
2768 sig = inspect.signature(test)
2769 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2770 # we won't have 'z' argument in the bound arguments object, as we didn't
2771 # pass it to the 'bind'
2772 self.assertEqual(tuple(ba.arguments.items()),
2773 (('a', 10), ('args', (20,)), ('b', 30),
2774 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2775 self.assertEqual(ba.kwargs,
2776 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2777 self.assertEqual(ba.args, (10, 20))
2778
2779 def test_signature_bind_positional_only(self):
2780 P = inspect.Parameter
2781
2782 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2783 return a_po, b_po, c_po, foo, bar, kwargs
2784
2785 sig = inspect.signature(test)
2786 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2787 for name in ('a_po', 'b_po', 'c_po'):
2788 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2789 new_sig = sig.replace(parameters=new_params.values())
2790 test.__signature__ = new_sig
2791
2792 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2793 (1, 2, 4, 5, 6, {}))
2794
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002795 self.assertEqual(self.call(test, 1, 2),
2796 (1, 2, 3, 42, 50, {}))
2797
2798 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
2799 (1, 2, 3, 4, 5, {}))
2800
2801 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
2802 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
2803
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002804 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002805 self.call(test, 1, 2, c_po=4)
2806
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002807 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002808 self.call(test, a_po=1, b_po=2)
2809
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002810 def test_signature_bind_with_self_arg(self):
2811 # Issue #17071: one of the parameters is named "self
2812 def test(a, self, b):
2813 pass
2814 sig = inspect.signature(test)
2815 ba = sig.bind(1, 2, 3)
2816 self.assertEqual(ba.args, (1, 2, 3))
2817 ba = sig.bind(1, self=2, b=3)
2818 self.assertEqual(ba.args, (1, 2, 3))
2819
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002820 def test_signature_bind_vararg_name(self):
2821 def test(a, *args):
2822 return a, args
2823 sig = inspect.signature(test)
2824
2825 with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
2826 sig.bind(a=0, args=1)
2827
2828 def test(*args, **kwargs):
2829 return args, kwargs
2830 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
2831
2832 sig = inspect.signature(test)
2833 ba = sig.bind(args=1)
2834 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
2835
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002836
2837class TestBoundArguments(unittest.TestCase):
2838 def test_signature_bound_arguments_unhashable(self):
2839 def foo(a): pass
2840 ba = inspect.signature(foo).bind(1)
2841
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002842 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002843 hash(ba)
2844
2845 def test_signature_bound_arguments_equality(self):
2846 def foo(a): pass
2847 ba = inspect.signature(foo).bind(1)
2848 self.assertEqual(ba, ba)
2849
2850 ba2 = inspect.signature(foo).bind(1)
2851 self.assertEqual(ba, ba2)
2852
2853 ba3 = inspect.signature(foo).bind(2)
2854 self.assertNotEqual(ba, ba3)
2855 ba3.arguments['a'] = 1
2856 self.assertEqual(ba, ba3)
2857
2858 def bar(b): pass
2859 ba4 = inspect.signature(bar).bind(1)
2860 self.assertNotEqual(ba, ba4)
2861
2862
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002863class TestSignaturePrivateHelpers(unittest.TestCase):
2864 def test_signature_get_bound_param(self):
2865 getter = inspect._signature_get_bound_param
2866
2867 self.assertEqual(getter('($self)'), 'self')
2868 self.assertEqual(getter('($self, obj)'), 'self')
2869 self.assertEqual(getter('($cls, /, obj)'), 'cls')
2870
Larry Hastings2623c8c2014-02-08 22:15:29 -08002871 def _strip_non_python_syntax(self, input,
2872 clean_signature, self_parameter, last_positional_only):
2873 computed_clean_signature, \
2874 computed_self_parameter, \
2875 computed_last_positional_only = \
2876 inspect._signature_strip_non_python_syntax(input)
2877 self.assertEqual(computed_clean_signature, clean_signature)
2878 self.assertEqual(computed_self_parameter, self_parameter)
2879 self.assertEqual(computed_last_positional_only, last_positional_only)
2880
2881 def test_signature_strip_non_python_syntax(self):
2882 self._strip_non_python_syntax(
2883 "($module, /, path, mode, *, dir_fd=None, " +
2884 "effective_ids=False,\n follow_symlinks=True)",
2885 "(module, path, mode, *, dir_fd=None, " +
2886 "effective_ids=False, follow_symlinks=True)",
2887 0,
2888 0)
2889
2890 self._strip_non_python_syntax(
2891 "($module, word, salt, /)",
2892 "(module, word, salt)",
2893 0,
2894 2)
2895
2896 self._strip_non_python_syntax(
2897 "(x, y=None, z=None, /)",
2898 "(x, y=None, z=None)",
2899 None,
2900 2)
2901
2902 self._strip_non_python_syntax(
2903 "(x, y=None, z=None)",
2904 "(x, y=None, z=None)",
2905 None,
2906 None)
2907
2908 self._strip_non_python_syntax(
2909 "(x,\n y=None,\n z = None )",
2910 "(x, y=None, z=None)",
2911 None,
2912 None)
2913
2914 self._strip_non_python_syntax(
2915 "",
2916 "",
2917 None,
2918 None)
2919
2920 self._strip_non_python_syntax(
2921 None,
2922 None,
2923 None,
2924 None)
2925
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002926
Nick Coghlane8c45d62013-07-28 20:00:01 +10002927class TestUnwrap(unittest.TestCase):
2928
2929 def test_unwrap_one(self):
2930 def func(a, b):
2931 return a + b
2932 wrapper = functools.lru_cache(maxsize=20)(func)
2933 self.assertIs(inspect.unwrap(wrapper), func)
2934
2935 def test_unwrap_several(self):
2936 def func(a, b):
2937 return a + b
2938 wrapper = func
2939 for __ in range(10):
2940 @functools.wraps(wrapper)
2941 def wrapper():
2942 pass
2943 self.assertIsNot(wrapper.__wrapped__, func)
2944 self.assertIs(inspect.unwrap(wrapper), func)
2945
2946 def test_stop(self):
2947 def func1(a, b):
2948 return a + b
2949 @functools.wraps(func1)
2950 def func2():
2951 pass
2952 @functools.wraps(func2)
2953 def wrapper():
2954 pass
2955 func2.stop_here = 1
2956 unwrapped = inspect.unwrap(wrapper,
2957 stop=(lambda f: hasattr(f, "stop_here")))
2958 self.assertIs(unwrapped, func2)
2959
2960 def test_cycle(self):
2961 def func1(): pass
2962 func1.__wrapped__ = func1
2963 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2964 inspect.unwrap(func1)
2965
2966 def func2(): pass
2967 func2.__wrapped__ = func1
2968 func1.__wrapped__ = func2
2969 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2970 inspect.unwrap(func1)
2971 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2972 inspect.unwrap(func2)
2973
2974 def test_unhashable(self):
2975 def func(): pass
2976 func.__wrapped__ = None
2977 class C:
2978 __hash__ = None
2979 __wrapped__ = func
2980 self.assertIsNone(inspect.unwrap(C()))
2981
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002982class TestMain(unittest.TestCase):
2983 def test_only_source(self):
2984 module = importlib.import_module('unittest')
2985 rc, out, err = assert_python_ok('-m', 'inspect',
2986 'unittest')
2987 lines = out.decode().splitlines()
2988 # ignore the final newline
2989 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
2990 self.assertEqual(err, b'')
2991
Brett Cannon634a8fc2013-10-02 10:25:42 -04002992 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04002993 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002994 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002995 rc, out, err = assert_python_ok('-m', 'inspect',
2996 'concurrent.futures:ThreadPoolExecutor')
2997 lines = out.decode().splitlines()
2998 # ignore the final newline
2999 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003000 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003001 self.assertEqual(err, b'')
3002
3003 def test_builtins(self):
3004 module = importlib.import_module('unittest')
3005 _, out, err = assert_python_failure('-m', 'inspect',
3006 'sys')
3007 lines = err.decode().splitlines()
3008 self.assertEqual(lines, ["Can't get info for builtin modules."])
3009
3010 def test_details(self):
3011 module = importlib.import_module('unittest')
3012 rc, out, err = assert_python_ok('-m', 'inspect',
3013 'unittest', '--details')
3014 output = out.decode()
3015 # Just a quick sanity check on the output
3016 self.assertIn(module.__name__, output)
3017 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02003018 if not sys.flags.optimize:
3019 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003020 self.assertEqual(err, b'')
3021
3022
3023
Nick Coghlane8c45d62013-07-28 20:00:01 +10003024
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003025def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003026 run_unittest(
3027 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3028 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3029 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003030 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003031 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003032 TestBoundArguments, TestSignaturePrivateHelpers, TestGetClosureVars,
3033 TestUnwrap, TestMain
Michael Foord95fc51d2010-11-20 15:07:30 +00003034 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003035
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003036if __name__ == "__main__":
3037 test_main()