blob: a2bb9b6a2a7a5f85229c3d95875a0a59103037ee [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
Yury Selivanov7de29682014-12-08 18:00:25 -050015import textwrap
Larry Hastings5c661892014-01-24 06:17:25 -080016import unicodedata
17import unittest
Yury Selivanov8dfb4572014-02-21 18:30:53 -050018import unittest.mock
Larry Hastings5c661892014-01-24 06:17:25 -080019
Brett Cannon634a8fc2013-10-02 10:25:42 -040020try:
21 from concurrent.futures import ThreadPoolExecutor
22except ImportError:
23 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000024
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020025from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -080026from test.support import MISSING_C_DOCSTRINGS
Nick Coghlanf94a16b2013-09-22 22:46:49 +100027from test.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000028from test import inspect_fodder as mod
29from test import inspect_fodder2 as mod2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000030
Yury Selivanov7de29682014-12-08 18:00:25 -050031from test.test_import import _ready_to_import
32
R. David Murray74b89242009-05-13 17:33:03 +000033
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000034# Functions tested in this suite:
35# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000036# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
37# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
38# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
39# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000040
Nick Coghlanf088e5e2008-12-14 11:50:48 +000041# NOTE: There are some additional tests relating to interaction with
42# zipimport in the test_zipimport_support test module.
43
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000044modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000045if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000046 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000047
Christian Heimesa3538eb2007-11-06 11:44:48 +000048# Normalize file names: on Windows, the case of file names of compiled
49# modules depends on the path used to start the python executable.
50modfile = normcase(modfile)
51
52def revise(filename, *args):
53 return (normcase(filename),) + args
54
Georg Brandl1a3284e2007-12-02 09:40:06 +000055import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000056
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000057git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000058
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000059class IsTestBase(unittest.TestCase):
60 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
61 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000062 inspect.ismodule, inspect.istraceback,
63 inspect.isgenerator, inspect.isgeneratorfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000064
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000065 def istest(self, predicate, exp):
66 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000067 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000068
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000069 for other in self.predicates - set([predicate]):
Christian Heimes7131fd92008-02-19 14:21:46 +000070 if predicate == inspect.isgeneratorfunction and\
71 other == inspect.isfunction:
72 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000073 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000074
Christian Heimes7131fd92008-02-19 14:21:46 +000075def generator_function_example(self):
76 for i in range(2):
77 yield i
78
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000079class TestPredicates(IsTestBase):
Christian Heimes227c8002008-03-03 20:34:40 +000080 def test_sixteen(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +000081 count = len([x for x in dir(inspect) if x.startswith('is')])
Christian Heimes7131fd92008-02-19 14:21:46 +000082 # This test is here for remember you to update Doc/library/inspect.rst
Christian Heimes78644762008-03-04 23:39:23 +000083 # which claims there are 16 such functions
Christian Heimes227c8002008-03-03 20:34:40 +000084 expected = 16
Thomas Wouters0e3f5912006-08-11 14:57:12 +000085 err_msg = "There are %d (not %d) is* functions" % (count, expected)
86 self.assertEqual(count, expected, err_msg)
Tim Peters5a9fb3c2005-01-07 16:01:32 +000087
Christian Heimes7131fd92008-02-19 14:21:46 +000088
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000089 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +020090 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000091 self.istest(inspect.isbuiltin, 'sys.exit')
92 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +000093 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +020094 try:
95 1/0
96 except:
97 tb = sys.exc_info()[2]
98 self.istest(inspect.isframe, 'tb.tb_frame')
99 self.istest(inspect.istraceback, 'tb')
100 if hasattr(types, 'GetSetDescriptorType'):
101 self.istest(inspect.isgetsetdescriptor,
102 'type(tb.tb_frame).f_locals')
103 else:
104 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
105 finally:
106 # Clear traceback and all the frames and local variables hanging to it.
107 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000108 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000109 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000110 self.istest(inspect.ismethod, 'git.argue')
111 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000112 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000113 self.istest(inspect.isgenerator, '(x for x in range(2))')
114 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000115 if hasattr(types, 'MemberDescriptorType'):
116 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
117 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000118 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000119
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000120 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000121 self.assertTrue(inspect.isroutine(mod.spam))
122 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000123
Benjamin Petersonc4656002009-01-17 22:41:18 +0000124 def test_isclass(self):
125 self.istest(inspect.isclass, 'mod.StupidGit')
126 self.assertTrue(inspect.isclass(list))
127
128 class CustomGetattr(object):
129 def __getattr__(self, attr):
130 return None
131 self.assertFalse(inspect.isclass(CustomGetattr()))
132
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000133 def test_get_slot_members(self):
134 class C(object):
135 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000136 x = C()
137 x.a = 42
138 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000139 self.assertIn('a', members)
140 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000141
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000142 def test_isabstract(self):
143 from abc import ABCMeta, abstractmethod
144
145 class AbstractClassExample(metaclass=ABCMeta):
146
147 @abstractmethod
148 def foo(self):
149 pass
150
151 class ClassExample(AbstractClassExample):
152 def foo(self):
153 pass
154
155 a = ClassExample()
156
157 # Test general behaviour.
158 self.assertTrue(inspect.isabstract(AbstractClassExample))
159 self.assertFalse(inspect.isabstract(ClassExample))
160 self.assertFalse(inspect.isabstract(a))
161 self.assertFalse(inspect.isabstract(int))
162 self.assertFalse(inspect.isabstract(5))
163
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000164
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000165class TestInterpreterStack(IsTestBase):
166 def __init__(self, *args, **kwargs):
167 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000168
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000169 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000170
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000171 def test_abuse_done(self):
172 self.istest(inspect.istraceback, 'git.ex[2]')
173 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000174
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000175 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000176 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000177 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000178 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000179 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000180 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000181 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000182 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000183 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000184 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000185
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000186 def test_trace(self):
187 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000188 self.assertEqual(revise(*git.tr[0][1:]),
189 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
190 self.assertEqual(revise(*git.tr[1][1:]),
191 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
192 self.assertEqual(revise(*git.tr[2][1:]),
193 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000194
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000195 def test_frame(self):
196 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
197 self.assertEqual(args, ['x', 'y'])
198 self.assertEqual(varargs, None)
199 self.assertEqual(varkw, None)
200 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
201 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
202 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000203
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000204 def test_previous_frame(self):
205 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000206 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000207 self.assertEqual(varargs, 'g')
208 self.assertEqual(varkw, 'h')
209 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000210 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000211
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000212class GetSourceBase(unittest.TestCase):
213 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000214 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000215
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000216 def __init__(self, *args, **kwargs):
217 unittest.TestCase.__init__(self, *args, **kwargs)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000218
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000219 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000220 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000221
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000222 def sourcerange(self, top, bottom):
223 lines = self.source.split("\n")
224 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000225
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000226 def assertSourceEqual(self, obj, top, bottom):
227 self.assertEqual(inspect.getsource(obj),
228 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000229
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000230class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000231 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000232
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000233 def test_getclasses(self):
234 classes = inspect.getmembers(mod, inspect.isclass)
235 self.assertEqual(classes,
236 [('FesteringGob', mod.FesteringGob),
237 ('MalodorousPervert', mod.MalodorousPervert),
238 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300239 ('StupidGit', mod.StupidGit),
240 ('Tit', mod.MalodorousPervert),
241 ])
242 tree = inspect.getclasstree([cls[1] for cls in classes])
243 self.assertEqual(tree,
244 [(object, ()),
245 [(mod.ParrotDroppings, (object,)),
246 [(mod.FesteringGob, (mod.MalodorousPervert,
247 mod.ParrotDroppings))
248 ],
249 (mod.StupidGit, (object,)),
250 [(mod.MalodorousPervert, (mod.StupidGit,)),
251 [(mod.FesteringGob, (mod.MalodorousPervert,
252 mod.ParrotDroppings))
253 ]
254 ]
255 ]
256 ])
257 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000258 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000259 [(object, ()),
260 [(mod.ParrotDroppings, (object,)),
261 (mod.StupidGit, (object,)),
262 [(mod.MalodorousPervert, (mod.StupidGit,)),
263 [(mod.FesteringGob, (mod.MalodorousPervert,
264 mod.ParrotDroppings))
265 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000266 ]
267 ]
268 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000269
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000270 def test_getfunctions(self):
271 functions = inspect.getmembers(mod, inspect.isfunction)
272 self.assertEqual(functions, [('eggs', mod.eggs),
273 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000274
R. David Murray378c0cf2010-02-24 01:46:21 +0000275 @unittest.skipIf(sys.flags.optimize >= 2,
276 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000277 def test_getdoc(self):
278 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
279 self.assertEqual(inspect.getdoc(mod.StupidGit),
280 'A longer,\n\nindented\n\ndocstring.')
281 self.assertEqual(inspect.getdoc(git.abuse),
282 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000283
Georg Brandl0c77a822008-06-10 16:37:50 +0000284 def test_cleandoc(self):
285 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
286 'An\nindented\ndocstring.')
287
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000288 def test_getcomments(self):
289 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
290 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000291
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000292 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000293 # Check actual module
294 self.assertEqual(inspect.getmodule(mod), mod)
295 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000296 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000297 # Check a method (no __module__ attribute, falls back to filename)
298 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
299 # Do it again (check the caching isn't broken)
300 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
301 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000302 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000303 # Check filename override
304 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000305
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000306 def test_getsource(self):
307 self.assertSourceEqual(git.abuse, 29, 39)
308 self.assertSourceEqual(mod.StupidGit, 21, 46)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000309
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000310 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000311 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
312 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000313 fn = "_non_existing_filename_used_for_sourcefile_test.py"
314 co = compile("None", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000315 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000316 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200317 try:
318 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
319 finally:
320 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000321
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000322 def test_getfile(self):
323 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000324
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500325 def test_getfile_class_without_module(self):
326 class CM(type):
327 @property
328 def __module__(cls):
329 raise AttributeError
330 class C(metaclass=CM):
331 pass
332 with self.assertRaises(TypeError):
333 inspect.getfile(C)
334
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000335 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000336 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000337 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000338 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000339 m.__file__ = "<string>" # hopefully not a real filename...
340 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000341 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000342 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000343 del sys.modules[name]
344 inspect.getmodule(compile('a=10','','single'))
345
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500346 def test_proceed_with_fake_filename(self):
347 '''doctest monkeypatches linecache to enable inspection'''
348 fn, source = '<test>', 'def x(): pass\n'
349 getlines = linecache.getlines
350 def monkey(filename, module_globals=None):
351 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300352 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500353 else:
354 return getlines(filename, module_globals)
355 linecache.getlines = monkey
356 try:
357 ns = {}
358 exec(compile(source, fn, 'single'), ns)
359 inspect.getsource(ns["x"])
360 finally:
361 linecache.getlines = getlines
362
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000363class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000364 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000365
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000366 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000367 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000368
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000369 def test_replacing_decorator(self):
370 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000371
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000372class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000373 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000374 def test_oneline_lambda(self):
375 # Test inspect.getsource with a one-line lambda function.
376 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000377
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000378 def test_threeline_lambda(self):
379 # Test inspect.getsource with a three-line lambda function,
380 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000381 self.assertSourceEqual(mod2.tll, 28, 30)
382
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000383 def test_twoline_indented_lambda(self):
384 # Test inspect.getsource with a two-line lambda function,
385 # where the second line _is_ indented.
386 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000387
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000388 def test_onelinefunc(self):
389 # Test inspect.getsource with a regular one-line function.
390 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000391
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000392 def test_manyargs(self):
393 # Test inspect.getsource with a regular function where
394 # the arguments are on two lines and _not_ indented and
395 # the body on the second line with the last arguments.
396 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000397
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000398 def test_twolinefunc(self):
399 # Test inspect.getsource with a regular function where
400 # the body is on two lines, following the argument list and
401 # continued on the next line by a \\.
402 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000403
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000404 def test_lambda_in_list(self):
405 # Test inspect.getsource with a one-line lambda function
406 # defined in a list, indented.
407 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000408
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000409 def test_anonymous(self):
410 # Test inspect.getsource with a lambda function defined
411 # as argument to another function.
412 self.assertSourceEqual(mod2.anonymous, 55, 55)
413
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000414class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000415 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000416
417 def test_with_comment(self):
418 self.assertSourceEqual(mod2.with_comment, 58, 59)
419
420 def test_multiline_sig(self):
421 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
422
Armin Rigodd5c0232005-09-25 11:45:45 +0000423 def test_nested_class(self):
424 self.assertSourceEqual(mod2.func69().func71, 71, 72)
425
426 def test_one_liner_followed_by_non_name(self):
427 self.assertSourceEqual(mod2.func77, 77, 77)
428
429 def test_one_liner_dedent_non_name(self):
430 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
431
432 def test_with_comment_instead_of_docstring(self):
433 self.assertSourceEqual(mod2.func88, 88, 90)
434
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000435 def test_method_in_dynamic_class(self):
436 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
437
R David Murray32562d72014-10-03 11:15:38 -0400438 # This should not skip for CPython, but might on a repackaged python where
439 # unicodedata is not an external module, or on pypy.
440 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
441 unicodedata.__file__.endswith('.py'),
442 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000443 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200444 self.assertRaises(OSError, inspect.getsource, unicodedata)
445 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000446
R. David Murraya1b37402010-06-17 02:04:29 +0000447 def test_findsource_code_in_linecache(self):
448 lines = ["x=1"]
449 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200450 self.assertRaises(OSError, inspect.findsource, co)
451 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000452 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200453 try:
454 self.assertEqual(inspect.findsource(co), (lines,0))
455 self.assertEqual(inspect.getsource(co), lines[0])
456 finally:
457 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000458
Ezio Melotti1b145922013-03-30 05:17:24 +0200459 def test_findsource_without_filename(self):
460 for fname in ['', '<string>']:
461 co = compile('x=1', fname, "exec")
462 self.assertRaises(IOError, inspect.findsource, co)
463 self.assertRaises(IOError, inspect.getsource, co)
464
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000465class TestNoEOL(GetSourceBase):
466 def __init__(self, *args, **kwargs):
467 self.tempdir = TESTFN + '_dir'
468 os.mkdir(self.tempdir)
469 with open(os.path.join(self.tempdir,
470 'inspect_fodder3%spy' % os.extsep), 'w') as f:
471 f.write("class X:\n pass # No EOL")
472 with DirsOnSysPath(self.tempdir):
473 import inspect_fodder3 as mod3
474 self.fodderModule = mod3
475 GetSourceBase.__init__(self, *args, **kwargs)
476
477 def tearDown(self):
478 shutil.rmtree(self.tempdir)
479
480 def test_class(self):
481 self.assertSourceEqual(self.fodderModule.X, 1, 2)
482
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100483
484class _BrokenDataDescriptor(object):
485 """
486 A broken data descriptor. See bug #1785.
487 """
488 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700489 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100490
491 def __set__(*args):
492 raise RuntimeError
493
494 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700495 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100496
497
498class _BrokenMethodDescriptor(object):
499 """
500 A broken method descriptor. See bug #1785.
501 """
502 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700503 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100504
505 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700506 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100507
508
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000509# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000510def attrs_wo_objs(cls):
511 return [t[:3] for t in inspect.classify_class_attrs(cls)]
512
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100513
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000514class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000515 def test_newstyle_mro(self):
516 # The same w/ new-class MRO.
517 class A(object): pass
518 class B(A): pass
519 class C(A): pass
520 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000521
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000522 expected = (D, B, C, A, object)
523 got = inspect.getmro(D)
524 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000525
Christian Heimes3795b532007-11-08 13:48:53 +0000526 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
527 varkw_e=None, defaults_e=None, formatted=None):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000528 args, varargs, varkw, defaults = inspect.getargspec(routine)
529 self.assertEqual(args, args_e)
530 self.assertEqual(varargs, varargs_e)
531 self.assertEqual(varkw, varkw_e)
532 self.assertEqual(defaults, defaults_e)
533 if formatted is not None:
534 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
535 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000536
Christian Heimes3795b532007-11-08 13:48:53 +0000537 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
538 varkw_e=None, defaults_e=None,
539 kwonlyargs_e=[], kwonlydefaults_e=None,
540 ann_e={}, formatted=None):
541 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
542 inspect.getfullargspec(routine)
543 self.assertEqual(args, args_e)
544 self.assertEqual(varargs, varargs_e)
545 self.assertEqual(varkw, varkw_e)
546 self.assertEqual(defaults, defaults_e)
547 self.assertEqual(kwonlyargs, kwonlyargs_e)
548 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
549 self.assertEqual(ann, ann_e)
550 if formatted is not None:
551 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
552 kwonlyargs, kwonlydefaults, ann),
553 formatted)
554
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000555 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000556 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000557
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000558 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000559 ['a', 'b', 'c', 'd', 'e', 'f'],
560 'g', 'h', (3, 4, 5),
561 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000562
Christian Heimes3795b532007-11-08 13:48:53 +0000563 self.assertRaises(ValueError, self.assertArgSpecEquals,
564 mod2.keyworded, [])
565
566 self.assertRaises(ValueError, self.assertArgSpecEquals,
567 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000568 self.assertRaises(ValueError, self.assertArgSpecEquals,
569 mod2.keyword_only_arg, [])
570
Christian Heimes3795b532007-11-08 13:48:53 +0000571
572 def test_getfullargspec(self):
573 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
574 kwonlyargs_e=['arg2'],
575 kwonlydefaults_e={'arg2':1},
576 formatted='(*arg1, arg2=1)')
577
578 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000579 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000580 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000581 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
582 kwonlyargs_e=['arg'],
583 formatted='(*, arg)')
584
Yury Selivanovff385b82014-02-19 16:27:23 -0500585 def test_argspec_api_ignores_wrapped(self):
586 # Issue 20684: low level introspection API must ignore __wrapped__
587 @functools.wraps(mod.spam)
588 def ham(x, y):
589 pass
590 # Basic check
591 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
592 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
593 self.assertFullArgSpecEquals(functools.partial(ham),
594 ['x', 'y'], formatted='(x, y)')
595 # Other variants
596 def check_method(f):
597 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
598 formatted='(self, x, y)')
599 class C:
600 @functools.wraps(mod.spam)
601 def ham(self, x, y):
602 pass
603 pham = functools.partialmethod(ham)
604 @functools.wraps(mod.spam)
605 def __call__(self, x, y):
606 pass
607 check_method(C())
608 check_method(C.ham)
609 check_method(C().ham)
610 check_method(C.pham)
611 check_method(C().pham)
612
613 class C_new:
614 @functools.wraps(mod.spam)
615 def __new__(self, x, y):
616 pass
617 check_method(C_new)
618
619 class C_init:
620 @functools.wraps(mod.spam)
621 def __init__(self, x, y):
622 pass
623 check_method(C_init)
624
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500625 def test_getfullargspec_signature_attr(self):
626 def test():
627 pass
628 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
629 test.__signature__ = inspect.Signature(parameters=(spam_param,))
630
631 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
632
Yury Selivanov4cb93912014-01-29 11:54:12 -0500633 def test_getfullargspec_signature_annos(self):
634 def test(a:'spam') -> 'ham': pass
635 spec = inspect.getfullargspec(test)
636 self.assertEqual(test.__annotations__, spec.annotations)
637
638 def test(): pass
639 spec = inspect.getfullargspec(test)
640 self.assertEqual(test.__annotations__, spec.annotations)
641
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500642 @unittest.skipIf(MISSING_C_DOCSTRINGS,
643 "Signature information for builtins requires docstrings")
644 def test_getfullargspec_builtin_methods(self):
645 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
646 args_e=['self', 'obj'], formatted='(self, obj)')
647
648 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
649 args_e=['self', 'obj'], formatted='(self, obj)')
650
Yury Selivanovd224b6a2014-02-21 01:32:42 -0500651 self.assertFullArgSpecEquals(
652 os.stat,
653 args_e=['path'],
654 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
655 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
656 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
657
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200658 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500659 @unittest.skipIf(MISSING_C_DOCSTRINGS,
660 "Signature information for builtins requires docstrings")
661 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200662 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500663 builtin = _testcapi.docstring_with_signature_with_defaults
664 spec = inspect.getfullargspec(builtin)
665 self.assertEqual(spec.defaults[0], 'avocado')
666
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200667 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500668 @unittest.skipIf(MISSING_C_DOCSTRINGS,
669 "Signature information for builtins requires docstrings")
670 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200671 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500672 builtin = _testcapi.docstring_no_signature
673 with self.assertRaises(TypeError):
674 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000675
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000676 def test_getargspec_method(self):
677 class A(object):
678 def m(self):
679 pass
680 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000681
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000682 def test_classify_newstyle(self):
683 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000684
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000685 def s(): pass
686 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000687
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000688 def c(cls): pass
689 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000690
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000691 def getp(self): pass
692 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000693
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000694 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000695
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000696 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000697
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000698 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000699
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100700 dd = _BrokenDataDescriptor()
701 md = _BrokenMethodDescriptor()
702
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000703 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500704
705 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
706 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
707
Benjamin Peterson577473f2010-01-19 00:09:57 +0000708 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
709 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
710 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000711 self.assertIn(('m', 'method', A), attrs,
712 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000713 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
714 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100715 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
716 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000717
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000718 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000719
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000720 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000721
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000722 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000723 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
724 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
725 self.assertIn(('p', 'property', A), attrs, 'missing property')
726 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
727 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
728 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100729 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
730 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000731
732
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000733 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000734
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000735 def m(self): pass
736 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000737
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000738 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000739 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
740 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
741 self.assertIn(('p', 'property', A), attrs, 'missing property')
742 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
743 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
744 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100745 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
746 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000747
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000748 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000749
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000750 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000751
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000752 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000753 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
754 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
755 self.assertIn(('p', 'property', A), attrs, 'missing property')
756 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
757 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
758 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100759 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
760 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
761
762 def test_classify_builtin_types(self):
763 # Simple sanity check that all built-in types can have their
764 # attributes classified.
765 for name in dir(__builtins__):
766 builtin = getattr(__builtins__, name)
767 if isinstance(builtin, type):
768 inspect.classify_class_attrs(builtin)
769
Ethan Furman63c141c2013-10-18 00:27:39 -0700770 def test_classify_DynamicClassAttribute(self):
771 class Meta(type):
772 def __getattr__(self, name):
773 if name == 'ham':
774 return 'spam'
775 return super().__getattr__(name)
776 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700777 @types.DynamicClassAttribute
778 def ham(self):
779 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700780 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
781 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700782 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700783 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
784
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700785 def test_classify_metaclass_class_attribute(self):
786 class Meta(type):
787 fish = 'slap'
788 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200789 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700790 class Class(metaclass=Meta):
791 pass
792 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
793 self.assertIn(should_find, inspect.classify_class_attrs(Class))
794
Ethan Furman63c141c2013-10-18 00:27:39 -0700795 def test_classify_VirtualAttribute(self):
796 class Meta(type):
797 def __dir__(cls):
798 return ['__class__', '__module__', '__name__', 'BOOM']
799 def __getattr__(self, name):
800 if name =='BOOM':
801 return 42
802 return super().__getattr(name)
803 class Class(metaclass=Meta):
804 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700805 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700806 self.assertIn(should_find, inspect.classify_class_attrs(Class))
807
808 def test_classify_VirtualAttribute_multi_classes(self):
809 class Meta1(type):
810 def __dir__(cls):
811 return ['__class__', '__module__', '__name__', 'one']
812 def __getattr__(self, name):
813 if name =='one':
814 return 1
815 return super().__getattr__(name)
816 class Meta2(type):
817 def __dir__(cls):
818 return ['__class__', '__module__', '__name__', 'two']
819 def __getattr__(self, name):
820 if name =='two':
821 return 2
822 return super().__getattr__(name)
823 class Meta3(Meta1, Meta2):
824 def __dir__(cls):
825 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
826 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
827 def __getattr__(self, name):
828 if name =='three':
829 return 3
830 return super().__getattr__(name)
831 class Class1(metaclass=Meta1):
832 pass
833 class Class2(Class1, metaclass=Meta3):
834 pass
835
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700836 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
837 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
838 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700839 cca = inspect.classify_class_attrs(Class2)
840 for sf in (should_find1, should_find2, should_find3):
841 self.assertIn(sf, cca)
842
843 def test_classify_class_attrs_with_buggy_dir(self):
844 class M(type):
845 def __dir__(cls):
846 return ['__class__', '__name__', 'missing']
847 class C(metaclass=M):
848 pass
849 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
850 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700851
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100852 def test_getmembers_descriptors(self):
853 class A(object):
854 dd = _BrokenDataDescriptor()
855 md = _BrokenMethodDescriptor()
856
857 def pred_wrapper(pred):
858 # A quick'n'dirty way to discard standard attributes of new-style
859 # classes.
860 class Empty(object):
861 pass
862 def wrapped(x):
863 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
864 return False
865 return pred(x)
866 return wrapped
867
868 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
869 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
870
871 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
872 [('md', A.__dict__['md'])])
873 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
874 [('dd', A.__dict__['dd'])])
875
876 class B(A):
877 pass
878
879 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
880 [('md', A.__dict__['md'])])
881 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
882 [('dd', A.__dict__['dd'])])
883
Antoine Pitrou0c603812012-01-18 17:40:18 +0100884 def test_getmembers_method(self):
885 class B:
886 def f(self):
887 pass
888
889 self.assertIn(('f', B.f), inspect.getmembers(B))
890 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
891 b = B()
892 self.assertIn(('f', b.f), inspect.getmembers(b))
893 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
894
Ethan Furmane03ea372013-09-25 07:14:41 -0700895 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -0700896 class M(type):
897 def __getattr__(cls, name):
898 if name == 'eggs':
899 return 'scrambled'
900 return super().__getattr__(name)
901 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -0700902 @types.DynamicClassAttribute
903 def eggs(self):
904 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -0700905 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
906 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
907
908 def test_getmembers_with_buggy_dir(self):
909 class M(type):
910 def __dir__(cls):
911 return ['__class__', '__name__', 'missing']
912 class C(metaclass=M):
913 pass
914 attrs = [a[0] for a in inspect.getmembers(C)]
915 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700916
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000917
Nick Coghlan2f92e542012-06-23 19:39:55 +1000918_global_ref = object()
919class TestGetClosureVars(unittest.TestCase):
920
921 def test_name_resolution(self):
922 # Basic test of the 4 different resolution mechanisms
923 def f(nonlocal_ref):
924 def g(local_ref):
925 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
926 return g
927 _arg = object()
928 nonlocal_vars = {"nonlocal_ref": _arg}
929 global_vars = {"_global_ref": _global_ref}
930 builtin_vars = {"print": print}
931 unbound_names = {"unbound_ref"}
932 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
933 builtin_vars, unbound_names)
934 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
935
936 def test_generator_closure(self):
937 def f(nonlocal_ref):
938 def g(local_ref):
939 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
940 yield
941 return g
942 _arg = object()
943 nonlocal_vars = {"nonlocal_ref": _arg}
944 global_vars = {"_global_ref": _global_ref}
945 builtin_vars = {"print": print}
946 unbound_names = {"unbound_ref"}
947 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
948 builtin_vars, unbound_names)
949 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
950
951 def test_method_closure(self):
952 class C:
953 def f(self, nonlocal_ref):
954 def g(local_ref):
955 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
956 return g
957 _arg = object()
958 nonlocal_vars = {"nonlocal_ref": _arg}
959 global_vars = {"_global_ref": _global_ref}
960 builtin_vars = {"print": print}
961 unbound_names = {"unbound_ref"}
962 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
963 builtin_vars, unbound_names)
964 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
965
966 def test_nonlocal_vars(self):
967 # More complex tests of nonlocal resolution
968 def _nonlocal_vars(f):
969 return inspect.getclosurevars(f).nonlocals
970
971 def make_adder(x):
972 def add(y):
973 return x + y
974 return add
975
976 def curry(func, arg1):
977 return lambda arg2: func(arg1, arg2)
978
979 def less_than(a, b):
980 return a < b
981
982 # The infamous Y combinator.
983 def Y(le):
984 def g(f):
985 return le(lambda x: f(f)(x))
986 Y.g_ref = g
987 return g(g)
988
989 def check_y_combinator(func):
990 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
991
992 inc = make_adder(1)
993 add_two = make_adder(2)
994 greater_than_five = curry(less_than, 5)
995
996 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
997 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
998 self.assertEqual(_nonlocal_vars(greater_than_five),
999 {'arg1': 5, 'func': less_than})
1000 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1001 {'x': 3})
1002 Y(check_y_combinator)
1003
1004 def test_getclosurevars_empty(self):
1005 def foo(): pass
1006 _empty = inspect.ClosureVars({}, {}, {}, set())
1007 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1008 self.assertEqual(inspect.getclosurevars(foo), _empty)
1009
1010 def test_getclosurevars_error(self):
1011 class T: pass
1012 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1013 self.assertRaises(TypeError, inspect.getclosurevars, list)
1014 self.assertRaises(TypeError, inspect.getclosurevars, {})
1015
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001016 def _private_globals(self):
1017 code = """def f(): print(path)"""
1018 ns = {}
1019 exec(code, ns)
1020 return ns["f"], ns
1021
1022 def test_builtins_fallback(self):
1023 f, ns = self._private_globals()
1024 ns.pop("__builtins__", None)
1025 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1026 self.assertEqual(inspect.getclosurevars(f), expected)
1027
1028 def test_builtins_as_dict(self):
1029 f, ns = self._private_globals()
1030 ns["__builtins__"] = {"path":1}
1031 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1032 self.assertEqual(inspect.getclosurevars(f), expected)
1033
1034 def test_builtins_as_module(self):
1035 f, ns = self._private_globals()
1036 ns["__builtins__"] = os
1037 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1038 self.assertEqual(inspect.getclosurevars(f), expected)
1039
Nick Coghlan2f92e542012-06-23 19:39:55 +10001040
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001041class TestGetcallargsFunctions(unittest.TestCase):
1042
1043 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1044 locs = dict(locs or {}, func=func)
1045 r1 = eval('func(%s)' % call_params_string, None, locs)
1046 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1047 locs)
1048 self.assertEqual(r1, r2)
1049
1050 def assertEqualException(self, func, call_param_string, locs=None):
1051 locs = dict(locs or {}, func=func)
1052 try:
1053 eval('func(%s)' % call_param_string, None, locs)
1054 except Exception as e:
1055 ex1 = e
1056 else:
1057 self.fail('Exception not raised')
1058 try:
1059 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1060 locs)
1061 except Exception as e:
1062 ex2 = e
1063 else:
1064 self.fail('Exception not raised')
1065 self.assertIs(type(ex1), type(ex2))
1066 self.assertEqual(str(ex1), str(ex2))
1067 del ex1, ex2
1068
1069 def makeCallable(self, signature):
1070 """Create a function that returns its locals()"""
1071 code = "lambda %s: locals()"
1072 return eval(code % signature)
1073
1074 def test_plain(self):
1075 f = self.makeCallable('a, b=1')
1076 self.assertEqualCallArgs(f, '2')
1077 self.assertEqualCallArgs(f, '2, 3')
1078 self.assertEqualCallArgs(f, 'a=2')
1079 self.assertEqualCallArgs(f, 'b=3, a=2')
1080 self.assertEqualCallArgs(f, '2, b=3')
1081 # expand *iterable / **mapping
1082 self.assertEqualCallArgs(f, '*(2,)')
1083 self.assertEqualCallArgs(f, '*[2]')
1084 self.assertEqualCallArgs(f, '*(2, 3)')
1085 self.assertEqualCallArgs(f, '*[2, 3]')
1086 self.assertEqualCallArgs(f, '**{"a":2}')
1087 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1088 self.assertEqualCallArgs(f, '2, **{"b":3}')
1089 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1090 # expand UserList / UserDict
1091 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1092 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1093 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1094 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1095 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1096
1097 def test_varargs(self):
1098 f = self.makeCallable('a, b=1, *c')
1099 self.assertEqualCallArgs(f, '2')
1100 self.assertEqualCallArgs(f, '2, 3')
1101 self.assertEqualCallArgs(f, '2, 3, 4')
1102 self.assertEqualCallArgs(f, '*(2,3,4)')
1103 self.assertEqualCallArgs(f, '2, *[3,4]')
1104 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1105
1106 def test_varkw(self):
1107 f = self.makeCallable('a, b=1, **c')
1108 self.assertEqualCallArgs(f, 'a=2')
1109 self.assertEqualCallArgs(f, '2, b=3, c=4')
1110 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1111 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1112 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1113 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1114 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1115 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1116 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1117
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001118 def test_varkw_only(self):
1119 # issue11256:
1120 f = self.makeCallable('**c')
1121 self.assertEqualCallArgs(f, '')
1122 self.assertEqualCallArgs(f, 'a=1')
1123 self.assertEqualCallArgs(f, 'a=1, b=2')
1124 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1125 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1126 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1127
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001128 def test_keyword_only(self):
1129 f = self.makeCallable('a=3, *, c, d=2')
1130 self.assertEqualCallArgs(f, 'c=3')
1131 self.assertEqualCallArgs(f, 'c=3, a=3')
1132 self.assertEqualCallArgs(f, 'a=2, c=4')
1133 self.assertEqualCallArgs(f, '4, c=4')
1134 self.assertEqualException(f, '')
1135 self.assertEqualException(f, '3')
1136 self.assertEqualException(f, 'a=3')
1137 self.assertEqualException(f, 'd=4')
1138
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001139 f = self.makeCallable('*, c, d=2')
1140 self.assertEqualCallArgs(f, 'c=3')
1141 self.assertEqualCallArgs(f, 'c=3, d=4')
1142 self.assertEqualCallArgs(f, 'd=4, c=3')
1143
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001144 def test_multiple_features(self):
1145 f = self.makeCallable('a, b=2, *f, **g')
1146 self.assertEqualCallArgs(f, '2, 3, 7')
1147 self.assertEqualCallArgs(f, '2, 3, x=8')
1148 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1149 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1150 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1151 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1152 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1153 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1154 '(4,[5,6])]), **collections.UserDict('
1155 'y=9, z=10)')
1156
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001157 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1158 self.assertEqualCallArgs(f, '2, 3, x=8')
1159 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1160 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1161 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1162 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1163 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1164 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1165 '(4,[5,6])]), q=0, **collections.UserDict('
1166 'y=9, z=10)')
1167
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001168 def test_errors(self):
1169 f0 = self.makeCallable('')
1170 f1 = self.makeCallable('a, b')
1171 f2 = self.makeCallable('a, b=1')
1172 # f0 takes no arguments
1173 self.assertEqualException(f0, '1')
1174 self.assertEqualException(f0, 'x=1')
1175 self.assertEqualException(f0, '1,x=1')
1176 # f1 takes exactly 2 arguments
1177 self.assertEqualException(f1, '')
1178 self.assertEqualException(f1, '1')
1179 self.assertEqualException(f1, 'a=2')
1180 self.assertEqualException(f1, 'b=3')
1181 # f2 takes at least 1 argument
1182 self.assertEqualException(f2, '')
1183 self.assertEqualException(f2, 'b=3')
1184 for f in f1, f2:
1185 # f1/f2 takes exactly/at most 2 arguments
1186 self.assertEqualException(f, '2, 3, 4')
1187 self.assertEqualException(f, '1, 2, 3, a=1')
1188 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001189 # XXX: success of this one depends on dict order
1190 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001191 # f got an unexpected keyword argument
1192 self.assertEqualException(f, 'c=2')
1193 self.assertEqualException(f, '2, c=3')
1194 self.assertEqualException(f, '2, 3, c=4')
1195 self.assertEqualException(f, '2, c=4, b=3')
1196 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1197 # f got multiple values for keyword argument
1198 self.assertEqualException(f, '1, a=2')
1199 self.assertEqualException(f, '1, **{"a":2}')
1200 self.assertEqualException(f, '1, 2, b=3')
1201 # XXX: Python inconsistency
1202 # - for functions and bound methods: unexpected keyword 'c'
1203 # - for unbound methods: multiple values for keyword 'a'
1204 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001205 # issue11256:
1206 f3 = self.makeCallable('**c')
1207 self.assertEqualException(f3, '1, 2')
1208 self.assertEqualException(f3, '1, 2, a=1, b=2')
1209 f4 = self.makeCallable('*, a, b=0')
1210 self.assertEqualException(f3, '1, 2')
1211 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001212
Yury Selivanovb1d060b2014-03-27 18:23:03 -04001213 # issue #20816: getcallargs() fails to iterate over non-existent
1214 # kwonlydefaults and raises a wrong TypeError
1215 def f5(*, a): pass
1216 with self.assertRaisesRegex(TypeError,
1217 'missing 1 required keyword-only'):
1218 inspect.getcallargs(f5)
1219
1220
Yury Selivanov2542b662014-03-27 18:42:52 -04001221 # issue20817:
1222 def f6(a, b, c):
1223 pass
1224 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1225 inspect.getcallargs(f6)
1226
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001227class TestGetcallargsMethods(TestGetcallargsFunctions):
1228
1229 def setUp(self):
1230 class Foo(object):
1231 pass
1232 self.cls = Foo
1233 self.inst = Foo()
1234
1235 def makeCallable(self, signature):
1236 assert 'self' not in signature
1237 mk = super(TestGetcallargsMethods, self).makeCallable
1238 self.cls.method = mk('self, ' + signature)
1239 return self.inst.method
1240
1241class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1242
1243 def makeCallable(self, signature):
1244 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1245 return self.cls.method
1246
1247 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1248 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1249 *self._getAssertEqualParams(func, call_params_string, locs))
1250
1251 def assertEqualException(self, func, call_params_string, locs=None):
1252 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1253 *self._getAssertEqualParams(func, call_params_string, locs))
1254
1255 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1256 assert 'inst' not in call_params_string
1257 locs = dict(locs or {}, inst=self.inst)
1258 return (func, 'inst,' + call_params_string, locs)
1259
Michael Foord95fc51d2010-11-20 15:07:30 +00001260
1261class TestGetattrStatic(unittest.TestCase):
1262
1263 def test_basic(self):
1264 class Thing(object):
1265 x = object()
1266
1267 thing = Thing()
1268 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1269 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1270 with self.assertRaises(AttributeError):
1271 inspect.getattr_static(thing, 'y')
1272
1273 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1274
1275 def test_inherited(self):
1276 class Thing(object):
1277 x = object()
1278 class OtherThing(Thing):
1279 pass
1280
1281 something = OtherThing()
1282 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1283
1284 def test_instance_attr(self):
1285 class Thing(object):
1286 x = 2
1287 def __init__(self, x):
1288 self.x = x
1289 thing = Thing(3)
1290 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1291 del thing.x
1292 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1293
1294 def test_property(self):
1295 class Thing(object):
1296 @property
1297 def x(self):
1298 raise AttributeError("I'm pretending not to exist")
1299 thing = Thing()
1300 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1301
Ezio Melotti75cbd732011-04-28 00:59:29 +03001302 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001303 class descriptor(object):
1304 def __get__(*_):
1305 raise AttributeError("I'm pretending not to exist")
1306 desc = descriptor()
1307 class Thing(object):
1308 x = desc
1309 thing = Thing()
1310 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1311
1312 def test_classAttribute(self):
1313 class Thing(object):
1314 x = object()
1315
1316 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1317
Ethan Furmane03ea372013-09-25 07:14:41 -07001318 def test_classVirtualAttribute(self):
1319 class Thing(object):
1320 @types.DynamicClassAttribute
1321 def x(self):
1322 return self._x
1323 _x = object()
1324
1325 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1326
Michael Foord95fc51d2010-11-20 15:07:30 +00001327 def test_inherited_classattribute(self):
1328 class Thing(object):
1329 x = object()
1330 class OtherThing(Thing):
1331 pass
1332
1333 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1334
1335 def test_slots(self):
1336 class Thing(object):
1337 y = 'bar'
1338 __slots__ = ['x']
1339 def __init__(self):
1340 self.x = 'foo'
1341 thing = Thing()
1342 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1343 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1344
1345 del thing.x
1346 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1347
1348 def test_metaclass(self):
1349 class meta(type):
1350 attr = 'foo'
1351 class Thing(object, metaclass=meta):
1352 pass
1353 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1354
1355 class sub(meta):
1356 pass
1357 class OtherThing(object, metaclass=sub):
1358 x = 3
1359 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1360
1361 class OtherOtherThing(OtherThing):
1362 pass
1363 # this test is odd, but it was added as it exposed a bug
1364 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1365
1366 def test_no_dict_no_slots(self):
1367 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1368 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1369
1370 def test_no_dict_no_slots_instance_member(self):
1371 # returns descriptor
1372 with open(__file__) as handle:
1373 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1374
1375 def test_inherited_slots(self):
1376 # returns descriptor
1377 class Thing(object):
1378 __slots__ = ['x']
1379 def __init__(self):
1380 self.x = 'foo'
1381
1382 class OtherThing(Thing):
1383 pass
1384 # it would be nice if this worked...
1385 # we get the descriptor instead of the instance attribute
1386 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1387
1388 def test_descriptor(self):
1389 class descriptor(object):
1390 def __get__(self, instance, owner):
1391 return 3
1392 class Foo(object):
1393 d = descriptor()
1394
1395 foo = Foo()
1396
1397 # for a non data descriptor we return the instance attribute
1398 foo.__dict__['d'] = 1
1399 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1400
1401 # if the descriptor is a data-desciptor we should return the
1402 # descriptor
1403 descriptor.__set__ = lambda s, i, v: None
1404 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1405
1406
1407 def test_metaclass_with_descriptor(self):
1408 class descriptor(object):
1409 def __get__(self, instance, owner):
1410 return 3
1411 class meta(type):
1412 d = descriptor()
1413 class Thing(object, metaclass=meta):
1414 pass
1415 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1416
1417
Michael Foordcc7ebb82010-11-20 16:20:16 +00001418 def test_class_as_property(self):
1419 class Base(object):
1420 foo = 3
1421
1422 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001423 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001424 @property
1425 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001426 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001427 return object
1428
Michael Foord35184ed2010-11-20 16:58:30 +00001429 instance = Something()
1430 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1431 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001432 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1433
Michael Foorde5162652010-11-20 16:40:44 +00001434 def test_mro_as_property(self):
1435 class Meta(type):
1436 @property
1437 def __mro__(self):
1438 return (object,)
1439
1440 class Base(object):
1441 foo = 3
1442
1443 class Something(Base, metaclass=Meta):
1444 pass
1445
1446 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1447 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1448
Michael Foorddcebe0f2011-03-15 19:20:44 -04001449 def test_dict_as_property(self):
1450 test = self
1451 test.called = False
1452
1453 class Foo(dict):
1454 a = 3
1455 @property
1456 def __dict__(self):
1457 test.called = True
1458 return {}
1459
1460 foo = Foo()
1461 foo.a = 4
1462 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1463 self.assertFalse(test.called)
1464
1465 def test_custom_object_dict(self):
1466 test = self
1467 test.called = False
1468
1469 class Custom(dict):
1470 def get(self, key, default=None):
1471 test.called = True
1472 super().get(key, default)
1473
1474 class Foo(object):
1475 a = 3
1476 foo = Foo()
1477 foo.__dict__ = Custom()
1478 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1479 self.assertFalse(test.called)
1480
1481 def test_metaclass_dict_as_property(self):
1482 class Meta(type):
1483 @property
1484 def __dict__(self):
1485 self.executed = True
1486
1487 class Thing(metaclass=Meta):
1488 executed = False
1489
1490 def __init__(self):
1491 self.spam = 42
1492
1493 instance = Thing()
1494 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1495 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001496
Michael Foorda51623b2011-12-18 22:01:40 +00001497 def test_module(self):
1498 sentinel = object()
1499 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1500 sentinel)
1501
Michael Foord3ba95f82011-12-22 01:13:37 +00001502 def test_metaclass_with_metaclass_with_dict_as_property(self):
1503 class MetaMeta(type):
1504 @property
1505 def __dict__(self):
1506 self.executed = True
1507 return dict(spam=42)
1508
1509 class Meta(type, metaclass=MetaMeta):
1510 executed = False
1511
1512 class Thing(metaclass=Meta):
1513 pass
1514
1515 with self.assertRaises(AttributeError):
1516 inspect.getattr_static(Thing, "spam")
1517 self.assertFalse(Thing.executed)
1518
Nick Coghlane0f04652010-11-21 03:44:04 +00001519class TestGetGeneratorState(unittest.TestCase):
1520
1521 def setUp(self):
1522 def number_generator():
1523 for number in range(5):
1524 yield number
1525 self.generator = number_generator()
1526
1527 def _generatorstate(self):
1528 return inspect.getgeneratorstate(self.generator)
1529
1530 def test_created(self):
1531 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1532
1533 def test_suspended(self):
1534 next(self.generator)
1535 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1536
1537 def test_closed_after_exhaustion(self):
1538 for i in self.generator:
1539 pass
1540 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1541
1542 def test_closed_after_immediate_exception(self):
1543 with self.assertRaises(RuntimeError):
1544 self.generator.throw(RuntimeError)
1545 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1546
1547 def test_running(self):
1548 # As mentioned on issue #10220, checking for the RUNNING state only
1549 # makes sense inside the generator itself.
1550 # The following generator checks for this by using the closure's
1551 # reference to self and the generator state checking helper method
1552 def running_check_generator():
1553 for number in range(5):
1554 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1555 yield number
1556 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1557 self.generator = running_check_generator()
1558 # Running up to the first yield
1559 next(self.generator)
1560 # Running after the first yield
1561 next(self.generator)
1562
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001563 def test_easy_debugging(self):
1564 # repr() and str() of a generator state should contain the state name
1565 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1566 for name in names:
1567 state = getattr(inspect, name)
1568 self.assertIn(name, repr(state))
1569 self.assertIn(name, str(state))
1570
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001571 def test_getgeneratorlocals(self):
1572 def each(lst, a=None):
1573 b=(1, 2, 3)
1574 for v in lst:
1575 if v == 3:
1576 c = 12
1577 yield v
1578
1579 numbers = each([1, 2, 3])
1580 self.assertEqual(inspect.getgeneratorlocals(numbers),
1581 {'a': None, 'lst': [1, 2, 3]})
1582 next(numbers)
1583 self.assertEqual(inspect.getgeneratorlocals(numbers),
1584 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1585 'b': (1, 2, 3)})
1586 next(numbers)
1587 self.assertEqual(inspect.getgeneratorlocals(numbers),
1588 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1589 'b': (1, 2, 3)})
1590 next(numbers)
1591 self.assertEqual(inspect.getgeneratorlocals(numbers),
1592 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1593 'b': (1, 2, 3), 'c': 12})
1594 try:
1595 next(numbers)
1596 except StopIteration:
1597 pass
1598 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1599
1600 def test_getgeneratorlocals_empty(self):
1601 def yield_one():
1602 yield 1
1603 one = yield_one()
1604 self.assertEqual(inspect.getgeneratorlocals(one), {})
1605 try:
1606 next(one)
1607 except StopIteration:
1608 pass
1609 self.assertEqual(inspect.getgeneratorlocals(one), {})
1610
1611 def test_getgeneratorlocals_error(self):
1612 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1613 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1614 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1615 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1616
Nick Coghlane0f04652010-11-21 03:44:04 +00001617
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001618class TestSignatureObject(unittest.TestCase):
1619 @staticmethod
1620 def signature(func):
1621 sig = inspect.signature(func)
1622 return (tuple((param.name,
1623 (... if param.default is param.empty else param.default),
1624 (... if param.annotation is param.empty
1625 else param.annotation),
1626 str(param.kind).lower())
1627 for param in sig.parameters.values()),
1628 (... if sig.return_annotation is sig.empty
1629 else sig.return_annotation))
1630
1631 def test_signature_object(self):
1632 S = inspect.Signature
1633 P = inspect.Parameter
1634
1635 self.assertEqual(str(S()), '()')
1636
Yury Selivanov07a9e452014-01-29 10:58:16 -05001637 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001638 pass
1639 sig = inspect.signature(test)
1640 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001641 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001642 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001643 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001644 args = sig.parameters['args']
1645 ko = sig.parameters['ko']
1646 kwargs = sig.parameters['kwargs']
1647
1648 S((po, pk, args, ko, kwargs))
1649
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001650 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001651 S((pk, po, args, ko, kwargs))
1652
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001653 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001654 S((po, args, pk, ko, kwargs))
1655
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001656 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001657 S((args, po, pk, ko, kwargs))
1658
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001659 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001660 S((po, pk, args, kwargs, ko))
1661
1662 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001663 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001664 S((po, pk, args, kwargs2, ko))
1665
Yury Selivanov07a9e452014-01-29 10:58:16 -05001666 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1667 S((pod, po))
1668
1669 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1670 S((po, pkd, pk))
1671
1672 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1673 S((pkd, pk))
1674
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001675 def test_signature_immutability(self):
1676 def test(a):
1677 pass
1678 sig = inspect.signature(test)
1679
1680 with self.assertRaises(AttributeError):
1681 sig.foo = 'bar'
1682
1683 with self.assertRaises(TypeError):
1684 sig.parameters['a'] = None
1685
1686 def test_signature_on_noarg(self):
1687 def test():
1688 pass
1689 self.assertEqual(self.signature(test), ((), ...))
1690
1691 def test_signature_on_wargs(self):
1692 def test(a, b:'foo') -> 123:
1693 pass
1694 self.assertEqual(self.signature(test),
1695 ((('a', ..., ..., "positional_or_keyword"),
1696 ('b', ..., 'foo', "positional_or_keyword")),
1697 123))
1698
1699 def test_signature_on_wkwonly(self):
1700 def test(*, a:float, b:str) -> int:
1701 pass
1702 self.assertEqual(self.signature(test),
1703 ((('a', ..., float, "keyword_only"),
1704 ('b', ..., str, "keyword_only")),
1705 int))
1706
1707 def test_signature_on_complex_args(self):
1708 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1709 pass
1710 self.assertEqual(self.signature(test),
1711 ((('a', ..., ..., "positional_or_keyword"),
1712 ('b', 10, 'foo', "positional_or_keyword"),
1713 ('args', ..., 'bar', "var_positional"),
1714 ('spam', ..., 'baz', "keyword_only"),
1715 ('ham', 123, ..., "keyword_only"),
1716 ('kwargs', ..., int, "var_keyword")),
1717 ...))
1718
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001719 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001720 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1721 "Signature information for builtins requires docstrings")
1722 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001723 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001724
Larry Hastings5c661892014-01-24 06:17:25 -08001725 def test_unbound_method(o):
1726 """Use this to test unbound methods (things that should have a self)"""
1727 signature = inspect.signature(o)
1728 self.assertTrue(isinstance(signature, inspect.Signature))
1729 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1730 return signature
1731
1732 def test_callable(o):
1733 """Use this to test bound methods or normal callables (things that don't expect self)"""
1734 signature = inspect.signature(o)
1735 self.assertTrue(isinstance(signature, inspect.Signature))
1736 if signature.parameters:
1737 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1738 return signature
1739
1740 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001741 def p(name): return signature.parameters[name].default
1742 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001743 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001744 self.assertEqual(p('d'), 3.14)
1745 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001746 self.assertEqual(p('n'), None)
1747 self.assertEqual(p('t'), True)
1748 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001749 self.assertEqual(p('local'), 3)
1750 self.assertEqual(p('sys'), sys.maxsize)
1751 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001752
Larry Hastings5c661892014-01-24 06:17:25 -08001753 test_callable(object)
1754
1755 # normal method
1756 # (PyMethodDescr_Type, "method_descriptor")
1757 test_unbound_method(_pickle.Pickler.dump)
1758 d = _pickle.Pickler(io.StringIO())
1759 test_callable(d.dump)
1760
1761 # static method
1762 test_callable(str.maketrans)
1763 test_callable('abc'.maketrans)
1764
1765 # class method
1766 test_callable(dict.fromkeys)
1767 test_callable({}.fromkeys)
1768
1769 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1770 test_unbound_method(type.__call__)
1771 test_unbound_method(int.__add__)
1772 test_callable((3).__add__)
1773
1774 # _PyMethodWrapper_Type
1775 # support for 'method-wrapper'
1776 test_callable(min.__call__)
1777
Larry Hastings2623c8c2014-02-08 22:15:29 -08001778 # This doesn't work now.
1779 # (We don't have a valid signature for "type" in 3.4)
1780 with self.assertRaisesRegex(ValueError, "no signature found"):
1781 class ThisWorksNow:
1782 __call__ = type
1783 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08001784
Yury Selivanovd930d852014-03-02 12:25:27 -05001785 # Regression test for issue #20786
1786 test_unbound_method(dict.__delitem__)
1787 test_unbound_method(property.__delete__)
1788
1789
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001790 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05001791 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1792 "Signature information for builtins requires docstrings")
1793 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001794 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05001795 func = _testcapi.docstring_with_signature_with_defaults
1796
1797 def decorator(func):
1798 @functools.wraps(func)
1799 def wrapper(*args, **kwargs) -> int:
1800 return func(*args, **kwargs)
1801 return wrapper
1802
1803 decorated_func = decorator(func)
1804
1805 self.assertEqual(inspect.signature(func),
1806 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08001807
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001808 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08001809 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001810 import _testcapi
Larry Hastings5c661892014-01-24 06:17:25 -08001811 with self.assertRaisesRegex(ValueError, 'no signature found for builtin'):
1812 inspect.signature(_testcapi.docstring_no_signature)
1813
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001814 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001815 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001816 inspect.signature(42)
1817
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001818 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001819 inspect.Signature.from_function(42)
1820
Yury Selivanovb77511d2014-01-29 10:46:14 -05001821 def test_signature_from_builtin_errors(self):
1822 with self.assertRaisesRegex(TypeError, 'is not a Python builtin'):
1823 inspect.Signature.from_builtin(42)
1824
Yury Selivanov63da7c72014-01-31 14:48:37 -05001825 def test_signature_from_functionlike_object(self):
1826 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1827 pass
1828
1829 class funclike:
1830 # Has to be callable, and have correct
1831 # __code__, __annotations__, __defaults__, __name__,
1832 # and __kwdefaults__ attributes
1833
1834 def __init__(self, func):
1835 self.__name__ = func.__name__
1836 self.__code__ = func.__code__
1837 self.__annotations__ = func.__annotations__
1838 self.__defaults__ = func.__defaults__
1839 self.__kwdefaults__ = func.__kwdefaults__
1840 self.func = func
1841
1842 def __call__(self, *args, **kwargs):
1843 return self.func(*args, **kwargs)
1844
1845 sig_func = inspect.Signature.from_function(func)
1846
1847 sig_funclike = inspect.Signature.from_function(funclike(func))
1848 self.assertEqual(sig_funclike, sig_func)
1849
1850 sig_funclike = inspect.signature(funclike(func))
1851 self.assertEqual(sig_funclike, sig_func)
1852
1853 # If object is not a duck type of function, then
1854 # signature will try to get a signature for its '__call__'
1855 # method
1856 fl = funclike(func)
1857 del fl.__defaults__
1858 self.assertEqual(self.signature(fl),
1859 ((('args', ..., ..., "var_positional"),
1860 ('kwargs', ..., ..., "var_keyword")),
1861 ...))
1862
Yury Selivanov8dfb4572014-02-21 18:30:53 -05001863 # Test with cython-like builtins:
1864 _orig_isdesc = inspect.ismethoddescriptor
1865 def _isdesc(obj):
1866 if hasattr(obj, '_builtinmock'):
1867 return True
1868 return _orig_isdesc(obj)
1869
1870 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
1871 builtin_func = funclike(func)
1872 # Make sure that our mock setup is working
1873 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
1874 builtin_func._builtinmock = True
1875 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
1876 self.assertEqual(inspect.signature(builtin_func), sig_func)
1877
Yury Selivanov63da7c72014-01-31 14:48:37 -05001878 def test_signature_functionlike_class(self):
1879 # We only want to duck type function-like objects,
1880 # not classes.
1881
1882 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1883 pass
1884
1885 class funclike:
1886 def __init__(self, marker):
1887 pass
1888
1889 __name__ = func.__name__
1890 __code__ = func.__code__
1891 __annotations__ = func.__annotations__
1892 __defaults__ = func.__defaults__
1893 __kwdefaults__ = func.__kwdefaults__
1894
1895 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1896 inspect.Signature.from_function(funclike)
1897
1898 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
1899
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001900 def test_signature_on_method(self):
1901 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05001902 def __init__(*args):
1903 pass
1904 def m1(self, arg1, arg2=1) -> int:
1905 pass
1906 def m2(*args):
1907 pass
1908 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001909 pass
1910
Yury Selivanov62560fb2014-01-28 12:26:24 -05001911 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001912 ((('arg1', ..., ..., "positional_or_keyword"),
1913 ('arg2', 1, ..., "positional_or_keyword")),
1914 int))
1915
Yury Selivanov62560fb2014-01-28 12:26:24 -05001916 self.assertEqual(self.signature(Test().m2),
1917 ((('args', ..., ..., "var_positional"),),
1918 ...))
1919
1920 self.assertEqual(self.signature(Test),
1921 ((('args', ..., ..., "var_positional"),),
1922 ...))
1923
1924 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
1925 self.signature(Test())
1926
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001927 def test_signature_on_classmethod(self):
1928 class Test:
1929 @classmethod
1930 def foo(cls, arg1, *, arg2=1):
1931 pass
1932
1933 meth = Test().foo
1934 self.assertEqual(self.signature(meth),
1935 ((('arg1', ..., ..., "positional_or_keyword"),
1936 ('arg2', 1, ..., "keyword_only")),
1937 ...))
1938
1939 meth = Test.foo
1940 self.assertEqual(self.signature(meth),
1941 ((('arg1', ..., ..., "positional_or_keyword"),
1942 ('arg2', 1, ..., "keyword_only")),
1943 ...))
1944
1945 def test_signature_on_staticmethod(self):
1946 class Test:
1947 @staticmethod
1948 def foo(cls, *, arg):
1949 pass
1950
1951 meth = Test().foo
1952 self.assertEqual(self.signature(meth),
1953 ((('cls', ..., ..., "positional_or_keyword"),
1954 ('arg', ..., ..., "keyword_only")),
1955 ...))
1956
1957 meth = Test.foo
1958 self.assertEqual(self.signature(meth),
1959 ((('cls', ..., ..., "positional_or_keyword"),
1960 ('arg', ..., ..., "keyword_only")),
1961 ...))
1962
1963 def test_signature_on_partial(self):
1964 from functools import partial
1965
Yury Selivanov0fceaf42014-04-08 11:28:02 -04001966 Parameter = inspect.Parameter
1967
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001968 def test():
1969 pass
1970
1971 self.assertEqual(self.signature(partial(test)), ((), ...))
1972
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001973 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001974 inspect.signature(partial(test, 1))
1975
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001976 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001977 inspect.signature(partial(test, a=1))
1978
1979 def test(a, b, *, c, d):
1980 pass
1981
1982 self.assertEqual(self.signature(partial(test)),
1983 ((('a', ..., ..., "positional_or_keyword"),
1984 ('b', ..., ..., "positional_or_keyword"),
1985 ('c', ..., ..., "keyword_only"),
1986 ('d', ..., ..., "keyword_only")),
1987 ...))
1988
1989 self.assertEqual(self.signature(partial(test, 1)),
1990 ((('b', ..., ..., "positional_or_keyword"),
1991 ('c', ..., ..., "keyword_only"),
1992 ('d', ..., ..., "keyword_only")),
1993 ...))
1994
1995 self.assertEqual(self.signature(partial(test, 1, c=2)),
1996 ((('b', ..., ..., "positional_or_keyword"),
1997 ('c', 2, ..., "keyword_only"),
1998 ('d', ..., ..., "keyword_only")),
1999 ...))
2000
2001 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2002 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002003 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002004 ('c', 2, ..., "keyword_only"),
2005 ('d', ..., ..., "keyword_only")),
2006 ...))
2007
2008 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002009 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002010 ('c', 2, ..., "keyword_only"),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002011 ('d', ..., ..., "keyword_only")),
2012 ...))
2013
2014 self.assertEqual(self.signature(partial(test, a=1)),
2015 ((('a', 1, ..., "keyword_only"),
2016 ('b', ..., ..., "keyword_only"),
2017 ('c', ..., ..., "keyword_only"),
2018 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002019 ...))
2020
2021 def test(a, *args, b, **kwargs):
2022 pass
2023
2024 self.assertEqual(self.signature(partial(test, 1)),
2025 ((('args', ..., ..., "var_positional"),
2026 ('b', ..., ..., "keyword_only"),
2027 ('kwargs', ..., ..., "var_keyword")),
2028 ...))
2029
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002030 self.assertEqual(self.signature(partial(test, a=1)),
2031 ((('a', 1, ..., "keyword_only"),
2032 ('b', ..., ..., "keyword_only"),
2033 ('kwargs', ..., ..., "var_keyword")),
2034 ...))
2035
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002036 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2037 ((('args', ..., ..., "var_positional"),
2038 ('b', ..., ..., "keyword_only"),
2039 ('kwargs', ..., ..., "var_keyword")),
2040 ...))
2041
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002042 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2043 ((('args', ..., ..., "var_positional"),
2044 ('b', ..., ..., "keyword_only"),
2045 ('kwargs', ..., ..., "var_keyword")),
2046 ...))
2047
2048 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2049 ((('args', ..., ..., "var_positional"),
2050 ('b', 0, ..., "keyword_only"),
2051 ('kwargs', ..., ..., "var_keyword")),
2052 ...))
2053
2054 self.assertEqual(self.signature(partial(test, b=0)),
2055 ((('a', ..., ..., "positional_or_keyword"),
2056 ('args', ..., ..., "var_positional"),
2057 ('b', 0, ..., "keyword_only"),
2058 ('kwargs', ..., ..., "var_keyword")),
2059 ...))
2060
2061 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2062 ((('a', ..., ..., "positional_or_keyword"),
2063 ('args', ..., ..., "var_positional"),
2064 ('b', 0, ..., "keyword_only"),
2065 ('kwargs', ..., ..., "var_keyword")),
2066 ...))
2067
2068 def test(a, b, c:int) -> 42:
2069 pass
2070
2071 sig = test.__signature__ = inspect.signature(test)
2072
2073 self.assertEqual(self.signature(partial(partial(test, 1))),
2074 ((('b', ..., ..., "positional_or_keyword"),
2075 ('c', ..., int, "positional_or_keyword")),
2076 42))
2077
2078 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2079 ((('c', ..., int, "positional_or_keyword"),),
2080 42))
2081
2082 psig = inspect.signature(partial(partial(test, 1), 2))
2083
2084 def foo(a):
2085 return a
2086 _foo = partial(partial(foo, a=10), a=20)
2087 self.assertEqual(self.signature(_foo),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002088 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002089 ...))
2090 # check that we don't have any side-effects in signature(),
2091 # and the partial object is still functioning
2092 self.assertEqual(_foo(), 20)
2093
2094 def foo(a, b, c):
2095 return a, b, c
2096 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002097
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002098 self.assertEqual(self.signature(_foo),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002099 ((('b', 30, ..., "keyword_only"),
2100 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002101 ...))
2102 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002103
2104 def foo(a, b, c, *, d):
2105 return a, b, c, d
2106 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2107 self.assertEqual(self.signature(_foo),
2108 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002109 ('b', 10, ..., "keyword_only"),
2110 ('c', 20, ..., "keyword_only"),
2111 ('d', 30, ..., "keyword_only"),
2112 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002113 ...))
2114 ba = inspect.signature(_foo).bind(a=200, b=11)
2115 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2116
2117 def foo(a=1, b=2, c=3):
2118 return a, b, c
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002119 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2120
2121 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002122 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002123
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002124 ba = inspect.signature(_foo).bind(11, 12)
2125 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002126
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002127 ba = inspect.signature(_foo).bind(11, b=12)
2128 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002129
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002130 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002131 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2132
2133 _foo = partial(_foo, b=10, c=20)
2134 ba = inspect.signature(_foo).bind(12)
2135 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2136
2137
2138 def foo(a, b, c, d, **kwargs):
2139 pass
2140 sig = inspect.signature(foo)
2141 params = sig.parameters.copy()
2142 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2143 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2144 foo.__signature__ = inspect.Signature(params.values())
2145 sig = inspect.signature(foo)
2146 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2147
2148 self.assertEqual(self.signature(partial(foo, 1)),
2149 ((('b', ..., ..., 'positional_only'),
2150 ('c', ..., ..., 'positional_or_keyword'),
2151 ('d', ..., ..., 'positional_or_keyword'),
2152 ('kwargs', ..., ..., 'var_keyword')),
2153 ...))
2154
2155 self.assertEqual(self.signature(partial(foo, 1, 2)),
2156 ((('c', ..., ..., 'positional_or_keyword'),
2157 ('d', ..., ..., 'positional_or_keyword'),
2158 ('kwargs', ..., ..., 'var_keyword')),
2159 ...))
2160
2161 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2162 ((('d', ..., ..., 'positional_or_keyword'),
2163 ('kwargs', ..., ..., 'var_keyword')),
2164 ...))
2165
2166 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2167 ((('c', 3, ..., 'keyword_only'),
2168 ('d', ..., ..., 'keyword_only'),
2169 ('kwargs', ..., ..., 'var_keyword')),
2170 ...))
2171
2172 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2173 ((('b', ..., ..., 'positional_only'),
2174 ('c', 3, ..., 'keyword_only'),
2175 ('d', ..., ..., 'keyword_only'),
2176 ('kwargs', ..., ..., 'var_keyword')),
2177 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002178
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002179 def test_signature_on_partialmethod(self):
2180 from functools import partialmethod
2181
2182 class Spam:
2183 def test():
2184 pass
2185 ham = partialmethod(test)
2186
2187 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2188 inspect.signature(Spam.ham)
2189
2190 class Spam:
2191 def test(it, a, *, c) -> 'spam':
2192 pass
2193 ham = partialmethod(test, c=1)
2194
2195 self.assertEqual(self.signature(Spam.ham),
2196 ((('it', ..., ..., 'positional_or_keyword'),
2197 ('a', ..., ..., 'positional_or_keyword'),
2198 ('c', 1, ..., 'keyword_only')),
2199 'spam'))
2200
2201 self.assertEqual(self.signature(Spam().ham),
2202 ((('a', ..., ..., 'positional_or_keyword'),
2203 ('c', 1, ..., 'keyword_only')),
2204 'spam'))
2205
Yury Selivanov0486f812014-01-29 12:18:59 -05002206 def test_signature_on_fake_partialmethod(self):
2207 def foo(a): pass
2208 foo._partialmethod = 'spam'
2209 self.assertEqual(str(inspect.signature(foo)), '(a)')
2210
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002211 def test_signature_on_decorated(self):
2212 import functools
2213
2214 def decorator(func):
2215 @functools.wraps(func)
2216 def wrapper(*args, **kwargs) -> int:
2217 return func(*args, **kwargs)
2218 return wrapper
2219
2220 class Foo:
2221 @decorator
2222 def bar(self, a, b):
2223 pass
2224
2225 self.assertEqual(self.signature(Foo.bar),
2226 ((('self', ..., ..., "positional_or_keyword"),
2227 ('a', ..., ..., "positional_or_keyword"),
2228 ('b', ..., ..., "positional_or_keyword")),
2229 ...))
2230
2231 self.assertEqual(self.signature(Foo().bar),
2232 ((('a', ..., ..., "positional_or_keyword"),
2233 ('b', ..., ..., "positional_or_keyword")),
2234 ...))
2235
2236 # Test that we handle method wrappers correctly
2237 def decorator(func):
2238 @functools.wraps(func)
2239 def wrapper(*args, **kwargs) -> int:
2240 return func(42, *args, **kwargs)
2241 sig = inspect.signature(func)
2242 new_params = tuple(sig.parameters.values())[1:]
2243 wrapper.__signature__ = sig.replace(parameters=new_params)
2244 return wrapper
2245
2246 class Foo:
2247 @decorator
2248 def __call__(self, a, b):
2249 pass
2250
2251 self.assertEqual(self.signature(Foo.__call__),
2252 ((('a', ..., ..., "positional_or_keyword"),
2253 ('b', ..., ..., "positional_or_keyword")),
2254 ...))
2255
2256 self.assertEqual(self.signature(Foo().__call__),
2257 ((('b', ..., ..., "positional_or_keyword"),),
2258 ...))
2259
Nick Coghlane8c45d62013-07-28 20:00:01 +10002260 # Test we handle __signature__ partway down the wrapper stack
2261 def wrapped_foo_call():
2262 pass
2263 wrapped_foo_call.__wrapped__ = Foo.__call__
2264
2265 self.assertEqual(self.signature(wrapped_foo_call),
2266 ((('a', ..., ..., "positional_or_keyword"),
2267 ('b', ..., ..., "positional_or_keyword")),
2268 ...))
2269
2270
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002271 def test_signature_on_class(self):
2272 class C:
2273 def __init__(self, a):
2274 pass
2275
2276 self.assertEqual(self.signature(C),
2277 ((('a', ..., ..., "positional_or_keyword"),),
2278 ...))
2279
2280 class CM(type):
2281 def __call__(cls, a):
2282 pass
2283 class C(metaclass=CM):
2284 def __init__(self, b):
2285 pass
2286
2287 self.assertEqual(self.signature(C),
2288 ((('a', ..., ..., "positional_or_keyword"),),
2289 ...))
2290
2291 class CM(type):
2292 def __new__(mcls, name, bases, dct, *, foo=1):
2293 return super().__new__(mcls, name, bases, dct)
2294 class C(metaclass=CM):
2295 def __init__(self, b):
2296 pass
2297
2298 self.assertEqual(self.signature(C),
2299 ((('b', ..., ..., "positional_or_keyword"),),
2300 ...))
2301
2302 self.assertEqual(self.signature(CM),
2303 ((('name', ..., ..., "positional_or_keyword"),
2304 ('bases', ..., ..., "positional_or_keyword"),
2305 ('dct', ..., ..., "positional_or_keyword"),
2306 ('foo', 1, ..., "keyword_only")),
2307 ...))
2308
2309 class CMM(type):
2310 def __new__(mcls, name, bases, dct, *, foo=1):
2311 return super().__new__(mcls, name, bases, dct)
2312 def __call__(cls, nm, bs, dt):
2313 return type(nm, bs, dt)
2314 class CM(type, metaclass=CMM):
2315 def __new__(mcls, name, bases, dct, *, bar=2):
2316 return super().__new__(mcls, name, bases, dct)
2317 class C(metaclass=CM):
2318 def __init__(self, b):
2319 pass
2320
2321 self.assertEqual(self.signature(CMM),
2322 ((('name', ..., ..., "positional_or_keyword"),
2323 ('bases', ..., ..., "positional_or_keyword"),
2324 ('dct', ..., ..., "positional_or_keyword"),
2325 ('foo', 1, ..., "keyword_only")),
2326 ...))
2327
2328 self.assertEqual(self.signature(CM),
2329 ((('nm', ..., ..., "positional_or_keyword"),
2330 ('bs', ..., ..., "positional_or_keyword"),
2331 ('dt', ..., ..., "positional_or_keyword")),
2332 ...))
2333
2334 self.assertEqual(self.signature(C),
2335 ((('b', ..., ..., "positional_or_keyword"),),
2336 ...))
2337
2338 class CM(type):
2339 def __init__(cls, name, bases, dct, *, bar=2):
2340 return super().__init__(name, bases, dct)
2341 class C(metaclass=CM):
2342 def __init__(self, b):
2343 pass
2344
2345 self.assertEqual(self.signature(CM),
2346 ((('name', ..., ..., "positional_or_keyword"),
2347 ('bases', ..., ..., "positional_or_keyword"),
2348 ('dct', ..., ..., "positional_or_keyword"),
2349 ('bar', 2, ..., "keyword_only")),
2350 ...))
2351
Yury Selivanov145dff82014-02-01 13:49:29 -05002352 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2353 "Signature information for builtins requires docstrings")
2354 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002355 # Test classes without user-defined __init__ or __new__
2356 class C: pass
2357 self.assertEqual(str(inspect.signature(C)), '()')
2358 class D(C): pass
2359 self.assertEqual(str(inspect.signature(D)), '()')
2360
2361 # Test meta-classes without user-defined __init__ or __new__
2362 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002363 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002364 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2365 self.assertEqual(inspect.signature(C), None)
2366 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2367 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002368
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002369 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2370 "Signature information for builtins requires docstrings")
2371 def test_signature_on_builtin_class(self):
2372 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2373 '(file, protocol=None, fix_imports=True)')
2374
2375 class P(_pickle.Pickler): pass
2376 class EmptyTrait: pass
2377 class P2(EmptyTrait, P): pass
2378 self.assertEqual(str(inspect.signature(P)),
2379 '(file, protocol=None, fix_imports=True)')
2380 self.assertEqual(str(inspect.signature(P2)),
2381 '(file, protocol=None, fix_imports=True)')
2382
2383 class P3(P2):
2384 def __init__(self, spam):
2385 pass
2386 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2387
2388 class MetaP(type):
2389 def __call__(cls, foo, bar):
2390 pass
2391 class P4(P2, metaclass=MetaP):
2392 pass
2393 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2394
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002395 def test_signature_on_callable_objects(self):
2396 class Foo:
2397 def __call__(self, a):
2398 pass
2399
2400 self.assertEqual(self.signature(Foo()),
2401 ((('a', ..., ..., "positional_or_keyword"),),
2402 ...))
2403
2404 class Spam:
2405 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002406 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002407 inspect.signature(Spam())
2408
2409 class Bar(Spam, Foo):
2410 pass
2411
2412 self.assertEqual(self.signature(Bar()),
2413 ((('a', ..., ..., "positional_or_keyword"),),
2414 ...))
2415
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002416 class Wrapped:
2417 pass
2418 Wrapped.__wrapped__ = lambda a: None
2419 self.assertEqual(self.signature(Wrapped),
2420 ((('a', ..., ..., "positional_or_keyword"),),
2421 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002422 # wrapper loop:
2423 Wrapped.__wrapped__ = Wrapped
2424 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2425 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002426
2427 def test_signature_on_lambdas(self):
2428 self.assertEqual(self.signature((lambda a=10: a)),
2429 ((('a', 10, ..., "positional_or_keyword"),),
2430 ...))
2431
2432 def test_signature_equality(self):
2433 def foo(a, *, b:int) -> float: pass
2434 self.assertNotEqual(inspect.signature(foo), 42)
2435
2436 def bar(a, *, b:int) -> float: pass
2437 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2438
2439 def bar(a, *, b:int) -> int: pass
2440 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2441
2442 def bar(a, *, b:int): pass
2443 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2444
2445 def bar(a, *, b:int=42) -> float: pass
2446 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2447
2448 def bar(a, *, c) -> float: pass
2449 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2450
2451 def bar(a, b:int) -> float: pass
2452 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2453 def spam(b:int, a) -> float: pass
2454 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
2455
2456 def foo(*, a, b, c): pass
2457 def bar(*, c, b, a): pass
2458 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2459
2460 def foo(*, a=1, b, c): pass
2461 def bar(*, c, b, a=1): pass
2462 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2463
2464 def foo(pos, *, a=1, b, c): pass
2465 def bar(pos, *, c, b, a=1): pass
2466 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2467
2468 def foo(pos, *, a, b, c): pass
2469 def bar(pos, *, c, b, a=1): pass
2470 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2471
2472 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2473 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2474 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2475
2476 def test_signature_unhashable(self):
2477 def foo(a): pass
2478 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002479 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002480 hash(sig)
2481
2482 def test_signature_str(self):
2483 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2484 pass
2485 self.assertEqual(str(inspect.signature(foo)),
2486 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2487
2488 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2489 pass
2490 self.assertEqual(str(inspect.signature(foo)),
2491 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2492
2493 def foo():
2494 pass
2495 self.assertEqual(str(inspect.signature(foo)), '()')
2496
2497 def test_signature_str_positional_only(self):
2498 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002499 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002500
2501 def test(a_po, *, b, **kwargs):
2502 return a_po, kwargs
2503
2504 sig = inspect.signature(test)
2505 new_params = list(sig.parameters.values())
2506 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2507 test.__signature__ = sig.replace(parameters=new_params)
2508
2509 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002510 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002511
Yury Selivanov2393dca2014-01-27 15:07:58 -05002512 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2513 '(foo, /)')
2514
2515 self.assertEqual(str(S(parameters=[
2516 P('foo', P.POSITIONAL_ONLY),
2517 P('bar', P.VAR_KEYWORD)])),
2518 '(foo, /, **bar)')
2519
2520 self.assertEqual(str(S(parameters=[
2521 P('foo', P.POSITIONAL_ONLY),
2522 P('bar', P.VAR_POSITIONAL)])),
2523 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002524
2525 def test_signature_replace_anno(self):
2526 def test() -> 42:
2527 pass
2528
2529 sig = inspect.signature(test)
2530 sig = sig.replace(return_annotation=None)
2531 self.assertIs(sig.return_annotation, None)
2532 sig = sig.replace(return_annotation=sig.empty)
2533 self.assertIs(sig.return_annotation, sig.empty)
2534 sig = sig.replace(return_annotation=42)
2535 self.assertEqual(sig.return_annotation, 42)
2536 self.assertEqual(sig, inspect.signature(test))
2537
Yury Selivanov026019f2014-02-18 12:49:41 -05002538 def test_signature_on_mangled_parameters(self):
2539 class Spam:
2540 def foo(self, __p1:1=2, *, __p2:2=3):
2541 pass
2542 class Ham(Spam):
2543 pass
2544
2545 self.assertEqual(self.signature(Spam.foo),
2546 ((('self', ..., ..., "positional_or_keyword"),
2547 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2548 ('_Spam__p2', 3, 2, "keyword_only")),
2549 ...))
2550
2551 self.assertEqual(self.signature(Spam.foo),
2552 self.signature(Ham.foo))
2553
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002554
2555class TestParameterObject(unittest.TestCase):
2556 def test_signature_parameter_kinds(self):
2557 P = inspect.Parameter
2558 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2559 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2560
2561 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2562 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2563
2564 def test_signature_parameter_object(self):
2565 p = inspect.Parameter('foo', default=10,
2566 kind=inspect.Parameter.POSITIONAL_ONLY)
2567 self.assertEqual(p.name, 'foo')
2568 self.assertEqual(p.default, 10)
2569 self.assertIs(p.annotation, p.empty)
2570 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2571
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002572 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002573 inspect.Parameter('foo', default=10, kind='123')
2574
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002575 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002576 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2577
Yury Selivanov2393dca2014-01-27 15:07:58 -05002578 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002579 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2580
Yury Selivanov2393dca2014-01-27 15:07:58 -05002581 with self.assertRaisesRegex(ValueError,
2582 'is not a valid parameter name'):
2583 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2584
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002585 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002586 inspect.Parameter('a', default=42,
2587 kind=inspect.Parameter.VAR_KEYWORD)
2588
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002589 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002590 inspect.Parameter('a', default=42,
2591 kind=inspect.Parameter.VAR_POSITIONAL)
2592
2593 p = inspect.Parameter('a', default=42,
2594 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002595 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002596 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2597
2598 self.assertTrue(repr(p).startswith('<Parameter'))
2599
2600 def test_signature_parameter_equality(self):
2601 P = inspect.Parameter
2602 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2603
2604 self.assertEqual(p, p)
2605 self.assertNotEqual(p, 42)
2606
2607 self.assertEqual(p, P('foo', default=42,
2608 kind=inspect.Parameter.KEYWORD_ONLY))
2609
2610 def test_signature_parameter_unhashable(self):
2611 p = inspect.Parameter('foo', default=42,
2612 kind=inspect.Parameter.KEYWORD_ONLY)
2613
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002614 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002615 hash(p)
2616
2617 def test_signature_parameter_replace(self):
2618 p = inspect.Parameter('foo', default=42,
2619 kind=inspect.Parameter.KEYWORD_ONLY)
2620
2621 self.assertIsNot(p, p.replace())
2622 self.assertEqual(p, p.replace())
2623
2624 p2 = p.replace(annotation=1)
2625 self.assertEqual(p2.annotation, 1)
2626 p2 = p2.replace(annotation=p2.empty)
2627 self.assertEqual(p, p2)
2628
2629 p2 = p2.replace(name='bar')
2630 self.assertEqual(p2.name, 'bar')
2631 self.assertNotEqual(p2, p)
2632
Yury Selivanov2393dca2014-01-27 15:07:58 -05002633 with self.assertRaisesRegex(ValueError,
2634 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002635 p2 = p2.replace(name=p2.empty)
2636
2637 p2 = p2.replace(name='foo', default=None)
2638 self.assertIs(p2.default, None)
2639 self.assertNotEqual(p2, p)
2640
2641 p2 = p2.replace(name='foo', default=p2.empty)
2642 self.assertIs(p2.default, p2.empty)
2643
2644
2645 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2646 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2647 self.assertNotEqual(p2, p)
2648
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002649 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002650 p2 = p2.replace(kind=p2.empty)
2651
2652 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2653 self.assertEqual(p2, p)
2654
2655 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002656 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2657 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002658
2659 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002660 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002661
2662 with self.assertRaises(AttributeError):
2663 p.foo = 'bar'
2664
2665 with self.assertRaises(AttributeError):
2666 p.kind = 123
2667
2668
2669class TestSignatureBind(unittest.TestCase):
2670 @staticmethod
2671 def call(func, *args, **kwargs):
2672 sig = inspect.signature(func)
2673 ba = sig.bind(*args, **kwargs)
2674 return func(*ba.args, **ba.kwargs)
2675
2676 def test_signature_bind_empty(self):
2677 def test():
2678 return 42
2679
2680 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002681 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002682 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002683 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002684 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002685 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002686 self.call(test, spam=1)
2687
2688 def test_signature_bind_var(self):
2689 def test(*args, **kwargs):
2690 return args, kwargs
2691
2692 self.assertEqual(self.call(test), ((), {}))
2693 self.assertEqual(self.call(test, 1), ((1,), {}))
2694 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2695 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2696 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2697 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2698 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2699 ((1, 2), {'foo': 'bar'}))
2700
2701 def test_signature_bind_just_args(self):
2702 def test(a, b, c):
2703 return a, b, c
2704
2705 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2706
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002707 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002708 self.call(test, 1, 2, 3, 4)
2709
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002710 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002711 self.call(test, 1)
2712
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002713 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002714 self.call(test)
2715
2716 def test(a, b, c=10):
2717 return a, b, c
2718 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2719 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2720
2721 def test(a=1, b=2, c=3):
2722 return a, b, c
2723 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2724 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2725 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2726
2727 def test_signature_bind_varargs_order(self):
2728 def test(*args):
2729 return args
2730
2731 self.assertEqual(self.call(test), ())
2732 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2733
2734 def test_signature_bind_args_and_varargs(self):
2735 def test(a, b, c=3, *args):
2736 return a, b, c, args
2737
2738 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2739 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2740 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2741 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2742
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002743 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002744 "multiple values for argument 'c'"):
2745 self.call(test, 1, 2, 3, c=4)
2746
2747 def test_signature_bind_just_kwargs(self):
2748 def test(**kwargs):
2749 return kwargs
2750
2751 self.assertEqual(self.call(test), {})
2752 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2753 {'foo': 'bar', 'spam': 'ham'})
2754
2755 def test_signature_bind_args_and_kwargs(self):
2756 def test(a, b, c=3, **kwargs):
2757 return a, b, c, kwargs
2758
2759 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2760 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2761 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2762 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2763 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2764 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2765 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2766 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2767 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2768 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2769 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2770 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2771 (1, 2, 4, {'foo': 'bar'}))
2772 self.assertEqual(self.call(test, c=5, a=4, b=3),
2773 (4, 3, 5, {}))
2774
2775 def test_signature_bind_kwonly(self):
2776 def test(*, foo):
2777 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002778 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002779 'too many positional arguments'):
2780 self.call(test, 1)
2781 self.assertEqual(self.call(test, foo=1), 1)
2782
2783 def test(a, *, foo=1, bar):
2784 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002785 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002786 "'bar' parameter lacking default value"):
2787 self.call(test, 1)
2788
2789 def test(foo, *, bar):
2790 return foo, bar
2791 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2792 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2793
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002794 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002795 'too many keyword arguments'):
2796 self.call(test, bar=2, foo=1, spam=10)
2797
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002798 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002799 'too many positional arguments'):
2800 self.call(test, 1, 2)
2801
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002802 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002803 'too many positional arguments'):
2804 self.call(test, 1, 2, bar=2)
2805
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002806 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002807 'too many keyword arguments'):
2808 self.call(test, 1, bar=2, spam='ham')
2809
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002810 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002811 "'bar' parameter lacking default value"):
2812 self.call(test, 1)
2813
2814 def test(foo, *, bar, **bin):
2815 return foo, bar, bin
2816 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2817 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2818 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2819 (1, 2, {'spam': 'ham'}))
2820 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2821 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002822 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002823 "'foo' parameter lacking default value"):
2824 self.call(test, spam='ham', bar=2)
2825 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2826 (1, 2, {'bin': 1, 'spam': 10}))
2827
2828 def test_signature_bind_arguments(self):
2829 def test(a, *args, b, z=100, **kwargs):
2830 pass
2831 sig = inspect.signature(test)
2832 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2833 # we won't have 'z' argument in the bound arguments object, as we didn't
2834 # pass it to the 'bind'
2835 self.assertEqual(tuple(ba.arguments.items()),
2836 (('a', 10), ('args', (20,)), ('b', 30),
2837 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2838 self.assertEqual(ba.kwargs,
2839 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2840 self.assertEqual(ba.args, (10, 20))
2841
2842 def test_signature_bind_positional_only(self):
2843 P = inspect.Parameter
2844
2845 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2846 return a_po, b_po, c_po, foo, bar, kwargs
2847
2848 sig = inspect.signature(test)
2849 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2850 for name in ('a_po', 'b_po', 'c_po'):
2851 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2852 new_sig = sig.replace(parameters=new_params.values())
2853 test.__signature__ = new_sig
2854
2855 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2856 (1, 2, 4, 5, 6, {}))
2857
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002858 self.assertEqual(self.call(test, 1, 2),
2859 (1, 2, 3, 42, 50, {}))
2860
2861 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
2862 (1, 2, 3, 4, 5, {}))
2863
2864 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
2865 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
2866
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002867 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002868 self.call(test, 1, 2, c_po=4)
2869
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002870 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002871 self.call(test, a_po=1, b_po=2)
2872
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002873 def test_signature_bind_with_self_arg(self):
2874 # Issue #17071: one of the parameters is named "self
2875 def test(a, self, b):
2876 pass
2877 sig = inspect.signature(test)
2878 ba = sig.bind(1, 2, 3)
2879 self.assertEqual(ba.args, (1, 2, 3))
2880 ba = sig.bind(1, self=2, b=3)
2881 self.assertEqual(ba.args, (1, 2, 3))
2882
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002883 def test_signature_bind_vararg_name(self):
2884 def test(a, *args):
2885 return a, args
2886 sig = inspect.signature(test)
2887
2888 with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
2889 sig.bind(a=0, args=1)
2890
2891 def test(*args, **kwargs):
2892 return args, kwargs
2893 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
2894
2895 sig = inspect.signature(test)
2896 ba = sig.bind(args=1)
2897 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
2898
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002899
2900class TestBoundArguments(unittest.TestCase):
2901 def test_signature_bound_arguments_unhashable(self):
2902 def foo(a): pass
2903 ba = inspect.signature(foo).bind(1)
2904
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002905 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002906 hash(ba)
2907
2908 def test_signature_bound_arguments_equality(self):
2909 def foo(a): pass
2910 ba = inspect.signature(foo).bind(1)
2911 self.assertEqual(ba, ba)
2912
2913 ba2 = inspect.signature(foo).bind(1)
2914 self.assertEqual(ba, ba2)
2915
2916 ba3 = inspect.signature(foo).bind(2)
2917 self.assertNotEqual(ba, ba3)
2918 ba3.arguments['a'] = 1
2919 self.assertEqual(ba, ba3)
2920
2921 def bar(b): pass
2922 ba4 = inspect.signature(bar).bind(1)
2923 self.assertNotEqual(ba, ba4)
2924
2925
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002926class TestSignaturePrivateHelpers(unittest.TestCase):
2927 def test_signature_get_bound_param(self):
2928 getter = inspect._signature_get_bound_param
2929
2930 self.assertEqual(getter('($self)'), 'self')
2931 self.assertEqual(getter('($self, obj)'), 'self')
2932 self.assertEqual(getter('($cls, /, obj)'), 'cls')
2933
Larry Hastings2623c8c2014-02-08 22:15:29 -08002934 def _strip_non_python_syntax(self, input,
2935 clean_signature, self_parameter, last_positional_only):
2936 computed_clean_signature, \
2937 computed_self_parameter, \
2938 computed_last_positional_only = \
2939 inspect._signature_strip_non_python_syntax(input)
2940 self.assertEqual(computed_clean_signature, clean_signature)
2941 self.assertEqual(computed_self_parameter, self_parameter)
2942 self.assertEqual(computed_last_positional_only, last_positional_only)
2943
2944 def test_signature_strip_non_python_syntax(self):
2945 self._strip_non_python_syntax(
2946 "($module, /, path, mode, *, dir_fd=None, " +
2947 "effective_ids=False,\n follow_symlinks=True)",
2948 "(module, path, mode, *, dir_fd=None, " +
2949 "effective_ids=False, follow_symlinks=True)",
2950 0,
2951 0)
2952
2953 self._strip_non_python_syntax(
2954 "($module, word, salt, /)",
2955 "(module, word, salt)",
2956 0,
2957 2)
2958
2959 self._strip_non_python_syntax(
2960 "(x, y=None, z=None, /)",
2961 "(x, y=None, z=None)",
2962 None,
2963 2)
2964
2965 self._strip_non_python_syntax(
2966 "(x, y=None, z=None)",
2967 "(x, y=None, z=None)",
2968 None,
2969 None)
2970
2971 self._strip_non_python_syntax(
2972 "(x,\n y=None,\n z = None )",
2973 "(x, y=None, z=None)",
2974 None,
2975 None)
2976
2977 self._strip_non_python_syntax(
2978 "",
2979 "",
2980 None,
2981 None)
2982
2983 self._strip_non_python_syntax(
2984 None,
2985 None,
2986 None,
2987 None)
2988
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002989
Nick Coghlane8c45d62013-07-28 20:00:01 +10002990class TestUnwrap(unittest.TestCase):
2991
2992 def test_unwrap_one(self):
2993 def func(a, b):
2994 return a + b
2995 wrapper = functools.lru_cache(maxsize=20)(func)
2996 self.assertIs(inspect.unwrap(wrapper), func)
2997
2998 def test_unwrap_several(self):
2999 def func(a, b):
3000 return a + b
3001 wrapper = func
3002 for __ in range(10):
3003 @functools.wraps(wrapper)
3004 def wrapper():
3005 pass
3006 self.assertIsNot(wrapper.__wrapped__, func)
3007 self.assertIs(inspect.unwrap(wrapper), func)
3008
3009 def test_stop(self):
3010 def func1(a, b):
3011 return a + b
3012 @functools.wraps(func1)
3013 def func2():
3014 pass
3015 @functools.wraps(func2)
3016 def wrapper():
3017 pass
3018 func2.stop_here = 1
3019 unwrapped = inspect.unwrap(wrapper,
3020 stop=(lambda f: hasattr(f, "stop_here")))
3021 self.assertIs(unwrapped, func2)
3022
3023 def test_cycle(self):
3024 def func1(): pass
3025 func1.__wrapped__ = func1
3026 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3027 inspect.unwrap(func1)
3028
3029 def func2(): pass
3030 func2.__wrapped__ = func1
3031 func1.__wrapped__ = func2
3032 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3033 inspect.unwrap(func1)
3034 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3035 inspect.unwrap(func2)
3036
3037 def test_unhashable(self):
3038 def func(): pass
3039 func.__wrapped__ = None
3040 class C:
3041 __hash__ = None
3042 __wrapped__ = func
3043 self.assertIsNone(inspect.unwrap(C()))
3044
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003045class TestMain(unittest.TestCase):
3046 def test_only_source(self):
3047 module = importlib.import_module('unittest')
3048 rc, out, err = assert_python_ok('-m', 'inspect',
3049 'unittest')
3050 lines = out.decode().splitlines()
3051 # ignore the final newline
3052 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3053 self.assertEqual(err, b'')
3054
Yury Selivanovc0f964f2014-06-23 10:21:04 -07003055 def test_custom_getattr(self):
3056 def foo():
3057 pass
3058 foo.__signature__ = 42
3059 with self.assertRaises(TypeError):
3060 inspect.signature(foo)
3061
Brett Cannon634a8fc2013-10-02 10:25:42 -04003062 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003063 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003064 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003065 rc, out, err = assert_python_ok('-m', 'inspect',
3066 'concurrent.futures:ThreadPoolExecutor')
3067 lines = out.decode().splitlines()
3068 # ignore the final newline
3069 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003070 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003071 self.assertEqual(err, b'')
3072
3073 def test_builtins(self):
3074 module = importlib.import_module('unittest')
3075 _, out, err = assert_python_failure('-m', 'inspect',
3076 'sys')
3077 lines = err.decode().splitlines()
3078 self.assertEqual(lines, ["Can't get info for builtin modules."])
3079
3080 def test_details(self):
3081 module = importlib.import_module('unittest')
3082 rc, out, err = assert_python_ok('-m', 'inspect',
3083 'unittest', '--details')
3084 output = out.decode()
3085 # Just a quick sanity check on the output
3086 self.assertIn(module.__name__, output)
3087 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02003088 if not sys.flags.optimize:
3089 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003090 self.assertEqual(err, b'')
3091
3092
Yury Selivanov7de29682014-12-08 18:00:25 -05003093class TestReload(unittest.TestCase):
3094
3095 src_before = textwrap.dedent("""\
3096def foo():
3097 print("Bla")
3098 """)
3099
3100 src_after = textwrap.dedent("""\
3101def foo():
3102 print("Oh no!")
3103 """)
3104
3105 def assertInspectEqual(self, path, source):
3106 inspected_src = inspect.getsource(source)
3107 with open(path) as src:
3108 self.assertEqual(
3109 src.read().splitlines(True),
3110 inspected_src.splitlines(True)
3111 )
3112
3113 def test_getsource_reload(self):
3114 # see issue 1218234
3115 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3116 module = importlib.import_module(name)
3117 self.assertInspectEqual(path, module)
3118 with open(path, 'w') as src:
3119 src.write(self.src_after)
3120 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003121
Nick Coghlane8c45d62013-07-28 20:00:01 +10003122
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003123def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003124 run_unittest(
3125 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3126 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3127 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003128 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003129 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003130 TestBoundArguments, TestSignaturePrivateHelpers, TestGetClosureVars,
Yury Selivanov7de29682014-12-08 18:00:25 -05003131 TestUnwrap, TestMain, TestReload
Michael Foord95fc51d2010-11-20 15:07:30 +00003132 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003133
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003134if __name__ == "__main__":
3135 test_main()