blob: b94353031bde3c9a2ffab227b87e93657cc2fb5d [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
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001219class TestGetcallargsMethods(TestGetcallargsFunctions):
1220
1221 def setUp(self):
1222 class Foo(object):
1223 pass
1224 self.cls = Foo
1225 self.inst = Foo()
1226
1227 def makeCallable(self, signature):
1228 assert 'self' not in signature
1229 mk = super(TestGetcallargsMethods, self).makeCallable
1230 self.cls.method = mk('self, ' + signature)
1231 return self.inst.method
1232
1233class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1234
1235 def makeCallable(self, signature):
1236 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1237 return self.cls.method
1238
1239 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1240 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1241 *self._getAssertEqualParams(func, call_params_string, locs))
1242
1243 def assertEqualException(self, func, call_params_string, locs=None):
1244 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1245 *self._getAssertEqualParams(func, call_params_string, locs))
1246
1247 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1248 assert 'inst' not in call_params_string
1249 locs = dict(locs or {}, inst=self.inst)
1250 return (func, 'inst,' + call_params_string, locs)
1251
Michael Foord95fc51d2010-11-20 15:07:30 +00001252
1253class TestGetattrStatic(unittest.TestCase):
1254
1255 def test_basic(self):
1256 class Thing(object):
1257 x = object()
1258
1259 thing = Thing()
1260 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1261 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1262 with self.assertRaises(AttributeError):
1263 inspect.getattr_static(thing, 'y')
1264
1265 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1266
1267 def test_inherited(self):
1268 class Thing(object):
1269 x = object()
1270 class OtherThing(Thing):
1271 pass
1272
1273 something = OtherThing()
1274 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1275
1276 def test_instance_attr(self):
1277 class Thing(object):
1278 x = 2
1279 def __init__(self, x):
1280 self.x = x
1281 thing = Thing(3)
1282 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1283 del thing.x
1284 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1285
1286 def test_property(self):
1287 class Thing(object):
1288 @property
1289 def x(self):
1290 raise AttributeError("I'm pretending not to exist")
1291 thing = Thing()
1292 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1293
Ezio Melotti75cbd732011-04-28 00:59:29 +03001294 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001295 class descriptor(object):
1296 def __get__(*_):
1297 raise AttributeError("I'm pretending not to exist")
1298 desc = descriptor()
1299 class Thing(object):
1300 x = desc
1301 thing = Thing()
1302 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1303
1304 def test_classAttribute(self):
1305 class Thing(object):
1306 x = object()
1307
1308 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1309
Ethan Furmane03ea372013-09-25 07:14:41 -07001310 def test_classVirtualAttribute(self):
1311 class Thing(object):
1312 @types.DynamicClassAttribute
1313 def x(self):
1314 return self._x
1315 _x = object()
1316
1317 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1318
Michael Foord95fc51d2010-11-20 15:07:30 +00001319 def test_inherited_classattribute(self):
1320 class Thing(object):
1321 x = object()
1322 class OtherThing(Thing):
1323 pass
1324
1325 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1326
1327 def test_slots(self):
1328 class Thing(object):
1329 y = 'bar'
1330 __slots__ = ['x']
1331 def __init__(self):
1332 self.x = 'foo'
1333 thing = Thing()
1334 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1335 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1336
1337 del thing.x
1338 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1339
1340 def test_metaclass(self):
1341 class meta(type):
1342 attr = 'foo'
1343 class Thing(object, metaclass=meta):
1344 pass
1345 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1346
1347 class sub(meta):
1348 pass
1349 class OtherThing(object, metaclass=sub):
1350 x = 3
1351 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1352
1353 class OtherOtherThing(OtherThing):
1354 pass
1355 # this test is odd, but it was added as it exposed a bug
1356 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1357
1358 def test_no_dict_no_slots(self):
1359 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1360 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1361
1362 def test_no_dict_no_slots_instance_member(self):
1363 # returns descriptor
1364 with open(__file__) as handle:
1365 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1366
1367 def test_inherited_slots(self):
1368 # returns descriptor
1369 class Thing(object):
1370 __slots__ = ['x']
1371 def __init__(self):
1372 self.x = 'foo'
1373
1374 class OtherThing(Thing):
1375 pass
1376 # it would be nice if this worked...
1377 # we get the descriptor instead of the instance attribute
1378 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1379
1380 def test_descriptor(self):
1381 class descriptor(object):
1382 def __get__(self, instance, owner):
1383 return 3
1384 class Foo(object):
1385 d = descriptor()
1386
1387 foo = Foo()
1388
1389 # for a non data descriptor we return the instance attribute
1390 foo.__dict__['d'] = 1
1391 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1392
1393 # if the descriptor is a data-desciptor we should return the
1394 # descriptor
1395 descriptor.__set__ = lambda s, i, v: None
1396 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1397
1398
1399 def test_metaclass_with_descriptor(self):
1400 class descriptor(object):
1401 def __get__(self, instance, owner):
1402 return 3
1403 class meta(type):
1404 d = descriptor()
1405 class Thing(object, metaclass=meta):
1406 pass
1407 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1408
1409
Michael Foordcc7ebb82010-11-20 16:20:16 +00001410 def test_class_as_property(self):
1411 class Base(object):
1412 foo = 3
1413
1414 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001415 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001416 @property
1417 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001418 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001419 return object
1420
Michael Foord35184ed2010-11-20 16:58:30 +00001421 instance = Something()
1422 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1423 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001424 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1425
Michael Foorde5162652010-11-20 16:40:44 +00001426 def test_mro_as_property(self):
1427 class Meta(type):
1428 @property
1429 def __mro__(self):
1430 return (object,)
1431
1432 class Base(object):
1433 foo = 3
1434
1435 class Something(Base, metaclass=Meta):
1436 pass
1437
1438 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1439 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1440
Michael Foorddcebe0f2011-03-15 19:20:44 -04001441 def test_dict_as_property(self):
1442 test = self
1443 test.called = False
1444
1445 class Foo(dict):
1446 a = 3
1447 @property
1448 def __dict__(self):
1449 test.called = True
1450 return {}
1451
1452 foo = Foo()
1453 foo.a = 4
1454 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1455 self.assertFalse(test.called)
1456
1457 def test_custom_object_dict(self):
1458 test = self
1459 test.called = False
1460
1461 class Custom(dict):
1462 def get(self, key, default=None):
1463 test.called = True
1464 super().get(key, default)
1465
1466 class Foo(object):
1467 a = 3
1468 foo = Foo()
1469 foo.__dict__ = Custom()
1470 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1471 self.assertFalse(test.called)
1472
1473 def test_metaclass_dict_as_property(self):
1474 class Meta(type):
1475 @property
1476 def __dict__(self):
1477 self.executed = True
1478
1479 class Thing(metaclass=Meta):
1480 executed = False
1481
1482 def __init__(self):
1483 self.spam = 42
1484
1485 instance = Thing()
1486 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1487 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001488
Michael Foorda51623b2011-12-18 22:01:40 +00001489 def test_module(self):
1490 sentinel = object()
1491 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1492 sentinel)
1493
Michael Foord3ba95f82011-12-22 01:13:37 +00001494 def test_metaclass_with_metaclass_with_dict_as_property(self):
1495 class MetaMeta(type):
1496 @property
1497 def __dict__(self):
1498 self.executed = True
1499 return dict(spam=42)
1500
1501 class Meta(type, metaclass=MetaMeta):
1502 executed = False
1503
1504 class Thing(metaclass=Meta):
1505 pass
1506
1507 with self.assertRaises(AttributeError):
1508 inspect.getattr_static(Thing, "spam")
1509 self.assertFalse(Thing.executed)
1510
Nick Coghlane0f04652010-11-21 03:44:04 +00001511class TestGetGeneratorState(unittest.TestCase):
1512
1513 def setUp(self):
1514 def number_generator():
1515 for number in range(5):
1516 yield number
1517 self.generator = number_generator()
1518
1519 def _generatorstate(self):
1520 return inspect.getgeneratorstate(self.generator)
1521
1522 def test_created(self):
1523 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1524
1525 def test_suspended(self):
1526 next(self.generator)
1527 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1528
1529 def test_closed_after_exhaustion(self):
1530 for i in self.generator:
1531 pass
1532 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1533
1534 def test_closed_after_immediate_exception(self):
1535 with self.assertRaises(RuntimeError):
1536 self.generator.throw(RuntimeError)
1537 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1538
1539 def test_running(self):
1540 # As mentioned on issue #10220, checking for the RUNNING state only
1541 # makes sense inside the generator itself.
1542 # The following generator checks for this by using the closure's
1543 # reference to self and the generator state checking helper method
1544 def running_check_generator():
1545 for number in range(5):
1546 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1547 yield number
1548 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1549 self.generator = running_check_generator()
1550 # Running up to the first yield
1551 next(self.generator)
1552 # Running after the first yield
1553 next(self.generator)
1554
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001555 def test_easy_debugging(self):
1556 # repr() and str() of a generator state should contain the state name
1557 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1558 for name in names:
1559 state = getattr(inspect, name)
1560 self.assertIn(name, repr(state))
1561 self.assertIn(name, str(state))
1562
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001563 def test_getgeneratorlocals(self):
1564 def each(lst, a=None):
1565 b=(1, 2, 3)
1566 for v in lst:
1567 if v == 3:
1568 c = 12
1569 yield v
1570
1571 numbers = each([1, 2, 3])
1572 self.assertEqual(inspect.getgeneratorlocals(numbers),
1573 {'a': None, 'lst': [1, 2, 3]})
1574 next(numbers)
1575 self.assertEqual(inspect.getgeneratorlocals(numbers),
1576 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1577 'b': (1, 2, 3)})
1578 next(numbers)
1579 self.assertEqual(inspect.getgeneratorlocals(numbers),
1580 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1581 'b': (1, 2, 3)})
1582 next(numbers)
1583 self.assertEqual(inspect.getgeneratorlocals(numbers),
1584 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1585 'b': (1, 2, 3), 'c': 12})
1586 try:
1587 next(numbers)
1588 except StopIteration:
1589 pass
1590 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1591
1592 def test_getgeneratorlocals_empty(self):
1593 def yield_one():
1594 yield 1
1595 one = yield_one()
1596 self.assertEqual(inspect.getgeneratorlocals(one), {})
1597 try:
1598 next(one)
1599 except StopIteration:
1600 pass
1601 self.assertEqual(inspect.getgeneratorlocals(one), {})
1602
1603 def test_getgeneratorlocals_error(self):
1604 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1605 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1606 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1607 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1608
Nick Coghlane0f04652010-11-21 03:44:04 +00001609
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001610class MySignature(inspect.Signature):
1611 # Top-level to make it picklable;
1612 # used in test_signature_object_pickle
1613 pass
1614
1615class MyParameter(inspect.Parameter):
1616 # Top-level to make it picklable;
1617 # used in test_signature_object_pickle
1618 pass
1619
1620
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001621class TestSignatureObject(unittest.TestCase):
1622 @staticmethod
1623 def signature(func):
1624 sig = inspect.signature(func)
1625 return (tuple((param.name,
1626 (... if param.default is param.empty else param.default),
1627 (... if param.annotation is param.empty
1628 else param.annotation),
1629 str(param.kind).lower())
1630 for param in sig.parameters.values()),
1631 (... if sig.return_annotation is sig.empty
1632 else sig.return_annotation))
1633
1634 def test_signature_object(self):
1635 S = inspect.Signature
1636 P = inspect.Parameter
1637
1638 self.assertEqual(str(S()), '()')
1639
Yury Selivanov07a9e452014-01-29 10:58:16 -05001640 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001641 pass
1642 sig = inspect.signature(test)
1643 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001644 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001645 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001646 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001647 args = sig.parameters['args']
1648 ko = sig.parameters['ko']
1649 kwargs = sig.parameters['kwargs']
1650
1651 S((po, pk, args, ko, kwargs))
1652
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001653 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001654 S((pk, po, args, ko, kwargs))
1655
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001656 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001657 S((po, args, pk, ko, kwargs))
1658
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001659 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001660 S((args, po, pk, 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, pk, args, kwargs, ko))
1664
1665 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001666 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001667 S((po, pk, args, kwargs2, ko))
1668
Yury Selivanov07a9e452014-01-29 10:58:16 -05001669 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1670 S((pod, po))
1671
1672 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1673 S((po, pkd, pk))
1674
1675 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1676 S((pkd, pk))
1677
Yury Selivanov374375d2014-03-27 12:41:53 -04001678 self.assertTrue(repr(sig).startswith('<Signature'))
1679 self.assertTrue('"(po, pk' in repr(sig))
1680
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001681 def test_signature_object_pickle(self):
1682 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
1683 foo_partial = functools.partial(foo, a=1)
1684
1685 sig = inspect.signature(foo_partial)
1686 self.assertTrue(sig.parameters['a']._partial_kwarg)
1687
1688 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1689 with self.subTest(pickle_ver=ver, subclass=False):
1690 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
1691 self.assertEqual(sig, sig_pickled)
1692 self.assertTrue(sig_pickled.parameters['a']._partial_kwarg)
1693
1694 # Test that basic sub-classing works
1695 sig = inspect.signature(foo)
1696 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
1697 myparams = collections.OrderedDict(sig.parameters, a=myparam)
1698 mysig = MySignature().replace(parameters=myparams.values(),
1699 return_annotation=sig.return_annotation)
1700 self.assertTrue(isinstance(mysig, MySignature))
1701 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
1702
1703 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1704 with self.subTest(pickle_ver=ver, subclass=True):
1705 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
1706 self.assertEqual(mysig, sig_pickled)
1707 self.assertTrue(isinstance(sig_pickled, MySignature))
1708 self.assertTrue(isinstance(sig_pickled.parameters['z'],
1709 MyParameter))
1710
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001711 def test_signature_immutability(self):
1712 def test(a):
1713 pass
1714 sig = inspect.signature(test)
1715
1716 with self.assertRaises(AttributeError):
1717 sig.foo = 'bar'
1718
1719 with self.assertRaises(TypeError):
1720 sig.parameters['a'] = None
1721
1722 def test_signature_on_noarg(self):
1723 def test():
1724 pass
1725 self.assertEqual(self.signature(test), ((), ...))
1726
1727 def test_signature_on_wargs(self):
1728 def test(a, b:'foo') -> 123:
1729 pass
1730 self.assertEqual(self.signature(test),
1731 ((('a', ..., ..., "positional_or_keyword"),
1732 ('b', ..., 'foo', "positional_or_keyword")),
1733 123))
1734
1735 def test_signature_on_wkwonly(self):
1736 def test(*, a:float, b:str) -> int:
1737 pass
1738 self.assertEqual(self.signature(test),
1739 ((('a', ..., float, "keyword_only"),
1740 ('b', ..., str, "keyword_only")),
1741 int))
1742
1743 def test_signature_on_complex_args(self):
1744 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1745 pass
1746 self.assertEqual(self.signature(test),
1747 ((('a', ..., ..., "positional_or_keyword"),
1748 ('b', 10, 'foo', "positional_or_keyword"),
1749 ('args', ..., 'bar', "var_positional"),
1750 ('spam', ..., 'baz', "keyword_only"),
1751 ('ham', 123, ..., "keyword_only"),
1752 ('kwargs', ..., int, "var_keyword")),
1753 ...))
1754
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001755 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001756 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1757 "Signature information for builtins requires docstrings")
1758 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001759 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001760
Larry Hastings5c661892014-01-24 06:17:25 -08001761 def test_unbound_method(o):
1762 """Use this to test unbound methods (things that should have a self)"""
1763 signature = inspect.signature(o)
1764 self.assertTrue(isinstance(signature, inspect.Signature))
1765 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1766 return signature
1767
1768 def test_callable(o):
1769 """Use this to test bound methods or normal callables (things that don't expect self)"""
1770 signature = inspect.signature(o)
1771 self.assertTrue(isinstance(signature, inspect.Signature))
1772 if signature.parameters:
1773 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1774 return signature
1775
1776 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001777 def p(name): return signature.parameters[name].default
1778 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001779 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001780 self.assertEqual(p('d'), 3.14)
1781 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001782 self.assertEqual(p('n'), None)
1783 self.assertEqual(p('t'), True)
1784 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001785 self.assertEqual(p('local'), 3)
1786 self.assertEqual(p('sys'), sys.maxsize)
1787 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001788
Larry Hastings5c661892014-01-24 06:17:25 -08001789 test_callable(object)
1790
1791 # normal method
1792 # (PyMethodDescr_Type, "method_descriptor")
1793 test_unbound_method(_pickle.Pickler.dump)
1794 d = _pickle.Pickler(io.StringIO())
1795 test_callable(d.dump)
1796
1797 # static method
1798 test_callable(str.maketrans)
1799 test_callable('abc'.maketrans)
1800
1801 # class method
1802 test_callable(dict.fromkeys)
1803 test_callable({}.fromkeys)
1804
1805 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1806 test_unbound_method(type.__call__)
1807 test_unbound_method(int.__add__)
1808 test_callable((3).__add__)
1809
1810 # _PyMethodWrapper_Type
1811 # support for 'method-wrapper'
1812 test_callable(min.__call__)
1813
Larry Hastings2623c8c2014-02-08 22:15:29 -08001814 # This doesn't work now.
1815 # (We don't have a valid signature for "type" in 3.4)
1816 with self.assertRaisesRegex(ValueError, "no signature found"):
1817 class ThisWorksNow:
1818 __call__ = type
1819 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08001820
Yury Selivanov056e2652014-03-02 12:25:27 -05001821 # Regression test for issue #20786
1822 test_unbound_method(dict.__delitem__)
1823 test_unbound_method(property.__delete__)
1824
1825
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001826 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05001827 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1828 "Signature information for builtins requires docstrings")
1829 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001830 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05001831 func = _testcapi.docstring_with_signature_with_defaults
1832
1833 def decorator(func):
1834 @functools.wraps(func)
1835 def wrapper(*args, **kwargs) -> int:
1836 return func(*args, **kwargs)
1837 return wrapper
1838
1839 decorated_func = decorator(func)
1840
1841 self.assertEqual(inspect.signature(func),
1842 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08001843
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001844 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08001845 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001846 import _testcapi
Larry Hastings5c661892014-01-24 06:17:25 -08001847 with self.assertRaisesRegex(ValueError, 'no signature found for builtin'):
1848 inspect.signature(_testcapi.docstring_no_signature)
1849
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001850 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001851 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001852 inspect.signature(42)
1853
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001854 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001855 inspect.Signature.from_function(42)
1856
Yury Selivanovb77511d2014-01-29 10:46:14 -05001857 def test_signature_from_builtin_errors(self):
1858 with self.assertRaisesRegex(TypeError, 'is not a Python builtin'):
1859 inspect.Signature.from_builtin(42)
1860
Yury Selivanov63da7c72014-01-31 14:48:37 -05001861 def test_signature_from_functionlike_object(self):
1862 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1863 pass
1864
1865 class funclike:
1866 # Has to be callable, and have correct
1867 # __code__, __annotations__, __defaults__, __name__,
1868 # and __kwdefaults__ attributes
1869
1870 def __init__(self, func):
1871 self.__name__ = func.__name__
1872 self.__code__ = func.__code__
1873 self.__annotations__ = func.__annotations__
1874 self.__defaults__ = func.__defaults__
1875 self.__kwdefaults__ = func.__kwdefaults__
1876 self.func = func
1877
1878 def __call__(self, *args, **kwargs):
1879 return self.func(*args, **kwargs)
1880
1881 sig_func = inspect.Signature.from_function(func)
1882
1883 sig_funclike = inspect.Signature.from_function(funclike(func))
1884 self.assertEqual(sig_funclike, sig_func)
1885
1886 sig_funclike = inspect.signature(funclike(func))
1887 self.assertEqual(sig_funclike, sig_func)
1888
1889 # If object is not a duck type of function, then
1890 # signature will try to get a signature for its '__call__'
1891 # method
1892 fl = funclike(func)
1893 del fl.__defaults__
1894 self.assertEqual(self.signature(fl),
1895 ((('args', ..., ..., "var_positional"),
1896 ('kwargs', ..., ..., "var_keyword")),
1897 ...))
1898
Yury Selivanova773de02014-02-21 18:30:53 -05001899 # Test with cython-like builtins:
1900 _orig_isdesc = inspect.ismethoddescriptor
1901 def _isdesc(obj):
1902 if hasattr(obj, '_builtinmock'):
1903 return True
1904 return _orig_isdesc(obj)
1905
1906 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
1907 builtin_func = funclike(func)
1908 # Make sure that our mock setup is working
1909 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
1910 builtin_func._builtinmock = True
1911 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
1912 self.assertEqual(inspect.signature(builtin_func), sig_func)
1913
Yury Selivanov63da7c72014-01-31 14:48:37 -05001914 def test_signature_functionlike_class(self):
1915 # We only want to duck type function-like objects,
1916 # not classes.
1917
1918 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1919 pass
1920
1921 class funclike:
1922 def __init__(self, marker):
1923 pass
1924
1925 __name__ = func.__name__
1926 __code__ = func.__code__
1927 __annotations__ = func.__annotations__
1928 __defaults__ = func.__defaults__
1929 __kwdefaults__ = func.__kwdefaults__
1930
1931 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1932 inspect.Signature.from_function(funclike)
1933
1934 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
1935
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001936 def test_signature_on_method(self):
1937 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05001938 def __init__(*args):
1939 pass
1940 def m1(self, arg1, arg2=1) -> int:
1941 pass
1942 def m2(*args):
1943 pass
1944 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001945 pass
1946
Yury Selivanov62560fb2014-01-28 12:26:24 -05001947 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001948 ((('arg1', ..., ..., "positional_or_keyword"),
1949 ('arg2', 1, ..., "positional_or_keyword")),
1950 int))
1951
Yury Selivanov62560fb2014-01-28 12:26:24 -05001952 self.assertEqual(self.signature(Test().m2),
1953 ((('args', ..., ..., "var_positional"),),
1954 ...))
1955
1956 self.assertEqual(self.signature(Test),
1957 ((('args', ..., ..., "var_positional"),),
1958 ...))
1959
1960 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
1961 self.signature(Test())
1962
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001963 def test_signature_on_classmethod(self):
1964 class Test:
1965 @classmethod
1966 def foo(cls, arg1, *, arg2=1):
1967 pass
1968
1969 meth = Test().foo
1970 self.assertEqual(self.signature(meth),
1971 ((('arg1', ..., ..., "positional_or_keyword"),
1972 ('arg2', 1, ..., "keyword_only")),
1973 ...))
1974
1975 meth = Test.foo
1976 self.assertEqual(self.signature(meth),
1977 ((('arg1', ..., ..., "positional_or_keyword"),
1978 ('arg2', 1, ..., "keyword_only")),
1979 ...))
1980
1981 def test_signature_on_staticmethod(self):
1982 class Test:
1983 @staticmethod
1984 def foo(cls, *, arg):
1985 pass
1986
1987 meth = Test().foo
1988 self.assertEqual(self.signature(meth),
1989 ((('cls', ..., ..., "positional_or_keyword"),
1990 ('arg', ..., ..., "keyword_only")),
1991 ...))
1992
1993 meth = Test.foo
1994 self.assertEqual(self.signature(meth),
1995 ((('cls', ..., ..., "positional_or_keyword"),
1996 ('arg', ..., ..., "keyword_only")),
1997 ...))
1998
1999 def test_signature_on_partial(self):
2000 from functools import partial
2001
2002 def test():
2003 pass
2004
2005 self.assertEqual(self.signature(partial(test)), ((), ...))
2006
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002007 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002008 inspect.signature(partial(test, 1))
2009
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002010 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002011 inspect.signature(partial(test, a=1))
2012
2013 def test(a, b, *, c, d):
2014 pass
2015
2016 self.assertEqual(self.signature(partial(test)),
2017 ((('a', ..., ..., "positional_or_keyword"),
2018 ('b', ..., ..., "positional_or_keyword"),
2019 ('c', ..., ..., "keyword_only"),
2020 ('d', ..., ..., "keyword_only")),
2021 ...))
2022
2023 self.assertEqual(self.signature(partial(test, 1)),
2024 ((('b', ..., ..., "positional_or_keyword"),
2025 ('c', ..., ..., "keyword_only"),
2026 ('d', ..., ..., "keyword_only")),
2027 ...))
2028
2029 self.assertEqual(self.signature(partial(test, 1, c=2)),
2030 ((('b', ..., ..., "positional_or_keyword"),
2031 ('c', 2, ..., "keyword_only"),
2032 ('d', ..., ..., "keyword_only")),
2033 ...))
2034
2035 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2036 ((('a', ..., ..., "positional_or_keyword"),
2037 ('b', 1, ..., "positional_or_keyword"),
2038 ('c', 2, ..., "keyword_only"),
2039 ('d', ..., ..., "keyword_only")),
2040 ...))
2041
2042 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
2043 ((('b', 1, ..., "positional_or_keyword"),
2044 ('c', 2, ..., "keyword_only"),
2045 ('d', ..., ..., "keyword_only"),),
2046 ...))
2047
2048 def test(a, *args, b, **kwargs):
2049 pass
2050
2051 self.assertEqual(self.signature(partial(test, 1)),
2052 ((('args', ..., ..., "var_positional"),
2053 ('b', ..., ..., "keyword_only"),
2054 ('kwargs', ..., ..., "var_keyword")),
2055 ...))
2056
2057 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2058 ((('args', ..., ..., "var_positional"),
2059 ('b', ..., ..., "keyword_only"),
2060 ('kwargs', ..., ..., "var_keyword")),
2061 ...))
2062
2063
2064 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2065 ((('args', ..., ..., "var_positional"),
2066 ('b', ..., ..., "keyword_only"),
2067 ('kwargs', ..., ..., "var_keyword")),
2068 ...))
2069
2070 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2071 ((('args', ..., ..., "var_positional"),
2072 ('b', 0, ..., "keyword_only"),
2073 ('kwargs', ..., ..., "var_keyword")),
2074 ...))
2075
2076 self.assertEqual(self.signature(partial(test, b=0)),
2077 ((('a', ..., ..., "positional_or_keyword"),
2078 ('args', ..., ..., "var_positional"),
2079 ('b', 0, ..., "keyword_only"),
2080 ('kwargs', ..., ..., "var_keyword")),
2081 ...))
2082
2083 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2084 ((('a', ..., ..., "positional_or_keyword"),
2085 ('args', ..., ..., "var_positional"),
2086 ('b', 0, ..., "keyword_only"),
2087 ('kwargs', ..., ..., "var_keyword")),
2088 ...))
2089
2090 def test(a, b, c:int) -> 42:
2091 pass
2092
2093 sig = test.__signature__ = inspect.signature(test)
2094
2095 self.assertEqual(self.signature(partial(partial(test, 1))),
2096 ((('b', ..., ..., "positional_or_keyword"),
2097 ('c', ..., int, "positional_or_keyword")),
2098 42))
2099
2100 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2101 ((('c', ..., int, "positional_or_keyword"),),
2102 42))
2103
2104 psig = inspect.signature(partial(partial(test, 1), 2))
2105
2106 def foo(a):
2107 return a
2108 _foo = partial(partial(foo, a=10), a=20)
2109 self.assertEqual(self.signature(_foo),
2110 ((('a', 20, ..., "positional_or_keyword"),),
2111 ...))
2112 # check that we don't have any side-effects in signature(),
2113 # and the partial object is still functioning
2114 self.assertEqual(_foo(), 20)
2115
2116 def foo(a, b, c):
2117 return a, b, c
2118 _foo = partial(partial(foo, 1, b=20), b=30)
2119 self.assertEqual(self.signature(_foo),
2120 ((('b', 30, ..., "positional_or_keyword"),
2121 ('c', ..., ..., "positional_or_keyword")),
2122 ...))
2123 self.assertEqual(_foo(c=10), (1, 30, 10))
2124 _foo = partial(_foo, 2) # now 'b' has two values -
2125 # positional and keyword
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002126 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002127 inspect.signature(_foo)
2128
2129 def foo(a, b, c, *, d):
2130 return a, b, c, d
2131 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2132 self.assertEqual(self.signature(_foo),
2133 ((('a', ..., ..., "positional_or_keyword"),
2134 ('b', 10, ..., "positional_or_keyword"),
2135 ('c', 20, ..., "positional_or_keyword"),
2136 ('d', 30, ..., "keyword_only")),
2137 ...))
2138 ba = inspect.signature(_foo).bind(a=200, b=11)
2139 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2140
2141 def foo(a=1, b=2, c=3):
2142 return a, b, c
2143 _foo = partial(foo, a=10, c=13)
2144 ba = inspect.signature(_foo).bind(11)
2145 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
2146 ba = inspect.signature(_foo).bind(11, 12)
2147 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
2148 ba = inspect.signature(_foo).bind(11, b=12)
2149 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
2150 ba = inspect.signature(_foo).bind(b=12)
2151 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
2152 _foo = partial(_foo, b=10)
2153 ba = inspect.signature(_foo).bind(12, 14)
2154 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
2155
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002156 def test_signature_on_partialmethod(self):
2157 from functools import partialmethod
2158
2159 class Spam:
2160 def test():
2161 pass
2162 ham = partialmethod(test)
2163
2164 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2165 inspect.signature(Spam.ham)
2166
2167 class Spam:
2168 def test(it, a, *, c) -> 'spam':
2169 pass
2170 ham = partialmethod(test, c=1)
2171
2172 self.assertEqual(self.signature(Spam.ham),
2173 ((('it', ..., ..., 'positional_or_keyword'),
2174 ('a', ..., ..., 'positional_or_keyword'),
2175 ('c', 1, ..., 'keyword_only')),
2176 'spam'))
2177
2178 self.assertEqual(self.signature(Spam().ham),
2179 ((('a', ..., ..., 'positional_or_keyword'),
2180 ('c', 1, ..., 'keyword_only')),
2181 'spam'))
2182
Yury Selivanov0486f812014-01-29 12:18:59 -05002183 def test_signature_on_fake_partialmethod(self):
2184 def foo(a): pass
2185 foo._partialmethod = 'spam'
2186 self.assertEqual(str(inspect.signature(foo)), '(a)')
2187
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002188 def test_signature_on_decorated(self):
2189 import functools
2190
2191 def decorator(func):
2192 @functools.wraps(func)
2193 def wrapper(*args, **kwargs) -> int:
2194 return func(*args, **kwargs)
2195 return wrapper
2196
2197 class Foo:
2198 @decorator
2199 def bar(self, a, b):
2200 pass
2201
2202 self.assertEqual(self.signature(Foo.bar),
2203 ((('self', ..., ..., "positional_or_keyword"),
2204 ('a', ..., ..., "positional_or_keyword"),
2205 ('b', ..., ..., "positional_or_keyword")),
2206 ...))
2207
2208 self.assertEqual(self.signature(Foo().bar),
2209 ((('a', ..., ..., "positional_or_keyword"),
2210 ('b', ..., ..., "positional_or_keyword")),
2211 ...))
2212
2213 # Test that we handle method wrappers correctly
2214 def decorator(func):
2215 @functools.wraps(func)
2216 def wrapper(*args, **kwargs) -> int:
2217 return func(42, *args, **kwargs)
2218 sig = inspect.signature(func)
2219 new_params = tuple(sig.parameters.values())[1:]
2220 wrapper.__signature__ = sig.replace(parameters=new_params)
2221 return wrapper
2222
2223 class Foo:
2224 @decorator
2225 def __call__(self, a, b):
2226 pass
2227
2228 self.assertEqual(self.signature(Foo.__call__),
2229 ((('a', ..., ..., "positional_or_keyword"),
2230 ('b', ..., ..., "positional_or_keyword")),
2231 ...))
2232
2233 self.assertEqual(self.signature(Foo().__call__),
2234 ((('b', ..., ..., "positional_or_keyword"),),
2235 ...))
2236
Nick Coghlane8c45d62013-07-28 20:00:01 +10002237 # Test we handle __signature__ partway down the wrapper stack
2238 def wrapped_foo_call():
2239 pass
2240 wrapped_foo_call.__wrapped__ = Foo.__call__
2241
2242 self.assertEqual(self.signature(wrapped_foo_call),
2243 ((('a', ..., ..., "positional_or_keyword"),
2244 ('b', ..., ..., "positional_or_keyword")),
2245 ...))
2246
2247
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002248 def test_signature_on_class(self):
2249 class C:
2250 def __init__(self, a):
2251 pass
2252
2253 self.assertEqual(self.signature(C),
2254 ((('a', ..., ..., "positional_or_keyword"),),
2255 ...))
2256
2257 class CM(type):
2258 def __call__(cls, a):
2259 pass
2260 class C(metaclass=CM):
2261 def __init__(self, b):
2262 pass
2263
2264 self.assertEqual(self.signature(C),
2265 ((('a', ..., ..., "positional_or_keyword"),),
2266 ...))
2267
2268 class CM(type):
2269 def __new__(mcls, name, bases, dct, *, foo=1):
2270 return super().__new__(mcls, name, bases, dct)
2271 class C(metaclass=CM):
2272 def __init__(self, b):
2273 pass
2274
2275 self.assertEqual(self.signature(C),
2276 ((('b', ..., ..., "positional_or_keyword"),),
2277 ...))
2278
2279 self.assertEqual(self.signature(CM),
2280 ((('name', ..., ..., "positional_or_keyword"),
2281 ('bases', ..., ..., "positional_or_keyword"),
2282 ('dct', ..., ..., "positional_or_keyword"),
2283 ('foo', 1, ..., "keyword_only")),
2284 ...))
2285
2286 class CMM(type):
2287 def __new__(mcls, name, bases, dct, *, foo=1):
2288 return super().__new__(mcls, name, bases, dct)
2289 def __call__(cls, nm, bs, dt):
2290 return type(nm, bs, dt)
2291 class CM(type, metaclass=CMM):
2292 def __new__(mcls, name, bases, dct, *, bar=2):
2293 return super().__new__(mcls, name, bases, dct)
2294 class C(metaclass=CM):
2295 def __init__(self, b):
2296 pass
2297
2298 self.assertEqual(self.signature(CMM),
2299 ((('name', ..., ..., "positional_or_keyword"),
2300 ('bases', ..., ..., "positional_or_keyword"),
2301 ('dct', ..., ..., "positional_or_keyword"),
2302 ('foo', 1, ..., "keyword_only")),
2303 ...))
2304
2305 self.assertEqual(self.signature(CM),
2306 ((('nm', ..., ..., "positional_or_keyword"),
2307 ('bs', ..., ..., "positional_or_keyword"),
2308 ('dt', ..., ..., "positional_or_keyword")),
2309 ...))
2310
2311 self.assertEqual(self.signature(C),
2312 ((('b', ..., ..., "positional_or_keyword"),),
2313 ...))
2314
2315 class CM(type):
2316 def __init__(cls, name, bases, dct, *, bar=2):
2317 return super().__init__(name, bases, dct)
2318 class C(metaclass=CM):
2319 def __init__(self, b):
2320 pass
2321
2322 self.assertEqual(self.signature(CM),
2323 ((('name', ..., ..., "positional_or_keyword"),
2324 ('bases', ..., ..., "positional_or_keyword"),
2325 ('dct', ..., ..., "positional_or_keyword"),
2326 ('bar', 2, ..., "keyword_only")),
2327 ...))
2328
Yury Selivanov145dff82014-02-01 13:49:29 -05002329 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2330 "Signature information for builtins requires docstrings")
2331 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002332 # Test classes without user-defined __init__ or __new__
2333 class C: pass
2334 self.assertEqual(str(inspect.signature(C)), '()')
2335 class D(C): pass
2336 self.assertEqual(str(inspect.signature(D)), '()')
2337
2338 # Test meta-classes without user-defined __init__ or __new__
2339 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002340 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002341 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2342 self.assertEqual(inspect.signature(C), None)
2343 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2344 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002345
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002346 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2347 "Signature information for builtins requires docstrings")
2348 def test_signature_on_builtin_class(self):
2349 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2350 '(file, protocol=None, fix_imports=True)')
2351
2352 class P(_pickle.Pickler): pass
2353 class EmptyTrait: pass
2354 class P2(EmptyTrait, P): pass
2355 self.assertEqual(str(inspect.signature(P)),
2356 '(file, protocol=None, fix_imports=True)')
2357 self.assertEqual(str(inspect.signature(P2)),
2358 '(file, protocol=None, fix_imports=True)')
2359
2360 class P3(P2):
2361 def __init__(self, spam):
2362 pass
2363 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2364
2365 class MetaP(type):
2366 def __call__(cls, foo, bar):
2367 pass
2368 class P4(P2, metaclass=MetaP):
2369 pass
2370 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2371
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002372 def test_signature_on_callable_objects(self):
2373 class Foo:
2374 def __call__(self, a):
2375 pass
2376
2377 self.assertEqual(self.signature(Foo()),
2378 ((('a', ..., ..., "positional_or_keyword"),),
2379 ...))
2380
2381 class Spam:
2382 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002383 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002384 inspect.signature(Spam())
2385
2386 class Bar(Spam, Foo):
2387 pass
2388
2389 self.assertEqual(self.signature(Bar()),
2390 ((('a', ..., ..., "positional_or_keyword"),),
2391 ...))
2392
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002393 class Wrapped:
2394 pass
2395 Wrapped.__wrapped__ = lambda a: None
2396 self.assertEqual(self.signature(Wrapped),
2397 ((('a', ..., ..., "positional_or_keyword"),),
2398 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002399 # wrapper loop:
2400 Wrapped.__wrapped__ = Wrapped
2401 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2402 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002403
2404 def test_signature_on_lambdas(self):
2405 self.assertEqual(self.signature((lambda a=10: a)),
2406 ((('a', 10, ..., "positional_or_keyword"),),
2407 ...))
2408
2409 def test_signature_equality(self):
2410 def foo(a, *, b:int) -> float: pass
2411 self.assertNotEqual(inspect.signature(foo), 42)
2412
2413 def bar(a, *, b:int) -> float: pass
2414 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2415
2416 def bar(a, *, b:int) -> int: pass
2417 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2418
2419 def bar(a, *, b:int): pass
2420 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2421
2422 def bar(a, *, b:int=42) -> float: pass
2423 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2424
2425 def bar(a, *, c) -> float: pass
2426 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2427
2428 def bar(a, b:int) -> float: pass
2429 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2430 def spam(b:int, a) -> float: pass
2431 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
2432
2433 def foo(*, a, b, c): pass
2434 def bar(*, c, b, a): pass
2435 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2436
2437 def foo(*, a=1, b, c): pass
2438 def bar(*, c, b, a=1): pass
2439 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2440
2441 def foo(pos, *, a=1, b, c): pass
2442 def bar(pos, *, c, b, a=1): pass
2443 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2444
2445 def foo(pos, *, a, b, c): pass
2446 def bar(pos, *, c, b, a=1): pass
2447 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2448
2449 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2450 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2451 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2452
2453 def test_signature_unhashable(self):
2454 def foo(a): pass
2455 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002456 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002457 hash(sig)
2458
2459 def test_signature_str(self):
2460 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2461 pass
2462 self.assertEqual(str(inspect.signature(foo)),
2463 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2464
2465 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2466 pass
2467 self.assertEqual(str(inspect.signature(foo)),
2468 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2469
2470 def foo():
2471 pass
2472 self.assertEqual(str(inspect.signature(foo)), '()')
2473
2474 def test_signature_str_positional_only(self):
2475 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002476 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002477
2478 def test(a_po, *, b, **kwargs):
2479 return a_po, kwargs
2480
2481 sig = inspect.signature(test)
2482 new_params = list(sig.parameters.values())
2483 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2484 test.__signature__ = sig.replace(parameters=new_params)
2485
2486 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002487 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002488
Yury Selivanov2393dca2014-01-27 15:07:58 -05002489 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2490 '(foo, /)')
2491
2492 self.assertEqual(str(S(parameters=[
2493 P('foo', P.POSITIONAL_ONLY),
2494 P('bar', P.VAR_KEYWORD)])),
2495 '(foo, /, **bar)')
2496
2497 self.assertEqual(str(S(parameters=[
2498 P('foo', P.POSITIONAL_ONLY),
2499 P('bar', P.VAR_POSITIONAL)])),
2500 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002501
2502 def test_signature_replace_anno(self):
2503 def test() -> 42:
2504 pass
2505
2506 sig = inspect.signature(test)
2507 sig = sig.replace(return_annotation=None)
2508 self.assertIs(sig.return_annotation, None)
2509 sig = sig.replace(return_annotation=sig.empty)
2510 self.assertIs(sig.return_annotation, sig.empty)
2511 sig = sig.replace(return_annotation=42)
2512 self.assertEqual(sig.return_annotation, 42)
2513 self.assertEqual(sig, inspect.signature(test))
2514
Yury Selivanov34ce99f2014-02-18 12:49:41 -05002515 def test_signature_on_mangled_parameters(self):
2516 class Spam:
2517 def foo(self, __p1:1=2, *, __p2:2=3):
2518 pass
2519 class Ham(Spam):
2520 pass
2521
2522 self.assertEqual(self.signature(Spam.foo),
2523 ((('self', ..., ..., "positional_or_keyword"),
2524 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2525 ('_Spam__p2', 3, 2, "keyword_only")),
2526 ...))
2527
2528 self.assertEqual(self.signature(Spam.foo),
2529 self.signature(Ham.foo))
2530
Yury Selivanovda396452014-03-27 12:09:24 -04002531 def test_signature_from_callable_python_obj(self):
2532 class MySignature(inspect.Signature): pass
2533 def foo(a, *, b:1): pass
2534 foo_sig = MySignature.from_callable(foo)
2535 self.assertTrue(isinstance(foo_sig, MySignature))
2536
2537 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2538 "Signature information for builtins requires docstrings")
2539 def test_signature_from_callable_builtin_obj(self):
2540 class MySignature(inspect.Signature): pass
2541 sig = MySignature.from_callable(_pickle.Pickler)
2542 self.assertTrue(isinstance(sig, MySignature))
2543
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002544
2545class TestParameterObject(unittest.TestCase):
2546 def test_signature_parameter_kinds(self):
2547 P = inspect.Parameter
2548 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2549 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2550
2551 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2552 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2553
2554 def test_signature_parameter_object(self):
2555 p = inspect.Parameter('foo', default=10,
2556 kind=inspect.Parameter.POSITIONAL_ONLY)
2557 self.assertEqual(p.name, 'foo')
2558 self.assertEqual(p.default, 10)
2559 self.assertIs(p.annotation, p.empty)
2560 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2561
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002562 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002563 inspect.Parameter('foo', default=10, kind='123')
2564
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002565 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002566 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2567
Yury Selivanov2393dca2014-01-27 15:07:58 -05002568 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002569 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2570
Yury Selivanov2393dca2014-01-27 15:07:58 -05002571 with self.assertRaisesRegex(ValueError,
2572 'is not a valid parameter name'):
2573 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2574
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002575 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002576 inspect.Parameter('a', default=42,
2577 kind=inspect.Parameter.VAR_KEYWORD)
2578
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002579 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002580 inspect.Parameter('a', default=42,
2581 kind=inspect.Parameter.VAR_POSITIONAL)
2582
2583 p = inspect.Parameter('a', default=42,
2584 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002585 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002586 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2587
2588 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04002589 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002590
2591 def test_signature_parameter_equality(self):
2592 P = inspect.Parameter
2593 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2594
2595 self.assertEqual(p, p)
2596 self.assertNotEqual(p, 42)
2597
2598 self.assertEqual(p, P('foo', default=42,
2599 kind=inspect.Parameter.KEYWORD_ONLY))
2600
2601 def test_signature_parameter_unhashable(self):
2602 p = inspect.Parameter('foo', default=42,
2603 kind=inspect.Parameter.KEYWORD_ONLY)
2604
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002605 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002606 hash(p)
2607
2608 def test_signature_parameter_replace(self):
2609 p = inspect.Parameter('foo', default=42,
2610 kind=inspect.Parameter.KEYWORD_ONLY)
2611
2612 self.assertIsNot(p, p.replace())
2613 self.assertEqual(p, p.replace())
2614
2615 p2 = p.replace(annotation=1)
2616 self.assertEqual(p2.annotation, 1)
2617 p2 = p2.replace(annotation=p2.empty)
2618 self.assertEqual(p, p2)
2619
2620 p2 = p2.replace(name='bar')
2621 self.assertEqual(p2.name, 'bar')
2622 self.assertNotEqual(p2, p)
2623
Yury Selivanov2393dca2014-01-27 15:07:58 -05002624 with self.assertRaisesRegex(ValueError,
2625 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002626 p2 = p2.replace(name=p2.empty)
2627
2628 p2 = p2.replace(name='foo', default=None)
2629 self.assertIs(p2.default, None)
2630 self.assertNotEqual(p2, p)
2631
2632 p2 = p2.replace(name='foo', default=p2.empty)
2633 self.assertIs(p2.default, p2.empty)
2634
2635
2636 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2637 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2638 self.assertNotEqual(p2, p)
2639
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002640 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002641 p2 = p2.replace(kind=p2.empty)
2642
2643 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2644 self.assertEqual(p2, p)
2645
2646 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002647 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2648 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002649
2650 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002651 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002652
2653 with self.assertRaises(AttributeError):
2654 p.foo = 'bar'
2655
2656 with self.assertRaises(AttributeError):
2657 p.kind = 123
2658
2659
2660class TestSignatureBind(unittest.TestCase):
2661 @staticmethod
2662 def call(func, *args, **kwargs):
2663 sig = inspect.signature(func)
2664 ba = sig.bind(*args, **kwargs)
2665 return func(*ba.args, **ba.kwargs)
2666
2667 def test_signature_bind_empty(self):
2668 def test():
2669 return 42
2670
2671 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002672 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002673 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002674 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002675 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002676 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002677 self.call(test, spam=1)
2678
2679 def test_signature_bind_var(self):
2680 def test(*args, **kwargs):
2681 return args, kwargs
2682
2683 self.assertEqual(self.call(test), ((), {}))
2684 self.assertEqual(self.call(test, 1), ((1,), {}))
2685 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2686 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2687 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2688 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2689 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2690 ((1, 2), {'foo': 'bar'}))
2691
2692 def test_signature_bind_just_args(self):
2693 def test(a, b, c):
2694 return a, b, c
2695
2696 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2697
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002698 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002699 self.call(test, 1, 2, 3, 4)
2700
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002701 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002702 self.call(test, 1)
2703
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002704 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002705 self.call(test)
2706
2707 def test(a, b, c=10):
2708 return a, b, c
2709 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2710 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2711
2712 def test(a=1, b=2, c=3):
2713 return a, b, c
2714 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2715 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2716 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2717
2718 def test_signature_bind_varargs_order(self):
2719 def test(*args):
2720 return args
2721
2722 self.assertEqual(self.call(test), ())
2723 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2724
2725 def test_signature_bind_args_and_varargs(self):
2726 def test(a, b, c=3, *args):
2727 return a, b, c, args
2728
2729 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2730 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2731 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2732 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2733
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002734 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002735 "multiple values for argument 'c'"):
2736 self.call(test, 1, 2, 3, c=4)
2737
2738 def test_signature_bind_just_kwargs(self):
2739 def test(**kwargs):
2740 return kwargs
2741
2742 self.assertEqual(self.call(test), {})
2743 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2744 {'foo': 'bar', 'spam': 'ham'})
2745
2746 def test_signature_bind_args_and_kwargs(self):
2747 def test(a, b, c=3, **kwargs):
2748 return a, b, c, kwargs
2749
2750 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2751 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2752 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2753 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2754 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2755 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2756 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2757 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2758 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2759 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2760 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2761 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2762 (1, 2, 4, {'foo': 'bar'}))
2763 self.assertEqual(self.call(test, c=5, a=4, b=3),
2764 (4, 3, 5, {}))
2765
2766 def test_signature_bind_kwonly(self):
2767 def test(*, foo):
2768 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002769 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002770 'too many positional arguments'):
2771 self.call(test, 1)
2772 self.assertEqual(self.call(test, foo=1), 1)
2773
2774 def test(a, *, foo=1, bar):
2775 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002776 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002777 "'bar' parameter lacking default value"):
2778 self.call(test, 1)
2779
2780 def test(foo, *, bar):
2781 return foo, bar
2782 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2783 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2784
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002785 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002786 'too many keyword arguments'):
2787 self.call(test, bar=2, foo=1, spam=10)
2788
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002789 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002790 'too many positional arguments'):
2791 self.call(test, 1, 2)
2792
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002793 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002794 'too many positional arguments'):
2795 self.call(test, 1, 2, bar=2)
2796
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002797 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002798 'too many keyword arguments'):
2799 self.call(test, 1, bar=2, spam='ham')
2800
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002801 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002802 "'bar' parameter lacking default value"):
2803 self.call(test, 1)
2804
2805 def test(foo, *, bar, **bin):
2806 return foo, bar, bin
2807 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2808 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2809 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2810 (1, 2, {'spam': 'ham'}))
2811 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2812 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002813 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002814 "'foo' parameter lacking default value"):
2815 self.call(test, spam='ham', bar=2)
2816 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2817 (1, 2, {'bin': 1, 'spam': 10}))
2818
2819 def test_signature_bind_arguments(self):
2820 def test(a, *args, b, z=100, **kwargs):
2821 pass
2822 sig = inspect.signature(test)
2823 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2824 # we won't have 'z' argument in the bound arguments object, as we didn't
2825 # pass it to the 'bind'
2826 self.assertEqual(tuple(ba.arguments.items()),
2827 (('a', 10), ('args', (20,)), ('b', 30),
2828 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2829 self.assertEqual(ba.kwargs,
2830 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2831 self.assertEqual(ba.args, (10, 20))
2832
2833 def test_signature_bind_positional_only(self):
2834 P = inspect.Parameter
2835
2836 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2837 return a_po, b_po, c_po, foo, bar, kwargs
2838
2839 sig = inspect.signature(test)
2840 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2841 for name in ('a_po', 'b_po', 'c_po'):
2842 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2843 new_sig = sig.replace(parameters=new_params.values())
2844 test.__signature__ = new_sig
2845
2846 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2847 (1, 2, 4, 5, 6, {}))
2848
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002849 self.assertEqual(self.call(test, 1, 2),
2850 (1, 2, 3, 42, 50, {}))
2851
2852 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
2853 (1, 2, 3, 4, 5, {}))
2854
2855 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
2856 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
2857
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002858 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002859 self.call(test, 1, 2, c_po=4)
2860
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002861 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002862 self.call(test, a_po=1, b_po=2)
2863
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002864 def test_signature_bind_with_self_arg(self):
2865 # Issue #17071: one of the parameters is named "self
2866 def test(a, self, b):
2867 pass
2868 sig = inspect.signature(test)
2869 ba = sig.bind(1, 2, 3)
2870 self.assertEqual(ba.args, (1, 2, 3))
2871 ba = sig.bind(1, self=2, b=3)
2872 self.assertEqual(ba.args, (1, 2, 3))
2873
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002874 def test_signature_bind_vararg_name(self):
2875 def test(a, *args):
2876 return a, args
2877 sig = inspect.signature(test)
2878
2879 with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
2880 sig.bind(a=0, args=1)
2881
2882 def test(*args, **kwargs):
2883 return args, kwargs
2884 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
2885
2886 sig = inspect.signature(test)
2887 ba = sig.bind(args=1)
2888 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
2889
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002890
2891class TestBoundArguments(unittest.TestCase):
2892 def test_signature_bound_arguments_unhashable(self):
2893 def foo(a): pass
2894 ba = inspect.signature(foo).bind(1)
2895
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002896 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002897 hash(ba)
2898
2899 def test_signature_bound_arguments_equality(self):
2900 def foo(a): pass
2901 ba = inspect.signature(foo).bind(1)
2902 self.assertEqual(ba, ba)
2903
2904 ba2 = inspect.signature(foo).bind(1)
2905 self.assertEqual(ba, ba2)
2906
2907 ba3 = inspect.signature(foo).bind(2)
2908 self.assertNotEqual(ba, ba3)
2909 ba3.arguments['a'] = 1
2910 self.assertEqual(ba, ba3)
2911
2912 def bar(b): pass
2913 ba4 = inspect.signature(bar).bind(1)
2914 self.assertNotEqual(ba, ba4)
2915
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002916 def test_signature_bound_arguments_pickle(self):
2917 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2918 sig = inspect.signature(foo)
2919 ba = sig.bind(20, 30, z={})
2920
2921 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2922 with self.subTest(pickle_ver=ver):
2923 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
2924 self.assertEqual(ba, ba_pickled)
2925
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002926
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002927class TestSignaturePrivateHelpers(unittest.TestCase):
2928 def test_signature_get_bound_param(self):
2929 getter = inspect._signature_get_bound_param
2930
2931 self.assertEqual(getter('($self)'), 'self')
2932 self.assertEqual(getter('($self, obj)'), 'self')
2933 self.assertEqual(getter('($cls, /, obj)'), 'cls')
2934
Larry Hastings2623c8c2014-02-08 22:15:29 -08002935 def _strip_non_python_syntax(self, input,
2936 clean_signature, self_parameter, last_positional_only):
2937 computed_clean_signature, \
2938 computed_self_parameter, \
2939 computed_last_positional_only = \
2940 inspect._signature_strip_non_python_syntax(input)
2941 self.assertEqual(computed_clean_signature, clean_signature)
2942 self.assertEqual(computed_self_parameter, self_parameter)
2943 self.assertEqual(computed_last_positional_only, last_positional_only)
2944
2945 def test_signature_strip_non_python_syntax(self):
2946 self._strip_non_python_syntax(
2947 "($module, /, path, mode, *, dir_fd=None, " +
2948 "effective_ids=False,\n follow_symlinks=True)",
2949 "(module, path, mode, *, dir_fd=None, " +
2950 "effective_ids=False, follow_symlinks=True)",
2951 0,
2952 0)
2953
2954 self._strip_non_python_syntax(
2955 "($module, word, salt, /)",
2956 "(module, word, salt)",
2957 0,
2958 2)
2959
2960 self._strip_non_python_syntax(
2961 "(x, y=None, z=None, /)",
2962 "(x, y=None, z=None)",
2963 None,
2964 2)
2965
2966 self._strip_non_python_syntax(
2967 "(x, y=None, z=None)",
2968 "(x, y=None, z=None)",
2969 None,
2970 None)
2971
2972 self._strip_non_python_syntax(
2973 "(x,\n y=None,\n z = None )",
2974 "(x, y=None, z=None)",
2975 None,
2976 None)
2977
2978 self._strip_non_python_syntax(
2979 "",
2980 "",
2981 None,
2982 None)
2983
2984 self._strip_non_python_syntax(
2985 None,
2986 None,
2987 None,
2988 None)
2989
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002990
Nick Coghlane8c45d62013-07-28 20:00:01 +10002991class TestUnwrap(unittest.TestCase):
2992
2993 def test_unwrap_one(self):
2994 def func(a, b):
2995 return a + b
2996 wrapper = functools.lru_cache(maxsize=20)(func)
2997 self.assertIs(inspect.unwrap(wrapper), func)
2998
2999 def test_unwrap_several(self):
3000 def func(a, b):
3001 return a + b
3002 wrapper = func
3003 for __ in range(10):
3004 @functools.wraps(wrapper)
3005 def wrapper():
3006 pass
3007 self.assertIsNot(wrapper.__wrapped__, func)
3008 self.assertIs(inspect.unwrap(wrapper), func)
3009
3010 def test_stop(self):
3011 def func1(a, b):
3012 return a + b
3013 @functools.wraps(func1)
3014 def func2():
3015 pass
3016 @functools.wraps(func2)
3017 def wrapper():
3018 pass
3019 func2.stop_here = 1
3020 unwrapped = inspect.unwrap(wrapper,
3021 stop=(lambda f: hasattr(f, "stop_here")))
3022 self.assertIs(unwrapped, func2)
3023
3024 def test_cycle(self):
3025 def func1(): pass
3026 func1.__wrapped__ = func1
3027 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3028 inspect.unwrap(func1)
3029
3030 def func2(): pass
3031 func2.__wrapped__ = func1
3032 func1.__wrapped__ = func2
3033 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3034 inspect.unwrap(func1)
3035 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3036 inspect.unwrap(func2)
3037
3038 def test_unhashable(self):
3039 def func(): pass
3040 func.__wrapped__ = None
3041 class C:
3042 __hash__ = None
3043 __wrapped__ = func
3044 self.assertIsNone(inspect.unwrap(C()))
3045
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003046class TestMain(unittest.TestCase):
3047 def test_only_source(self):
3048 module = importlib.import_module('unittest')
3049 rc, out, err = assert_python_ok('-m', 'inspect',
3050 'unittest')
3051 lines = out.decode().splitlines()
3052 # ignore the final newline
3053 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3054 self.assertEqual(err, b'')
3055
Brett Cannon634a8fc2013-10-02 10:25:42 -04003056 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003057 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003058 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003059 rc, out, err = assert_python_ok('-m', 'inspect',
3060 'concurrent.futures:ThreadPoolExecutor')
3061 lines = out.decode().splitlines()
3062 # ignore the final newline
3063 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003064 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003065 self.assertEqual(err, b'')
3066
3067 def test_builtins(self):
3068 module = importlib.import_module('unittest')
3069 _, out, err = assert_python_failure('-m', 'inspect',
3070 'sys')
3071 lines = err.decode().splitlines()
3072 self.assertEqual(lines, ["Can't get info for builtin modules."])
3073
3074 def test_details(self):
3075 module = importlib.import_module('unittest')
3076 rc, out, err = assert_python_ok('-m', 'inspect',
3077 'unittest', '--details')
3078 output = out.decode()
3079 # Just a quick sanity check on the output
3080 self.assertIn(module.__name__, output)
3081 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02003082 if not sys.flags.optimize:
3083 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003084 self.assertEqual(err, b'')
3085
3086
3087
Nick Coghlane8c45d62013-07-28 20:00:01 +10003088
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003089def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003090 run_unittest(
3091 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3092 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3093 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003094 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003095 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003096 TestBoundArguments, TestSignaturePrivateHelpers, TestGetClosureVars,
3097 TestUnwrap, TestMain
Michael Foord95fc51d2010-11-20 15:07:30 +00003098 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003099
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003100if __name__ == "__main__":
3101 test_main()