blob: 95b88779f98c57ec423daa48105d98e4db2f30f3 [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
1211class TestGetcallargsMethods(TestGetcallargsFunctions):
1212
1213 def setUp(self):
1214 class Foo(object):
1215 pass
1216 self.cls = Foo
1217 self.inst = Foo()
1218
1219 def makeCallable(self, signature):
1220 assert 'self' not in signature
1221 mk = super(TestGetcallargsMethods, self).makeCallable
1222 self.cls.method = mk('self, ' + signature)
1223 return self.inst.method
1224
1225class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1226
1227 def makeCallable(self, signature):
1228 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1229 return self.cls.method
1230
1231 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1232 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1233 *self._getAssertEqualParams(func, call_params_string, locs))
1234
1235 def assertEqualException(self, func, call_params_string, locs=None):
1236 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1237 *self._getAssertEqualParams(func, call_params_string, locs))
1238
1239 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1240 assert 'inst' not in call_params_string
1241 locs = dict(locs or {}, inst=self.inst)
1242 return (func, 'inst,' + call_params_string, locs)
1243
Michael Foord95fc51d2010-11-20 15:07:30 +00001244
1245class TestGetattrStatic(unittest.TestCase):
1246
1247 def test_basic(self):
1248 class Thing(object):
1249 x = object()
1250
1251 thing = Thing()
1252 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1253 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1254 with self.assertRaises(AttributeError):
1255 inspect.getattr_static(thing, 'y')
1256
1257 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1258
1259 def test_inherited(self):
1260 class Thing(object):
1261 x = object()
1262 class OtherThing(Thing):
1263 pass
1264
1265 something = OtherThing()
1266 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1267
1268 def test_instance_attr(self):
1269 class Thing(object):
1270 x = 2
1271 def __init__(self, x):
1272 self.x = x
1273 thing = Thing(3)
1274 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1275 del thing.x
1276 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1277
1278 def test_property(self):
1279 class Thing(object):
1280 @property
1281 def x(self):
1282 raise AttributeError("I'm pretending not to exist")
1283 thing = Thing()
1284 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1285
Ezio Melotti75cbd732011-04-28 00:59:29 +03001286 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001287 class descriptor(object):
1288 def __get__(*_):
1289 raise AttributeError("I'm pretending not to exist")
1290 desc = descriptor()
1291 class Thing(object):
1292 x = desc
1293 thing = Thing()
1294 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1295
1296 def test_classAttribute(self):
1297 class Thing(object):
1298 x = object()
1299
1300 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1301
Ethan Furmane03ea372013-09-25 07:14:41 -07001302 def test_classVirtualAttribute(self):
1303 class Thing(object):
1304 @types.DynamicClassAttribute
1305 def x(self):
1306 return self._x
1307 _x = object()
1308
1309 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1310
Michael Foord95fc51d2010-11-20 15:07:30 +00001311 def test_inherited_classattribute(self):
1312 class Thing(object):
1313 x = object()
1314 class OtherThing(Thing):
1315 pass
1316
1317 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1318
1319 def test_slots(self):
1320 class Thing(object):
1321 y = 'bar'
1322 __slots__ = ['x']
1323 def __init__(self):
1324 self.x = 'foo'
1325 thing = Thing()
1326 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1327 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1328
1329 del thing.x
1330 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1331
1332 def test_metaclass(self):
1333 class meta(type):
1334 attr = 'foo'
1335 class Thing(object, metaclass=meta):
1336 pass
1337 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1338
1339 class sub(meta):
1340 pass
1341 class OtherThing(object, metaclass=sub):
1342 x = 3
1343 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1344
1345 class OtherOtherThing(OtherThing):
1346 pass
1347 # this test is odd, but it was added as it exposed a bug
1348 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1349
1350 def test_no_dict_no_slots(self):
1351 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1352 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1353
1354 def test_no_dict_no_slots_instance_member(self):
1355 # returns descriptor
1356 with open(__file__) as handle:
1357 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1358
1359 def test_inherited_slots(self):
1360 # returns descriptor
1361 class Thing(object):
1362 __slots__ = ['x']
1363 def __init__(self):
1364 self.x = 'foo'
1365
1366 class OtherThing(Thing):
1367 pass
1368 # it would be nice if this worked...
1369 # we get the descriptor instead of the instance attribute
1370 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1371
1372 def test_descriptor(self):
1373 class descriptor(object):
1374 def __get__(self, instance, owner):
1375 return 3
1376 class Foo(object):
1377 d = descriptor()
1378
1379 foo = Foo()
1380
1381 # for a non data descriptor we return the instance attribute
1382 foo.__dict__['d'] = 1
1383 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1384
1385 # if the descriptor is a data-desciptor we should return the
1386 # descriptor
1387 descriptor.__set__ = lambda s, i, v: None
1388 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1389
1390
1391 def test_metaclass_with_descriptor(self):
1392 class descriptor(object):
1393 def __get__(self, instance, owner):
1394 return 3
1395 class meta(type):
1396 d = descriptor()
1397 class Thing(object, metaclass=meta):
1398 pass
1399 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1400
1401
Michael Foordcc7ebb82010-11-20 16:20:16 +00001402 def test_class_as_property(self):
1403 class Base(object):
1404 foo = 3
1405
1406 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001407 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001408 @property
1409 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001410 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001411 return object
1412
Michael Foord35184ed2010-11-20 16:58:30 +00001413 instance = Something()
1414 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1415 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001416 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1417
Michael Foorde5162652010-11-20 16:40:44 +00001418 def test_mro_as_property(self):
1419 class Meta(type):
1420 @property
1421 def __mro__(self):
1422 return (object,)
1423
1424 class Base(object):
1425 foo = 3
1426
1427 class Something(Base, metaclass=Meta):
1428 pass
1429
1430 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1431 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1432
Michael Foorddcebe0f2011-03-15 19:20:44 -04001433 def test_dict_as_property(self):
1434 test = self
1435 test.called = False
1436
1437 class Foo(dict):
1438 a = 3
1439 @property
1440 def __dict__(self):
1441 test.called = True
1442 return {}
1443
1444 foo = Foo()
1445 foo.a = 4
1446 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1447 self.assertFalse(test.called)
1448
1449 def test_custom_object_dict(self):
1450 test = self
1451 test.called = False
1452
1453 class Custom(dict):
1454 def get(self, key, default=None):
1455 test.called = True
1456 super().get(key, default)
1457
1458 class Foo(object):
1459 a = 3
1460 foo = Foo()
1461 foo.__dict__ = Custom()
1462 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1463 self.assertFalse(test.called)
1464
1465 def test_metaclass_dict_as_property(self):
1466 class Meta(type):
1467 @property
1468 def __dict__(self):
1469 self.executed = True
1470
1471 class Thing(metaclass=Meta):
1472 executed = False
1473
1474 def __init__(self):
1475 self.spam = 42
1476
1477 instance = Thing()
1478 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1479 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001480
Michael Foorda51623b2011-12-18 22:01:40 +00001481 def test_module(self):
1482 sentinel = object()
1483 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1484 sentinel)
1485
Michael Foord3ba95f82011-12-22 01:13:37 +00001486 def test_metaclass_with_metaclass_with_dict_as_property(self):
1487 class MetaMeta(type):
1488 @property
1489 def __dict__(self):
1490 self.executed = True
1491 return dict(spam=42)
1492
1493 class Meta(type, metaclass=MetaMeta):
1494 executed = False
1495
1496 class Thing(metaclass=Meta):
1497 pass
1498
1499 with self.assertRaises(AttributeError):
1500 inspect.getattr_static(Thing, "spam")
1501 self.assertFalse(Thing.executed)
1502
Nick Coghlane0f04652010-11-21 03:44:04 +00001503class TestGetGeneratorState(unittest.TestCase):
1504
1505 def setUp(self):
1506 def number_generator():
1507 for number in range(5):
1508 yield number
1509 self.generator = number_generator()
1510
1511 def _generatorstate(self):
1512 return inspect.getgeneratorstate(self.generator)
1513
1514 def test_created(self):
1515 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1516
1517 def test_suspended(self):
1518 next(self.generator)
1519 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1520
1521 def test_closed_after_exhaustion(self):
1522 for i in self.generator:
1523 pass
1524 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1525
1526 def test_closed_after_immediate_exception(self):
1527 with self.assertRaises(RuntimeError):
1528 self.generator.throw(RuntimeError)
1529 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1530
1531 def test_running(self):
1532 # As mentioned on issue #10220, checking for the RUNNING state only
1533 # makes sense inside the generator itself.
1534 # The following generator checks for this by using the closure's
1535 # reference to self and the generator state checking helper method
1536 def running_check_generator():
1537 for number in range(5):
1538 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1539 yield number
1540 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1541 self.generator = running_check_generator()
1542 # Running up to the first yield
1543 next(self.generator)
1544 # Running after the first yield
1545 next(self.generator)
1546
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001547 def test_easy_debugging(self):
1548 # repr() and str() of a generator state should contain the state name
1549 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1550 for name in names:
1551 state = getattr(inspect, name)
1552 self.assertIn(name, repr(state))
1553 self.assertIn(name, str(state))
1554
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001555 def test_getgeneratorlocals(self):
1556 def each(lst, a=None):
1557 b=(1, 2, 3)
1558 for v in lst:
1559 if v == 3:
1560 c = 12
1561 yield v
1562
1563 numbers = each([1, 2, 3])
1564 self.assertEqual(inspect.getgeneratorlocals(numbers),
1565 {'a': None, 'lst': [1, 2, 3]})
1566 next(numbers)
1567 self.assertEqual(inspect.getgeneratorlocals(numbers),
1568 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1569 'b': (1, 2, 3)})
1570 next(numbers)
1571 self.assertEqual(inspect.getgeneratorlocals(numbers),
1572 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1573 'b': (1, 2, 3)})
1574 next(numbers)
1575 self.assertEqual(inspect.getgeneratorlocals(numbers),
1576 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1577 'b': (1, 2, 3), 'c': 12})
1578 try:
1579 next(numbers)
1580 except StopIteration:
1581 pass
1582 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1583
1584 def test_getgeneratorlocals_empty(self):
1585 def yield_one():
1586 yield 1
1587 one = yield_one()
1588 self.assertEqual(inspect.getgeneratorlocals(one), {})
1589 try:
1590 next(one)
1591 except StopIteration:
1592 pass
1593 self.assertEqual(inspect.getgeneratorlocals(one), {})
1594
1595 def test_getgeneratorlocals_error(self):
1596 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1597 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1598 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1599 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1600
Nick Coghlane0f04652010-11-21 03:44:04 +00001601
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001602class MySignature(inspect.Signature):
1603 # Top-level to make it picklable;
1604 # used in test_signature_object_pickle
1605 pass
1606
1607class MyParameter(inspect.Parameter):
1608 # Top-level to make it picklable;
1609 # used in test_signature_object_pickle
1610 pass
1611
1612
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001613class TestSignatureObject(unittest.TestCase):
1614 @staticmethod
1615 def signature(func):
1616 sig = inspect.signature(func)
1617 return (tuple((param.name,
1618 (... if param.default is param.empty else param.default),
1619 (... if param.annotation is param.empty
1620 else param.annotation),
1621 str(param.kind).lower())
1622 for param in sig.parameters.values()),
1623 (... if sig.return_annotation is sig.empty
1624 else sig.return_annotation))
1625
1626 def test_signature_object(self):
1627 S = inspect.Signature
1628 P = inspect.Parameter
1629
1630 self.assertEqual(str(S()), '()')
1631
Yury Selivanov07a9e452014-01-29 10:58:16 -05001632 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001633 pass
1634 sig = inspect.signature(test)
1635 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001636 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001637 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001638 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001639 args = sig.parameters['args']
1640 ko = sig.parameters['ko']
1641 kwargs = sig.parameters['kwargs']
1642
1643 S((po, pk, args, ko, kwargs))
1644
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001645 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001646 S((pk, po, args, ko, kwargs))
1647
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001648 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001649 S((po, args, pk, ko, kwargs))
1650
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001651 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001652 S((args, po, pk, ko, kwargs))
1653
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001654 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001655 S((po, pk, args, kwargs, ko))
1656
1657 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001658 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001659 S((po, pk, args, kwargs2, ko))
1660
Yury Selivanov07a9e452014-01-29 10:58:16 -05001661 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1662 S((pod, po))
1663
1664 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1665 S((po, pkd, pk))
1666
1667 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1668 S((pkd, pk))
1669
Yury Selivanov374375d2014-03-27 12:41:53 -04001670 self.assertTrue(repr(sig).startswith('<Signature'))
1671 self.assertTrue('"(po, pk' in repr(sig))
1672
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001673 def test_signature_object_pickle(self):
1674 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
1675 foo_partial = functools.partial(foo, a=1)
1676
1677 sig = inspect.signature(foo_partial)
1678 self.assertTrue(sig.parameters['a']._partial_kwarg)
1679
1680 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1681 with self.subTest(pickle_ver=ver, subclass=False):
1682 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
1683 self.assertEqual(sig, sig_pickled)
1684 self.assertTrue(sig_pickled.parameters['a']._partial_kwarg)
1685
1686 # Test that basic sub-classing works
1687 sig = inspect.signature(foo)
1688 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
1689 myparams = collections.OrderedDict(sig.parameters, a=myparam)
1690 mysig = MySignature().replace(parameters=myparams.values(),
1691 return_annotation=sig.return_annotation)
1692 self.assertTrue(isinstance(mysig, MySignature))
1693 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
1694
1695 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1696 with self.subTest(pickle_ver=ver, subclass=True):
1697 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
1698 self.assertEqual(mysig, sig_pickled)
1699 self.assertTrue(isinstance(sig_pickled, MySignature))
1700 self.assertTrue(isinstance(sig_pickled.parameters['z'],
1701 MyParameter))
1702
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001703 def test_signature_immutability(self):
1704 def test(a):
1705 pass
1706 sig = inspect.signature(test)
1707
1708 with self.assertRaises(AttributeError):
1709 sig.foo = 'bar'
1710
1711 with self.assertRaises(TypeError):
1712 sig.parameters['a'] = None
1713
1714 def test_signature_on_noarg(self):
1715 def test():
1716 pass
1717 self.assertEqual(self.signature(test), ((), ...))
1718
1719 def test_signature_on_wargs(self):
1720 def test(a, b:'foo') -> 123:
1721 pass
1722 self.assertEqual(self.signature(test),
1723 ((('a', ..., ..., "positional_or_keyword"),
1724 ('b', ..., 'foo', "positional_or_keyword")),
1725 123))
1726
1727 def test_signature_on_wkwonly(self):
1728 def test(*, a:float, b:str) -> int:
1729 pass
1730 self.assertEqual(self.signature(test),
1731 ((('a', ..., float, "keyword_only"),
1732 ('b', ..., str, "keyword_only")),
1733 int))
1734
1735 def test_signature_on_complex_args(self):
1736 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1737 pass
1738 self.assertEqual(self.signature(test),
1739 ((('a', ..., ..., "positional_or_keyword"),
1740 ('b', 10, 'foo', "positional_or_keyword"),
1741 ('args', ..., 'bar', "var_positional"),
1742 ('spam', ..., 'baz', "keyword_only"),
1743 ('ham', 123, ..., "keyword_only"),
1744 ('kwargs', ..., int, "var_keyword")),
1745 ...))
1746
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001747 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001748 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1749 "Signature information for builtins requires docstrings")
1750 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001751 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001752
Larry Hastings5c661892014-01-24 06:17:25 -08001753 def test_unbound_method(o):
1754 """Use this to test unbound methods (things that should have a self)"""
1755 signature = inspect.signature(o)
1756 self.assertTrue(isinstance(signature, inspect.Signature))
1757 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1758 return signature
1759
1760 def test_callable(o):
1761 """Use this to test bound methods or normal callables (things that don't expect self)"""
1762 signature = inspect.signature(o)
1763 self.assertTrue(isinstance(signature, inspect.Signature))
1764 if signature.parameters:
1765 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1766 return signature
1767
1768 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001769 def p(name): return signature.parameters[name].default
1770 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001771 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001772 self.assertEqual(p('d'), 3.14)
1773 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001774 self.assertEqual(p('n'), None)
1775 self.assertEqual(p('t'), True)
1776 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001777 self.assertEqual(p('local'), 3)
1778 self.assertEqual(p('sys'), sys.maxsize)
1779 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001780
Larry Hastings5c661892014-01-24 06:17:25 -08001781 test_callable(object)
1782
1783 # normal method
1784 # (PyMethodDescr_Type, "method_descriptor")
1785 test_unbound_method(_pickle.Pickler.dump)
1786 d = _pickle.Pickler(io.StringIO())
1787 test_callable(d.dump)
1788
1789 # static method
1790 test_callable(str.maketrans)
1791 test_callable('abc'.maketrans)
1792
1793 # class method
1794 test_callable(dict.fromkeys)
1795 test_callable({}.fromkeys)
1796
1797 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1798 test_unbound_method(type.__call__)
1799 test_unbound_method(int.__add__)
1800 test_callable((3).__add__)
1801
1802 # _PyMethodWrapper_Type
1803 # support for 'method-wrapper'
1804 test_callable(min.__call__)
1805
Larry Hastings2623c8c2014-02-08 22:15:29 -08001806 # This doesn't work now.
1807 # (We don't have a valid signature for "type" in 3.4)
1808 with self.assertRaisesRegex(ValueError, "no signature found"):
1809 class ThisWorksNow:
1810 __call__ = type
1811 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08001812
Yury Selivanov056e2652014-03-02 12:25:27 -05001813 # Regression test for issue #20786
1814 test_unbound_method(dict.__delitem__)
1815 test_unbound_method(property.__delete__)
1816
1817
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001818 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05001819 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1820 "Signature information for builtins requires docstrings")
1821 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001822 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05001823 func = _testcapi.docstring_with_signature_with_defaults
1824
1825 def decorator(func):
1826 @functools.wraps(func)
1827 def wrapper(*args, **kwargs) -> int:
1828 return func(*args, **kwargs)
1829 return wrapper
1830
1831 decorated_func = decorator(func)
1832
1833 self.assertEqual(inspect.signature(func),
1834 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08001835
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001836 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08001837 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001838 import _testcapi
Larry Hastings5c661892014-01-24 06:17:25 -08001839 with self.assertRaisesRegex(ValueError, 'no signature found for builtin'):
1840 inspect.signature(_testcapi.docstring_no_signature)
1841
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001842 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001843 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001844 inspect.signature(42)
1845
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001846 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001847 inspect.Signature.from_function(42)
1848
Yury Selivanovb77511d2014-01-29 10:46:14 -05001849 def test_signature_from_builtin_errors(self):
1850 with self.assertRaisesRegex(TypeError, 'is not a Python builtin'):
1851 inspect.Signature.from_builtin(42)
1852
Yury Selivanov63da7c72014-01-31 14:48:37 -05001853 def test_signature_from_functionlike_object(self):
1854 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1855 pass
1856
1857 class funclike:
1858 # Has to be callable, and have correct
1859 # __code__, __annotations__, __defaults__, __name__,
1860 # and __kwdefaults__ attributes
1861
1862 def __init__(self, func):
1863 self.__name__ = func.__name__
1864 self.__code__ = func.__code__
1865 self.__annotations__ = func.__annotations__
1866 self.__defaults__ = func.__defaults__
1867 self.__kwdefaults__ = func.__kwdefaults__
1868 self.func = func
1869
1870 def __call__(self, *args, **kwargs):
1871 return self.func(*args, **kwargs)
1872
1873 sig_func = inspect.Signature.from_function(func)
1874
1875 sig_funclike = inspect.Signature.from_function(funclike(func))
1876 self.assertEqual(sig_funclike, sig_func)
1877
1878 sig_funclike = inspect.signature(funclike(func))
1879 self.assertEqual(sig_funclike, sig_func)
1880
1881 # If object is not a duck type of function, then
1882 # signature will try to get a signature for its '__call__'
1883 # method
1884 fl = funclike(func)
1885 del fl.__defaults__
1886 self.assertEqual(self.signature(fl),
1887 ((('args', ..., ..., "var_positional"),
1888 ('kwargs', ..., ..., "var_keyword")),
1889 ...))
1890
Yury Selivanova773de02014-02-21 18:30:53 -05001891 # Test with cython-like builtins:
1892 _orig_isdesc = inspect.ismethoddescriptor
1893 def _isdesc(obj):
1894 if hasattr(obj, '_builtinmock'):
1895 return True
1896 return _orig_isdesc(obj)
1897
1898 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
1899 builtin_func = funclike(func)
1900 # Make sure that our mock setup is working
1901 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
1902 builtin_func._builtinmock = True
1903 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
1904 self.assertEqual(inspect.signature(builtin_func), sig_func)
1905
Yury Selivanov63da7c72014-01-31 14:48:37 -05001906 def test_signature_functionlike_class(self):
1907 # We only want to duck type function-like objects,
1908 # not classes.
1909
1910 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1911 pass
1912
1913 class funclike:
1914 def __init__(self, marker):
1915 pass
1916
1917 __name__ = func.__name__
1918 __code__ = func.__code__
1919 __annotations__ = func.__annotations__
1920 __defaults__ = func.__defaults__
1921 __kwdefaults__ = func.__kwdefaults__
1922
1923 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1924 inspect.Signature.from_function(funclike)
1925
1926 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
1927
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001928 def test_signature_on_method(self):
1929 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05001930 def __init__(*args):
1931 pass
1932 def m1(self, arg1, arg2=1) -> int:
1933 pass
1934 def m2(*args):
1935 pass
1936 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001937 pass
1938
Yury Selivanov62560fb2014-01-28 12:26:24 -05001939 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001940 ((('arg1', ..., ..., "positional_or_keyword"),
1941 ('arg2', 1, ..., "positional_or_keyword")),
1942 int))
1943
Yury Selivanov62560fb2014-01-28 12:26:24 -05001944 self.assertEqual(self.signature(Test().m2),
1945 ((('args', ..., ..., "var_positional"),),
1946 ...))
1947
1948 self.assertEqual(self.signature(Test),
1949 ((('args', ..., ..., "var_positional"),),
1950 ...))
1951
1952 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
1953 self.signature(Test())
1954
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001955 def test_signature_on_classmethod(self):
1956 class Test:
1957 @classmethod
1958 def foo(cls, arg1, *, arg2=1):
1959 pass
1960
1961 meth = Test().foo
1962 self.assertEqual(self.signature(meth),
1963 ((('arg1', ..., ..., "positional_or_keyword"),
1964 ('arg2', 1, ..., "keyword_only")),
1965 ...))
1966
1967 meth = Test.foo
1968 self.assertEqual(self.signature(meth),
1969 ((('arg1', ..., ..., "positional_or_keyword"),
1970 ('arg2', 1, ..., "keyword_only")),
1971 ...))
1972
1973 def test_signature_on_staticmethod(self):
1974 class Test:
1975 @staticmethod
1976 def foo(cls, *, arg):
1977 pass
1978
1979 meth = Test().foo
1980 self.assertEqual(self.signature(meth),
1981 ((('cls', ..., ..., "positional_or_keyword"),
1982 ('arg', ..., ..., "keyword_only")),
1983 ...))
1984
1985 meth = Test.foo
1986 self.assertEqual(self.signature(meth),
1987 ((('cls', ..., ..., "positional_or_keyword"),
1988 ('arg', ..., ..., "keyword_only")),
1989 ...))
1990
1991 def test_signature_on_partial(self):
1992 from functools import partial
1993
1994 def test():
1995 pass
1996
1997 self.assertEqual(self.signature(partial(test)), ((), ...))
1998
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001999 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002000 inspect.signature(partial(test, 1))
2001
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002002 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002003 inspect.signature(partial(test, a=1))
2004
2005 def test(a, b, *, c, d):
2006 pass
2007
2008 self.assertEqual(self.signature(partial(test)),
2009 ((('a', ..., ..., "positional_or_keyword"),
2010 ('b', ..., ..., "positional_or_keyword"),
2011 ('c', ..., ..., "keyword_only"),
2012 ('d', ..., ..., "keyword_only")),
2013 ...))
2014
2015 self.assertEqual(self.signature(partial(test, 1)),
2016 ((('b', ..., ..., "positional_or_keyword"),
2017 ('c', ..., ..., "keyword_only"),
2018 ('d', ..., ..., "keyword_only")),
2019 ...))
2020
2021 self.assertEqual(self.signature(partial(test, 1, c=2)),
2022 ((('b', ..., ..., "positional_or_keyword"),
2023 ('c', 2, ..., "keyword_only"),
2024 ('d', ..., ..., "keyword_only")),
2025 ...))
2026
2027 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2028 ((('a', ..., ..., "positional_or_keyword"),
2029 ('b', 1, ..., "positional_or_keyword"),
2030 ('c', 2, ..., "keyword_only"),
2031 ('d', ..., ..., "keyword_only")),
2032 ...))
2033
2034 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
2035 ((('b', 1, ..., "positional_or_keyword"),
2036 ('c', 2, ..., "keyword_only"),
2037 ('d', ..., ..., "keyword_only"),),
2038 ...))
2039
2040 def test(a, *args, b, **kwargs):
2041 pass
2042
2043 self.assertEqual(self.signature(partial(test, 1)),
2044 ((('args', ..., ..., "var_positional"),
2045 ('b', ..., ..., "keyword_only"),
2046 ('kwargs', ..., ..., "var_keyword")),
2047 ...))
2048
2049 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2050 ((('args', ..., ..., "var_positional"),
2051 ('b', ..., ..., "keyword_only"),
2052 ('kwargs', ..., ..., "var_keyword")),
2053 ...))
2054
2055
2056 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2057 ((('args', ..., ..., "var_positional"),
2058 ('b', ..., ..., "keyword_only"),
2059 ('kwargs', ..., ..., "var_keyword")),
2060 ...))
2061
2062 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2063 ((('args', ..., ..., "var_positional"),
2064 ('b', 0, ..., "keyword_only"),
2065 ('kwargs', ..., ..., "var_keyword")),
2066 ...))
2067
2068 self.assertEqual(self.signature(partial(test, b=0)),
2069 ((('a', ..., ..., "positional_or_keyword"),
2070 ('args', ..., ..., "var_positional"),
2071 ('b', 0, ..., "keyword_only"),
2072 ('kwargs', ..., ..., "var_keyword")),
2073 ...))
2074
2075 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2076 ((('a', ..., ..., "positional_or_keyword"),
2077 ('args', ..., ..., "var_positional"),
2078 ('b', 0, ..., "keyword_only"),
2079 ('kwargs', ..., ..., "var_keyword")),
2080 ...))
2081
2082 def test(a, b, c:int) -> 42:
2083 pass
2084
2085 sig = test.__signature__ = inspect.signature(test)
2086
2087 self.assertEqual(self.signature(partial(partial(test, 1))),
2088 ((('b', ..., ..., "positional_or_keyword"),
2089 ('c', ..., int, "positional_or_keyword")),
2090 42))
2091
2092 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2093 ((('c', ..., int, "positional_or_keyword"),),
2094 42))
2095
2096 psig = inspect.signature(partial(partial(test, 1), 2))
2097
2098 def foo(a):
2099 return a
2100 _foo = partial(partial(foo, a=10), a=20)
2101 self.assertEqual(self.signature(_foo),
2102 ((('a', 20, ..., "positional_or_keyword"),),
2103 ...))
2104 # check that we don't have any side-effects in signature(),
2105 # and the partial object is still functioning
2106 self.assertEqual(_foo(), 20)
2107
2108 def foo(a, b, c):
2109 return a, b, c
2110 _foo = partial(partial(foo, 1, b=20), b=30)
2111 self.assertEqual(self.signature(_foo),
2112 ((('b', 30, ..., "positional_or_keyword"),
2113 ('c', ..., ..., "positional_or_keyword")),
2114 ...))
2115 self.assertEqual(_foo(c=10), (1, 30, 10))
2116 _foo = partial(_foo, 2) # now 'b' has two values -
2117 # positional and keyword
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002118 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002119 inspect.signature(_foo)
2120
2121 def foo(a, b, c, *, d):
2122 return a, b, c, d
2123 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2124 self.assertEqual(self.signature(_foo),
2125 ((('a', ..., ..., "positional_or_keyword"),
2126 ('b', 10, ..., "positional_or_keyword"),
2127 ('c', 20, ..., "positional_or_keyword"),
2128 ('d', 30, ..., "keyword_only")),
2129 ...))
2130 ba = inspect.signature(_foo).bind(a=200, b=11)
2131 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2132
2133 def foo(a=1, b=2, c=3):
2134 return a, b, c
2135 _foo = partial(foo, a=10, c=13)
2136 ba = inspect.signature(_foo).bind(11)
2137 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
2138 ba = inspect.signature(_foo).bind(11, 12)
2139 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
2140 ba = inspect.signature(_foo).bind(11, b=12)
2141 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
2142 ba = inspect.signature(_foo).bind(b=12)
2143 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
2144 _foo = partial(_foo, b=10)
2145 ba = inspect.signature(_foo).bind(12, 14)
2146 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
2147
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002148 def test_signature_on_partialmethod(self):
2149 from functools import partialmethod
2150
2151 class Spam:
2152 def test():
2153 pass
2154 ham = partialmethod(test)
2155
2156 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2157 inspect.signature(Spam.ham)
2158
2159 class Spam:
2160 def test(it, a, *, c) -> 'spam':
2161 pass
2162 ham = partialmethod(test, c=1)
2163
2164 self.assertEqual(self.signature(Spam.ham),
2165 ((('it', ..., ..., 'positional_or_keyword'),
2166 ('a', ..., ..., 'positional_or_keyword'),
2167 ('c', 1, ..., 'keyword_only')),
2168 'spam'))
2169
2170 self.assertEqual(self.signature(Spam().ham),
2171 ((('a', ..., ..., 'positional_or_keyword'),
2172 ('c', 1, ..., 'keyword_only')),
2173 'spam'))
2174
Yury Selivanov0486f812014-01-29 12:18:59 -05002175 def test_signature_on_fake_partialmethod(self):
2176 def foo(a): pass
2177 foo._partialmethod = 'spam'
2178 self.assertEqual(str(inspect.signature(foo)), '(a)')
2179
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002180 def test_signature_on_decorated(self):
2181 import functools
2182
2183 def decorator(func):
2184 @functools.wraps(func)
2185 def wrapper(*args, **kwargs) -> int:
2186 return func(*args, **kwargs)
2187 return wrapper
2188
2189 class Foo:
2190 @decorator
2191 def bar(self, a, b):
2192 pass
2193
2194 self.assertEqual(self.signature(Foo.bar),
2195 ((('self', ..., ..., "positional_or_keyword"),
2196 ('a', ..., ..., "positional_or_keyword"),
2197 ('b', ..., ..., "positional_or_keyword")),
2198 ...))
2199
2200 self.assertEqual(self.signature(Foo().bar),
2201 ((('a', ..., ..., "positional_or_keyword"),
2202 ('b', ..., ..., "positional_or_keyword")),
2203 ...))
2204
2205 # Test that we handle method wrappers correctly
2206 def decorator(func):
2207 @functools.wraps(func)
2208 def wrapper(*args, **kwargs) -> int:
2209 return func(42, *args, **kwargs)
2210 sig = inspect.signature(func)
2211 new_params = tuple(sig.parameters.values())[1:]
2212 wrapper.__signature__ = sig.replace(parameters=new_params)
2213 return wrapper
2214
2215 class Foo:
2216 @decorator
2217 def __call__(self, a, b):
2218 pass
2219
2220 self.assertEqual(self.signature(Foo.__call__),
2221 ((('a', ..., ..., "positional_or_keyword"),
2222 ('b', ..., ..., "positional_or_keyword")),
2223 ...))
2224
2225 self.assertEqual(self.signature(Foo().__call__),
2226 ((('b', ..., ..., "positional_or_keyword"),),
2227 ...))
2228
Nick Coghlane8c45d62013-07-28 20:00:01 +10002229 # Test we handle __signature__ partway down the wrapper stack
2230 def wrapped_foo_call():
2231 pass
2232 wrapped_foo_call.__wrapped__ = Foo.__call__
2233
2234 self.assertEqual(self.signature(wrapped_foo_call),
2235 ((('a', ..., ..., "positional_or_keyword"),
2236 ('b', ..., ..., "positional_or_keyword")),
2237 ...))
2238
2239
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002240 def test_signature_on_class(self):
2241 class C:
2242 def __init__(self, a):
2243 pass
2244
2245 self.assertEqual(self.signature(C),
2246 ((('a', ..., ..., "positional_or_keyword"),),
2247 ...))
2248
2249 class CM(type):
2250 def __call__(cls, a):
2251 pass
2252 class C(metaclass=CM):
2253 def __init__(self, b):
2254 pass
2255
2256 self.assertEqual(self.signature(C),
2257 ((('a', ..., ..., "positional_or_keyword"),),
2258 ...))
2259
2260 class CM(type):
2261 def __new__(mcls, name, bases, dct, *, foo=1):
2262 return super().__new__(mcls, name, bases, dct)
2263 class C(metaclass=CM):
2264 def __init__(self, b):
2265 pass
2266
2267 self.assertEqual(self.signature(C),
2268 ((('b', ..., ..., "positional_or_keyword"),),
2269 ...))
2270
2271 self.assertEqual(self.signature(CM),
2272 ((('name', ..., ..., "positional_or_keyword"),
2273 ('bases', ..., ..., "positional_or_keyword"),
2274 ('dct', ..., ..., "positional_or_keyword"),
2275 ('foo', 1, ..., "keyword_only")),
2276 ...))
2277
2278 class CMM(type):
2279 def __new__(mcls, name, bases, dct, *, foo=1):
2280 return super().__new__(mcls, name, bases, dct)
2281 def __call__(cls, nm, bs, dt):
2282 return type(nm, bs, dt)
2283 class CM(type, metaclass=CMM):
2284 def __new__(mcls, name, bases, dct, *, bar=2):
2285 return super().__new__(mcls, name, bases, dct)
2286 class C(metaclass=CM):
2287 def __init__(self, b):
2288 pass
2289
2290 self.assertEqual(self.signature(CMM),
2291 ((('name', ..., ..., "positional_or_keyword"),
2292 ('bases', ..., ..., "positional_or_keyword"),
2293 ('dct', ..., ..., "positional_or_keyword"),
2294 ('foo', 1, ..., "keyword_only")),
2295 ...))
2296
2297 self.assertEqual(self.signature(CM),
2298 ((('nm', ..., ..., "positional_or_keyword"),
2299 ('bs', ..., ..., "positional_or_keyword"),
2300 ('dt', ..., ..., "positional_or_keyword")),
2301 ...))
2302
2303 self.assertEqual(self.signature(C),
2304 ((('b', ..., ..., "positional_or_keyword"),),
2305 ...))
2306
2307 class CM(type):
2308 def __init__(cls, name, bases, dct, *, bar=2):
2309 return super().__init__(name, bases, dct)
2310 class C(metaclass=CM):
2311 def __init__(self, b):
2312 pass
2313
2314 self.assertEqual(self.signature(CM),
2315 ((('name', ..., ..., "positional_or_keyword"),
2316 ('bases', ..., ..., "positional_or_keyword"),
2317 ('dct', ..., ..., "positional_or_keyword"),
2318 ('bar', 2, ..., "keyword_only")),
2319 ...))
2320
Yury Selivanov145dff82014-02-01 13:49:29 -05002321 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2322 "Signature information for builtins requires docstrings")
2323 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002324 # Test classes without user-defined __init__ or __new__
2325 class C: pass
2326 self.assertEqual(str(inspect.signature(C)), '()')
2327 class D(C): pass
2328 self.assertEqual(str(inspect.signature(D)), '()')
2329
2330 # Test meta-classes without user-defined __init__ or __new__
2331 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002332 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002333 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2334 self.assertEqual(inspect.signature(C), None)
2335 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2336 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002337
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002338 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2339 "Signature information for builtins requires docstrings")
2340 def test_signature_on_builtin_class(self):
2341 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2342 '(file, protocol=None, fix_imports=True)')
2343
2344 class P(_pickle.Pickler): pass
2345 class EmptyTrait: pass
2346 class P2(EmptyTrait, P): pass
2347 self.assertEqual(str(inspect.signature(P)),
2348 '(file, protocol=None, fix_imports=True)')
2349 self.assertEqual(str(inspect.signature(P2)),
2350 '(file, protocol=None, fix_imports=True)')
2351
2352 class P3(P2):
2353 def __init__(self, spam):
2354 pass
2355 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2356
2357 class MetaP(type):
2358 def __call__(cls, foo, bar):
2359 pass
2360 class P4(P2, metaclass=MetaP):
2361 pass
2362 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2363
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002364 def test_signature_on_callable_objects(self):
2365 class Foo:
2366 def __call__(self, a):
2367 pass
2368
2369 self.assertEqual(self.signature(Foo()),
2370 ((('a', ..., ..., "positional_or_keyword"),),
2371 ...))
2372
2373 class Spam:
2374 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002375 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002376 inspect.signature(Spam())
2377
2378 class Bar(Spam, Foo):
2379 pass
2380
2381 self.assertEqual(self.signature(Bar()),
2382 ((('a', ..., ..., "positional_or_keyword"),),
2383 ...))
2384
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002385 class Wrapped:
2386 pass
2387 Wrapped.__wrapped__ = lambda a: None
2388 self.assertEqual(self.signature(Wrapped),
2389 ((('a', ..., ..., "positional_or_keyword"),),
2390 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002391 # wrapper loop:
2392 Wrapped.__wrapped__ = Wrapped
2393 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2394 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002395
2396 def test_signature_on_lambdas(self):
2397 self.assertEqual(self.signature((lambda a=10: a)),
2398 ((('a', 10, ..., "positional_or_keyword"),),
2399 ...))
2400
2401 def test_signature_equality(self):
2402 def foo(a, *, b:int) -> float: pass
2403 self.assertNotEqual(inspect.signature(foo), 42)
2404
2405 def bar(a, *, b:int) -> float: pass
2406 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2407
2408 def bar(a, *, b:int) -> int: pass
2409 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2410
2411 def bar(a, *, b:int): pass
2412 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2413
2414 def bar(a, *, b:int=42) -> float: pass
2415 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2416
2417 def bar(a, *, c) -> float: pass
2418 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2419
2420 def bar(a, b:int) -> float: pass
2421 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2422 def spam(b:int, a) -> float: pass
2423 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
2424
2425 def foo(*, a, b, c): pass
2426 def bar(*, c, b, a): pass
2427 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2428
2429 def foo(*, a=1, b, c): pass
2430 def bar(*, c, b, a=1): pass
2431 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2432
2433 def foo(pos, *, a=1, b, c): pass
2434 def bar(pos, *, c, b, a=1): pass
2435 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2436
2437 def foo(pos, *, a, b, c): pass
2438 def bar(pos, *, c, b, a=1): pass
2439 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2440
2441 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2442 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2443 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2444
2445 def test_signature_unhashable(self):
2446 def foo(a): pass
2447 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002448 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002449 hash(sig)
2450
2451 def test_signature_str(self):
2452 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2453 pass
2454 self.assertEqual(str(inspect.signature(foo)),
2455 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2456
2457 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2458 pass
2459 self.assertEqual(str(inspect.signature(foo)),
2460 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2461
2462 def foo():
2463 pass
2464 self.assertEqual(str(inspect.signature(foo)), '()')
2465
2466 def test_signature_str_positional_only(self):
2467 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002468 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002469
2470 def test(a_po, *, b, **kwargs):
2471 return a_po, kwargs
2472
2473 sig = inspect.signature(test)
2474 new_params = list(sig.parameters.values())
2475 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2476 test.__signature__ = sig.replace(parameters=new_params)
2477
2478 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002479 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002480
Yury Selivanov2393dca2014-01-27 15:07:58 -05002481 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2482 '(foo, /)')
2483
2484 self.assertEqual(str(S(parameters=[
2485 P('foo', P.POSITIONAL_ONLY),
2486 P('bar', P.VAR_KEYWORD)])),
2487 '(foo, /, **bar)')
2488
2489 self.assertEqual(str(S(parameters=[
2490 P('foo', P.POSITIONAL_ONLY),
2491 P('bar', P.VAR_POSITIONAL)])),
2492 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002493
2494 def test_signature_replace_anno(self):
2495 def test() -> 42:
2496 pass
2497
2498 sig = inspect.signature(test)
2499 sig = sig.replace(return_annotation=None)
2500 self.assertIs(sig.return_annotation, None)
2501 sig = sig.replace(return_annotation=sig.empty)
2502 self.assertIs(sig.return_annotation, sig.empty)
2503 sig = sig.replace(return_annotation=42)
2504 self.assertEqual(sig.return_annotation, 42)
2505 self.assertEqual(sig, inspect.signature(test))
2506
Yury Selivanov34ce99f2014-02-18 12:49:41 -05002507 def test_signature_on_mangled_parameters(self):
2508 class Spam:
2509 def foo(self, __p1:1=2, *, __p2:2=3):
2510 pass
2511 class Ham(Spam):
2512 pass
2513
2514 self.assertEqual(self.signature(Spam.foo),
2515 ((('self', ..., ..., "positional_or_keyword"),
2516 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2517 ('_Spam__p2', 3, 2, "keyword_only")),
2518 ...))
2519
2520 self.assertEqual(self.signature(Spam.foo),
2521 self.signature(Ham.foo))
2522
Yury Selivanovda396452014-03-27 12:09:24 -04002523 def test_signature_from_callable_python_obj(self):
2524 class MySignature(inspect.Signature): pass
2525 def foo(a, *, b:1): pass
2526 foo_sig = MySignature.from_callable(foo)
2527 self.assertTrue(isinstance(foo_sig, MySignature))
2528
2529 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2530 "Signature information for builtins requires docstrings")
2531 def test_signature_from_callable_builtin_obj(self):
2532 class MySignature(inspect.Signature): pass
2533 sig = MySignature.from_callable(_pickle.Pickler)
2534 self.assertTrue(isinstance(sig, MySignature))
2535
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002536
2537class TestParameterObject(unittest.TestCase):
2538 def test_signature_parameter_kinds(self):
2539 P = inspect.Parameter
2540 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2541 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2542
2543 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2544 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2545
2546 def test_signature_parameter_object(self):
2547 p = inspect.Parameter('foo', default=10,
2548 kind=inspect.Parameter.POSITIONAL_ONLY)
2549 self.assertEqual(p.name, 'foo')
2550 self.assertEqual(p.default, 10)
2551 self.assertIs(p.annotation, p.empty)
2552 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2553
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002554 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002555 inspect.Parameter('foo', default=10, kind='123')
2556
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002557 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002558 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2559
Yury Selivanov2393dca2014-01-27 15:07:58 -05002560 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002561 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2562
Yury Selivanov2393dca2014-01-27 15:07:58 -05002563 with self.assertRaisesRegex(ValueError,
2564 'is not a valid parameter name'):
2565 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2566
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002567 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002568 inspect.Parameter('a', default=42,
2569 kind=inspect.Parameter.VAR_KEYWORD)
2570
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002571 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002572 inspect.Parameter('a', default=42,
2573 kind=inspect.Parameter.VAR_POSITIONAL)
2574
2575 p = inspect.Parameter('a', default=42,
2576 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002577 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002578 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2579
2580 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04002581 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002582
2583 def test_signature_parameter_equality(self):
2584 P = inspect.Parameter
2585 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2586
2587 self.assertEqual(p, p)
2588 self.assertNotEqual(p, 42)
2589
2590 self.assertEqual(p, P('foo', default=42,
2591 kind=inspect.Parameter.KEYWORD_ONLY))
2592
2593 def test_signature_parameter_unhashable(self):
2594 p = inspect.Parameter('foo', default=42,
2595 kind=inspect.Parameter.KEYWORD_ONLY)
2596
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002597 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002598 hash(p)
2599
2600 def test_signature_parameter_replace(self):
2601 p = inspect.Parameter('foo', default=42,
2602 kind=inspect.Parameter.KEYWORD_ONLY)
2603
2604 self.assertIsNot(p, p.replace())
2605 self.assertEqual(p, p.replace())
2606
2607 p2 = p.replace(annotation=1)
2608 self.assertEqual(p2.annotation, 1)
2609 p2 = p2.replace(annotation=p2.empty)
2610 self.assertEqual(p, p2)
2611
2612 p2 = p2.replace(name='bar')
2613 self.assertEqual(p2.name, 'bar')
2614 self.assertNotEqual(p2, p)
2615
Yury Selivanov2393dca2014-01-27 15:07:58 -05002616 with self.assertRaisesRegex(ValueError,
2617 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002618 p2 = p2.replace(name=p2.empty)
2619
2620 p2 = p2.replace(name='foo', default=None)
2621 self.assertIs(p2.default, None)
2622 self.assertNotEqual(p2, p)
2623
2624 p2 = p2.replace(name='foo', default=p2.empty)
2625 self.assertIs(p2.default, p2.empty)
2626
2627
2628 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2629 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2630 self.assertNotEqual(p2, p)
2631
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002632 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002633 p2 = p2.replace(kind=p2.empty)
2634
2635 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2636 self.assertEqual(p2, p)
2637
2638 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002639 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2640 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002641
2642 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002643 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002644
2645 with self.assertRaises(AttributeError):
2646 p.foo = 'bar'
2647
2648 with self.assertRaises(AttributeError):
2649 p.kind = 123
2650
2651
2652class TestSignatureBind(unittest.TestCase):
2653 @staticmethod
2654 def call(func, *args, **kwargs):
2655 sig = inspect.signature(func)
2656 ba = sig.bind(*args, **kwargs)
2657 return func(*ba.args, **ba.kwargs)
2658
2659 def test_signature_bind_empty(self):
2660 def test():
2661 return 42
2662
2663 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002664 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002665 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002666 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002667 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002668 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002669 self.call(test, spam=1)
2670
2671 def test_signature_bind_var(self):
2672 def test(*args, **kwargs):
2673 return args, kwargs
2674
2675 self.assertEqual(self.call(test), ((), {}))
2676 self.assertEqual(self.call(test, 1), ((1,), {}))
2677 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2678 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2679 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2680 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2681 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2682 ((1, 2), {'foo': 'bar'}))
2683
2684 def test_signature_bind_just_args(self):
2685 def test(a, b, c):
2686 return a, b, c
2687
2688 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2689
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002690 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002691 self.call(test, 1, 2, 3, 4)
2692
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002693 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002694 self.call(test, 1)
2695
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002696 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002697 self.call(test)
2698
2699 def test(a, b, c=10):
2700 return a, b, c
2701 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2702 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2703
2704 def test(a=1, b=2, c=3):
2705 return a, b, c
2706 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2707 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2708 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2709
2710 def test_signature_bind_varargs_order(self):
2711 def test(*args):
2712 return args
2713
2714 self.assertEqual(self.call(test), ())
2715 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2716
2717 def test_signature_bind_args_and_varargs(self):
2718 def test(a, b, c=3, *args):
2719 return a, b, c, args
2720
2721 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2722 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2723 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2724 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2725
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002726 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002727 "multiple values for argument 'c'"):
2728 self.call(test, 1, 2, 3, c=4)
2729
2730 def test_signature_bind_just_kwargs(self):
2731 def test(**kwargs):
2732 return kwargs
2733
2734 self.assertEqual(self.call(test), {})
2735 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2736 {'foo': 'bar', 'spam': 'ham'})
2737
2738 def test_signature_bind_args_and_kwargs(self):
2739 def test(a, b, c=3, **kwargs):
2740 return a, b, c, kwargs
2741
2742 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2743 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2744 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2745 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2746 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2747 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2748 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2749 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2750 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2751 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2752 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2753 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2754 (1, 2, 4, {'foo': 'bar'}))
2755 self.assertEqual(self.call(test, c=5, a=4, b=3),
2756 (4, 3, 5, {}))
2757
2758 def test_signature_bind_kwonly(self):
2759 def test(*, foo):
2760 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002761 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002762 'too many positional arguments'):
2763 self.call(test, 1)
2764 self.assertEqual(self.call(test, foo=1), 1)
2765
2766 def test(a, *, foo=1, bar):
2767 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002768 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002769 "'bar' parameter lacking default value"):
2770 self.call(test, 1)
2771
2772 def test(foo, *, bar):
2773 return foo, bar
2774 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2775 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2776
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002777 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002778 'too many keyword arguments'):
2779 self.call(test, bar=2, foo=1, spam=10)
2780
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002781 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002782 'too many positional arguments'):
2783 self.call(test, 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 positional arguments'):
2787 self.call(test, 1, 2, bar=2)
2788
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002789 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002790 'too many keyword arguments'):
2791 self.call(test, 1, bar=2, spam='ham')
2792
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002793 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002794 "'bar' parameter lacking default value"):
2795 self.call(test, 1)
2796
2797 def test(foo, *, bar, **bin):
2798 return foo, bar, bin
2799 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2800 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2801 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2802 (1, 2, {'spam': 'ham'}))
2803 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2804 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002805 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002806 "'foo' parameter lacking default value"):
2807 self.call(test, spam='ham', bar=2)
2808 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2809 (1, 2, {'bin': 1, 'spam': 10}))
2810
2811 def test_signature_bind_arguments(self):
2812 def test(a, *args, b, z=100, **kwargs):
2813 pass
2814 sig = inspect.signature(test)
2815 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2816 # we won't have 'z' argument in the bound arguments object, as we didn't
2817 # pass it to the 'bind'
2818 self.assertEqual(tuple(ba.arguments.items()),
2819 (('a', 10), ('args', (20,)), ('b', 30),
2820 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2821 self.assertEqual(ba.kwargs,
2822 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2823 self.assertEqual(ba.args, (10, 20))
2824
2825 def test_signature_bind_positional_only(self):
2826 P = inspect.Parameter
2827
2828 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2829 return a_po, b_po, c_po, foo, bar, kwargs
2830
2831 sig = inspect.signature(test)
2832 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2833 for name in ('a_po', 'b_po', 'c_po'):
2834 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2835 new_sig = sig.replace(parameters=new_params.values())
2836 test.__signature__ = new_sig
2837
2838 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2839 (1, 2, 4, 5, 6, {}))
2840
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002841 self.assertEqual(self.call(test, 1, 2),
2842 (1, 2, 3, 42, 50, {}))
2843
2844 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
2845 (1, 2, 3, 4, 5, {}))
2846
2847 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
2848 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
2849
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002850 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002851 self.call(test, 1, 2, c_po=4)
2852
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002853 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002854 self.call(test, a_po=1, b_po=2)
2855
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002856 def test_signature_bind_with_self_arg(self):
2857 # Issue #17071: one of the parameters is named "self
2858 def test(a, self, b):
2859 pass
2860 sig = inspect.signature(test)
2861 ba = sig.bind(1, 2, 3)
2862 self.assertEqual(ba.args, (1, 2, 3))
2863 ba = sig.bind(1, self=2, b=3)
2864 self.assertEqual(ba.args, (1, 2, 3))
2865
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002866 def test_signature_bind_vararg_name(self):
2867 def test(a, *args):
2868 return a, args
2869 sig = inspect.signature(test)
2870
2871 with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
2872 sig.bind(a=0, args=1)
2873
2874 def test(*args, **kwargs):
2875 return args, kwargs
2876 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
2877
2878 sig = inspect.signature(test)
2879 ba = sig.bind(args=1)
2880 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
2881
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002882
2883class TestBoundArguments(unittest.TestCase):
2884 def test_signature_bound_arguments_unhashable(self):
2885 def foo(a): pass
2886 ba = inspect.signature(foo).bind(1)
2887
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002888 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002889 hash(ba)
2890
2891 def test_signature_bound_arguments_equality(self):
2892 def foo(a): pass
2893 ba = inspect.signature(foo).bind(1)
2894 self.assertEqual(ba, ba)
2895
2896 ba2 = inspect.signature(foo).bind(1)
2897 self.assertEqual(ba, ba2)
2898
2899 ba3 = inspect.signature(foo).bind(2)
2900 self.assertNotEqual(ba, ba3)
2901 ba3.arguments['a'] = 1
2902 self.assertEqual(ba, ba3)
2903
2904 def bar(b): pass
2905 ba4 = inspect.signature(bar).bind(1)
2906 self.assertNotEqual(ba, ba4)
2907
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002908 def test_signature_bound_arguments_pickle(self):
2909 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2910 sig = inspect.signature(foo)
2911 ba = sig.bind(20, 30, z={})
2912
2913 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2914 with self.subTest(pickle_ver=ver):
2915 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
2916 self.assertEqual(ba, ba_pickled)
2917
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002918
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002919class TestSignaturePrivateHelpers(unittest.TestCase):
2920 def test_signature_get_bound_param(self):
2921 getter = inspect._signature_get_bound_param
2922
2923 self.assertEqual(getter('($self)'), 'self')
2924 self.assertEqual(getter('($self, obj)'), 'self')
2925 self.assertEqual(getter('($cls, /, obj)'), 'cls')
2926
Larry Hastings2623c8c2014-02-08 22:15:29 -08002927 def _strip_non_python_syntax(self, input,
2928 clean_signature, self_parameter, last_positional_only):
2929 computed_clean_signature, \
2930 computed_self_parameter, \
2931 computed_last_positional_only = \
2932 inspect._signature_strip_non_python_syntax(input)
2933 self.assertEqual(computed_clean_signature, clean_signature)
2934 self.assertEqual(computed_self_parameter, self_parameter)
2935 self.assertEqual(computed_last_positional_only, last_positional_only)
2936
2937 def test_signature_strip_non_python_syntax(self):
2938 self._strip_non_python_syntax(
2939 "($module, /, path, mode, *, dir_fd=None, " +
2940 "effective_ids=False,\n follow_symlinks=True)",
2941 "(module, path, mode, *, dir_fd=None, " +
2942 "effective_ids=False, follow_symlinks=True)",
2943 0,
2944 0)
2945
2946 self._strip_non_python_syntax(
2947 "($module, word, salt, /)",
2948 "(module, word, salt)",
2949 0,
2950 2)
2951
2952 self._strip_non_python_syntax(
2953 "(x, y=None, z=None, /)",
2954 "(x, y=None, z=None)",
2955 None,
2956 2)
2957
2958 self._strip_non_python_syntax(
2959 "(x, y=None, z=None)",
2960 "(x, y=None, z=None)",
2961 None,
2962 None)
2963
2964 self._strip_non_python_syntax(
2965 "(x,\n y=None,\n z = None )",
2966 "(x, y=None, z=None)",
2967 None,
2968 None)
2969
2970 self._strip_non_python_syntax(
2971 "",
2972 "",
2973 None,
2974 None)
2975
2976 self._strip_non_python_syntax(
2977 None,
2978 None,
2979 None,
2980 None)
2981
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002982
Nick Coghlane8c45d62013-07-28 20:00:01 +10002983class TestUnwrap(unittest.TestCase):
2984
2985 def test_unwrap_one(self):
2986 def func(a, b):
2987 return a + b
2988 wrapper = functools.lru_cache(maxsize=20)(func)
2989 self.assertIs(inspect.unwrap(wrapper), func)
2990
2991 def test_unwrap_several(self):
2992 def func(a, b):
2993 return a + b
2994 wrapper = func
2995 for __ in range(10):
2996 @functools.wraps(wrapper)
2997 def wrapper():
2998 pass
2999 self.assertIsNot(wrapper.__wrapped__, func)
3000 self.assertIs(inspect.unwrap(wrapper), func)
3001
3002 def test_stop(self):
3003 def func1(a, b):
3004 return a + b
3005 @functools.wraps(func1)
3006 def func2():
3007 pass
3008 @functools.wraps(func2)
3009 def wrapper():
3010 pass
3011 func2.stop_here = 1
3012 unwrapped = inspect.unwrap(wrapper,
3013 stop=(lambda f: hasattr(f, "stop_here")))
3014 self.assertIs(unwrapped, func2)
3015
3016 def test_cycle(self):
3017 def func1(): pass
3018 func1.__wrapped__ = func1
3019 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3020 inspect.unwrap(func1)
3021
3022 def func2(): pass
3023 func2.__wrapped__ = func1
3024 func1.__wrapped__ = func2
3025 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3026 inspect.unwrap(func1)
3027 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3028 inspect.unwrap(func2)
3029
3030 def test_unhashable(self):
3031 def func(): pass
3032 func.__wrapped__ = None
3033 class C:
3034 __hash__ = None
3035 __wrapped__ = func
3036 self.assertIsNone(inspect.unwrap(C()))
3037
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003038class TestMain(unittest.TestCase):
3039 def test_only_source(self):
3040 module = importlib.import_module('unittest')
3041 rc, out, err = assert_python_ok('-m', 'inspect',
3042 'unittest')
3043 lines = out.decode().splitlines()
3044 # ignore the final newline
3045 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3046 self.assertEqual(err, b'')
3047
Brett Cannon634a8fc2013-10-02 10:25:42 -04003048 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003049 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003050 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003051 rc, out, err = assert_python_ok('-m', 'inspect',
3052 'concurrent.futures:ThreadPoolExecutor')
3053 lines = out.decode().splitlines()
3054 # ignore the final newline
3055 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003056 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003057 self.assertEqual(err, b'')
3058
3059 def test_builtins(self):
3060 module = importlib.import_module('unittest')
3061 _, out, err = assert_python_failure('-m', 'inspect',
3062 'sys')
3063 lines = err.decode().splitlines()
3064 self.assertEqual(lines, ["Can't get info for builtin modules."])
3065
3066 def test_details(self):
3067 module = importlib.import_module('unittest')
3068 rc, out, err = assert_python_ok('-m', 'inspect',
3069 'unittest', '--details')
3070 output = out.decode()
3071 # Just a quick sanity check on the output
3072 self.assertIn(module.__name__, output)
3073 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02003074 if not sys.flags.optimize:
3075 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003076 self.assertEqual(err, b'')
3077
3078
3079
Nick Coghlane8c45d62013-07-28 20:00:01 +10003080
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003081def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003082 run_unittest(
3083 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3084 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3085 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003086 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003087 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003088 TestBoundArguments, TestSignaturePrivateHelpers, TestGetClosureVars,
3089 TestUnwrap, TestMain
Michael Foord95fc51d2010-11-20 15:07:30 +00003090 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003091
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003092if __name__ == "__main__":
3093 test_main()