blob: 7ad190b0562838b806f97243a32ba210d247ab98 [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
Yury Selivanova5d63dd2014-03-27 11:31:43 -040011import pickle
Larry Hastings5c661892014-01-24 06:17:25 -080012import re
13import shutil
14import sys
15import types
16import unicodedata
17import unittest
Yury Selivanova773de02014-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
R. David Murray74b89242009-05-13 17:33:03 +000031
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000032# Functions tested in this suite:
33# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000034# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
35# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
36# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
37# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000038
Nick Coghlanf088e5e2008-12-14 11:50:48 +000039# NOTE: There are some additional tests relating to interaction with
40# zipimport in the test_zipimport_support test module.
41
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000042modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000043if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000044 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000045
Christian Heimesa3538eb2007-11-06 11:44:48 +000046# Normalize file names: on Windows, the case of file names of compiled
47# modules depends on the path used to start the python executable.
48modfile = normcase(modfile)
49
50def revise(filename, *args):
51 return (normcase(filename),) + args
52
Georg Brandl1a3284e2007-12-02 09:40:06 +000053import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000054
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000055git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000056
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000057class IsTestBase(unittest.TestCase):
58 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
59 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000060 inspect.ismodule, inspect.istraceback,
61 inspect.isgenerator, inspect.isgeneratorfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000062
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000063 def istest(self, predicate, exp):
64 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000065 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000066
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000067 for other in self.predicates - set([predicate]):
Christian Heimes7131fd92008-02-19 14:21:46 +000068 if predicate == inspect.isgeneratorfunction and\
69 other == inspect.isfunction:
70 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000071 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000072
Christian Heimes7131fd92008-02-19 14:21:46 +000073def generator_function_example(self):
74 for i in range(2):
75 yield i
76
Yury Selivanova5d63dd2014-03-27 11:31:43 -040077
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000078class TestPredicates(IsTestBase):
Christian Heimes227c8002008-03-03 20:34:40 +000079 def test_sixteen(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +000080 count = len([x for x in dir(inspect) if x.startswith('is')])
Christian Heimes7131fd92008-02-19 14:21:46 +000081 # This test is here for remember you to update Doc/library/inspect.rst
Christian Heimes78644762008-03-04 23:39:23 +000082 # which claims there are 16 such functions
Christian Heimes227c8002008-03-03 20:34:40 +000083 expected = 16
Thomas Wouters0e3f5912006-08-11 14:57:12 +000084 err_msg = "There are %d (not %d) is* functions" % (count, expected)
85 self.assertEqual(count, expected, err_msg)
Tim Peters5a9fb3c2005-01-07 16:01:32 +000086
Christian Heimes7131fd92008-02-19 14:21:46 +000087
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000088 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +020089 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000090 self.istest(inspect.isbuiltin, 'sys.exit')
91 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +000092 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +020093 try:
94 1/0
95 except:
96 tb = sys.exc_info()[2]
97 self.istest(inspect.isframe, 'tb.tb_frame')
98 self.istest(inspect.istraceback, 'tb')
99 if hasattr(types, 'GetSetDescriptorType'):
100 self.istest(inspect.isgetsetdescriptor,
101 'type(tb.tb_frame).f_locals')
102 else:
103 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
104 finally:
105 # Clear traceback and all the frames and local variables hanging to it.
106 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000107 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000108 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000109 self.istest(inspect.ismethod, 'git.argue')
110 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000111 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000112 self.istest(inspect.isgenerator, '(x for x in range(2))')
113 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000114 if hasattr(types, 'MemberDescriptorType'):
115 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
116 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000117 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000118
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000119 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000120 self.assertTrue(inspect.isroutine(mod.spam))
121 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000122
Benjamin Petersonc4656002009-01-17 22:41:18 +0000123 def test_isclass(self):
124 self.istest(inspect.isclass, 'mod.StupidGit')
125 self.assertTrue(inspect.isclass(list))
126
127 class CustomGetattr(object):
128 def __getattr__(self, attr):
129 return None
130 self.assertFalse(inspect.isclass(CustomGetattr()))
131
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000132 def test_get_slot_members(self):
133 class C(object):
134 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000135 x = C()
136 x.a = 42
137 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000138 self.assertIn('a', members)
139 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000140
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000141 def test_isabstract(self):
142 from abc import ABCMeta, abstractmethod
143
144 class AbstractClassExample(metaclass=ABCMeta):
145
146 @abstractmethod
147 def foo(self):
148 pass
149
150 class ClassExample(AbstractClassExample):
151 def foo(self):
152 pass
153
154 a = ClassExample()
155
156 # Test general behaviour.
157 self.assertTrue(inspect.isabstract(AbstractClassExample))
158 self.assertFalse(inspect.isabstract(ClassExample))
159 self.assertFalse(inspect.isabstract(a))
160 self.assertFalse(inspect.isabstract(int))
161 self.assertFalse(inspect.isabstract(5))
162
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000163
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000164class TestInterpreterStack(IsTestBase):
165 def __init__(self, *args, **kwargs):
166 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000167
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000168 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000169
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000170 def test_abuse_done(self):
171 self.istest(inspect.istraceback, 'git.ex[2]')
172 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000173
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000174 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000175 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000176 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000177 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000178 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000179 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000180 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000181 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000182 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000183 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000184
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000185 def test_trace(self):
186 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000187 self.assertEqual(revise(*git.tr[0][1:]),
188 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
189 self.assertEqual(revise(*git.tr[1][1:]),
190 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
191 self.assertEqual(revise(*git.tr[2][1:]),
192 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000193
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000194 def test_frame(self):
195 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
196 self.assertEqual(args, ['x', 'y'])
197 self.assertEqual(varargs, None)
198 self.assertEqual(varkw, None)
199 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
200 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
201 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000202
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000203 def test_previous_frame(self):
204 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000205 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000206 self.assertEqual(varargs, 'g')
207 self.assertEqual(varkw, 'h')
208 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000209 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000210
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000211class GetSourceBase(unittest.TestCase):
212 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000213 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000214
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000215 def __init__(self, *args, **kwargs):
216 unittest.TestCase.__init__(self, *args, **kwargs)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000217
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000218 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000219 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000220
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000221 def sourcerange(self, top, bottom):
222 lines = self.source.split("\n")
223 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000224
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000225 def assertSourceEqual(self, obj, top, bottom):
226 self.assertEqual(inspect.getsource(obj),
227 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000228
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000229class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000230 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000231
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000232 def test_getclasses(self):
233 classes = inspect.getmembers(mod, inspect.isclass)
234 self.assertEqual(classes,
235 [('FesteringGob', mod.FesteringGob),
236 ('MalodorousPervert', mod.MalodorousPervert),
237 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300238 ('StupidGit', mod.StupidGit),
239 ('Tit', mod.MalodorousPervert),
240 ])
241 tree = inspect.getclasstree([cls[1] for cls in classes])
242 self.assertEqual(tree,
243 [(object, ()),
244 [(mod.ParrotDroppings, (object,)),
245 [(mod.FesteringGob, (mod.MalodorousPervert,
246 mod.ParrotDroppings))
247 ],
248 (mod.StupidGit, (object,)),
249 [(mod.MalodorousPervert, (mod.StupidGit,)),
250 [(mod.FesteringGob, (mod.MalodorousPervert,
251 mod.ParrotDroppings))
252 ]
253 ]
254 ]
255 ])
256 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000257 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000258 [(object, ()),
259 [(mod.ParrotDroppings, (object,)),
260 (mod.StupidGit, (object,)),
261 [(mod.MalodorousPervert, (mod.StupidGit,)),
262 [(mod.FesteringGob, (mod.MalodorousPervert,
263 mod.ParrotDroppings))
264 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000265 ]
266 ]
267 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000268
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000269 def test_getfunctions(self):
270 functions = inspect.getmembers(mod, inspect.isfunction)
271 self.assertEqual(functions, [('eggs', mod.eggs),
272 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000273
R. David Murray378c0cf2010-02-24 01:46:21 +0000274 @unittest.skipIf(sys.flags.optimize >= 2,
275 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000276 def test_getdoc(self):
277 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
278 self.assertEqual(inspect.getdoc(mod.StupidGit),
279 'A longer,\n\nindented\n\ndocstring.')
280 self.assertEqual(inspect.getdoc(git.abuse),
281 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000282
Georg Brandl0c77a822008-06-10 16:37:50 +0000283 def test_cleandoc(self):
284 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
285 'An\nindented\ndocstring.')
286
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000287 def test_getcomments(self):
288 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
289 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000290
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000291 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000292 # Check actual module
293 self.assertEqual(inspect.getmodule(mod), mod)
294 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000295 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000296 # Check a method (no __module__ attribute, falls back to filename)
297 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
298 # Do it again (check the caching isn't broken)
299 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
300 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000301 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000302 # Check filename override
303 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000304
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000305 def test_getsource(self):
306 self.assertSourceEqual(git.abuse, 29, 39)
307 self.assertSourceEqual(mod.StupidGit, 21, 46)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000308
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000309 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000310 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
311 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000312 fn = "_non_existing_filename_used_for_sourcefile_test.py"
313 co = compile("None", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000314 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000315 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200316 try:
317 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
318 finally:
319 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000320
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000321 def test_getfile(self):
322 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000323
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500324 def test_getfile_class_without_module(self):
325 class CM(type):
326 @property
327 def __module__(cls):
328 raise AttributeError
329 class C(metaclass=CM):
330 pass
331 with self.assertRaises(TypeError):
332 inspect.getfile(C)
333
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000334 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000335 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000336 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000337 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000338 m.__file__ = "<string>" # hopefully not a real filename...
339 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000340 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000341 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000342 del sys.modules[name]
343 inspect.getmodule(compile('a=10','','single'))
344
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500345 def test_proceed_with_fake_filename(self):
346 '''doctest monkeypatches linecache to enable inspection'''
347 fn, source = '<test>', 'def x(): pass\n'
348 getlines = linecache.getlines
349 def monkey(filename, module_globals=None):
350 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300351 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500352 else:
353 return getlines(filename, module_globals)
354 linecache.getlines = monkey
355 try:
356 ns = {}
357 exec(compile(source, fn, 'single'), ns)
358 inspect.getsource(ns["x"])
359 finally:
360 linecache.getlines = getlines
361
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000362class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000363 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000364
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000365 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000366 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000367
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000368 def test_replacing_decorator(self):
369 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000370
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000371class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000372 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000373 def test_oneline_lambda(self):
374 # Test inspect.getsource with a one-line lambda function.
375 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000376
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000377 def test_threeline_lambda(self):
378 # Test inspect.getsource with a three-line lambda function,
379 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000380 self.assertSourceEqual(mod2.tll, 28, 30)
381
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000382 def test_twoline_indented_lambda(self):
383 # Test inspect.getsource with a two-line lambda function,
384 # where the second line _is_ indented.
385 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000386
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000387 def test_onelinefunc(self):
388 # Test inspect.getsource with a regular one-line function.
389 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000390
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000391 def test_manyargs(self):
392 # Test inspect.getsource with a regular function where
393 # the arguments are on two lines and _not_ indented and
394 # the body on the second line with the last arguments.
395 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000396
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000397 def test_twolinefunc(self):
398 # Test inspect.getsource with a regular function where
399 # the body is on two lines, following the argument list and
400 # continued on the next line by a \\.
401 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000402
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000403 def test_lambda_in_list(self):
404 # Test inspect.getsource with a one-line lambda function
405 # defined in a list, indented.
406 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000407
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000408 def test_anonymous(self):
409 # Test inspect.getsource with a lambda function defined
410 # as argument to another function.
411 self.assertSourceEqual(mod2.anonymous, 55, 55)
412
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000413class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000414 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000415
416 def test_with_comment(self):
417 self.assertSourceEqual(mod2.with_comment, 58, 59)
418
419 def test_multiline_sig(self):
420 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
421
Armin Rigodd5c0232005-09-25 11:45:45 +0000422 def test_nested_class(self):
423 self.assertSourceEqual(mod2.func69().func71, 71, 72)
424
425 def test_one_liner_followed_by_non_name(self):
426 self.assertSourceEqual(mod2.func77, 77, 77)
427
428 def test_one_liner_dedent_non_name(self):
429 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
430
431 def test_with_comment_instead_of_docstring(self):
432 self.assertSourceEqual(mod2.func88, 88, 90)
433
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000434 def test_method_in_dynamic_class(self):
435 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
436
R. David Murrayb5655772009-05-14 16:17:50 +0000437 @unittest.skipIf(
438 not hasattr(unicodedata, '__file__') or
439 unicodedata.__file__[-4:] in (".pyc", ".pyo"),
440 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000441 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200442 self.assertRaises(OSError, inspect.getsource, unicodedata)
443 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000444
R. David Murraya1b37402010-06-17 02:04:29 +0000445 def test_findsource_code_in_linecache(self):
446 lines = ["x=1"]
447 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200448 self.assertRaises(OSError, inspect.findsource, co)
449 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000450 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200451 try:
452 self.assertEqual(inspect.findsource(co), (lines,0))
453 self.assertEqual(inspect.getsource(co), lines[0])
454 finally:
455 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000456
Ezio Melotti1b145922013-03-30 05:17:24 +0200457 def test_findsource_without_filename(self):
458 for fname in ['', '<string>']:
459 co = compile('x=1', fname, "exec")
460 self.assertRaises(IOError, inspect.findsource, co)
461 self.assertRaises(IOError, inspect.getsource, co)
462
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000463class TestNoEOL(GetSourceBase):
464 def __init__(self, *args, **kwargs):
465 self.tempdir = TESTFN + '_dir'
466 os.mkdir(self.tempdir)
467 with open(os.path.join(self.tempdir,
468 'inspect_fodder3%spy' % os.extsep), 'w') as f:
469 f.write("class X:\n pass # No EOL")
470 with DirsOnSysPath(self.tempdir):
471 import inspect_fodder3 as mod3
472 self.fodderModule = mod3
473 GetSourceBase.__init__(self, *args, **kwargs)
474
475 def tearDown(self):
476 shutil.rmtree(self.tempdir)
477
478 def test_class(self):
479 self.assertSourceEqual(self.fodderModule.X, 1, 2)
480
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100481
482class _BrokenDataDescriptor(object):
483 """
484 A broken data descriptor. See bug #1785.
485 """
486 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700487 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100488
489 def __set__(*args):
490 raise RuntimeError
491
492 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700493 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100494
495
496class _BrokenMethodDescriptor(object):
497 """
498 A broken method descriptor. See bug #1785.
499 """
500 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700501 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100502
503 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700504 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100505
506
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000507# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000508def attrs_wo_objs(cls):
509 return [t[:3] for t in inspect.classify_class_attrs(cls)]
510
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100511
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000512class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000513 def test_newstyle_mro(self):
514 # The same w/ new-class MRO.
515 class A(object): pass
516 class B(A): pass
517 class C(A): pass
518 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000519
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000520 expected = (D, B, C, A, object)
521 got = inspect.getmro(D)
522 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000523
Christian Heimes3795b532007-11-08 13:48:53 +0000524 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
525 varkw_e=None, defaults_e=None, formatted=None):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000526 args, varargs, varkw, defaults = inspect.getargspec(routine)
527 self.assertEqual(args, args_e)
528 self.assertEqual(varargs, varargs_e)
529 self.assertEqual(varkw, varkw_e)
530 self.assertEqual(defaults, defaults_e)
531 if formatted is not None:
532 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
533 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000534
Christian Heimes3795b532007-11-08 13:48:53 +0000535 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
536 varkw_e=None, defaults_e=None,
537 kwonlyargs_e=[], kwonlydefaults_e=None,
538 ann_e={}, formatted=None):
539 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
540 inspect.getfullargspec(routine)
541 self.assertEqual(args, args_e)
542 self.assertEqual(varargs, varargs_e)
543 self.assertEqual(varkw, varkw_e)
544 self.assertEqual(defaults, defaults_e)
545 self.assertEqual(kwonlyargs, kwonlyargs_e)
546 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
547 self.assertEqual(ann, ann_e)
548 if formatted is not None:
549 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
550 kwonlyargs, kwonlydefaults, ann),
551 formatted)
552
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000553 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000554 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000555
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000556 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000557 ['a', 'b', 'c', 'd', 'e', 'f'],
558 'g', 'h', (3, 4, 5),
559 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000560
Christian Heimes3795b532007-11-08 13:48:53 +0000561 self.assertRaises(ValueError, self.assertArgSpecEquals,
562 mod2.keyworded, [])
563
564 self.assertRaises(ValueError, self.assertArgSpecEquals,
565 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000566 self.assertRaises(ValueError, self.assertArgSpecEquals,
567 mod2.keyword_only_arg, [])
568
Christian Heimes3795b532007-11-08 13:48:53 +0000569
570 def test_getfullargspec(self):
571 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
572 kwonlyargs_e=['arg2'],
573 kwonlydefaults_e={'arg2':1},
574 formatted='(*arg1, arg2=1)')
575
576 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000577 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000578 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000579 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
580 kwonlyargs_e=['arg'],
581 formatted='(*, arg)')
582
Yury Selivanov57d240e2014-02-19 16:27:23 -0500583 def test_argspec_api_ignores_wrapped(self):
584 # Issue 20684: low level introspection API must ignore __wrapped__
585 @functools.wraps(mod.spam)
586 def ham(x, y):
587 pass
588 # Basic check
589 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
590 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
591 self.assertFullArgSpecEquals(functools.partial(ham),
592 ['x', 'y'], formatted='(x, y)')
593 # Other variants
594 def check_method(f):
595 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
596 formatted='(self, x, y)')
597 class C:
598 @functools.wraps(mod.spam)
599 def ham(self, x, y):
600 pass
601 pham = functools.partialmethod(ham)
602 @functools.wraps(mod.spam)
603 def __call__(self, x, y):
604 pass
605 check_method(C())
606 check_method(C.ham)
607 check_method(C().ham)
608 check_method(C.pham)
609 check_method(C().pham)
610
611 class C_new:
612 @functools.wraps(mod.spam)
613 def __new__(self, x, y):
614 pass
615 check_method(C_new)
616
617 class C_init:
618 @functools.wraps(mod.spam)
619 def __init__(self, x, y):
620 pass
621 check_method(C_init)
622
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500623 def test_getfullargspec_signature_attr(self):
624 def test():
625 pass
626 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
627 test.__signature__ = inspect.Signature(parameters=(spam_param,))
628
629 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
630
Yury Selivanov4cb93912014-01-29 11:54:12 -0500631 def test_getfullargspec_signature_annos(self):
632 def test(a:'spam') -> 'ham': pass
633 spec = inspect.getfullargspec(test)
634 self.assertEqual(test.__annotations__, spec.annotations)
635
636 def test(): pass
637 spec = inspect.getfullargspec(test)
638 self.assertEqual(test.__annotations__, spec.annotations)
639
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500640 @unittest.skipIf(MISSING_C_DOCSTRINGS,
641 "Signature information for builtins requires docstrings")
642 def test_getfullargspec_builtin_methods(self):
643 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
644 args_e=['self', 'obj'], formatted='(self, obj)')
645
646 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
647 args_e=['self', 'obj'], formatted='(self, obj)')
648
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500649 self.assertFullArgSpecEquals(
650 os.stat,
651 args_e=['path'],
652 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
653 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
654 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
655
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200656 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500657 @unittest.skipIf(MISSING_C_DOCSTRINGS,
658 "Signature information for builtins requires docstrings")
659 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200660 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500661 builtin = _testcapi.docstring_with_signature_with_defaults
662 spec = inspect.getfullargspec(builtin)
663 self.assertEqual(spec.defaults[0], 'avocado')
664
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200665 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500666 @unittest.skipIf(MISSING_C_DOCSTRINGS,
667 "Signature information for builtins requires docstrings")
668 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200669 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500670 builtin = _testcapi.docstring_no_signature
671 with self.assertRaises(TypeError):
672 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000673
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000674 def test_getargspec_method(self):
675 class A(object):
676 def m(self):
677 pass
678 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000679
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000680 def test_classify_newstyle(self):
681 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000682
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000683 def s(): pass
684 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000685
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000686 def c(cls): pass
687 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000688
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000689 def getp(self): pass
690 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000691
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000692 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000693
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000694 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000695
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000696 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000697
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100698 dd = _BrokenDataDescriptor()
699 md = _BrokenMethodDescriptor()
700
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000701 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500702
703 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
704 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
705
Benjamin Peterson577473f2010-01-19 00:09:57 +0000706 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
707 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
708 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000709 self.assertIn(('m', 'method', A), attrs,
710 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000711 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
712 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100713 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
714 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000715
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000716 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000717
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000718 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000719
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000720 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000721 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
722 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
723 self.assertIn(('p', 'property', A), attrs, 'missing property')
724 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
725 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
726 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100727 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
728 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000729
730
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000731 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000732
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000733 def m(self): pass
734 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000735
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000736 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000737 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
738 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
739 self.assertIn(('p', 'property', A), attrs, 'missing property')
740 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
741 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
742 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100743 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
744 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000745
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000746 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000747
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000748 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000749
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000750 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000751 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
752 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
753 self.assertIn(('p', 'property', A), attrs, 'missing property')
754 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
755 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
756 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100757 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
758 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
759
760 def test_classify_builtin_types(self):
761 # Simple sanity check that all built-in types can have their
762 # attributes classified.
763 for name in dir(__builtins__):
764 builtin = getattr(__builtins__, name)
765 if isinstance(builtin, type):
766 inspect.classify_class_attrs(builtin)
767
Ethan Furman63c141c2013-10-18 00:27:39 -0700768 def test_classify_DynamicClassAttribute(self):
769 class Meta(type):
770 def __getattr__(self, name):
771 if name == 'ham':
772 return 'spam'
773 return super().__getattr__(name)
774 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700775 @types.DynamicClassAttribute
776 def ham(self):
777 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700778 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
779 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700780 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700781 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
782
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700783 def test_classify_metaclass_class_attribute(self):
784 class Meta(type):
785 fish = 'slap'
786 def __dir__(self):
787 return ['__class__', '__modules__', '__name__', 'fish']
788 class Class(metaclass=Meta):
789 pass
790 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
791 self.assertIn(should_find, inspect.classify_class_attrs(Class))
792
Ethan Furman63c141c2013-10-18 00:27:39 -0700793 def test_classify_VirtualAttribute(self):
794 class Meta(type):
795 def __dir__(cls):
796 return ['__class__', '__module__', '__name__', 'BOOM']
797 def __getattr__(self, name):
798 if name =='BOOM':
799 return 42
800 return super().__getattr(name)
801 class Class(metaclass=Meta):
802 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700803 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700804 self.assertIn(should_find, inspect.classify_class_attrs(Class))
805
806 def test_classify_VirtualAttribute_multi_classes(self):
807 class Meta1(type):
808 def __dir__(cls):
809 return ['__class__', '__module__', '__name__', 'one']
810 def __getattr__(self, name):
811 if name =='one':
812 return 1
813 return super().__getattr__(name)
814 class Meta2(type):
815 def __dir__(cls):
816 return ['__class__', '__module__', '__name__', 'two']
817 def __getattr__(self, name):
818 if name =='two':
819 return 2
820 return super().__getattr__(name)
821 class Meta3(Meta1, Meta2):
822 def __dir__(cls):
823 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
824 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
825 def __getattr__(self, name):
826 if name =='three':
827 return 3
828 return super().__getattr__(name)
829 class Class1(metaclass=Meta1):
830 pass
831 class Class2(Class1, metaclass=Meta3):
832 pass
833
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700834 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
835 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
836 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700837 cca = inspect.classify_class_attrs(Class2)
838 for sf in (should_find1, should_find2, should_find3):
839 self.assertIn(sf, cca)
840
841 def test_classify_class_attrs_with_buggy_dir(self):
842 class M(type):
843 def __dir__(cls):
844 return ['__class__', '__name__', 'missing']
845 class C(metaclass=M):
846 pass
847 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
848 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700849
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100850 def test_getmembers_descriptors(self):
851 class A(object):
852 dd = _BrokenDataDescriptor()
853 md = _BrokenMethodDescriptor()
854
855 def pred_wrapper(pred):
856 # A quick'n'dirty way to discard standard attributes of new-style
857 # classes.
858 class Empty(object):
859 pass
860 def wrapped(x):
861 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
862 return False
863 return pred(x)
864 return wrapped
865
866 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
867 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
868
869 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
870 [('md', A.__dict__['md'])])
871 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
872 [('dd', A.__dict__['dd'])])
873
874 class B(A):
875 pass
876
877 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
878 [('md', A.__dict__['md'])])
879 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
880 [('dd', A.__dict__['dd'])])
881
Antoine Pitrou0c603812012-01-18 17:40:18 +0100882 def test_getmembers_method(self):
883 class B:
884 def f(self):
885 pass
886
887 self.assertIn(('f', B.f), inspect.getmembers(B))
888 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
889 b = B()
890 self.assertIn(('f', b.f), inspect.getmembers(b))
891 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
892
Ethan Furmane03ea372013-09-25 07:14:41 -0700893 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -0700894 class M(type):
895 def __getattr__(cls, name):
896 if name == 'eggs':
897 return 'scrambled'
898 return super().__getattr__(name)
899 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -0700900 @types.DynamicClassAttribute
901 def eggs(self):
902 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -0700903 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
904 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
905
906 def test_getmembers_with_buggy_dir(self):
907 class M(type):
908 def __dir__(cls):
909 return ['__class__', '__name__', 'missing']
910 class C(metaclass=M):
911 pass
912 attrs = [a[0] for a in inspect.getmembers(C)]
913 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700914
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000915
Nick Coghlan2f92e542012-06-23 19:39:55 +1000916_global_ref = object()
917class TestGetClosureVars(unittest.TestCase):
918
919 def test_name_resolution(self):
920 # Basic test of the 4 different resolution mechanisms
921 def f(nonlocal_ref):
922 def g(local_ref):
923 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
924 return g
925 _arg = object()
926 nonlocal_vars = {"nonlocal_ref": _arg}
927 global_vars = {"_global_ref": _global_ref}
928 builtin_vars = {"print": print}
929 unbound_names = {"unbound_ref"}
930 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
931 builtin_vars, unbound_names)
932 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
933
934 def test_generator_closure(self):
935 def f(nonlocal_ref):
936 def g(local_ref):
937 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
938 yield
939 return g
940 _arg = object()
941 nonlocal_vars = {"nonlocal_ref": _arg}
942 global_vars = {"_global_ref": _global_ref}
943 builtin_vars = {"print": print}
944 unbound_names = {"unbound_ref"}
945 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
946 builtin_vars, unbound_names)
947 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
948
949 def test_method_closure(self):
950 class C:
951 def f(self, nonlocal_ref):
952 def g(local_ref):
953 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
954 return g
955 _arg = object()
956 nonlocal_vars = {"nonlocal_ref": _arg}
957 global_vars = {"_global_ref": _global_ref}
958 builtin_vars = {"print": print}
959 unbound_names = {"unbound_ref"}
960 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
961 builtin_vars, unbound_names)
962 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
963
964 def test_nonlocal_vars(self):
965 # More complex tests of nonlocal resolution
966 def _nonlocal_vars(f):
967 return inspect.getclosurevars(f).nonlocals
968
969 def make_adder(x):
970 def add(y):
971 return x + y
972 return add
973
974 def curry(func, arg1):
975 return lambda arg2: func(arg1, arg2)
976
977 def less_than(a, b):
978 return a < b
979
980 # The infamous Y combinator.
981 def Y(le):
982 def g(f):
983 return le(lambda x: f(f)(x))
984 Y.g_ref = g
985 return g(g)
986
987 def check_y_combinator(func):
988 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
989
990 inc = make_adder(1)
991 add_two = make_adder(2)
992 greater_than_five = curry(less_than, 5)
993
994 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
995 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
996 self.assertEqual(_nonlocal_vars(greater_than_five),
997 {'arg1': 5, 'func': less_than})
998 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
999 {'x': 3})
1000 Y(check_y_combinator)
1001
1002 def test_getclosurevars_empty(self):
1003 def foo(): pass
1004 _empty = inspect.ClosureVars({}, {}, {}, set())
1005 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1006 self.assertEqual(inspect.getclosurevars(foo), _empty)
1007
1008 def test_getclosurevars_error(self):
1009 class T: pass
1010 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1011 self.assertRaises(TypeError, inspect.getclosurevars, list)
1012 self.assertRaises(TypeError, inspect.getclosurevars, {})
1013
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001014 def _private_globals(self):
1015 code = """def f(): print(path)"""
1016 ns = {}
1017 exec(code, ns)
1018 return ns["f"], ns
1019
1020 def test_builtins_fallback(self):
1021 f, ns = self._private_globals()
1022 ns.pop("__builtins__", None)
1023 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1024 self.assertEqual(inspect.getclosurevars(f), expected)
1025
1026 def test_builtins_as_dict(self):
1027 f, ns = self._private_globals()
1028 ns["__builtins__"] = {"path":1}
1029 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1030 self.assertEqual(inspect.getclosurevars(f), expected)
1031
1032 def test_builtins_as_module(self):
1033 f, ns = self._private_globals()
1034 ns["__builtins__"] = os
1035 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1036 self.assertEqual(inspect.getclosurevars(f), expected)
1037
Nick Coghlan2f92e542012-06-23 19:39:55 +10001038
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001039class TestGetcallargsFunctions(unittest.TestCase):
1040
1041 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1042 locs = dict(locs or {}, func=func)
1043 r1 = eval('func(%s)' % call_params_string, None, locs)
1044 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1045 locs)
1046 self.assertEqual(r1, r2)
1047
1048 def assertEqualException(self, func, call_param_string, locs=None):
1049 locs = dict(locs or {}, func=func)
1050 try:
1051 eval('func(%s)' % call_param_string, None, locs)
1052 except Exception as e:
1053 ex1 = e
1054 else:
1055 self.fail('Exception not raised')
1056 try:
1057 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1058 locs)
1059 except Exception as e:
1060 ex2 = e
1061 else:
1062 self.fail('Exception not raised')
1063 self.assertIs(type(ex1), type(ex2))
1064 self.assertEqual(str(ex1), str(ex2))
1065 del ex1, ex2
1066
1067 def makeCallable(self, signature):
1068 """Create a function that returns its locals()"""
1069 code = "lambda %s: locals()"
1070 return eval(code % signature)
1071
1072 def test_plain(self):
1073 f = self.makeCallable('a, b=1')
1074 self.assertEqualCallArgs(f, '2')
1075 self.assertEqualCallArgs(f, '2, 3')
1076 self.assertEqualCallArgs(f, 'a=2')
1077 self.assertEqualCallArgs(f, 'b=3, a=2')
1078 self.assertEqualCallArgs(f, '2, b=3')
1079 # expand *iterable / **mapping
1080 self.assertEqualCallArgs(f, '*(2,)')
1081 self.assertEqualCallArgs(f, '*[2]')
1082 self.assertEqualCallArgs(f, '*(2, 3)')
1083 self.assertEqualCallArgs(f, '*[2, 3]')
1084 self.assertEqualCallArgs(f, '**{"a":2}')
1085 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1086 self.assertEqualCallArgs(f, '2, **{"b":3}')
1087 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1088 # expand UserList / UserDict
1089 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1090 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1091 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1092 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1093 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1094
1095 def test_varargs(self):
1096 f = self.makeCallable('a, b=1, *c')
1097 self.assertEqualCallArgs(f, '2')
1098 self.assertEqualCallArgs(f, '2, 3')
1099 self.assertEqualCallArgs(f, '2, 3, 4')
1100 self.assertEqualCallArgs(f, '*(2,3,4)')
1101 self.assertEqualCallArgs(f, '2, *[3,4]')
1102 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1103
1104 def test_varkw(self):
1105 f = self.makeCallable('a, b=1, **c')
1106 self.assertEqualCallArgs(f, 'a=2')
1107 self.assertEqualCallArgs(f, '2, b=3, c=4')
1108 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1109 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1110 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1111 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1112 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1113 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1114 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1115
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001116 def test_varkw_only(self):
1117 # issue11256:
1118 f = self.makeCallable('**c')
1119 self.assertEqualCallArgs(f, '')
1120 self.assertEqualCallArgs(f, 'a=1')
1121 self.assertEqualCallArgs(f, 'a=1, b=2')
1122 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1123 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1124 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1125
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001126 def test_keyword_only(self):
1127 f = self.makeCallable('a=3, *, c, d=2')
1128 self.assertEqualCallArgs(f, 'c=3')
1129 self.assertEqualCallArgs(f, 'c=3, a=3')
1130 self.assertEqualCallArgs(f, 'a=2, c=4')
1131 self.assertEqualCallArgs(f, '4, c=4')
1132 self.assertEqualException(f, '')
1133 self.assertEqualException(f, '3')
1134 self.assertEqualException(f, 'a=3')
1135 self.assertEqualException(f, 'd=4')
1136
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001137 f = self.makeCallable('*, c, d=2')
1138 self.assertEqualCallArgs(f, 'c=3')
1139 self.assertEqualCallArgs(f, 'c=3, d=4')
1140 self.assertEqualCallArgs(f, 'd=4, c=3')
1141
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001142 def test_multiple_features(self):
1143 f = self.makeCallable('a, b=2, *f, **g')
1144 self.assertEqualCallArgs(f, '2, 3, 7')
1145 self.assertEqualCallArgs(f, '2, 3, x=8')
1146 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1147 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1148 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1149 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1150 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1151 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1152 '(4,[5,6])]), **collections.UserDict('
1153 'y=9, z=10)')
1154
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001155 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1156 self.assertEqualCallArgs(f, '2, 3, x=8')
1157 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1158 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1159 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1160 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1161 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1162 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1163 '(4,[5,6])]), q=0, **collections.UserDict('
1164 'y=9, z=10)')
1165
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001166 def test_errors(self):
1167 f0 = self.makeCallable('')
1168 f1 = self.makeCallable('a, b')
1169 f2 = self.makeCallable('a, b=1')
1170 # f0 takes no arguments
1171 self.assertEqualException(f0, '1')
1172 self.assertEqualException(f0, 'x=1')
1173 self.assertEqualException(f0, '1,x=1')
1174 # f1 takes exactly 2 arguments
1175 self.assertEqualException(f1, '')
1176 self.assertEqualException(f1, '1')
1177 self.assertEqualException(f1, 'a=2')
1178 self.assertEqualException(f1, 'b=3')
1179 # f2 takes at least 1 argument
1180 self.assertEqualException(f2, '')
1181 self.assertEqualException(f2, 'b=3')
1182 for f in f1, f2:
1183 # f1/f2 takes exactly/at most 2 arguments
1184 self.assertEqualException(f, '2, 3, 4')
1185 self.assertEqualException(f, '1, 2, 3, a=1')
1186 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001187 # XXX: success of this one depends on dict order
1188 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001189 # f got an unexpected keyword argument
1190 self.assertEqualException(f, 'c=2')
1191 self.assertEqualException(f, '2, c=3')
1192 self.assertEqualException(f, '2, 3, c=4')
1193 self.assertEqualException(f, '2, c=4, b=3')
1194 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1195 # f got multiple values for keyword argument
1196 self.assertEqualException(f, '1, a=2')
1197 self.assertEqualException(f, '1, **{"a":2}')
1198 self.assertEqualException(f, '1, 2, b=3')
1199 # XXX: Python inconsistency
1200 # - for functions and bound methods: unexpected keyword 'c'
1201 # - for unbound methods: multiple values for keyword 'a'
1202 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001203 # issue11256:
1204 f3 = self.makeCallable('**c')
1205 self.assertEqualException(f3, '1, 2')
1206 self.assertEqualException(f3, '1, 2, a=1, b=2')
1207 f4 = self.makeCallable('*, a, b=0')
1208 self.assertEqualException(f3, '1, 2')
1209 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001210
Yury Selivanov875df202014-03-27 18:23:03 -04001211 # issue #20816: getcallargs() fails to iterate over non-existent
1212 # kwonlydefaults and raises a wrong TypeError
1213 def f5(*, a): pass
1214 with self.assertRaisesRegex(TypeError,
1215 'missing 1 required keyword-only'):
1216 inspect.getcallargs(f5)
1217
1218
Yury Selivanovdccfa132014-03-27 18:42:52 -04001219 # issue20817:
1220 def f6(a, b, c):
1221 pass
1222 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1223 inspect.getcallargs(f6)
1224
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001225class TestGetcallargsMethods(TestGetcallargsFunctions):
1226
1227 def setUp(self):
1228 class Foo(object):
1229 pass
1230 self.cls = Foo
1231 self.inst = Foo()
1232
1233 def makeCallable(self, signature):
1234 assert 'self' not in signature
1235 mk = super(TestGetcallargsMethods, self).makeCallable
1236 self.cls.method = mk('self, ' + signature)
1237 return self.inst.method
1238
1239class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1240
1241 def makeCallable(self, signature):
1242 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1243 return self.cls.method
1244
1245 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1246 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1247 *self._getAssertEqualParams(func, call_params_string, locs))
1248
1249 def assertEqualException(self, func, call_params_string, locs=None):
1250 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1251 *self._getAssertEqualParams(func, call_params_string, locs))
1252
1253 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1254 assert 'inst' not in call_params_string
1255 locs = dict(locs or {}, inst=self.inst)
1256 return (func, 'inst,' + call_params_string, locs)
1257
Michael Foord95fc51d2010-11-20 15:07:30 +00001258
1259class TestGetattrStatic(unittest.TestCase):
1260
1261 def test_basic(self):
1262 class Thing(object):
1263 x = object()
1264
1265 thing = Thing()
1266 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1267 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1268 with self.assertRaises(AttributeError):
1269 inspect.getattr_static(thing, 'y')
1270
1271 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1272
1273 def test_inherited(self):
1274 class Thing(object):
1275 x = object()
1276 class OtherThing(Thing):
1277 pass
1278
1279 something = OtherThing()
1280 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1281
1282 def test_instance_attr(self):
1283 class Thing(object):
1284 x = 2
1285 def __init__(self, x):
1286 self.x = x
1287 thing = Thing(3)
1288 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1289 del thing.x
1290 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1291
1292 def test_property(self):
1293 class Thing(object):
1294 @property
1295 def x(self):
1296 raise AttributeError("I'm pretending not to exist")
1297 thing = Thing()
1298 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1299
Ezio Melotti75cbd732011-04-28 00:59:29 +03001300 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001301 class descriptor(object):
1302 def __get__(*_):
1303 raise AttributeError("I'm pretending not to exist")
1304 desc = descriptor()
1305 class Thing(object):
1306 x = desc
1307 thing = Thing()
1308 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1309
1310 def test_classAttribute(self):
1311 class Thing(object):
1312 x = object()
1313
1314 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1315
Ethan Furmane03ea372013-09-25 07:14:41 -07001316 def test_classVirtualAttribute(self):
1317 class Thing(object):
1318 @types.DynamicClassAttribute
1319 def x(self):
1320 return self._x
1321 _x = object()
1322
1323 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1324
Michael Foord95fc51d2010-11-20 15:07:30 +00001325 def test_inherited_classattribute(self):
1326 class Thing(object):
1327 x = object()
1328 class OtherThing(Thing):
1329 pass
1330
1331 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1332
1333 def test_slots(self):
1334 class Thing(object):
1335 y = 'bar'
1336 __slots__ = ['x']
1337 def __init__(self):
1338 self.x = 'foo'
1339 thing = Thing()
1340 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1341 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1342
1343 del thing.x
1344 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1345
1346 def test_metaclass(self):
1347 class meta(type):
1348 attr = 'foo'
1349 class Thing(object, metaclass=meta):
1350 pass
1351 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1352
1353 class sub(meta):
1354 pass
1355 class OtherThing(object, metaclass=sub):
1356 x = 3
1357 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1358
1359 class OtherOtherThing(OtherThing):
1360 pass
1361 # this test is odd, but it was added as it exposed a bug
1362 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1363
1364 def test_no_dict_no_slots(self):
1365 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1366 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1367
1368 def test_no_dict_no_slots_instance_member(self):
1369 # returns descriptor
1370 with open(__file__) as handle:
1371 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1372
1373 def test_inherited_slots(self):
1374 # returns descriptor
1375 class Thing(object):
1376 __slots__ = ['x']
1377 def __init__(self):
1378 self.x = 'foo'
1379
1380 class OtherThing(Thing):
1381 pass
1382 # it would be nice if this worked...
1383 # we get the descriptor instead of the instance attribute
1384 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1385
1386 def test_descriptor(self):
1387 class descriptor(object):
1388 def __get__(self, instance, owner):
1389 return 3
1390 class Foo(object):
1391 d = descriptor()
1392
1393 foo = Foo()
1394
1395 # for a non data descriptor we return the instance attribute
1396 foo.__dict__['d'] = 1
1397 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1398
1399 # if the descriptor is a data-desciptor we should return the
1400 # descriptor
1401 descriptor.__set__ = lambda s, i, v: None
1402 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1403
1404
1405 def test_metaclass_with_descriptor(self):
1406 class descriptor(object):
1407 def __get__(self, instance, owner):
1408 return 3
1409 class meta(type):
1410 d = descriptor()
1411 class Thing(object, metaclass=meta):
1412 pass
1413 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1414
1415
Michael Foordcc7ebb82010-11-20 16:20:16 +00001416 def test_class_as_property(self):
1417 class Base(object):
1418 foo = 3
1419
1420 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001421 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001422 @property
1423 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001424 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001425 return object
1426
Michael Foord35184ed2010-11-20 16:58:30 +00001427 instance = Something()
1428 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1429 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001430 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1431
Michael Foorde5162652010-11-20 16:40:44 +00001432 def test_mro_as_property(self):
1433 class Meta(type):
1434 @property
1435 def __mro__(self):
1436 return (object,)
1437
1438 class Base(object):
1439 foo = 3
1440
1441 class Something(Base, metaclass=Meta):
1442 pass
1443
1444 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1445 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1446
Michael Foorddcebe0f2011-03-15 19:20:44 -04001447 def test_dict_as_property(self):
1448 test = self
1449 test.called = False
1450
1451 class Foo(dict):
1452 a = 3
1453 @property
1454 def __dict__(self):
1455 test.called = True
1456 return {}
1457
1458 foo = Foo()
1459 foo.a = 4
1460 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1461 self.assertFalse(test.called)
1462
1463 def test_custom_object_dict(self):
1464 test = self
1465 test.called = False
1466
1467 class Custom(dict):
1468 def get(self, key, default=None):
1469 test.called = True
1470 super().get(key, default)
1471
1472 class Foo(object):
1473 a = 3
1474 foo = Foo()
1475 foo.__dict__ = Custom()
1476 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1477 self.assertFalse(test.called)
1478
1479 def test_metaclass_dict_as_property(self):
1480 class Meta(type):
1481 @property
1482 def __dict__(self):
1483 self.executed = True
1484
1485 class Thing(metaclass=Meta):
1486 executed = False
1487
1488 def __init__(self):
1489 self.spam = 42
1490
1491 instance = Thing()
1492 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1493 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001494
Michael Foorda51623b2011-12-18 22:01:40 +00001495 def test_module(self):
1496 sentinel = object()
1497 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1498 sentinel)
1499
Michael Foord3ba95f82011-12-22 01:13:37 +00001500 def test_metaclass_with_metaclass_with_dict_as_property(self):
1501 class MetaMeta(type):
1502 @property
1503 def __dict__(self):
1504 self.executed = True
1505 return dict(spam=42)
1506
1507 class Meta(type, metaclass=MetaMeta):
1508 executed = False
1509
1510 class Thing(metaclass=Meta):
1511 pass
1512
1513 with self.assertRaises(AttributeError):
1514 inspect.getattr_static(Thing, "spam")
1515 self.assertFalse(Thing.executed)
1516
Nick Coghlane0f04652010-11-21 03:44:04 +00001517class TestGetGeneratorState(unittest.TestCase):
1518
1519 def setUp(self):
1520 def number_generator():
1521 for number in range(5):
1522 yield number
1523 self.generator = number_generator()
1524
1525 def _generatorstate(self):
1526 return inspect.getgeneratorstate(self.generator)
1527
1528 def test_created(self):
1529 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1530
1531 def test_suspended(self):
1532 next(self.generator)
1533 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1534
1535 def test_closed_after_exhaustion(self):
1536 for i in self.generator:
1537 pass
1538 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1539
1540 def test_closed_after_immediate_exception(self):
1541 with self.assertRaises(RuntimeError):
1542 self.generator.throw(RuntimeError)
1543 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1544
1545 def test_running(self):
1546 # As mentioned on issue #10220, checking for the RUNNING state only
1547 # makes sense inside the generator itself.
1548 # The following generator checks for this by using the closure's
1549 # reference to self and the generator state checking helper method
1550 def running_check_generator():
1551 for number in range(5):
1552 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1553 yield number
1554 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1555 self.generator = running_check_generator()
1556 # Running up to the first yield
1557 next(self.generator)
1558 # Running after the first yield
1559 next(self.generator)
1560
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001561 def test_easy_debugging(self):
1562 # repr() and str() of a generator state should contain the state name
1563 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1564 for name in names:
1565 state = getattr(inspect, name)
1566 self.assertIn(name, repr(state))
1567 self.assertIn(name, str(state))
1568
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001569 def test_getgeneratorlocals(self):
1570 def each(lst, a=None):
1571 b=(1, 2, 3)
1572 for v in lst:
1573 if v == 3:
1574 c = 12
1575 yield v
1576
1577 numbers = each([1, 2, 3])
1578 self.assertEqual(inspect.getgeneratorlocals(numbers),
1579 {'a': None, 'lst': [1, 2, 3]})
1580 next(numbers)
1581 self.assertEqual(inspect.getgeneratorlocals(numbers),
1582 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1583 'b': (1, 2, 3)})
1584 next(numbers)
1585 self.assertEqual(inspect.getgeneratorlocals(numbers),
1586 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1587 'b': (1, 2, 3)})
1588 next(numbers)
1589 self.assertEqual(inspect.getgeneratorlocals(numbers),
1590 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1591 'b': (1, 2, 3), 'c': 12})
1592 try:
1593 next(numbers)
1594 except StopIteration:
1595 pass
1596 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1597
1598 def test_getgeneratorlocals_empty(self):
1599 def yield_one():
1600 yield 1
1601 one = yield_one()
1602 self.assertEqual(inspect.getgeneratorlocals(one), {})
1603 try:
1604 next(one)
1605 except StopIteration:
1606 pass
1607 self.assertEqual(inspect.getgeneratorlocals(one), {})
1608
1609 def test_getgeneratorlocals_error(self):
1610 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1611 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1612 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1613 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1614
Nick Coghlane0f04652010-11-21 03:44:04 +00001615
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001616class MySignature(inspect.Signature):
1617 # Top-level to make it picklable;
1618 # used in test_signature_object_pickle
1619 pass
1620
1621class MyParameter(inspect.Parameter):
1622 # Top-level to make it picklable;
1623 # used in test_signature_object_pickle
1624 pass
1625
1626
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001627class TestSignatureObject(unittest.TestCase):
1628 @staticmethod
1629 def signature(func):
1630 sig = inspect.signature(func)
1631 return (tuple((param.name,
1632 (... if param.default is param.empty else param.default),
1633 (... if param.annotation is param.empty
1634 else param.annotation),
1635 str(param.kind).lower())
1636 for param in sig.parameters.values()),
1637 (... if sig.return_annotation is sig.empty
1638 else sig.return_annotation))
1639
1640 def test_signature_object(self):
1641 S = inspect.Signature
1642 P = inspect.Parameter
1643
1644 self.assertEqual(str(S()), '()')
1645
Yury Selivanov07a9e452014-01-29 10:58:16 -05001646 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001647 pass
1648 sig = inspect.signature(test)
1649 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001650 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001651 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001652 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001653 args = sig.parameters['args']
1654 ko = sig.parameters['ko']
1655 kwargs = sig.parameters['kwargs']
1656
1657 S((po, pk, args, 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((pk, po, args, ko, kwargs))
1661
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001662 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001663 S((po, args, pk, ko, kwargs))
1664
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001665 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001666 S((args, po, pk, ko, kwargs))
1667
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001668 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001669 S((po, pk, args, kwargs, ko))
1670
1671 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001672 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001673 S((po, pk, args, kwargs2, ko))
1674
Yury Selivanov07a9e452014-01-29 10:58:16 -05001675 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1676 S((pod, po))
1677
1678 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1679 S((po, pkd, pk))
1680
1681 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1682 S((pkd, pk))
1683
Yury Selivanov374375d2014-03-27 12:41:53 -04001684 self.assertTrue(repr(sig).startswith('<Signature'))
1685 self.assertTrue('"(po, pk' in repr(sig))
1686
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001687 def test_signature_object_pickle(self):
1688 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
1689 foo_partial = functools.partial(foo, a=1)
1690
1691 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001692
1693 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1694 with self.subTest(pickle_ver=ver, subclass=False):
1695 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
1696 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001697
1698 # Test that basic sub-classing works
1699 sig = inspect.signature(foo)
1700 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
1701 myparams = collections.OrderedDict(sig.parameters, a=myparam)
1702 mysig = MySignature().replace(parameters=myparams.values(),
1703 return_annotation=sig.return_annotation)
1704 self.assertTrue(isinstance(mysig, MySignature))
1705 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
1706
1707 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1708 with self.subTest(pickle_ver=ver, subclass=True):
1709 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
1710 self.assertEqual(mysig, sig_pickled)
1711 self.assertTrue(isinstance(sig_pickled, MySignature))
1712 self.assertTrue(isinstance(sig_pickled.parameters['z'],
1713 MyParameter))
1714
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001715 def test_signature_immutability(self):
1716 def test(a):
1717 pass
1718 sig = inspect.signature(test)
1719
1720 with self.assertRaises(AttributeError):
1721 sig.foo = 'bar'
1722
1723 with self.assertRaises(TypeError):
1724 sig.parameters['a'] = None
1725
1726 def test_signature_on_noarg(self):
1727 def test():
1728 pass
1729 self.assertEqual(self.signature(test), ((), ...))
1730
1731 def test_signature_on_wargs(self):
1732 def test(a, b:'foo') -> 123:
1733 pass
1734 self.assertEqual(self.signature(test),
1735 ((('a', ..., ..., "positional_or_keyword"),
1736 ('b', ..., 'foo', "positional_or_keyword")),
1737 123))
1738
1739 def test_signature_on_wkwonly(self):
1740 def test(*, a:float, b:str) -> int:
1741 pass
1742 self.assertEqual(self.signature(test),
1743 ((('a', ..., float, "keyword_only"),
1744 ('b', ..., str, "keyword_only")),
1745 int))
1746
1747 def test_signature_on_complex_args(self):
1748 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1749 pass
1750 self.assertEqual(self.signature(test),
1751 ((('a', ..., ..., "positional_or_keyword"),
1752 ('b', 10, 'foo', "positional_or_keyword"),
1753 ('args', ..., 'bar', "var_positional"),
1754 ('spam', ..., 'baz', "keyword_only"),
1755 ('ham', 123, ..., "keyword_only"),
1756 ('kwargs', ..., int, "var_keyword")),
1757 ...))
1758
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001759 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001760 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1761 "Signature information for builtins requires docstrings")
1762 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001763 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001764
Larry Hastings5c661892014-01-24 06:17:25 -08001765 def test_unbound_method(o):
1766 """Use this to test unbound methods (things that should have a self)"""
1767 signature = inspect.signature(o)
1768 self.assertTrue(isinstance(signature, inspect.Signature))
1769 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1770 return signature
1771
1772 def test_callable(o):
1773 """Use this to test bound methods or normal callables (things that don't expect self)"""
1774 signature = inspect.signature(o)
1775 self.assertTrue(isinstance(signature, inspect.Signature))
1776 if signature.parameters:
1777 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1778 return signature
1779
1780 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001781 def p(name): return signature.parameters[name].default
1782 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001783 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001784 self.assertEqual(p('d'), 3.14)
1785 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001786 self.assertEqual(p('n'), None)
1787 self.assertEqual(p('t'), True)
1788 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001789 self.assertEqual(p('local'), 3)
1790 self.assertEqual(p('sys'), sys.maxsize)
1791 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001792
Larry Hastings5c661892014-01-24 06:17:25 -08001793 test_callable(object)
1794
1795 # normal method
1796 # (PyMethodDescr_Type, "method_descriptor")
1797 test_unbound_method(_pickle.Pickler.dump)
1798 d = _pickle.Pickler(io.StringIO())
1799 test_callable(d.dump)
1800
1801 # static method
1802 test_callable(str.maketrans)
1803 test_callable('abc'.maketrans)
1804
1805 # class method
1806 test_callable(dict.fromkeys)
1807 test_callable({}.fromkeys)
1808
1809 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1810 test_unbound_method(type.__call__)
1811 test_unbound_method(int.__add__)
1812 test_callable((3).__add__)
1813
1814 # _PyMethodWrapper_Type
1815 # support for 'method-wrapper'
1816 test_callable(min.__call__)
1817
Larry Hastings2623c8c2014-02-08 22:15:29 -08001818 # This doesn't work now.
1819 # (We don't have a valid signature for "type" in 3.4)
1820 with self.assertRaisesRegex(ValueError, "no signature found"):
1821 class ThisWorksNow:
1822 __call__ = type
1823 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08001824
Yury Selivanov056e2652014-03-02 12:25:27 -05001825 # Regression test for issue #20786
1826 test_unbound_method(dict.__delitem__)
1827 test_unbound_method(property.__delete__)
1828
1829
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001830 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05001831 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1832 "Signature information for builtins requires docstrings")
1833 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001834 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05001835 func = _testcapi.docstring_with_signature_with_defaults
1836
1837 def decorator(func):
1838 @functools.wraps(func)
1839 def wrapper(*args, **kwargs) -> int:
1840 return func(*args, **kwargs)
1841 return wrapper
1842
1843 decorated_func = decorator(func)
1844
1845 self.assertEqual(inspect.signature(func),
1846 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08001847
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001848 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08001849 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001850 import _testcapi
Larry Hastings5c661892014-01-24 06:17:25 -08001851 with self.assertRaisesRegex(ValueError, 'no signature found for builtin'):
1852 inspect.signature(_testcapi.docstring_no_signature)
1853
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001854 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001855 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001856 inspect.signature(42)
1857
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001858 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001859 inspect.Signature.from_function(42)
1860
Yury Selivanovb77511d2014-01-29 10:46:14 -05001861 def test_signature_from_builtin_errors(self):
1862 with self.assertRaisesRegex(TypeError, 'is not a Python builtin'):
1863 inspect.Signature.from_builtin(42)
1864
Yury Selivanov63da7c72014-01-31 14:48:37 -05001865 def test_signature_from_functionlike_object(self):
1866 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1867 pass
1868
1869 class funclike:
1870 # Has to be callable, and have correct
1871 # __code__, __annotations__, __defaults__, __name__,
1872 # and __kwdefaults__ attributes
1873
1874 def __init__(self, func):
1875 self.__name__ = func.__name__
1876 self.__code__ = func.__code__
1877 self.__annotations__ = func.__annotations__
1878 self.__defaults__ = func.__defaults__
1879 self.__kwdefaults__ = func.__kwdefaults__
1880 self.func = func
1881
1882 def __call__(self, *args, **kwargs):
1883 return self.func(*args, **kwargs)
1884
1885 sig_func = inspect.Signature.from_function(func)
1886
1887 sig_funclike = inspect.Signature.from_function(funclike(func))
1888 self.assertEqual(sig_funclike, sig_func)
1889
1890 sig_funclike = inspect.signature(funclike(func))
1891 self.assertEqual(sig_funclike, sig_func)
1892
1893 # If object is not a duck type of function, then
1894 # signature will try to get a signature for its '__call__'
1895 # method
1896 fl = funclike(func)
1897 del fl.__defaults__
1898 self.assertEqual(self.signature(fl),
1899 ((('args', ..., ..., "var_positional"),
1900 ('kwargs', ..., ..., "var_keyword")),
1901 ...))
1902
Yury Selivanova773de02014-02-21 18:30:53 -05001903 # Test with cython-like builtins:
1904 _orig_isdesc = inspect.ismethoddescriptor
1905 def _isdesc(obj):
1906 if hasattr(obj, '_builtinmock'):
1907 return True
1908 return _orig_isdesc(obj)
1909
1910 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
1911 builtin_func = funclike(func)
1912 # Make sure that our mock setup is working
1913 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
1914 builtin_func._builtinmock = True
1915 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
1916 self.assertEqual(inspect.signature(builtin_func), sig_func)
1917
Yury Selivanov63da7c72014-01-31 14:48:37 -05001918 def test_signature_functionlike_class(self):
1919 # We only want to duck type function-like objects,
1920 # not classes.
1921
1922 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1923 pass
1924
1925 class funclike:
1926 def __init__(self, marker):
1927 pass
1928
1929 __name__ = func.__name__
1930 __code__ = func.__code__
1931 __annotations__ = func.__annotations__
1932 __defaults__ = func.__defaults__
1933 __kwdefaults__ = func.__kwdefaults__
1934
1935 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1936 inspect.Signature.from_function(funclike)
1937
1938 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
1939
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001940 def test_signature_on_method(self):
1941 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05001942 def __init__(*args):
1943 pass
1944 def m1(self, arg1, arg2=1) -> int:
1945 pass
1946 def m2(*args):
1947 pass
1948 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001949 pass
1950
Yury Selivanov62560fb2014-01-28 12:26:24 -05001951 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001952 ((('arg1', ..., ..., "positional_or_keyword"),
1953 ('arg2', 1, ..., "positional_or_keyword")),
1954 int))
1955
Yury Selivanov62560fb2014-01-28 12:26:24 -05001956 self.assertEqual(self.signature(Test().m2),
1957 ((('args', ..., ..., "var_positional"),),
1958 ...))
1959
1960 self.assertEqual(self.signature(Test),
1961 ((('args', ..., ..., "var_positional"),),
1962 ...))
1963
1964 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
1965 self.signature(Test())
1966
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001967 def test_signature_on_classmethod(self):
1968 class Test:
1969 @classmethod
1970 def foo(cls, arg1, *, arg2=1):
1971 pass
1972
1973 meth = Test().foo
1974 self.assertEqual(self.signature(meth),
1975 ((('arg1', ..., ..., "positional_or_keyword"),
1976 ('arg2', 1, ..., "keyword_only")),
1977 ...))
1978
1979 meth = Test.foo
1980 self.assertEqual(self.signature(meth),
1981 ((('arg1', ..., ..., "positional_or_keyword"),
1982 ('arg2', 1, ..., "keyword_only")),
1983 ...))
1984
1985 def test_signature_on_staticmethod(self):
1986 class Test:
1987 @staticmethod
1988 def foo(cls, *, arg):
1989 pass
1990
1991 meth = Test().foo
1992 self.assertEqual(self.signature(meth),
1993 ((('cls', ..., ..., "positional_or_keyword"),
1994 ('arg', ..., ..., "keyword_only")),
1995 ...))
1996
1997 meth = Test.foo
1998 self.assertEqual(self.signature(meth),
1999 ((('cls', ..., ..., "positional_or_keyword"),
2000 ('arg', ..., ..., "keyword_only")),
2001 ...))
2002
2003 def test_signature_on_partial(self):
2004 from functools import partial
2005
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002006 Parameter = inspect.Parameter
2007
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002008 def test():
2009 pass
2010
2011 self.assertEqual(self.signature(partial(test)), ((), ...))
2012
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002013 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002014 inspect.signature(partial(test, 1))
2015
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002016 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002017 inspect.signature(partial(test, a=1))
2018
2019 def test(a, b, *, c, d):
2020 pass
2021
2022 self.assertEqual(self.signature(partial(test)),
2023 ((('a', ..., ..., "positional_or_keyword"),
2024 ('b', ..., ..., "positional_or_keyword"),
2025 ('c', ..., ..., "keyword_only"),
2026 ('d', ..., ..., "keyword_only")),
2027 ...))
2028
2029 self.assertEqual(self.signature(partial(test, 1)),
2030 ((('b', ..., ..., "positional_or_keyword"),
2031 ('c', ..., ..., "keyword_only"),
2032 ('d', ..., ..., "keyword_only")),
2033 ...))
2034
2035 self.assertEqual(self.signature(partial(test, 1, c=2)),
2036 ((('b', ..., ..., "positional_or_keyword"),
2037 ('c', 2, ..., "keyword_only"),
2038 ('d', ..., ..., "keyword_only")),
2039 ...))
2040
2041 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2042 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002043 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002044 ('c', 2, ..., "keyword_only"),
2045 ('d', ..., ..., "keyword_only")),
2046 ...))
2047
2048 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002049 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002050 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002051 ('d', ..., ..., "keyword_only")),
2052 ...))
2053
2054 self.assertEqual(self.signature(partial(test, a=1)),
2055 ((('a', 1, ..., "keyword_only"),
2056 ('b', ..., ..., "keyword_only"),
2057 ('c', ..., ..., "keyword_only"),
2058 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002059 ...))
2060
2061 def test(a, *args, b, **kwargs):
2062 pass
2063
2064 self.assertEqual(self.signature(partial(test, 1)),
2065 ((('args', ..., ..., "var_positional"),
2066 ('b', ..., ..., "keyword_only"),
2067 ('kwargs', ..., ..., "var_keyword")),
2068 ...))
2069
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002070 self.assertEqual(self.signature(partial(test, a=1)),
2071 ((('a', 1, ..., "keyword_only"),
2072 ('b', ..., ..., "keyword_only"),
2073 ('kwargs', ..., ..., "var_keyword")),
2074 ...))
2075
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002076 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2077 ((('args', ..., ..., "var_positional"),
2078 ('b', ..., ..., "keyword_only"),
2079 ('kwargs', ..., ..., "var_keyword")),
2080 ...))
2081
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002082 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2083 ((('args', ..., ..., "var_positional"),
2084 ('b', ..., ..., "keyword_only"),
2085 ('kwargs', ..., ..., "var_keyword")),
2086 ...))
2087
2088 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2089 ((('args', ..., ..., "var_positional"),
2090 ('b', 0, ..., "keyword_only"),
2091 ('kwargs', ..., ..., "var_keyword")),
2092 ...))
2093
2094 self.assertEqual(self.signature(partial(test, b=0)),
2095 ((('a', ..., ..., "positional_or_keyword"),
2096 ('args', ..., ..., "var_positional"),
2097 ('b', 0, ..., "keyword_only"),
2098 ('kwargs', ..., ..., "var_keyword")),
2099 ...))
2100
2101 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2102 ((('a', ..., ..., "positional_or_keyword"),
2103 ('args', ..., ..., "var_positional"),
2104 ('b', 0, ..., "keyword_only"),
2105 ('kwargs', ..., ..., "var_keyword")),
2106 ...))
2107
2108 def test(a, b, c:int) -> 42:
2109 pass
2110
2111 sig = test.__signature__ = inspect.signature(test)
2112
2113 self.assertEqual(self.signature(partial(partial(test, 1))),
2114 ((('b', ..., ..., "positional_or_keyword"),
2115 ('c', ..., int, "positional_or_keyword")),
2116 42))
2117
2118 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2119 ((('c', ..., int, "positional_or_keyword"),),
2120 42))
2121
2122 psig = inspect.signature(partial(partial(test, 1), 2))
2123
2124 def foo(a):
2125 return a
2126 _foo = partial(partial(foo, a=10), a=20)
2127 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002128 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002129 ...))
2130 # check that we don't have any side-effects in signature(),
2131 # and the partial object is still functioning
2132 self.assertEqual(_foo(), 20)
2133
2134 def foo(a, b, c):
2135 return a, b, c
2136 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002137
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002138 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002139 ((('b', 30, ..., "keyword_only"),
2140 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002141 ...))
2142 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002143
2144 def foo(a, b, c, *, d):
2145 return a, b, c, d
2146 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2147 self.assertEqual(self.signature(_foo),
2148 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002149 ('b', 10, ..., "keyword_only"),
2150 ('c', 20, ..., "keyword_only"),
2151 ('d', 30, ..., "keyword_only"),
2152 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002153 ...))
2154 ba = inspect.signature(_foo).bind(a=200, b=11)
2155 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2156
2157 def foo(a=1, b=2, c=3):
2158 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002159 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2160
2161 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002162 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002163
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002164 ba = inspect.signature(_foo).bind(11, 12)
2165 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002166
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002167 ba = inspect.signature(_foo).bind(11, b=12)
2168 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002169
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002170 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002171 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2172
2173 _foo = partial(_foo, b=10, c=20)
2174 ba = inspect.signature(_foo).bind(12)
2175 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2176
2177
2178 def foo(a, b, c, d, **kwargs):
2179 pass
2180 sig = inspect.signature(foo)
2181 params = sig.parameters.copy()
2182 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2183 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2184 foo.__signature__ = inspect.Signature(params.values())
2185 sig = inspect.signature(foo)
2186 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2187
2188 self.assertEqual(self.signature(partial(foo, 1)),
2189 ((('b', ..., ..., 'positional_only'),
2190 ('c', ..., ..., 'positional_or_keyword'),
2191 ('d', ..., ..., 'positional_or_keyword'),
2192 ('kwargs', ..., ..., 'var_keyword')),
2193 ...))
2194
2195 self.assertEqual(self.signature(partial(foo, 1, 2)),
2196 ((('c', ..., ..., 'positional_or_keyword'),
2197 ('d', ..., ..., 'positional_or_keyword'),
2198 ('kwargs', ..., ..., 'var_keyword')),
2199 ...))
2200
2201 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2202 ((('d', ..., ..., 'positional_or_keyword'),
2203 ('kwargs', ..., ..., 'var_keyword')),
2204 ...))
2205
2206 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2207 ((('c', 3, ..., 'keyword_only'),
2208 ('d', ..., ..., 'keyword_only'),
2209 ('kwargs', ..., ..., 'var_keyword')),
2210 ...))
2211
2212 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2213 ((('b', ..., ..., 'positional_only'),
2214 ('c', 3, ..., 'keyword_only'),
2215 ('d', ..., ..., 'keyword_only'),
2216 ('kwargs', ..., ..., 'var_keyword')),
2217 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002218
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002219 def test_signature_on_partialmethod(self):
2220 from functools import partialmethod
2221
2222 class Spam:
2223 def test():
2224 pass
2225 ham = partialmethod(test)
2226
2227 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2228 inspect.signature(Spam.ham)
2229
2230 class Spam:
2231 def test(it, a, *, c) -> 'spam':
2232 pass
2233 ham = partialmethod(test, c=1)
2234
2235 self.assertEqual(self.signature(Spam.ham),
2236 ((('it', ..., ..., 'positional_or_keyword'),
2237 ('a', ..., ..., 'positional_or_keyword'),
2238 ('c', 1, ..., 'keyword_only')),
2239 'spam'))
2240
2241 self.assertEqual(self.signature(Spam().ham),
2242 ((('a', ..., ..., 'positional_or_keyword'),
2243 ('c', 1, ..., 'keyword_only')),
2244 'spam'))
2245
Yury Selivanov0486f812014-01-29 12:18:59 -05002246 def test_signature_on_fake_partialmethod(self):
2247 def foo(a): pass
2248 foo._partialmethod = 'spam'
2249 self.assertEqual(str(inspect.signature(foo)), '(a)')
2250
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002251 def test_signature_on_decorated(self):
2252 import functools
2253
2254 def decorator(func):
2255 @functools.wraps(func)
2256 def wrapper(*args, **kwargs) -> int:
2257 return func(*args, **kwargs)
2258 return wrapper
2259
2260 class Foo:
2261 @decorator
2262 def bar(self, a, b):
2263 pass
2264
2265 self.assertEqual(self.signature(Foo.bar),
2266 ((('self', ..., ..., "positional_or_keyword"),
2267 ('a', ..., ..., "positional_or_keyword"),
2268 ('b', ..., ..., "positional_or_keyword")),
2269 ...))
2270
2271 self.assertEqual(self.signature(Foo().bar),
2272 ((('a', ..., ..., "positional_or_keyword"),
2273 ('b', ..., ..., "positional_or_keyword")),
2274 ...))
2275
2276 # Test that we handle method wrappers correctly
2277 def decorator(func):
2278 @functools.wraps(func)
2279 def wrapper(*args, **kwargs) -> int:
2280 return func(42, *args, **kwargs)
2281 sig = inspect.signature(func)
2282 new_params = tuple(sig.parameters.values())[1:]
2283 wrapper.__signature__ = sig.replace(parameters=new_params)
2284 return wrapper
2285
2286 class Foo:
2287 @decorator
2288 def __call__(self, a, b):
2289 pass
2290
2291 self.assertEqual(self.signature(Foo.__call__),
2292 ((('a', ..., ..., "positional_or_keyword"),
2293 ('b', ..., ..., "positional_or_keyword")),
2294 ...))
2295
2296 self.assertEqual(self.signature(Foo().__call__),
2297 ((('b', ..., ..., "positional_or_keyword"),),
2298 ...))
2299
Nick Coghlane8c45d62013-07-28 20:00:01 +10002300 # Test we handle __signature__ partway down the wrapper stack
2301 def wrapped_foo_call():
2302 pass
2303 wrapped_foo_call.__wrapped__ = Foo.__call__
2304
2305 self.assertEqual(self.signature(wrapped_foo_call),
2306 ((('a', ..., ..., "positional_or_keyword"),
2307 ('b', ..., ..., "positional_or_keyword")),
2308 ...))
2309
2310
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002311 def test_signature_on_class(self):
2312 class C:
2313 def __init__(self, a):
2314 pass
2315
2316 self.assertEqual(self.signature(C),
2317 ((('a', ..., ..., "positional_or_keyword"),),
2318 ...))
2319
2320 class CM(type):
2321 def __call__(cls, a):
2322 pass
2323 class C(metaclass=CM):
2324 def __init__(self, b):
2325 pass
2326
2327 self.assertEqual(self.signature(C),
2328 ((('a', ..., ..., "positional_or_keyword"),),
2329 ...))
2330
2331 class CM(type):
2332 def __new__(mcls, name, bases, dct, *, foo=1):
2333 return super().__new__(mcls, name, bases, dct)
2334 class C(metaclass=CM):
2335 def __init__(self, b):
2336 pass
2337
2338 self.assertEqual(self.signature(C),
2339 ((('b', ..., ..., "positional_or_keyword"),),
2340 ...))
2341
2342 self.assertEqual(self.signature(CM),
2343 ((('name', ..., ..., "positional_or_keyword"),
2344 ('bases', ..., ..., "positional_or_keyword"),
2345 ('dct', ..., ..., "positional_or_keyword"),
2346 ('foo', 1, ..., "keyword_only")),
2347 ...))
2348
2349 class CMM(type):
2350 def __new__(mcls, name, bases, dct, *, foo=1):
2351 return super().__new__(mcls, name, bases, dct)
2352 def __call__(cls, nm, bs, dt):
2353 return type(nm, bs, dt)
2354 class CM(type, metaclass=CMM):
2355 def __new__(mcls, name, bases, dct, *, bar=2):
2356 return super().__new__(mcls, name, bases, dct)
2357 class C(metaclass=CM):
2358 def __init__(self, b):
2359 pass
2360
2361 self.assertEqual(self.signature(CMM),
2362 ((('name', ..., ..., "positional_or_keyword"),
2363 ('bases', ..., ..., "positional_or_keyword"),
2364 ('dct', ..., ..., "positional_or_keyword"),
2365 ('foo', 1, ..., "keyword_only")),
2366 ...))
2367
2368 self.assertEqual(self.signature(CM),
2369 ((('nm', ..., ..., "positional_or_keyword"),
2370 ('bs', ..., ..., "positional_or_keyword"),
2371 ('dt', ..., ..., "positional_or_keyword")),
2372 ...))
2373
2374 self.assertEqual(self.signature(C),
2375 ((('b', ..., ..., "positional_or_keyword"),),
2376 ...))
2377
2378 class CM(type):
2379 def __init__(cls, name, bases, dct, *, bar=2):
2380 return super().__init__(name, bases, dct)
2381 class C(metaclass=CM):
2382 def __init__(self, b):
2383 pass
2384
2385 self.assertEqual(self.signature(CM),
2386 ((('name', ..., ..., "positional_or_keyword"),
2387 ('bases', ..., ..., "positional_or_keyword"),
2388 ('dct', ..., ..., "positional_or_keyword"),
2389 ('bar', 2, ..., "keyword_only")),
2390 ...))
2391
Yury Selivanov145dff82014-02-01 13:49:29 -05002392 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2393 "Signature information for builtins requires docstrings")
2394 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002395 # Test classes without user-defined __init__ or __new__
2396 class C: pass
2397 self.assertEqual(str(inspect.signature(C)), '()')
2398 class D(C): pass
2399 self.assertEqual(str(inspect.signature(D)), '()')
2400
2401 # Test meta-classes without user-defined __init__ or __new__
2402 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002403 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002404 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2405 self.assertEqual(inspect.signature(C), None)
2406 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2407 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002408
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002409 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2410 "Signature information for builtins requires docstrings")
2411 def test_signature_on_builtin_class(self):
2412 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2413 '(file, protocol=None, fix_imports=True)')
2414
2415 class P(_pickle.Pickler): pass
2416 class EmptyTrait: pass
2417 class P2(EmptyTrait, P): pass
2418 self.assertEqual(str(inspect.signature(P)),
2419 '(file, protocol=None, fix_imports=True)')
2420 self.assertEqual(str(inspect.signature(P2)),
2421 '(file, protocol=None, fix_imports=True)')
2422
2423 class P3(P2):
2424 def __init__(self, spam):
2425 pass
2426 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2427
2428 class MetaP(type):
2429 def __call__(cls, foo, bar):
2430 pass
2431 class P4(P2, metaclass=MetaP):
2432 pass
2433 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2434
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002435 def test_signature_on_callable_objects(self):
2436 class Foo:
2437 def __call__(self, a):
2438 pass
2439
2440 self.assertEqual(self.signature(Foo()),
2441 ((('a', ..., ..., "positional_or_keyword"),),
2442 ...))
2443
2444 class Spam:
2445 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002446 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002447 inspect.signature(Spam())
2448
2449 class Bar(Spam, Foo):
2450 pass
2451
2452 self.assertEqual(self.signature(Bar()),
2453 ((('a', ..., ..., "positional_or_keyword"),),
2454 ...))
2455
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002456 class Wrapped:
2457 pass
2458 Wrapped.__wrapped__ = lambda a: None
2459 self.assertEqual(self.signature(Wrapped),
2460 ((('a', ..., ..., "positional_or_keyword"),),
2461 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002462 # wrapper loop:
2463 Wrapped.__wrapped__ = Wrapped
2464 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2465 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002466
2467 def test_signature_on_lambdas(self):
2468 self.assertEqual(self.signature((lambda a=10: a)),
2469 ((('a', 10, ..., "positional_or_keyword"),),
2470 ...))
2471
2472 def test_signature_equality(self):
2473 def foo(a, *, b:int) -> float: pass
2474 self.assertNotEqual(inspect.signature(foo), 42)
2475
2476 def bar(a, *, b:int) -> float: pass
2477 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2478
2479 def bar(a, *, b:int) -> int: pass
2480 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2481
2482 def bar(a, *, b:int): pass
2483 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2484
2485 def bar(a, *, b:int=42) -> float: pass
2486 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2487
2488 def bar(a, *, c) -> float: pass
2489 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2490
2491 def bar(a, b:int) -> float: pass
2492 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2493 def spam(b:int, a) -> float: pass
2494 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
2495
2496 def foo(*, a, b, c): pass
2497 def bar(*, c, b, a): pass
2498 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2499
2500 def foo(*, a=1, b, c): pass
2501 def bar(*, c, b, a=1): pass
2502 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2503
2504 def foo(pos, *, a=1, b, c): pass
2505 def bar(pos, *, c, b, a=1): pass
2506 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2507
2508 def foo(pos, *, a, b, c): pass
2509 def bar(pos, *, c, b, a=1): pass
2510 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2511
2512 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2513 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2514 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2515
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002516 def test_signature_hashable(self):
2517 S = inspect.Signature
2518 P = inspect.Parameter
2519
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002520 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002521 foo_sig = inspect.signature(foo)
2522
2523 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2524
2525 self.assertEqual(hash(foo_sig), hash(manual_sig))
2526 self.assertNotEqual(hash(foo_sig),
2527 hash(manual_sig.replace(return_annotation='spam')))
2528
2529 def bar(a) -> 1: pass
2530 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2531
2532 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002533 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002534 hash(inspect.signature(foo))
2535
2536 def foo(a) -> {}: pass
2537 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2538 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002539
2540 def test_signature_str(self):
2541 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2542 pass
2543 self.assertEqual(str(inspect.signature(foo)),
2544 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2545
2546 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2547 pass
2548 self.assertEqual(str(inspect.signature(foo)),
2549 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2550
2551 def foo():
2552 pass
2553 self.assertEqual(str(inspect.signature(foo)), '()')
2554
2555 def test_signature_str_positional_only(self):
2556 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002557 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002558
2559 def test(a_po, *, b, **kwargs):
2560 return a_po, kwargs
2561
2562 sig = inspect.signature(test)
2563 new_params = list(sig.parameters.values())
2564 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2565 test.__signature__ = sig.replace(parameters=new_params)
2566
2567 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002568 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002569
Yury Selivanov2393dca2014-01-27 15:07:58 -05002570 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2571 '(foo, /)')
2572
2573 self.assertEqual(str(S(parameters=[
2574 P('foo', P.POSITIONAL_ONLY),
2575 P('bar', P.VAR_KEYWORD)])),
2576 '(foo, /, **bar)')
2577
2578 self.assertEqual(str(S(parameters=[
2579 P('foo', P.POSITIONAL_ONLY),
2580 P('bar', P.VAR_POSITIONAL)])),
2581 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002582
2583 def test_signature_replace_anno(self):
2584 def test() -> 42:
2585 pass
2586
2587 sig = inspect.signature(test)
2588 sig = sig.replace(return_annotation=None)
2589 self.assertIs(sig.return_annotation, None)
2590 sig = sig.replace(return_annotation=sig.empty)
2591 self.assertIs(sig.return_annotation, sig.empty)
2592 sig = sig.replace(return_annotation=42)
2593 self.assertEqual(sig.return_annotation, 42)
2594 self.assertEqual(sig, inspect.signature(test))
2595
Yury Selivanov34ce99f2014-02-18 12:49:41 -05002596 def test_signature_on_mangled_parameters(self):
2597 class Spam:
2598 def foo(self, __p1:1=2, *, __p2:2=3):
2599 pass
2600 class Ham(Spam):
2601 pass
2602
2603 self.assertEqual(self.signature(Spam.foo),
2604 ((('self', ..., ..., "positional_or_keyword"),
2605 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2606 ('_Spam__p2', 3, 2, "keyword_only")),
2607 ...))
2608
2609 self.assertEqual(self.signature(Spam.foo),
2610 self.signature(Ham.foo))
2611
Yury Selivanovda396452014-03-27 12:09:24 -04002612 def test_signature_from_callable_python_obj(self):
2613 class MySignature(inspect.Signature): pass
2614 def foo(a, *, b:1): pass
2615 foo_sig = MySignature.from_callable(foo)
2616 self.assertTrue(isinstance(foo_sig, MySignature))
2617
2618 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2619 "Signature information for builtins requires docstrings")
2620 def test_signature_from_callable_builtin_obj(self):
2621 class MySignature(inspect.Signature): pass
2622 sig = MySignature.from_callable(_pickle.Pickler)
2623 self.assertTrue(isinstance(sig, MySignature))
2624
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002625
2626class TestParameterObject(unittest.TestCase):
2627 def test_signature_parameter_kinds(self):
2628 P = inspect.Parameter
2629 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2630 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2631
2632 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2633 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2634
2635 def test_signature_parameter_object(self):
2636 p = inspect.Parameter('foo', default=10,
2637 kind=inspect.Parameter.POSITIONAL_ONLY)
2638 self.assertEqual(p.name, 'foo')
2639 self.assertEqual(p.default, 10)
2640 self.assertIs(p.annotation, p.empty)
2641 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2642
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002643 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002644 inspect.Parameter('foo', default=10, kind='123')
2645
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002646 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002647 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2648
Yury Selivanov2393dca2014-01-27 15:07:58 -05002649 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002650 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2651
Yury Selivanov2393dca2014-01-27 15:07:58 -05002652 with self.assertRaisesRegex(ValueError,
2653 'is not a valid parameter name'):
2654 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2655
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002656 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002657 inspect.Parameter('a', default=42,
2658 kind=inspect.Parameter.VAR_KEYWORD)
2659
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002660 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002661 inspect.Parameter('a', default=42,
2662 kind=inspect.Parameter.VAR_POSITIONAL)
2663
2664 p = inspect.Parameter('a', default=42,
2665 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002666 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002667 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2668
2669 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04002670 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002671
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002672 def test_signature_parameter_hashable(self):
2673 P = inspect.Parameter
2674 foo = P('foo', kind=P.POSITIONAL_ONLY)
2675 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
2676 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
2677 default=42)))
2678 self.assertNotEqual(hash(foo),
2679 hash(foo.replace(kind=P.VAR_POSITIONAL)))
2680
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002681 def test_signature_parameter_equality(self):
2682 P = inspect.Parameter
2683 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2684
2685 self.assertEqual(p, p)
2686 self.assertNotEqual(p, 42)
2687
2688 self.assertEqual(p, P('foo', default=42,
2689 kind=inspect.Parameter.KEYWORD_ONLY))
2690
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002691 def test_signature_parameter_replace(self):
2692 p = inspect.Parameter('foo', default=42,
2693 kind=inspect.Parameter.KEYWORD_ONLY)
2694
2695 self.assertIsNot(p, p.replace())
2696 self.assertEqual(p, p.replace())
2697
2698 p2 = p.replace(annotation=1)
2699 self.assertEqual(p2.annotation, 1)
2700 p2 = p2.replace(annotation=p2.empty)
2701 self.assertEqual(p, p2)
2702
2703 p2 = p2.replace(name='bar')
2704 self.assertEqual(p2.name, 'bar')
2705 self.assertNotEqual(p2, p)
2706
Yury Selivanov2393dca2014-01-27 15:07:58 -05002707 with self.assertRaisesRegex(ValueError,
2708 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002709 p2 = p2.replace(name=p2.empty)
2710
2711 p2 = p2.replace(name='foo', default=None)
2712 self.assertIs(p2.default, None)
2713 self.assertNotEqual(p2, p)
2714
2715 p2 = p2.replace(name='foo', default=p2.empty)
2716 self.assertIs(p2.default, p2.empty)
2717
2718
2719 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2720 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2721 self.assertNotEqual(p2, p)
2722
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002723 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002724 p2 = p2.replace(kind=p2.empty)
2725
2726 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2727 self.assertEqual(p2, p)
2728
2729 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002730 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2731 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002732
2733 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002734 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002735
2736 with self.assertRaises(AttributeError):
2737 p.foo = 'bar'
2738
2739 with self.assertRaises(AttributeError):
2740 p.kind = 123
2741
2742
2743class TestSignatureBind(unittest.TestCase):
2744 @staticmethod
2745 def call(func, *args, **kwargs):
2746 sig = inspect.signature(func)
2747 ba = sig.bind(*args, **kwargs)
2748 return func(*ba.args, **ba.kwargs)
2749
2750 def test_signature_bind_empty(self):
2751 def test():
2752 return 42
2753
2754 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002755 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002756 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002757 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002758 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002759 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002760 self.call(test, spam=1)
2761
2762 def test_signature_bind_var(self):
2763 def test(*args, **kwargs):
2764 return args, kwargs
2765
2766 self.assertEqual(self.call(test), ((), {}))
2767 self.assertEqual(self.call(test, 1), ((1,), {}))
2768 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2769 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2770 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2771 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2772 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2773 ((1, 2), {'foo': 'bar'}))
2774
2775 def test_signature_bind_just_args(self):
2776 def test(a, b, c):
2777 return a, b, c
2778
2779 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2780
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002781 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002782 self.call(test, 1, 2, 3, 4)
2783
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002784 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002785 self.call(test, 1)
2786
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002787 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002788 self.call(test)
2789
2790 def test(a, b, c=10):
2791 return a, b, c
2792 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2793 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2794
2795 def test(a=1, b=2, c=3):
2796 return a, b, c
2797 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2798 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2799 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2800
2801 def test_signature_bind_varargs_order(self):
2802 def test(*args):
2803 return args
2804
2805 self.assertEqual(self.call(test), ())
2806 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2807
2808 def test_signature_bind_args_and_varargs(self):
2809 def test(a, b, c=3, *args):
2810 return a, b, c, args
2811
2812 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2813 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2814 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2815 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2816
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002817 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002818 "multiple values for argument 'c'"):
2819 self.call(test, 1, 2, 3, c=4)
2820
2821 def test_signature_bind_just_kwargs(self):
2822 def test(**kwargs):
2823 return kwargs
2824
2825 self.assertEqual(self.call(test), {})
2826 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2827 {'foo': 'bar', 'spam': 'ham'})
2828
2829 def test_signature_bind_args_and_kwargs(self):
2830 def test(a, b, c=3, **kwargs):
2831 return a, b, c, kwargs
2832
2833 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2834 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2835 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2836 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2837 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2838 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2839 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2840 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2841 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2842 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2843 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2844 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2845 (1, 2, 4, {'foo': 'bar'}))
2846 self.assertEqual(self.call(test, c=5, a=4, b=3),
2847 (4, 3, 5, {}))
2848
2849 def test_signature_bind_kwonly(self):
2850 def test(*, foo):
2851 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002852 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002853 'too many positional arguments'):
2854 self.call(test, 1)
2855 self.assertEqual(self.call(test, foo=1), 1)
2856
2857 def test(a, *, foo=1, bar):
2858 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002859 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002860 "'bar' parameter lacking default value"):
2861 self.call(test, 1)
2862
2863 def test(foo, *, bar):
2864 return foo, bar
2865 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2866 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2867
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002868 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002869 'too many keyword arguments'):
2870 self.call(test, bar=2, foo=1, spam=10)
2871
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002872 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002873 'too many positional arguments'):
2874 self.call(test, 1, 2)
2875
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002876 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002877 'too many positional arguments'):
2878 self.call(test, 1, 2, bar=2)
2879
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002880 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002881 'too many keyword arguments'):
2882 self.call(test, 1, bar=2, spam='ham')
2883
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002884 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002885 "'bar' parameter lacking default value"):
2886 self.call(test, 1)
2887
2888 def test(foo, *, bar, **bin):
2889 return foo, bar, bin
2890 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2891 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2892 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2893 (1, 2, {'spam': 'ham'}))
2894 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2895 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002896 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002897 "'foo' parameter lacking default value"):
2898 self.call(test, spam='ham', bar=2)
2899 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2900 (1, 2, {'bin': 1, 'spam': 10}))
2901
2902 def test_signature_bind_arguments(self):
2903 def test(a, *args, b, z=100, **kwargs):
2904 pass
2905 sig = inspect.signature(test)
2906 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2907 # we won't have 'z' argument in the bound arguments object, as we didn't
2908 # pass it to the 'bind'
2909 self.assertEqual(tuple(ba.arguments.items()),
2910 (('a', 10), ('args', (20,)), ('b', 30),
2911 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2912 self.assertEqual(ba.kwargs,
2913 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2914 self.assertEqual(ba.args, (10, 20))
2915
2916 def test_signature_bind_positional_only(self):
2917 P = inspect.Parameter
2918
2919 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2920 return a_po, b_po, c_po, foo, bar, kwargs
2921
2922 sig = inspect.signature(test)
2923 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2924 for name in ('a_po', 'b_po', 'c_po'):
2925 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2926 new_sig = sig.replace(parameters=new_params.values())
2927 test.__signature__ = new_sig
2928
2929 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2930 (1, 2, 4, 5, 6, {}))
2931
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002932 self.assertEqual(self.call(test, 1, 2),
2933 (1, 2, 3, 42, 50, {}))
2934
2935 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
2936 (1, 2, 3, 4, 5, {}))
2937
2938 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
2939 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
2940
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002941 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002942 self.call(test, 1, 2, c_po=4)
2943
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002944 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002945 self.call(test, a_po=1, b_po=2)
2946
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002947 def test_signature_bind_with_self_arg(self):
2948 # Issue #17071: one of the parameters is named "self
2949 def test(a, self, b):
2950 pass
2951 sig = inspect.signature(test)
2952 ba = sig.bind(1, 2, 3)
2953 self.assertEqual(ba.args, (1, 2, 3))
2954 ba = sig.bind(1, self=2, b=3)
2955 self.assertEqual(ba.args, (1, 2, 3))
2956
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002957 def test_signature_bind_vararg_name(self):
2958 def test(a, *args):
2959 return a, args
2960 sig = inspect.signature(test)
2961
2962 with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
2963 sig.bind(a=0, args=1)
2964
2965 def test(*args, **kwargs):
2966 return args, kwargs
2967 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
2968
2969 sig = inspect.signature(test)
2970 ba = sig.bind(args=1)
2971 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
2972
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002973
2974class TestBoundArguments(unittest.TestCase):
2975 def test_signature_bound_arguments_unhashable(self):
2976 def foo(a): pass
2977 ba = inspect.signature(foo).bind(1)
2978
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002979 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002980 hash(ba)
2981
2982 def test_signature_bound_arguments_equality(self):
2983 def foo(a): pass
2984 ba = inspect.signature(foo).bind(1)
2985 self.assertEqual(ba, ba)
2986
2987 ba2 = inspect.signature(foo).bind(1)
2988 self.assertEqual(ba, ba2)
2989
2990 ba3 = inspect.signature(foo).bind(2)
2991 self.assertNotEqual(ba, ba3)
2992 ba3.arguments['a'] = 1
2993 self.assertEqual(ba, ba3)
2994
2995 def bar(b): pass
2996 ba4 = inspect.signature(bar).bind(1)
2997 self.assertNotEqual(ba, ba4)
2998
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002999 def test_signature_bound_arguments_pickle(self):
3000 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3001 sig = inspect.signature(foo)
3002 ba = sig.bind(20, 30, z={})
3003
3004 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3005 with self.subTest(pickle_ver=ver):
3006 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3007 self.assertEqual(ba, ba_pickled)
3008
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003009
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003010class TestSignaturePrivateHelpers(unittest.TestCase):
3011 def test_signature_get_bound_param(self):
3012 getter = inspect._signature_get_bound_param
3013
3014 self.assertEqual(getter('($self)'), 'self')
3015 self.assertEqual(getter('($self, obj)'), 'self')
3016 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3017
Larry Hastings2623c8c2014-02-08 22:15:29 -08003018 def _strip_non_python_syntax(self, input,
3019 clean_signature, self_parameter, last_positional_only):
3020 computed_clean_signature, \
3021 computed_self_parameter, \
3022 computed_last_positional_only = \
3023 inspect._signature_strip_non_python_syntax(input)
3024 self.assertEqual(computed_clean_signature, clean_signature)
3025 self.assertEqual(computed_self_parameter, self_parameter)
3026 self.assertEqual(computed_last_positional_only, last_positional_only)
3027
3028 def test_signature_strip_non_python_syntax(self):
3029 self._strip_non_python_syntax(
3030 "($module, /, path, mode, *, dir_fd=None, " +
3031 "effective_ids=False,\n follow_symlinks=True)",
3032 "(module, path, mode, *, dir_fd=None, " +
3033 "effective_ids=False, follow_symlinks=True)",
3034 0,
3035 0)
3036
3037 self._strip_non_python_syntax(
3038 "($module, word, salt, /)",
3039 "(module, word, salt)",
3040 0,
3041 2)
3042
3043 self._strip_non_python_syntax(
3044 "(x, y=None, z=None, /)",
3045 "(x, y=None, z=None)",
3046 None,
3047 2)
3048
3049 self._strip_non_python_syntax(
3050 "(x, y=None, z=None)",
3051 "(x, y=None, z=None)",
3052 None,
3053 None)
3054
3055 self._strip_non_python_syntax(
3056 "(x,\n y=None,\n z = None )",
3057 "(x, y=None, z=None)",
3058 None,
3059 None)
3060
3061 self._strip_non_python_syntax(
3062 "",
3063 "",
3064 None,
3065 None)
3066
3067 self._strip_non_python_syntax(
3068 None,
3069 None,
3070 None,
3071 None)
3072
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003073
Nick Coghlane8c45d62013-07-28 20:00:01 +10003074class TestUnwrap(unittest.TestCase):
3075
3076 def test_unwrap_one(self):
3077 def func(a, b):
3078 return a + b
3079 wrapper = functools.lru_cache(maxsize=20)(func)
3080 self.assertIs(inspect.unwrap(wrapper), func)
3081
3082 def test_unwrap_several(self):
3083 def func(a, b):
3084 return a + b
3085 wrapper = func
3086 for __ in range(10):
3087 @functools.wraps(wrapper)
3088 def wrapper():
3089 pass
3090 self.assertIsNot(wrapper.__wrapped__, func)
3091 self.assertIs(inspect.unwrap(wrapper), func)
3092
3093 def test_stop(self):
3094 def func1(a, b):
3095 return a + b
3096 @functools.wraps(func1)
3097 def func2():
3098 pass
3099 @functools.wraps(func2)
3100 def wrapper():
3101 pass
3102 func2.stop_here = 1
3103 unwrapped = inspect.unwrap(wrapper,
3104 stop=(lambda f: hasattr(f, "stop_here")))
3105 self.assertIs(unwrapped, func2)
3106
3107 def test_cycle(self):
3108 def func1(): pass
3109 func1.__wrapped__ = func1
3110 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3111 inspect.unwrap(func1)
3112
3113 def func2(): pass
3114 func2.__wrapped__ = func1
3115 func1.__wrapped__ = func2
3116 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3117 inspect.unwrap(func1)
3118 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3119 inspect.unwrap(func2)
3120
3121 def test_unhashable(self):
3122 def func(): pass
3123 func.__wrapped__ = None
3124 class C:
3125 __hash__ = None
3126 __wrapped__ = func
3127 self.assertIsNone(inspect.unwrap(C()))
3128
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003129class TestMain(unittest.TestCase):
3130 def test_only_source(self):
3131 module = importlib.import_module('unittest')
3132 rc, out, err = assert_python_ok('-m', 'inspect',
3133 'unittest')
3134 lines = out.decode().splitlines()
3135 # ignore the final newline
3136 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3137 self.assertEqual(err, b'')
3138
Brett Cannon634a8fc2013-10-02 10:25:42 -04003139 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003140 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003141 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003142 rc, out, err = assert_python_ok('-m', 'inspect',
3143 'concurrent.futures:ThreadPoolExecutor')
3144 lines = out.decode().splitlines()
3145 # ignore the final newline
3146 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003147 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003148 self.assertEqual(err, b'')
3149
3150 def test_builtins(self):
3151 module = importlib.import_module('unittest')
3152 _, out, err = assert_python_failure('-m', 'inspect',
3153 'sys')
3154 lines = err.decode().splitlines()
3155 self.assertEqual(lines, ["Can't get info for builtin modules."])
3156
3157 def test_details(self):
3158 module = importlib.import_module('unittest')
3159 rc, out, err = assert_python_ok('-m', 'inspect',
3160 'unittest', '--details')
3161 output = out.decode()
3162 # Just a quick sanity check on the output
3163 self.assertIn(module.__name__, output)
3164 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02003165 if not sys.flags.optimize:
3166 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003167 self.assertEqual(err, b'')
3168
3169
3170
Nick Coghlane8c45d62013-07-28 20:00:01 +10003171
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003172def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003173 run_unittest(
3174 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3175 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3176 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003177 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003178 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003179 TestBoundArguments, TestSignaturePrivateHelpers, TestGetClosureVars,
3180 TestUnwrap, TestMain
Michael Foord95fc51d2010-11-20 15:07:30 +00003181 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003182
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003183if __name__ == "__main__":
3184 test_main()