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