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