blob: 711d2a3a6ba7172d13f72fa039ff7d49d73a63d6 [file] [log] [blame]
Guido van Rossum813b0e52007-05-21 18:11:34 +00001import collections
Larry Hastings5c661892014-01-24 06:17:25 -08002import datetime
Nick Coghlane8c45d62013-07-28 20:00:01 +10003import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004import importlib
Larry Hastings5c661892014-01-24 06:17:25 -08005import inspect
6import io
7import linecache
8import os
Christian Heimesa3538eb2007-11-06 11:44:48 +00009from os.path import normcase
Larry Hastings5c661892014-01-24 06:17:25 -080010import _pickle
11import re
12import shutil
13import sys
14import types
15import unicodedata
16import unittest
17
Brett Cannon634a8fc2013-10-02 10:25:42 -040018try:
19 from concurrent.futures import ThreadPoolExecutor
20except ImportError:
21 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000022
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020023from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -080024from test.support import MISSING_C_DOCSTRINGS
Nick Coghlanf94a16b2013-09-22 22:46:49 +100025from test.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000026from test import inspect_fodder as mod
27from test import inspect_fodder2 as mod2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000028
R. David Murray74b89242009-05-13 17:33:03 +000029
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000030# Functions tested in this suite:
31# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000032# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
33# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
34# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
35# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000036
Nick Coghlanf088e5e2008-12-14 11:50:48 +000037# NOTE: There are some additional tests relating to interaction with
38# zipimport in the test_zipimport_support test module.
39
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000040modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000041if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000042 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000043
Christian Heimesa3538eb2007-11-06 11:44:48 +000044# Normalize file names: on Windows, the case of file names of compiled
45# modules depends on the path used to start the python executable.
46modfile = normcase(modfile)
47
48def revise(filename, *args):
49 return (normcase(filename),) + args
50
Georg Brandl1a3284e2007-12-02 09:40:06 +000051import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000052
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000053git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000054
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000055class IsTestBase(unittest.TestCase):
56 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
57 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000058 inspect.ismodule, inspect.istraceback,
59 inspect.isgenerator, inspect.isgeneratorfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000060
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000061 def istest(self, predicate, exp):
62 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000063 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000064
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000065 for other in self.predicates - set([predicate]):
Christian Heimes7131fd92008-02-19 14:21:46 +000066 if predicate == inspect.isgeneratorfunction and\
67 other == inspect.isfunction:
68 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000069 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000070
Christian Heimes7131fd92008-02-19 14:21:46 +000071def generator_function_example(self):
72 for i in range(2):
73 yield i
74
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000075class TestPredicates(IsTestBase):
Christian Heimes227c8002008-03-03 20:34:40 +000076 def test_sixteen(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +000077 count = len([x for x in dir(inspect) if x.startswith('is')])
Christian Heimes7131fd92008-02-19 14:21:46 +000078 # This test is here for remember you to update Doc/library/inspect.rst
Christian Heimes78644762008-03-04 23:39:23 +000079 # which claims there are 16 such functions
Christian Heimes227c8002008-03-03 20:34:40 +000080 expected = 16
Thomas Wouters0e3f5912006-08-11 14:57:12 +000081 err_msg = "There are %d (not %d) is* functions" % (count, expected)
82 self.assertEqual(count, expected, err_msg)
Tim Peters5a9fb3c2005-01-07 16:01:32 +000083
Christian Heimes7131fd92008-02-19 14:21:46 +000084
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000085 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +020086 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000087 self.istest(inspect.isbuiltin, 'sys.exit')
88 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +000089 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +020090 try:
91 1/0
92 except:
93 tb = sys.exc_info()[2]
94 self.istest(inspect.isframe, 'tb.tb_frame')
95 self.istest(inspect.istraceback, 'tb')
96 if hasattr(types, 'GetSetDescriptorType'):
97 self.istest(inspect.isgetsetdescriptor,
98 'type(tb.tb_frame).f_locals')
99 else:
100 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
101 finally:
102 # Clear traceback and all the frames and local variables hanging to it.
103 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000104 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000105 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000106 self.istest(inspect.ismethod, 'git.argue')
107 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000108 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000109 self.istest(inspect.isgenerator, '(x for x in range(2))')
110 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000111 if hasattr(types, 'MemberDescriptorType'):
112 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
113 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000114 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000115
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000116 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000117 self.assertTrue(inspect.isroutine(mod.spam))
118 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000119
Benjamin Petersonc4656002009-01-17 22:41:18 +0000120 def test_isclass(self):
121 self.istest(inspect.isclass, 'mod.StupidGit')
122 self.assertTrue(inspect.isclass(list))
123
124 class CustomGetattr(object):
125 def __getattr__(self, attr):
126 return None
127 self.assertFalse(inspect.isclass(CustomGetattr()))
128
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000129 def test_get_slot_members(self):
130 class C(object):
131 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000132 x = C()
133 x.a = 42
134 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000135 self.assertIn('a', members)
136 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000137
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000138 def test_isabstract(self):
139 from abc import ABCMeta, abstractmethod
140
141 class AbstractClassExample(metaclass=ABCMeta):
142
143 @abstractmethod
144 def foo(self):
145 pass
146
147 class ClassExample(AbstractClassExample):
148 def foo(self):
149 pass
150
151 a = ClassExample()
152
153 # Test general behaviour.
154 self.assertTrue(inspect.isabstract(AbstractClassExample))
155 self.assertFalse(inspect.isabstract(ClassExample))
156 self.assertFalse(inspect.isabstract(a))
157 self.assertFalse(inspect.isabstract(int))
158 self.assertFalse(inspect.isabstract(5))
159
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000160
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000161class TestInterpreterStack(IsTestBase):
162 def __init__(self, *args, **kwargs):
163 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000164
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000165 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000166
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000167 def test_abuse_done(self):
168 self.istest(inspect.istraceback, 'git.ex[2]')
169 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000170
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000171 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000172 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000173 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000174 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000175 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000176 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000177 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000178 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000179 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000180 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000181
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000182 def test_trace(self):
183 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000184 self.assertEqual(revise(*git.tr[0][1:]),
185 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
186 self.assertEqual(revise(*git.tr[1][1:]),
187 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
188 self.assertEqual(revise(*git.tr[2][1:]),
189 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000190
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000191 def test_frame(self):
192 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
193 self.assertEqual(args, ['x', 'y'])
194 self.assertEqual(varargs, None)
195 self.assertEqual(varkw, None)
196 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
197 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
198 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000199
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000200 def test_previous_frame(self):
201 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000202 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000203 self.assertEqual(varargs, 'g')
204 self.assertEqual(varkw, 'h')
205 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000206 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000207
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000208class GetSourceBase(unittest.TestCase):
209 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000210 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000211
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000212 def __init__(self, *args, **kwargs):
213 unittest.TestCase.__init__(self, *args, **kwargs)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000214
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000215 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000216 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000217
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000218 def sourcerange(self, top, bottom):
219 lines = self.source.split("\n")
220 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000221
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000222 def assertSourceEqual(self, obj, top, bottom):
223 self.assertEqual(inspect.getsource(obj),
224 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000225
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000226class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000227 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000228
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000229 def test_getclasses(self):
230 classes = inspect.getmembers(mod, inspect.isclass)
231 self.assertEqual(classes,
232 [('FesteringGob', mod.FesteringGob),
233 ('MalodorousPervert', mod.MalodorousPervert),
234 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300235 ('StupidGit', mod.StupidGit),
236 ('Tit', mod.MalodorousPervert),
237 ])
238 tree = inspect.getclasstree([cls[1] for cls in classes])
239 self.assertEqual(tree,
240 [(object, ()),
241 [(mod.ParrotDroppings, (object,)),
242 [(mod.FesteringGob, (mod.MalodorousPervert,
243 mod.ParrotDroppings))
244 ],
245 (mod.StupidGit, (object,)),
246 [(mod.MalodorousPervert, (mod.StupidGit,)),
247 [(mod.FesteringGob, (mod.MalodorousPervert,
248 mod.ParrotDroppings))
249 ]
250 ]
251 ]
252 ])
253 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000254 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000255 [(object, ()),
256 [(mod.ParrotDroppings, (object,)),
257 (mod.StupidGit, (object,)),
258 [(mod.MalodorousPervert, (mod.StupidGit,)),
259 [(mod.FesteringGob, (mod.MalodorousPervert,
260 mod.ParrotDroppings))
261 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000262 ]
263 ]
264 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000265
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000266 def test_getfunctions(self):
267 functions = inspect.getmembers(mod, inspect.isfunction)
268 self.assertEqual(functions, [('eggs', mod.eggs),
269 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000270
R. David Murray378c0cf2010-02-24 01:46:21 +0000271 @unittest.skipIf(sys.flags.optimize >= 2,
272 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000273 def test_getdoc(self):
274 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
275 self.assertEqual(inspect.getdoc(mod.StupidGit),
276 'A longer,\n\nindented\n\ndocstring.')
277 self.assertEqual(inspect.getdoc(git.abuse),
278 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000279
Georg Brandl0c77a822008-06-10 16:37:50 +0000280 def test_cleandoc(self):
281 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
282 'An\nindented\ndocstring.')
283
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000284 def test_getcomments(self):
285 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
286 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000287
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000288 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000289 # Check actual module
290 self.assertEqual(inspect.getmodule(mod), mod)
291 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000292 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000293 # Check a method (no __module__ attribute, falls back to filename)
294 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
295 # Do it again (check the caching isn't broken)
296 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
297 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000298 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000299 # Check filename override
300 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000301
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000302 def test_getsource(self):
303 self.assertSourceEqual(git.abuse, 29, 39)
304 self.assertSourceEqual(mod.StupidGit, 21, 46)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000305
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000306 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000307 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
308 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000309 fn = "_non_existing_filename_used_for_sourcefile_test.py"
310 co = compile("None", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000311 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000312 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200313 try:
314 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
315 finally:
316 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000317
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000318 def test_getfile(self):
319 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000320
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500321 def test_getfile_class_without_module(self):
322 class CM(type):
323 @property
324 def __module__(cls):
325 raise AttributeError
326 class C(metaclass=CM):
327 pass
328 with self.assertRaises(TypeError):
329 inspect.getfile(C)
330
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000331 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000332 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000333 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000334 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000335 m.__file__ = "<string>" # hopefully not a real filename...
336 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000337 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000338 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000339 del sys.modules[name]
340 inspect.getmodule(compile('a=10','','single'))
341
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500342 def test_proceed_with_fake_filename(self):
343 '''doctest monkeypatches linecache to enable inspection'''
344 fn, source = '<test>', 'def x(): pass\n'
345 getlines = linecache.getlines
346 def monkey(filename, module_globals=None):
347 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300348 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500349 else:
350 return getlines(filename, module_globals)
351 linecache.getlines = monkey
352 try:
353 ns = {}
354 exec(compile(source, fn, 'single'), ns)
355 inspect.getsource(ns["x"])
356 finally:
357 linecache.getlines = getlines
358
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000359class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000360 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000361
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000362 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000363 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000364
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000365 def test_replacing_decorator(self):
366 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000367
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000368class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000369 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000370 def test_oneline_lambda(self):
371 # Test inspect.getsource with a one-line lambda function.
372 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000373
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000374 def test_threeline_lambda(self):
375 # Test inspect.getsource with a three-line lambda function,
376 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000377 self.assertSourceEqual(mod2.tll, 28, 30)
378
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000379 def test_twoline_indented_lambda(self):
380 # Test inspect.getsource with a two-line lambda function,
381 # where the second line _is_ indented.
382 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000383
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000384 def test_onelinefunc(self):
385 # Test inspect.getsource with a regular one-line function.
386 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000387
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000388 def test_manyargs(self):
389 # Test inspect.getsource with a regular function where
390 # the arguments are on two lines and _not_ indented and
391 # the body on the second line with the last arguments.
392 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000393
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000394 def test_twolinefunc(self):
395 # Test inspect.getsource with a regular function where
396 # the body is on two lines, following the argument list and
397 # continued on the next line by a \\.
398 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000399
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000400 def test_lambda_in_list(self):
401 # Test inspect.getsource with a one-line lambda function
402 # defined in a list, indented.
403 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000404
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000405 def test_anonymous(self):
406 # Test inspect.getsource with a lambda function defined
407 # as argument to another function.
408 self.assertSourceEqual(mod2.anonymous, 55, 55)
409
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000410class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000411 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000412
413 def test_with_comment(self):
414 self.assertSourceEqual(mod2.with_comment, 58, 59)
415
416 def test_multiline_sig(self):
417 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
418
Armin Rigodd5c0232005-09-25 11:45:45 +0000419 def test_nested_class(self):
420 self.assertSourceEqual(mod2.func69().func71, 71, 72)
421
422 def test_one_liner_followed_by_non_name(self):
423 self.assertSourceEqual(mod2.func77, 77, 77)
424
425 def test_one_liner_dedent_non_name(self):
426 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
427
428 def test_with_comment_instead_of_docstring(self):
429 self.assertSourceEqual(mod2.func88, 88, 90)
430
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000431 def test_method_in_dynamic_class(self):
432 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
433
R. David Murrayb5655772009-05-14 16:17:50 +0000434 @unittest.skipIf(
435 not hasattr(unicodedata, '__file__') or
436 unicodedata.__file__[-4:] in (".pyc", ".pyo"),
437 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000438 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200439 self.assertRaises(OSError, inspect.getsource, unicodedata)
440 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000441
R. David Murraya1b37402010-06-17 02:04:29 +0000442 def test_findsource_code_in_linecache(self):
443 lines = ["x=1"]
444 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200445 self.assertRaises(OSError, inspect.findsource, co)
446 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000447 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200448 try:
449 self.assertEqual(inspect.findsource(co), (lines,0))
450 self.assertEqual(inspect.getsource(co), lines[0])
451 finally:
452 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000453
Ezio Melotti1b145922013-03-30 05:17:24 +0200454 def test_findsource_without_filename(self):
455 for fname in ['', '<string>']:
456 co = compile('x=1', fname, "exec")
457 self.assertRaises(IOError, inspect.findsource, co)
458 self.assertRaises(IOError, inspect.getsource, co)
459
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000460class TestNoEOL(GetSourceBase):
461 def __init__(self, *args, **kwargs):
462 self.tempdir = TESTFN + '_dir'
463 os.mkdir(self.tempdir)
464 with open(os.path.join(self.tempdir,
465 'inspect_fodder3%spy' % os.extsep), 'w') as f:
466 f.write("class X:\n pass # No EOL")
467 with DirsOnSysPath(self.tempdir):
468 import inspect_fodder3 as mod3
469 self.fodderModule = mod3
470 GetSourceBase.__init__(self, *args, **kwargs)
471
472 def tearDown(self):
473 shutil.rmtree(self.tempdir)
474
475 def test_class(self):
476 self.assertSourceEqual(self.fodderModule.X, 1, 2)
477
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100478
479class _BrokenDataDescriptor(object):
480 """
481 A broken data descriptor. See bug #1785.
482 """
483 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700484 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100485
486 def __set__(*args):
487 raise RuntimeError
488
489 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700490 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100491
492
493class _BrokenMethodDescriptor(object):
494 """
495 A broken method descriptor. See bug #1785.
496 """
497 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700498 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100499
500 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700501 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100502
503
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000504# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000505def attrs_wo_objs(cls):
506 return [t[:3] for t in inspect.classify_class_attrs(cls)]
507
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100508
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000509class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000510 def test_newstyle_mro(self):
511 # The same w/ new-class MRO.
512 class A(object): pass
513 class B(A): pass
514 class C(A): pass
515 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000516
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000517 expected = (D, B, C, A, object)
518 got = inspect.getmro(D)
519 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000520
Christian Heimes3795b532007-11-08 13:48:53 +0000521 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
522 varkw_e=None, defaults_e=None, formatted=None):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000523 args, varargs, varkw, defaults = inspect.getargspec(routine)
524 self.assertEqual(args, args_e)
525 self.assertEqual(varargs, varargs_e)
526 self.assertEqual(varkw, varkw_e)
527 self.assertEqual(defaults, defaults_e)
528 if formatted is not None:
529 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
530 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000531
Christian Heimes3795b532007-11-08 13:48:53 +0000532 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
533 varkw_e=None, defaults_e=None,
534 kwonlyargs_e=[], kwonlydefaults_e=None,
535 ann_e={}, formatted=None):
536 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
537 inspect.getfullargspec(routine)
538 self.assertEqual(args, args_e)
539 self.assertEqual(varargs, varargs_e)
540 self.assertEqual(varkw, varkw_e)
541 self.assertEqual(defaults, defaults_e)
542 self.assertEqual(kwonlyargs, kwonlyargs_e)
543 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
544 self.assertEqual(ann, ann_e)
545 if formatted is not None:
546 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
547 kwonlyargs, kwonlydefaults, ann),
548 formatted)
549
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000550 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000551 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000552
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000553 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000554 ['a', 'b', 'c', 'd', 'e', 'f'],
555 'g', 'h', (3, 4, 5),
556 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000557
Christian Heimes3795b532007-11-08 13:48:53 +0000558 self.assertRaises(ValueError, self.assertArgSpecEquals,
559 mod2.keyworded, [])
560
561 self.assertRaises(ValueError, self.assertArgSpecEquals,
562 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000563 self.assertRaises(ValueError, self.assertArgSpecEquals,
564 mod2.keyword_only_arg, [])
565
Christian Heimes3795b532007-11-08 13:48:53 +0000566
567 def test_getfullargspec(self):
568 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
569 kwonlyargs_e=['arg2'],
570 kwonlydefaults_e={'arg2':1},
571 formatted='(*arg1, arg2=1)')
572
573 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000574 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000575 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000576 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
577 kwonlyargs_e=['arg'],
578 formatted='(*, arg)')
579
Yury Selivanovff385b82014-02-19 16:27:23 -0500580 def test_argspec_api_ignores_wrapped(self):
581 # Issue 20684: low level introspection API must ignore __wrapped__
582 @functools.wraps(mod.spam)
583 def ham(x, y):
584 pass
585 # Basic check
586 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
587 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
588 self.assertFullArgSpecEquals(functools.partial(ham),
589 ['x', 'y'], formatted='(x, y)')
590 # Other variants
591 def check_method(f):
592 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
593 formatted='(self, x, y)')
594 class C:
595 @functools.wraps(mod.spam)
596 def ham(self, x, y):
597 pass
598 pham = functools.partialmethod(ham)
599 @functools.wraps(mod.spam)
600 def __call__(self, x, y):
601 pass
602 check_method(C())
603 check_method(C.ham)
604 check_method(C().ham)
605 check_method(C.pham)
606 check_method(C().pham)
607
608 class C_new:
609 @functools.wraps(mod.spam)
610 def __new__(self, x, y):
611 pass
612 check_method(C_new)
613
614 class C_init:
615 @functools.wraps(mod.spam)
616 def __init__(self, x, y):
617 pass
618 check_method(C_init)
619
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500620 def test_getfullargspec_signature_attr(self):
621 def test():
622 pass
623 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
624 test.__signature__ = inspect.Signature(parameters=(spam_param,))
625
626 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
627
Yury Selivanov4cb93912014-01-29 11:54:12 -0500628 def test_getfullargspec_signature_annos(self):
629 def test(a:'spam') -> 'ham': pass
630 spec = inspect.getfullargspec(test)
631 self.assertEqual(test.__annotations__, spec.annotations)
632
633 def test(): pass
634 spec = inspect.getfullargspec(test)
635 self.assertEqual(test.__annotations__, spec.annotations)
636
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500637 @unittest.skipIf(MISSING_C_DOCSTRINGS,
638 "Signature information for builtins requires docstrings")
639 def test_getfullargspec_builtin_methods(self):
640 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
641 args_e=['self', 'obj'], formatted='(self, obj)')
642
643 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
644 args_e=['self', 'obj'], formatted='(self, obj)')
645
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200646 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500647 @unittest.skipIf(MISSING_C_DOCSTRINGS,
648 "Signature information for builtins requires docstrings")
649 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200650 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500651 builtin = _testcapi.docstring_with_signature_with_defaults
652 spec = inspect.getfullargspec(builtin)
653 self.assertEqual(spec.defaults[0], 'avocado')
654
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200655 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500656 @unittest.skipIf(MISSING_C_DOCSTRINGS,
657 "Signature information for builtins requires docstrings")
658 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200659 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500660 builtin = _testcapi.docstring_no_signature
661 with self.assertRaises(TypeError):
662 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000663
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000664 def test_getargspec_method(self):
665 class A(object):
666 def m(self):
667 pass
668 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000669
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000670 def test_classify_newstyle(self):
671 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000672
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000673 def s(): pass
674 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000675
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000676 def c(cls): pass
677 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000678
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000679 def getp(self): pass
680 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000681
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000682 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000683
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000684 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000685
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000686 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000687
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100688 dd = _BrokenDataDescriptor()
689 md = _BrokenMethodDescriptor()
690
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000691 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500692
693 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
694 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
695
Benjamin Peterson577473f2010-01-19 00:09:57 +0000696 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
697 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
698 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000699 self.assertIn(('m', 'method', A), attrs,
700 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000701 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
702 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100703 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
704 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000705
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000706 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000707
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000708 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000709
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000710 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000711 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
712 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
713 self.assertIn(('p', 'property', A), attrs, 'missing property')
714 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
715 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
716 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100717 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
718 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000719
720
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000721 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000722
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000723 def m(self): pass
724 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000725
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000726 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000727 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
728 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
729 self.assertIn(('p', 'property', A), attrs, 'missing property')
730 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
731 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
732 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100733 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
734 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000735
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000736 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000737
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000738 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000739
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000740 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000741 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
742 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
743 self.assertIn(('p', 'property', A), attrs, 'missing property')
744 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
745 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
746 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100747 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
748 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
749
750 def test_classify_builtin_types(self):
751 # Simple sanity check that all built-in types can have their
752 # attributes classified.
753 for name in dir(__builtins__):
754 builtin = getattr(__builtins__, name)
755 if isinstance(builtin, type):
756 inspect.classify_class_attrs(builtin)
757
Ethan Furman63c141c2013-10-18 00:27:39 -0700758 def test_classify_DynamicClassAttribute(self):
759 class Meta(type):
760 def __getattr__(self, name):
761 if name == 'ham':
762 return 'spam'
763 return super().__getattr__(name)
764 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700765 @types.DynamicClassAttribute
766 def ham(self):
767 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700768 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
769 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700770 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700771 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
772
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700773 def test_classify_metaclass_class_attribute(self):
774 class Meta(type):
775 fish = 'slap'
776 def __dir__(self):
777 return ['__class__', '__modules__', '__name__', 'fish']
778 class Class(metaclass=Meta):
779 pass
780 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
781 self.assertIn(should_find, inspect.classify_class_attrs(Class))
782
Ethan Furman63c141c2013-10-18 00:27:39 -0700783 def test_classify_VirtualAttribute(self):
784 class Meta(type):
785 def __dir__(cls):
786 return ['__class__', '__module__', '__name__', 'BOOM']
787 def __getattr__(self, name):
788 if name =='BOOM':
789 return 42
790 return super().__getattr(name)
791 class Class(metaclass=Meta):
792 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700793 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700794 self.assertIn(should_find, inspect.classify_class_attrs(Class))
795
796 def test_classify_VirtualAttribute_multi_classes(self):
797 class Meta1(type):
798 def __dir__(cls):
799 return ['__class__', '__module__', '__name__', 'one']
800 def __getattr__(self, name):
801 if name =='one':
802 return 1
803 return super().__getattr__(name)
804 class Meta2(type):
805 def __dir__(cls):
806 return ['__class__', '__module__', '__name__', 'two']
807 def __getattr__(self, name):
808 if name =='two':
809 return 2
810 return super().__getattr__(name)
811 class Meta3(Meta1, Meta2):
812 def __dir__(cls):
813 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
814 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
815 def __getattr__(self, name):
816 if name =='three':
817 return 3
818 return super().__getattr__(name)
819 class Class1(metaclass=Meta1):
820 pass
821 class Class2(Class1, metaclass=Meta3):
822 pass
823
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700824 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
825 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
826 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700827 cca = inspect.classify_class_attrs(Class2)
828 for sf in (should_find1, should_find2, should_find3):
829 self.assertIn(sf, cca)
830
831 def test_classify_class_attrs_with_buggy_dir(self):
832 class M(type):
833 def __dir__(cls):
834 return ['__class__', '__name__', 'missing']
835 class C(metaclass=M):
836 pass
837 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
838 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700839
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100840 def test_getmembers_descriptors(self):
841 class A(object):
842 dd = _BrokenDataDescriptor()
843 md = _BrokenMethodDescriptor()
844
845 def pred_wrapper(pred):
846 # A quick'n'dirty way to discard standard attributes of new-style
847 # classes.
848 class Empty(object):
849 pass
850 def wrapped(x):
851 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
852 return False
853 return pred(x)
854 return wrapped
855
856 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
857 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
858
859 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
860 [('md', A.__dict__['md'])])
861 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
862 [('dd', A.__dict__['dd'])])
863
864 class B(A):
865 pass
866
867 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
868 [('md', A.__dict__['md'])])
869 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
870 [('dd', A.__dict__['dd'])])
871
Antoine Pitrou0c603812012-01-18 17:40:18 +0100872 def test_getmembers_method(self):
873 class B:
874 def f(self):
875 pass
876
877 self.assertIn(('f', B.f), inspect.getmembers(B))
878 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
879 b = B()
880 self.assertIn(('f', b.f), inspect.getmembers(b))
881 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
882
Ethan Furmane03ea372013-09-25 07:14:41 -0700883 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -0700884 class M(type):
885 def __getattr__(cls, name):
886 if name == 'eggs':
887 return 'scrambled'
888 return super().__getattr__(name)
889 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -0700890 @types.DynamicClassAttribute
891 def eggs(self):
892 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -0700893 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
894 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
895
896 def test_getmembers_with_buggy_dir(self):
897 class M(type):
898 def __dir__(cls):
899 return ['__class__', '__name__', 'missing']
900 class C(metaclass=M):
901 pass
902 attrs = [a[0] for a in inspect.getmembers(C)]
903 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700904
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000905
Nick Coghlan2f92e542012-06-23 19:39:55 +1000906_global_ref = object()
907class TestGetClosureVars(unittest.TestCase):
908
909 def test_name_resolution(self):
910 # Basic test of the 4 different resolution mechanisms
911 def f(nonlocal_ref):
912 def g(local_ref):
913 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
914 return g
915 _arg = object()
916 nonlocal_vars = {"nonlocal_ref": _arg}
917 global_vars = {"_global_ref": _global_ref}
918 builtin_vars = {"print": print}
919 unbound_names = {"unbound_ref"}
920 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
921 builtin_vars, unbound_names)
922 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
923
924 def test_generator_closure(self):
925 def f(nonlocal_ref):
926 def g(local_ref):
927 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
928 yield
929 return g
930 _arg = object()
931 nonlocal_vars = {"nonlocal_ref": _arg}
932 global_vars = {"_global_ref": _global_ref}
933 builtin_vars = {"print": print}
934 unbound_names = {"unbound_ref"}
935 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
936 builtin_vars, unbound_names)
937 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
938
939 def test_method_closure(self):
940 class C:
941 def f(self, nonlocal_ref):
942 def g(local_ref):
943 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
944 return g
945 _arg = object()
946 nonlocal_vars = {"nonlocal_ref": _arg}
947 global_vars = {"_global_ref": _global_ref}
948 builtin_vars = {"print": print}
949 unbound_names = {"unbound_ref"}
950 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
951 builtin_vars, unbound_names)
952 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
953
954 def test_nonlocal_vars(self):
955 # More complex tests of nonlocal resolution
956 def _nonlocal_vars(f):
957 return inspect.getclosurevars(f).nonlocals
958
959 def make_adder(x):
960 def add(y):
961 return x + y
962 return add
963
964 def curry(func, arg1):
965 return lambda arg2: func(arg1, arg2)
966
967 def less_than(a, b):
968 return a < b
969
970 # The infamous Y combinator.
971 def Y(le):
972 def g(f):
973 return le(lambda x: f(f)(x))
974 Y.g_ref = g
975 return g(g)
976
977 def check_y_combinator(func):
978 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
979
980 inc = make_adder(1)
981 add_two = make_adder(2)
982 greater_than_five = curry(less_than, 5)
983
984 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
985 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
986 self.assertEqual(_nonlocal_vars(greater_than_five),
987 {'arg1': 5, 'func': less_than})
988 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
989 {'x': 3})
990 Y(check_y_combinator)
991
992 def test_getclosurevars_empty(self):
993 def foo(): pass
994 _empty = inspect.ClosureVars({}, {}, {}, set())
995 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
996 self.assertEqual(inspect.getclosurevars(foo), _empty)
997
998 def test_getclosurevars_error(self):
999 class T: pass
1000 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1001 self.assertRaises(TypeError, inspect.getclosurevars, list)
1002 self.assertRaises(TypeError, inspect.getclosurevars, {})
1003
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001004 def _private_globals(self):
1005 code = """def f(): print(path)"""
1006 ns = {}
1007 exec(code, ns)
1008 return ns["f"], ns
1009
1010 def test_builtins_fallback(self):
1011 f, ns = self._private_globals()
1012 ns.pop("__builtins__", None)
1013 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1014 self.assertEqual(inspect.getclosurevars(f), expected)
1015
1016 def test_builtins_as_dict(self):
1017 f, ns = self._private_globals()
1018 ns["__builtins__"] = {"path":1}
1019 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1020 self.assertEqual(inspect.getclosurevars(f), expected)
1021
1022 def test_builtins_as_module(self):
1023 f, ns = self._private_globals()
1024 ns["__builtins__"] = os
1025 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1026 self.assertEqual(inspect.getclosurevars(f), expected)
1027
Nick Coghlan2f92e542012-06-23 19:39:55 +10001028
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001029class TestGetcallargsFunctions(unittest.TestCase):
1030
1031 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1032 locs = dict(locs or {}, func=func)
1033 r1 = eval('func(%s)' % call_params_string, None, locs)
1034 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1035 locs)
1036 self.assertEqual(r1, r2)
1037
1038 def assertEqualException(self, func, call_param_string, locs=None):
1039 locs = dict(locs or {}, func=func)
1040 try:
1041 eval('func(%s)' % call_param_string, None, locs)
1042 except Exception as e:
1043 ex1 = e
1044 else:
1045 self.fail('Exception not raised')
1046 try:
1047 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1048 locs)
1049 except Exception as e:
1050 ex2 = e
1051 else:
1052 self.fail('Exception not raised')
1053 self.assertIs(type(ex1), type(ex2))
1054 self.assertEqual(str(ex1), str(ex2))
1055 del ex1, ex2
1056
1057 def makeCallable(self, signature):
1058 """Create a function that returns its locals()"""
1059 code = "lambda %s: locals()"
1060 return eval(code % signature)
1061
1062 def test_plain(self):
1063 f = self.makeCallable('a, b=1')
1064 self.assertEqualCallArgs(f, '2')
1065 self.assertEqualCallArgs(f, '2, 3')
1066 self.assertEqualCallArgs(f, 'a=2')
1067 self.assertEqualCallArgs(f, 'b=3, a=2')
1068 self.assertEqualCallArgs(f, '2, b=3')
1069 # expand *iterable / **mapping
1070 self.assertEqualCallArgs(f, '*(2,)')
1071 self.assertEqualCallArgs(f, '*[2]')
1072 self.assertEqualCallArgs(f, '*(2, 3)')
1073 self.assertEqualCallArgs(f, '*[2, 3]')
1074 self.assertEqualCallArgs(f, '**{"a":2}')
1075 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1076 self.assertEqualCallArgs(f, '2, **{"b":3}')
1077 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1078 # expand UserList / UserDict
1079 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1080 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1081 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1082 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1083 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1084
1085 def test_varargs(self):
1086 f = self.makeCallable('a, b=1, *c')
1087 self.assertEqualCallArgs(f, '2')
1088 self.assertEqualCallArgs(f, '2, 3')
1089 self.assertEqualCallArgs(f, '2, 3, 4')
1090 self.assertEqualCallArgs(f, '*(2,3,4)')
1091 self.assertEqualCallArgs(f, '2, *[3,4]')
1092 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1093
1094 def test_varkw(self):
1095 f = self.makeCallable('a, b=1, **c')
1096 self.assertEqualCallArgs(f, 'a=2')
1097 self.assertEqualCallArgs(f, '2, b=3, c=4')
1098 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1099 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1100 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1101 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1102 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1103 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1104 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1105
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001106 def test_varkw_only(self):
1107 # issue11256:
1108 f = self.makeCallable('**c')
1109 self.assertEqualCallArgs(f, '')
1110 self.assertEqualCallArgs(f, 'a=1')
1111 self.assertEqualCallArgs(f, 'a=1, b=2')
1112 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1113 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1114 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1115
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001116 def test_keyword_only(self):
1117 f = self.makeCallable('a=3, *, c, d=2')
1118 self.assertEqualCallArgs(f, 'c=3')
1119 self.assertEqualCallArgs(f, 'c=3, a=3')
1120 self.assertEqualCallArgs(f, 'a=2, c=4')
1121 self.assertEqualCallArgs(f, '4, c=4')
1122 self.assertEqualException(f, '')
1123 self.assertEqualException(f, '3')
1124 self.assertEqualException(f, 'a=3')
1125 self.assertEqualException(f, 'd=4')
1126
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001127 f = self.makeCallable('*, c, d=2')
1128 self.assertEqualCallArgs(f, 'c=3')
1129 self.assertEqualCallArgs(f, 'c=3, d=4')
1130 self.assertEqualCallArgs(f, 'd=4, c=3')
1131
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001132 def test_multiple_features(self):
1133 f = self.makeCallable('a, b=2, *f, **g')
1134 self.assertEqualCallArgs(f, '2, 3, 7')
1135 self.assertEqualCallArgs(f, '2, 3, x=8')
1136 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1137 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1138 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1139 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1140 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1141 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1142 '(4,[5,6])]), **collections.UserDict('
1143 'y=9, z=10)')
1144
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001145 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1146 self.assertEqualCallArgs(f, '2, 3, x=8')
1147 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1148 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1149 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1150 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1151 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1152 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1153 '(4,[5,6])]), q=0, **collections.UserDict('
1154 'y=9, z=10)')
1155
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001156 def test_errors(self):
1157 f0 = self.makeCallable('')
1158 f1 = self.makeCallable('a, b')
1159 f2 = self.makeCallable('a, b=1')
1160 # f0 takes no arguments
1161 self.assertEqualException(f0, '1')
1162 self.assertEqualException(f0, 'x=1')
1163 self.assertEqualException(f0, '1,x=1')
1164 # f1 takes exactly 2 arguments
1165 self.assertEqualException(f1, '')
1166 self.assertEqualException(f1, '1')
1167 self.assertEqualException(f1, 'a=2')
1168 self.assertEqualException(f1, 'b=3')
1169 # f2 takes at least 1 argument
1170 self.assertEqualException(f2, '')
1171 self.assertEqualException(f2, 'b=3')
1172 for f in f1, f2:
1173 # f1/f2 takes exactly/at most 2 arguments
1174 self.assertEqualException(f, '2, 3, 4')
1175 self.assertEqualException(f, '1, 2, 3, a=1')
1176 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001177 # XXX: success of this one depends on dict order
1178 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001179 # f got an unexpected keyword argument
1180 self.assertEqualException(f, 'c=2')
1181 self.assertEqualException(f, '2, c=3')
1182 self.assertEqualException(f, '2, 3, c=4')
1183 self.assertEqualException(f, '2, c=4, b=3')
1184 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1185 # f got multiple values for keyword argument
1186 self.assertEqualException(f, '1, a=2')
1187 self.assertEqualException(f, '1, **{"a":2}')
1188 self.assertEqualException(f, '1, 2, b=3')
1189 # XXX: Python inconsistency
1190 # - for functions and bound methods: unexpected keyword 'c'
1191 # - for unbound methods: multiple values for keyword 'a'
1192 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001193 # issue11256:
1194 f3 = self.makeCallable('**c')
1195 self.assertEqualException(f3, '1, 2')
1196 self.assertEqualException(f3, '1, 2, a=1, b=2')
1197 f4 = self.makeCallable('*, a, b=0')
1198 self.assertEqualException(f3, '1, 2')
1199 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001200
1201class TestGetcallargsMethods(TestGetcallargsFunctions):
1202
1203 def setUp(self):
1204 class Foo(object):
1205 pass
1206 self.cls = Foo
1207 self.inst = Foo()
1208
1209 def makeCallable(self, signature):
1210 assert 'self' not in signature
1211 mk = super(TestGetcallargsMethods, self).makeCallable
1212 self.cls.method = mk('self, ' + signature)
1213 return self.inst.method
1214
1215class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1216
1217 def makeCallable(self, signature):
1218 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1219 return self.cls.method
1220
1221 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1222 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1223 *self._getAssertEqualParams(func, call_params_string, locs))
1224
1225 def assertEqualException(self, func, call_params_string, locs=None):
1226 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1227 *self._getAssertEqualParams(func, call_params_string, locs))
1228
1229 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1230 assert 'inst' not in call_params_string
1231 locs = dict(locs or {}, inst=self.inst)
1232 return (func, 'inst,' + call_params_string, locs)
1233
Michael Foord95fc51d2010-11-20 15:07:30 +00001234
1235class TestGetattrStatic(unittest.TestCase):
1236
1237 def test_basic(self):
1238 class Thing(object):
1239 x = object()
1240
1241 thing = Thing()
1242 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1243 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1244 with self.assertRaises(AttributeError):
1245 inspect.getattr_static(thing, 'y')
1246
1247 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1248
1249 def test_inherited(self):
1250 class Thing(object):
1251 x = object()
1252 class OtherThing(Thing):
1253 pass
1254
1255 something = OtherThing()
1256 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1257
1258 def test_instance_attr(self):
1259 class Thing(object):
1260 x = 2
1261 def __init__(self, x):
1262 self.x = x
1263 thing = Thing(3)
1264 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1265 del thing.x
1266 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1267
1268 def test_property(self):
1269 class Thing(object):
1270 @property
1271 def x(self):
1272 raise AttributeError("I'm pretending not to exist")
1273 thing = Thing()
1274 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1275
Ezio Melotti75cbd732011-04-28 00:59:29 +03001276 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001277 class descriptor(object):
1278 def __get__(*_):
1279 raise AttributeError("I'm pretending not to exist")
1280 desc = descriptor()
1281 class Thing(object):
1282 x = desc
1283 thing = Thing()
1284 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1285
1286 def test_classAttribute(self):
1287 class Thing(object):
1288 x = object()
1289
1290 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1291
Ethan Furmane03ea372013-09-25 07:14:41 -07001292 def test_classVirtualAttribute(self):
1293 class Thing(object):
1294 @types.DynamicClassAttribute
1295 def x(self):
1296 return self._x
1297 _x = object()
1298
1299 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1300
Michael Foord95fc51d2010-11-20 15:07:30 +00001301 def test_inherited_classattribute(self):
1302 class Thing(object):
1303 x = object()
1304 class OtherThing(Thing):
1305 pass
1306
1307 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1308
1309 def test_slots(self):
1310 class Thing(object):
1311 y = 'bar'
1312 __slots__ = ['x']
1313 def __init__(self):
1314 self.x = 'foo'
1315 thing = Thing()
1316 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1317 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1318
1319 del thing.x
1320 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1321
1322 def test_metaclass(self):
1323 class meta(type):
1324 attr = 'foo'
1325 class Thing(object, metaclass=meta):
1326 pass
1327 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1328
1329 class sub(meta):
1330 pass
1331 class OtherThing(object, metaclass=sub):
1332 x = 3
1333 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1334
1335 class OtherOtherThing(OtherThing):
1336 pass
1337 # this test is odd, but it was added as it exposed a bug
1338 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1339
1340 def test_no_dict_no_slots(self):
1341 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1342 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1343
1344 def test_no_dict_no_slots_instance_member(self):
1345 # returns descriptor
1346 with open(__file__) as handle:
1347 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1348
1349 def test_inherited_slots(self):
1350 # returns descriptor
1351 class Thing(object):
1352 __slots__ = ['x']
1353 def __init__(self):
1354 self.x = 'foo'
1355
1356 class OtherThing(Thing):
1357 pass
1358 # it would be nice if this worked...
1359 # we get the descriptor instead of the instance attribute
1360 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1361
1362 def test_descriptor(self):
1363 class descriptor(object):
1364 def __get__(self, instance, owner):
1365 return 3
1366 class Foo(object):
1367 d = descriptor()
1368
1369 foo = Foo()
1370
1371 # for a non data descriptor we return the instance attribute
1372 foo.__dict__['d'] = 1
1373 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1374
1375 # if the descriptor is a data-desciptor we should return the
1376 # descriptor
1377 descriptor.__set__ = lambda s, i, v: None
1378 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1379
1380
1381 def test_metaclass_with_descriptor(self):
1382 class descriptor(object):
1383 def __get__(self, instance, owner):
1384 return 3
1385 class meta(type):
1386 d = descriptor()
1387 class Thing(object, metaclass=meta):
1388 pass
1389 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1390
1391
Michael Foordcc7ebb82010-11-20 16:20:16 +00001392 def test_class_as_property(self):
1393 class Base(object):
1394 foo = 3
1395
1396 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001397 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001398 @property
1399 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001400 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001401 return object
1402
Michael Foord35184ed2010-11-20 16:58:30 +00001403 instance = Something()
1404 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1405 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001406 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1407
Michael Foorde5162652010-11-20 16:40:44 +00001408 def test_mro_as_property(self):
1409 class Meta(type):
1410 @property
1411 def __mro__(self):
1412 return (object,)
1413
1414 class Base(object):
1415 foo = 3
1416
1417 class Something(Base, metaclass=Meta):
1418 pass
1419
1420 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1421 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1422
Michael Foorddcebe0f2011-03-15 19:20:44 -04001423 def test_dict_as_property(self):
1424 test = self
1425 test.called = False
1426
1427 class Foo(dict):
1428 a = 3
1429 @property
1430 def __dict__(self):
1431 test.called = True
1432 return {}
1433
1434 foo = Foo()
1435 foo.a = 4
1436 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1437 self.assertFalse(test.called)
1438
1439 def test_custom_object_dict(self):
1440 test = self
1441 test.called = False
1442
1443 class Custom(dict):
1444 def get(self, key, default=None):
1445 test.called = True
1446 super().get(key, default)
1447
1448 class Foo(object):
1449 a = 3
1450 foo = Foo()
1451 foo.__dict__ = Custom()
1452 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1453 self.assertFalse(test.called)
1454
1455 def test_metaclass_dict_as_property(self):
1456 class Meta(type):
1457 @property
1458 def __dict__(self):
1459 self.executed = True
1460
1461 class Thing(metaclass=Meta):
1462 executed = False
1463
1464 def __init__(self):
1465 self.spam = 42
1466
1467 instance = Thing()
1468 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1469 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001470
Michael Foorda51623b2011-12-18 22:01:40 +00001471 def test_module(self):
1472 sentinel = object()
1473 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1474 sentinel)
1475
Michael Foord3ba95f82011-12-22 01:13:37 +00001476 def test_metaclass_with_metaclass_with_dict_as_property(self):
1477 class MetaMeta(type):
1478 @property
1479 def __dict__(self):
1480 self.executed = True
1481 return dict(spam=42)
1482
1483 class Meta(type, metaclass=MetaMeta):
1484 executed = False
1485
1486 class Thing(metaclass=Meta):
1487 pass
1488
1489 with self.assertRaises(AttributeError):
1490 inspect.getattr_static(Thing, "spam")
1491 self.assertFalse(Thing.executed)
1492
Nick Coghlane0f04652010-11-21 03:44:04 +00001493class TestGetGeneratorState(unittest.TestCase):
1494
1495 def setUp(self):
1496 def number_generator():
1497 for number in range(5):
1498 yield number
1499 self.generator = number_generator()
1500
1501 def _generatorstate(self):
1502 return inspect.getgeneratorstate(self.generator)
1503
1504 def test_created(self):
1505 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1506
1507 def test_suspended(self):
1508 next(self.generator)
1509 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1510
1511 def test_closed_after_exhaustion(self):
1512 for i in self.generator:
1513 pass
1514 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1515
1516 def test_closed_after_immediate_exception(self):
1517 with self.assertRaises(RuntimeError):
1518 self.generator.throw(RuntimeError)
1519 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1520
1521 def test_running(self):
1522 # As mentioned on issue #10220, checking for the RUNNING state only
1523 # makes sense inside the generator itself.
1524 # The following generator checks for this by using the closure's
1525 # reference to self and the generator state checking helper method
1526 def running_check_generator():
1527 for number in range(5):
1528 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1529 yield number
1530 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1531 self.generator = running_check_generator()
1532 # Running up to the first yield
1533 next(self.generator)
1534 # Running after the first yield
1535 next(self.generator)
1536
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001537 def test_easy_debugging(self):
1538 # repr() and str() of a generator state should contain the state name
1539 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1540 for name in names:
1541 state = getattr(inspect, name)
1542 self.assertIn(name, repr(state))
1543 self.assertIn(name, str(state))
1544
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001545 def test_getgeneratorlocals(self):
1546 def each(lst, a=None):
1547 b=(1, 2, 3)
1548 for v in lst:
1549 if v == 3:
1550 c = 12
1551 yield v
1552
1553 numbers = each([1, 2, 3])
1554 self.assertEqual(inspect.getgeneratorlocals(numbers),
1555 {'a': None, 'lst': [1, 2, 3]})
1556 next(numbers)
1557 self.assertEqual(inspect.getgeneratorlocals(numbers),
1558 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1559 'b': (1, 2, 3)})
1560 next(numbers)
1561 self.assertEqual(inspect.getgeneratorlocals(numbers),
1562 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1563 'b': (1, 2, 3)})
1564 next(numbers)
1565 self.assertEqual(inspect.getgeneratorlocals(numbers),
1566 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1567 'b': (1, 2, 3), 'c': 12})
1568 try:
1569 next(numbers)
1570 except StopIteration:
1571 pass
1572 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1573
1574 def test_getgeneratorlocals_empty(self):
1575 def yield_one():
1576 yield 1
1577 one = yield_one()
1578 self.assertEqual(inspect.getgeneratorlocals(one), {})
1579 try:
1580 next(one)
1581 except StopIteration:
1582 pass
1583 self.assertEqual(inspect.getgeneratorlocals(one), {})
1584
1585 def test_getgeneratorlocals_error(self):
1586 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1587 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1588 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1589 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1590
Nick Coghlane0f04652010-11-21 03:44:04 +00001591
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001592class TestSignatureObject(unittest.TestCase):
1593 @staticmethod
1594 def signature(func):
1595 sig = inspect.signature(func)
1596 return (tuple((param.name,
1597 (... if param.default is param.empty else param.default),
1598 (... if param.annotation is param.empty
1599 else param.annotation),
1600 str(param.kind).lower())
1601 for param in sig.parameters.values()),
1602 (... if sig.return_annotation is sig.empty
1603 else sig.return_annotation))
1604
1605 def test_signature_object(self):
1606 S = inspect.Signature
1607 P = inspect.Parameter
1608
1609 self.assertEqual(str(S()), '()')
1610
Yury Selivanov07a9e452014-01-29 10:58:16 -05001611 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001612 pass
1613 sig = inspect.signature(test)
1614 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001615 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001616 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001617 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001618 args = sig.parameters['args']
1619 ko = sig.parameters['ko']
1620 kwargs = sig.parameters['kwargs']
1621
1622 S((po, pk, args, ko, kwargs))
1623
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001624 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001625 S((pk, po, args, ko, kwargs))
1626
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001627 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001628 S((po, args, pk, ko, kwargs))
1629
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001630 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001631 S((args, po, pk, ko, kwargs))
1632
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001633 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001634 S((po, pk, args, kwargs, ko))
1635
1636 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001637 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001638 S((po, pk, args, kwargs2, ko))
1639
Yury Selivanov07a9e452014-01-29 10:58:16 -05001640 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1641 S((pod, po))
1642
1643 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1644 S((po, pkd, pk))
1645
1646 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1647 S((pkd, pk))
1648
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001649 def test_signature_immutability(self):
1650 def test(a):
1651 pass
1652 sig = inspect.signature(test)
1653
1654 with self.assertRaises(AttributeError):
1655 sig.foo = 'bar'
1656
1657 with self.assertRaises(TypeError):
1658 sig.parameters['a'] = None
1659
1660 def test_signature_on_noarg(self):
1661 def test():
1662 pass
1663 self.assertEqual(self.signature(test), ((), ...))
1664
1665 def test_signature_on_wargs(self):
1666 def test(a, b:'foo') -> 123:
1667 pass
1668 self.assertEqual(self.signature(test),
1669 ((('a', ..., ..., "positional_or_keyword"),
1670 ('b', ..., 'foo', "positional_or_keyword")),
1671 123))
1672
1673 def test_signature_on_wkwonly(self):
1674 def test(*, a:float, b:str) -> int:
1675 pass
1676 self.assertEqual(self.signature(test),
1677 ((('a', ..., float, "keyword_only"),
1678 ('b', ..., str, "keyword_only")),
1679 int))
1680
1681 def test_signature_on_complex_args(self):
1682 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1683 pass
1684 self.assertEqual(self.signature(test),
1685 ((('a', ..., ..., "positional_or_keyword"),
1686 ('b', 10, 'foo', "positional_or_keyword"),
1687 ('args', ..., 'bar', "var_positional"),
1688 ('spam', ..., 'baz', "keyword_only"),
1689 ('ham', 123, ..., "keyword_only"),
1690 ('kwargs', ..., int, "var_keyword")),
1691 ...))
1692
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001693 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001694 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1695 "Signature information for builtins requires docstrings")
1696 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001697 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001698
Larry Hastings5c661892014-01-24 06:17:25 -08001699 def test_unbound_method(o):
1700 """Use this to test unbound methods (things that should have a self)"""
1701 signature = inspect.signature(o)
1702 self.assertTrue(isinstance(signature, inspect.Signature))
1703 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1704 return signature
1705
1706 def test_callable(o):
1707 """Use this to test bound methods or normal callables (things that don't expect self)"""
1708 signature = inspect.signature(o)
1709 self.assertTrue(isinstance(signature, inspect.Signature))
1710 if signature.parameters:
1711 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1712 return signature
1713
1714 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001715 def p(name): return signature.parameters[name].default
1716 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001717 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001718 self.assertEqual(p('d'), 3.14)
1719 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001720 self.assertEqual(p('n'), None)
1721 self.assertEqual(p('t'), True)
1722 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001723 self.assertEqual(p('local'), 3)
1724 self.assertEqual(p('sys'), sys.maxsize)
1725 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001726
Larry Hastings5c661892014-01-24 06:17:25 -08001727 test_callable(object)
1728
1729 # normal method
1730 # (PyMethodDescr_Type, "method_descriptor")
1731 test_unbound_method(_pickle.Pickler.dump)
1732 d = _pickle.Pickler(io.StringIO())
1733 test_callable(d.dump)
1734
1735 # static method
1736 test_callable(str.maketrans)
1737 test_callable('abc'.maketrans)
1738
1739 # class method
1740 test_callable(dict.fromkeys)
1741 test_callable({}.fromkeys)
1742
1743 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1744 test_unbound_method(type.__call__)
1745 test_unbound_method(int.__add__)
1746 test_callable((3).__add__)
1747
1748 # _PyMethodWrapper_Type
1749 # support for 'method-wrapper'
1750 test_callable(min.__call__)
1751
Larry Hastings2623c8c2014-02-08 22:15:29 -08001752 # This doesn't work now.
1753 # (We don't have a valid signature for "type" in 3.4)
1754 with self.assertRaisesRegex(ValueError, "no signature found"):
1755 class ThisWorksNow:
1756 __call__ = type
1757 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08001758
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001759 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05001760 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1761 "Signature information for builtins requires docstrings")
1762 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001763 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05001764 func = _testcapi.docstring_with_signature_with_defaults
1765
1766 def decorator(func):
1767 @functools.wraps(func)
1768 def wrapper(*args, **kwargs) -> int:
1769 return func(*args, **kwargs)
1770 return wrapper
1771
1772 decorated_func = decorator(func)
1773
1774 self.assertEqual(inspect.signature(func),
1775 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08001776
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001777 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08001778 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001779 import _testcapi
Larry Hastings5c661892014-01-24 06:17:25 -08001780 with self.assertRaisesRegex(ValueError, 'no signature found for builtin'):
1781 inspect.signature(_testcapi.docstring_no_signature)
1782
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001783 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001784 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001785 inspect.signature(42)
1786
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001787 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001788 inspect.Signature.from_function(42)
1789
Yury Selivanovb77511d2014-01-29 10:46:14 -05001790 def test_signature_from_builtin_errors(self):
1791 with self.assertRaisesRegex(TypeError, 'is not a Python builtin'):
1792 inspect.Signature.from_builtin(42)
1793
Yury Selivanov63da7c72014-01-31 14:48:37 -05001794 def test_signature_from_functionlike_object(self):
1795 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1796 pass
1797
1798 class funclike:
1799 # Has to be callable, and have correct
1800 # __code__, __annotations__, __defaults__, __name__,
1801 # and __kwdefaults__ attributes
1802
1803 def __init__(self, func):
1804 self.__name__ = func.__name__
1805 self.__code__ = func.__code__
1806 self.__annotations__ = func.__annotations__
1807 self.__defaults__ = func.__defaults__
1808 self.__kwdefaults__ = func.__kwdefaults__
1809 self.func = func
1810
1811 def __call__(self, *args, **kwargs):
1812 return self.func(*args, **kwargs)
1813
1814 sig_func = inspect.Signature.from_function(func)
1815
1816 sig_funclike = inspect.Signature.from_function(funclike(func))
1817 self.assertEqual(sig_funclike, sig_func)
1818
1819 sig_funclike = inspect.signature(funclike(func))
1820 self.assertEqual(sig_funclike, sig_func)
1821
1822 # If object is not a duck type of function, then
1823 # signature will try to get a signature for its '__call__'
1824 # method
1825 fl = funclike(func)
1826 del fl.__defaults__
1827 self.assertEqual(self.signature(fl),
1828 ((('args', ..., ..., "var_positional"),
1829 ('kwargs', ..., ..., "var_keyword")),
1830 ...))
1831
1832 def test_signature_functionlike_class(self):
1833 # We only want to duck type function-like objects,
1834 # not classes.
1835
1836 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1837 pass
1838
1839 class funclike:
1840 def __init__(self, marker):
1841 pass
1842
1843 __name__ = func.__name__
1844 __code__ = func.__code__
1845 __annotations__ = func.__annotations__
1846 __defaults__ = func.__defaults__
1847 __kwdefaults__ = func.__kwdefaults__
1848
1849 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1850 inspect.Signature.from_function(funclike)
1851
1852 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
1853
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001854 def test_signature_on_method(self):
1855 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05001856 def __init__(*args):
1857 pass
1858 def m1(self, arg1, arg2=1) -> int:
1859 pass
1860 def m2(*args):
1861 pass
1862 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001863 pass
1864
Yury Selivanov62560fb2014-01-28 12:26:24 -05001865 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001866 ((('arg1', ..., ..., "positional_or_keyword"),
1867 ('arg2', 1, ..., "positional_or_keyword")),
1868 int))
1869
Yury Selivanov62560fb2014-01-28 12:26:24 -05001870 self.assertEqual(self.signature(Test().m2),
1871 ((('args', ..., ..., "var_positional"),),
1872 ...))
1873
1874 self.assertEqual(self.signature(Test),
1875 ((('args', ..., ..., "var_positional"),),
1876 ...))
1877
1878 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
1879 self.signature(Test())
1880
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001881 def test_signature_on_classmethod(self):
1882 class Test:
1883 @classmethod
1884 def foo(cls, arg1, *, arg2=1):
1885 pass
1886
1887 meth = Test().foo
1888 self.assertEqual(self.signature(meth),
1889 ((('arg1', ..., ..., "positional_or_keyword"),
1890 ('arg2', 1, ..., "keyword_only")),
1891 ...))
1892
1893 meth = Test.foo
1894 self.assertEqual(self.signature(meth),
1895 ((('arg1', ..., ..., "positional_or_keyword"),
1896 ('arg2', 1, ..., "keyword_only")),
1897 ...))
1898
1899 def test_signature_on_staticmethod(self):
1900 class Test:
1901 @staticmethod
1902 def foo(cls, *, arg):
1903 pass
1904
1905 meth = Test().foo
1906 self.assertEqual(self.signature(meth),
1907 ((('cls', ..., ..., "positional_or_keyword"),
1908 ('arg', ..., ..., "keyword_only")),
1909 ...))
1910
1911 meth = Test.foo
1912 self.assertEqual(self.signature(meth),
1913 ((('cls', ..., ..., "positional_or_keyword"),
1914 ('arg', ..., ..., "keyword_only")),
1915 ...))
1916
1917 def test_signature_on_partial(self):
1918 from functools import partial
1919
1920 def test():
1921 pass
1922
1923 self.assertEqual(self.signature(partial(test)), ((), ...))
1924
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001925 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001926 inspect.signature(partial(test, 1))
1927
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001928 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001929 inspect.signature(partial(test, a=1))
1930
1931 def test(a, b, *, c, d):
1932 pass
1933
1934 self.assertEqual(self.signature(partial(test)),
1935 ((('a', ..., ..., "positional_or_keyword"),
1936 ('b', ..., ..., "positional_or_keyword"),
1937 ('c', ..., ..., "keyword_only"),
1938 ('d', ..., ..., "keyword_only")),
1939 ...))
1940
1941 self.assertEqual(self.signature(partial(test, 1)),
1942 ((('b', ..., ..., "positional_or_keyword"),
1943 ('c', ..., ..., "keyword_only"),
1944 ('d', ..., ..., "keyword_only")),
1945 ...))
1946
1947 self.assertEqual(self.signature(partial(test, 1, c=2)),
1948 ((('b', ..., ..., "positional_or_keyword"),
1949 ('c', 2, ..., "keyword_only"),
1950 ('d', ..., ..., "keyword_only")),
1951 ...))
1952
1953 self.assertEqual(self.signature(partial(test, b=1, c=2)),
1954 ((('a', ..., ..., "positional_or_keyword"),
1955 ('b', 1, ..., "positional_or_keyword"),
1956 ('c', 2, ..., "keyword_only"),
1957 ('d', ..., ..., "keyword_only")),
1958 ...))
1959
1960 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
1961 ((('b', 1, ..., "positional_or_keyword"),
1962 ('c', 2, ..., "keyword_only"),
1963 ('d', ..., ..., "keyword_only"),),
1964 ...))
1965
1966 def test(a, *args, b, **kwargs):
1967 pass
1968
1969 self.assertEqual(self.signature(partial(test, 1)),
1970 ((('args', ..., ..., "var_positional"),
1971 ('b', ..., ..., "keyword_only"),
1972 ('kwargs', ..., ..., "var_keyword")),
1973 ...))
1974
1975 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
1976 ((('args', ..., ..., "var_positional"),
1977 ('b', ..., ..., "keyword_only"),
1978 ('kwargs', ..., ..., "var_keyword")),
1979 ...))
1980
1981
1982 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
1983 ((('args', ..., ..., "var_positional"),
1984 ('b', ..., ..., "keyword_only"),
1985 ('kwargs', ..., ..., "var_keyword")),
1986 ...))
1987
1988 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
1989 ((('args', ..., ..., "var_positional"),
1990 ('b', 0, ..., "keyword_only"),
1991 ('kwargs', ..., ..., "var_keyword")),
1992 ...))
1993
1994 self.assertEqual(self.signature(partial(test, b=0)),
1995 ((('a', ..., ..., "positional_or_keyword"),
1996 ('args', ..., ..., "var_positional"),
1997 ('b', 0, ..., "keyword_only"),
1998 ('kwargs', ..., ..., "var_keyword")),
1999 ...))
2000
2001 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2002 ((('a', ..., ..., "positional_or_keyword"),
2003 ('args', ..., ..., "var_positional"),
2004 ('b', 0, ..., "keyword_only"),
2005 ('kwargs', ..., ..., "var_keyword")),
2006 ...))
2007
2008 def test(a, b, c:int) -> 42:
2009 pass
2010
2011 sig = test.__signature__ = inspect.signature(test)
2012
2013 self.assertEqual(self.signature(partial(partial(test, 1))),
2014 ((('b', ..., ..., "positional_or_keyword"),
2015 ('c', ..., int, "positional_or_keyword")),
2016 42))
2017
2018 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2019 ((('c', ..., int, "positional_or_keyword"),),
2020 42))
2021
2022 psig = inspect.signature(partial(partial(test, 1), 2))
2023
2024 def foo(a):
2025 return a
2026 _foo = partial(partial(foo, a=10), a=20)
2027 self.assertEqual(self.signature(_foo),
2028 ((('a', 20, ..., "positional_or_keyword"),),
2029 ...))
2030 # check that we don't have any side-effects in signature(),
2031 # and the partial object is still functioning
2032 self.assertEqual(_foo(), 20)
2033
2034 def foo(a, b, c):
2035 return a, b, c
2036 _foo = partial(partial(foo, 1, b=20), b=30)
2037 self.assertEqual(self.signature(_foo),
2038 ((('b', 30, ..., "positional_or_keyword"),
2039 ('c', ..., ..., "positional_or_keyword")),
2040 ...))
2041 self.assertEqual(_foo(c=10), (1, 30, 10))
2042 _foo = partial(_foo, 2) # now 'b' has two values -
2043 # positional and keyword
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002044 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002045 inspect.signature(_foo)
2046
2047 def foo(a, b, c, *, d):
2048 return a, b, c, d
2049 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2050 self.assertEqual(self.signature(_foo),
2051 ((('a', ..., ..., "positional_or_keyword"),
2052 ('b', 10, ..., "positional_or_keyword"),
2053 ('c', 20, ..., "positional_or_keyword"),
2054 ('d', 30, ..., "keyword_only")),
2055 ...))
2056 ba = inspect.signature(_foo).bind(a=200, b=11)
2057 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2058
2059 def foo(a=1, b=2, c=3):
2060 return a, b, c
2061 _foo = partial(foo, a=10, c=13)
2062 ba = inspect.signature(_foo).bind(11)
2063 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
2064 ba = inspect.signature(_foo).bind(11, 12)
2065 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
2066 ba = inspect.signature(_foo).bind(11, b=12)
2067 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
2068 ba = inspect.signature(_foo).bind(b=12)
2069 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
2070 _foo = partial(_foo, b=10)
2071 ba = inspect.signature(_foo).bind(12, 14)
2072 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
2073
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002074 def test_signature_on_partialmethod(self):
2075 from functools import partialmethod
2076
2077 class Spam:
2078 def test():
2079 pass
2080 ham = partialmethod(test)
2081
2082 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2083 inspect.signature(Spam.ham)
2084
2085 class Spam:
2086 def test(it, a, *, c) -> 'spam':
2087 pass
2088 ham = partialmethod(test, c=1)
2089
2090 self.assertEqual(self.signature(Spam.ham),
2091 ((('it', ..., ..., 'positional_or_keyword'),
2092 ('a', ..., ..., 'positional_or_keyword'),
2093 ('c', 1, ..., 'keyword_only')),
2094 'spam'))
2095
2096 self.assertEqual(self.signature(Spam().ham),
2097 ((('a', ..., ..., 'positional_or_keyword'),
2098 ('c', 1, ..., 'keyword_only')),
2099 'spam'))
2100
Yury Selivanov0486f812014-01-29 12:18:59 -05002101 def test_signature_on_fake_partialmethod(self):
2102 def foo(a): pass
2103 foo._partialmethod = 'spam'
2104 self.assertEqual(str(inspect.signature(foo)), '(a)')
2105
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002106 def test_signature_on_decorated(self):
2107 import functools
2108
2109 def decorator(func):
2110 @functools.wraps(func)
2111 def wrapper(*args, **kwargs) -> int:
2112 return func(*args, **kwargs)
2113 return wrapper
2114
2115 class Foo:
2116 @decorator
2117 def bar(self, a, b):
2118 pass
2119
2120 self.assertEqual(self.signature(Foo.bar),
2121 ((('self', ..., ..., "positional_or_keyword"),
2122 ('a', ..., ..., "positional_or_keyword"),
2123 ('b', ..., ..., "positional_or_keyword")),
2124 ...))
2125
2126 self.assertEqual(self.signature(Foo().bar),
2127 ((('a', ..., ..., "positional_or_keyword"),
2128 ('b', ..., ..., "positional_or_keyword")),
2129 ...))
2130
2131 # Test that we handle method wrappers correctly
2132 def decorator(func):
2133 @functools.wraps(func)
2134 def wrapper(*args, **kwargs) -> int:
2135 return func(42, *args, **kwargs)
2136 sig = inspect.signature(func)
2137 new_params = tuple(sig.parameters.values())[1:]
2138 wrapper.__signature__ = sig.replace(parameters=new_params)
2139 return wrapper
2140
2141 class Foo:
2142 @decorator
2143 def __call__(self, a, b):
2144 pass
2145
2146 self.assertEqual(self.signature(Foo.__call__),
2147 ((('a', ..., ..., "positional_or_keyword"),
2148 ('b', ..., ..., "positional_or_keyword")),
2149 ...))
2150
2151 self.assertEqual(self.signature(Foo().__call__),
2152 ((('b', ..., ..., "positional_or_keyword"),),
2153 ...))
2154
Nick Coghlane8c45d62013-07-28 20:00:01 +10002155 # Test we handle __signature__ partway down the wrapper stack
2156 def wrapped_foo_call():
2157 pass
2158 wrapped_foo_call.__wrapped__ = Foo.__call__
2159
2160 self.assertEqual(self.signature(wrapped_foo_call),
2161 ((('a', ..., ..., "positional_or_keyword"),
2162 ('b', ..., ..., "positional_or_keyword")),
2163 ...))
2164
2165
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002166 def test_signature_on_class(self):
2167 class C:
2168 def __init__(self, a):
2169 pass
2170
2171 self.assertEqual(self.signature(C),
2172 ((('a', ..., ..., "positional_or_keyword"),),
2173 ...))
2174
2175 class CM(type):
2176 def __call__(cls, a):
2177 pass
2178 class C(metaclass=CM):
2179 def __init__(self, b):
2180 pass
2181
2182 self.assertEqual(self.signature(C),
2183 ((('a', ..., ..., "positional_or_keyword"),),
2184 ...))
2185
2186 class CM(type):
2187 def __new__(mcls, name, bases, dct, *, foo=1):
2188 return super().__new__(mcls, name, bases, dct)
2189 class C(metaclass=CM):
2190 def __init__(self, b):
2191 pass
2192
2193 self.assertEqual(self.signature(C),
2194 ((('b', ..., ..., "positional_or_keyword"),),
2195 ...))
2196
2197 self.assertEqual(self.signature(CM),
2198 ((('name', ..., ..., "positional_or_keyword"),
2199 ('bases', ..., ..., "positional_or_keyword"),
2200 ('dct', ..., ..., "positional_or_keyword"),
2201 ('foo', 1, ..., "keyword_only")),
2202 ...))
2203
2204 class CMM(type):
2205 def __new__(mcls, name, bases, dct, *, foo=1):
2206 return super().__new__(mcls, name, bases, dct)
2207 def __call__(cls, nm, bs, dt):
2208 return type(nm, bs, dt)
2209 class CM(type, metaclass=CMM):
2210 def __new__(mcls, name, bases, dct, *, bar=2):
2211 return super().__new__(mcls, name, bases, dct)
2212 class C(metaclass=CM):
2213 def __init__(self, b):
2214 pass
2215
2216 self.assertEqual(self.signature(CMM),
2217 ((('name', ..., ..., "positional_or_keyword"),
2218 ('bases', ..., ..., "positional_or_keyword"),
2219 ('dct', ..., ..., "positional_or_keyword"),
2220 ('foo', 1, ..., "keyword_only")),
2221 ...))
2222
2223 self.assertEqual(self.signature(CM),
2224 ((('nm', ..., ..., "positional_or_keyword"),
2225 ('bs', ..., ..., "positional_or_keyword"),
2226 ('dt', ..., ..., "positional_or_keyword")),
2227 ...))
2228
2229 self.assertEqual(self.signature(C),
2230 ((('b', ..., ..., "positional_or_keyword"),),
2231 ...))
2232
2233 class CM(type):
2234 def __init__(cls, name, bases, dct, *, bar=2):
2235 return super().__init__(name, bases, dct)
2236 class C(metaclass=CM):
2237 def __init__(self, b):
2238 pass
2239
2240 self.assertEqual(self.signature(CM),
2241 ((('name', ..., ..., "positional_or_keyword"),
2242 ('bases', ..., ..., "positional_or_keyword"),
2243 ('dct', ..., ..., "positional_or_keyword"),
2244 ('bar', 2, ..., "keyword_only")),
2245 ...))
2246
Yury Selivanov145dff82014-02-01 13:49:29 -05002247 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2248 "Signature information for builtins requires docstrings")
2249 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002250 # Test classes without user-defined __init__ or __new__
2251 class C: pass
2252 self.assertEqual(str(inspect.signature(C)), '()')
2253 class D(C): pass
2254 self.assertEqual(str(inspect.signature(D)), '()')
2255
2256 # Test meta-classes without user-defined __init__ or __new__
2257 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002258 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002259 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2260 self.assertEqual(inspect.signature(C), None)
2261 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2262 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002263
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002264 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2265 "Signature information for builtins requires docstrings")
2266 def test_signature_on_builtin_class(self):
2267 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2268 '(file, protocol=None, fix_imports=True)')
2269
2270 class P(_pickle.Pickler): pass
2271 class EmptyTrait: pass
2272 class P2(EmptyTrait, P): pass
2273 self.assertEqual(str(inspect.signature(P)),
2274 '(file, protocol=None, fix_imports=True)')
2275 self.assertEqual(str(inspect.signature(P2)),
2276 '(file, protocol=None, fix_imports=True)')
2277
2278 class P3(P2):
2279 def __init__(self, spam):
2280 pass
2281 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2282
2283 class MetaP(type):
2284 def __call__(cls, foo, bar):
2285 pass
2286 class P4(P2, metaclass=MetaP):
2287 pass
2288 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2289
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002290 def test_signature_on_callable_objects(self):
2291 class Foo:
2292 def __call__(self, a):
2293 pass
2294
2295 self.assertEqual(self.signature(Foo()),
2296 ((('a', ..., ..., "positional_or_keyword"),),
2297 ...))
2298
2299 class Spam:
2300 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002301 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002302 inspect.signature(Spam())
2303
2304 class Bar(Spam, Foo):
2305 pass
2306
2307 self.assertEqual(self.signature(Bar()),
2308 ((('a', ..., ..., "positional_or_keyword"),),
2309 ...))
2310
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002311 class Wrapped:
2312 pass
2313 Wrapped.__wrapped__ = lambda a: None
2314 self.assertEqual(self.signature(Wrapped),
2315 ((('a', ..., ..., "positional_or_keyword"),),
2316 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002317 # wrapper loop:
2318 Wrapped.__wrapped__ = Wrapped
2319 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2320 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002321
2322 def test_signature_on_lambdas(self):
2323 self.assertEqual(self.signature((lambda a=10: a)),
2324 ((('a', 10, ..., "positional_or_keyword"),),
2325 ...))
2326
2327 def test_signature_equality(self):
2328 def foo(a, *, b:int) -> float: pass
2329 self.assertNotEqual(inspect.signature(foo), 42)
2330
2331 def bar(a, *, b:int) -> float: pass
2332 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2333
2334 def bar(a, *, b:int) -> int: pass
2335 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2336
2337 def bar(a, *, b:int): pass
2338 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2339
2340 def bar(a, *, b:int=42) -> float: pass
2341 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2342
2343 def bar(a, *, c) -> float: pass
2344 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2345
2346 def bar(a, b:int) -> float: pass
2347 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2348 def spam(b:int, a) -> float: pass
2349 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
2350
2351 def foo(*, a, b, c): pass
2352 def bar(*, c, b, a): pass
2353 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2354
2355 def foo(*, a=1, b, c): pass
2356 def bar(*, c, b, a=1): pass
2357 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2358
2359 def foo(pos, *, a=1, b, c): pass
2360 def bar(pos, *, c, b, a=1): pass
2361 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2362
2363 def foo(pos, *, a, b, c): pass
2364 def bar(pos, *, c, b, a=1): pass
2365 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2366
2367 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2368 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2369 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2370
2371 def test_signature_unhashable(self):
2372 def foo(a): pass
2373 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002374 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002375 hash(sig)
2376
2377 def test_signature_str(self):
2378 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2379 pass
2380 self.assertEqual(str(inspect.signature(foo)),
2381 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2382
2383 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2384 pass
2385 self.assertEqual(str(inspect.signature(foo)),
2386 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2387
2388 def foo():
2389 pass
2390 self.assertEqual(str(inspect.signature(foo)), '()')
2391
2392 def test_signature_str_positional_only(self):
2393 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002394 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002395
2396 def test(a_po, *, b, **kwargs):
2397 return a_po, kwargs
2398
2399 sig = inspect.signature(test)
2400 new_params = list(sig.parameters.values())
2401 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2402 test.__signature__ = sig.replace(parameters=new_params)
2403
2404 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002405 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002406
Yury Selivanov2393dca2014-01-27 15:07:58 -05002407 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2408 '(foo, /)')
2409
2410 self.assertEqual(str(S(parameters=[
2411 P('foo', P.POSITIONAL_ONLY),
2412 P('bar', P.VAR_KEYWORD)])),
2413 '(foo, /, **bar)')
2414
2415 self.assertEqual(str(S(parameters=[
2416 P('foo', P.POSITIONAL_ONLY),
2417 P('bar', P.VAR_POSITIONAL)])),
2418 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002419
2420 def test_signature_replace_anno(self):
2421 def test() -> 42:
2422 pass
2423
2424 sig = inspect.signature(test)
2425 sig = sig.replace(return_annotation=None)
2426 self.assertIs(sig.return_annotation, None)
2427 sig = sig.replace(return_annotation=sig.empty)
2428 self.assertIs(sig.return_annotation, sig.empty)
2429 sig = sig.replace(return_annotation=42)
2430 self.assertEqual(sig.return_annotation, 42)
2431 self.assertEqual(sig, inspect.signature(test))
2432
Yury Selivanov026019f2014-02-18 12:49:41 -05002433 def test_signature_on_mangled_parameters(self):
2434 class Spam:
2435 def foo(self, __p1:1=2, *, __p2:2=3):
2436 pass
2437 class Ham(Spam):
2438 pass
2439
2440 self.assertEqual(self.signature(Spam.foo),
2441 ((('self', ..., ..., "positional_or_keyword"),
2442 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2443 ('_Spam__p2', 3, 2, "keyword_only")),
2444 ...))
2445
2446 self.assertEqual(self.signature(Spam.foo),
2447 self.signature(Ham.foo))
2448
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002449
2450class TestParameterObject(unittest.TestCase):
2451 def test_signature_parameter_kinds(self):
2452 P = inspect.Parameter
2453 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2454 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2455
2456 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2457 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2458
2459 def test_signature_parameter_object(self):
2460 p = inspect.Parameter('foo', default=10,
2461 kind=inspect.Parameter.POSITIONAL_ONLY)
2462 self.assertEqual(p.name, 'foo')
2463 self.assertEqual(p.default, 10)
2464 self.assertIs(p.annotation, p.empty)
2465 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2466
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002467 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002468 inspect.Parameter('foo', default=10, kind='123')
2469
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002470 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002471 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2472
Yury Selivanov2393dca2014-01-27 15:07:58 -05002473 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002474 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2475
Yury Selivanov2393dca2014-01-27 15:07:58 -05002476 with self.assertRaisesRegex(ValueError,
2477 'is not a valid parameter name'):
2478 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2479
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002480 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002481 inspect.Parameter('a', default=42,
2482 kind=inspect.Parameter.VAR_KEYWORD)
2483
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002484 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002485 inspect.Parameter('a', default=42,
2486 kind=inspect.Parameter.VAR_POSITIONAL)
2487
2488 p = inspect.Parameter('a', default=42,
2489 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002490 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002491 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2492
2493 self.assertTrue(repr(p).startswith('<Parameter'))
2494
2495 def test_signature_parameter_equality(self):
2496 P = inspect.Parameter
2497 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2498
2499 self.assertEqual(p, p)
2500 self.assertNotEqual(p, 42)
2501
2502 self.assertEqual(p, P('foo', default=42,
2503 kind=inspect.Parameter.KEYWORD_ONLY))
2504
2505 def test_signature_parameter_unhashable(self):
2506 p = inspect.Parameter('foo', default=42,
2507 kind=inspect.Parameter.KEYWORD_ONLY)
2508
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002509 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002510 hash(p)
2511
2512 def test_signature_parameter_replace(self):
2513 p = inspect.Parameter('foo', default=42,
2514 kind=inspect.Parameter.KEYWORD_ONLY)
2515
2516 self.assertIsNot(p, p.replace())
2517 self.assertEqual(p, p.replace())
2518
2519 p2 = p.replace(annotation=1)
2520 self.assertEqual(p2.annotation, 1)
2521 p2 = p2.replace(annotation=p2.empty)
2522 self.assertEqual(p, p2)
2523
2524 p2 = p2.replace(name='bar')
2525 self.assertEqual(p2.name, 'bar')
2526 self.assertNotEqual(p2, p)
2527
Yury Selivanov2393dca2014-01-27 15:07:58 -05002528 with self.assertRaisesRegex(ValueError,
2529 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002530 p2 = p2.replace(name=p2.empty)
2531
2532 p2 = p2.replace(name='foo', default=None)
2533 self.assertIs(p2.default, None)
2534 self.assertNotEqual(p2, p)
2535
2536 p2 = p2.replace(name='foo', default=p2.empty)
2537 self.assertIs(p2.default, p2.empty)
2538
2539
2540 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2541 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2542 self.assertNotEqual(p2, p)
2543
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002544 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002545 p2 = p2.replace(kind=p2.empty)
2546
2547 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2548 self.assertEqual(p2, p)
2549
2550 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002551 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2552 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002553
2554 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002555 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002556
2557 with self.assertRaises(AttributeError):
2558 p.foo = 'bar'
2559
2560 with self.assertRaises(AttributeError):
2561 p.kind = 123
2562
2563
2564class TestSignatureBind(unittest.TestCase):
2565 @staticmethod
2566 def call(func, *args, **kwargs):
2567 sig = inspect.signature(func)
2568 ba = sig.bind(*args, **kwargs)
2569 return func(*ba.args, **ba.kwargs)
2570
2571 def test_signature_bind_empty(self):
2572 def test():
2573 return 42
2574
2575 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002576 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002577 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002578 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002579 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002580 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002581 self.call(test, spam=1)
2582
2583 def test_signature_bind_var(self):
2584 def test(*args, **kwargs):
2585 return args, kwargs
2586
2587 self.assertEqual(self.call(test), ((), {}))
2588 self.assertEqual(self.call(test, 1), ((1,), {}))
2589 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2590 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2591 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2592 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2593 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2594 ((1, 2), {'foo': 'bar'}))
2595
2596 def test_signature_bind_just_args(self):
2597 def test(a, b, c):
2598 return a, b, c
2599
2600 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2601
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002602 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002603 self.call(test, 1, 2, 3, 4)
2604
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002605 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002606 self.call(test, 1)
2607
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002608 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002609 self.call(test)
2610
2611 def test(a, b, c=10):
2612 return a, b, c
2613 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2614 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2615
2616 def test(a=1, b=2, c=3):
2617 return a, b, c
2618 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2619 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2620 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2621
2622 def test_signature_bind_varargs_order(self):
2623 def test(*args):
2624 return args
2625
2626 self.assertEqual(self.call(test), ())
2627 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2628
2629 def test_signature_bind_args_and_varargs(self):
2630 def test(a, b, c=3, *args):
2631 return a, b, c, args
2632
2633 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2634 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2635 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2636 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2637
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002638 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002639 "multiple values for argument 'c'"):
2640 self.call(test, 1, 2, 3, c=4)
2641
2642 def test_signature_bind_just_kwargs(self):
2643 def test(**kwargs):
2644 return kwargs
2645
2646 self.assertEqual(self.call(test), {})
2647 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2648 {'foo': 'bar', 'spam': 'ham'})
2649
2650 def test_signature_bind_args_and_kwargs(self):
2651 def test(a, b, c=3, **kwargs):
2652 return a, b, c, kwargs
2653
2654 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2655 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2656 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2657 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2658 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2659 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2660 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2661 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2662 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2663 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2664 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2665 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2666 (1, 2, 4, {'foo': 'bar'}))
2667 self.assertEqual(self.call(test, c=5, a=4, b=3),
2668 (4, 3, 5, {}))
2669
2670 def test_signature_bind_kwonly(self):
2671 def test(*, foo):
2672 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002673 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002674 'too many positional arguments'):
2675 self.call(test, 1)
2676 self.assertEqual(self.call(test, foo=1), 1)
2677
2678 def test(a, *, foo=1, bar):
2679 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002680 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002681 "'bar' parameter lacking default value"):
2682 self.call(test, 1)
2683
2684 def test(foo, *, bar):
2685 return foo, bar
2686 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2687 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2688
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002689 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002690 'too many keyword arguments'):
2691 self.call(test, bar=2, foo=1, spam=10)
2692
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002693 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002694 'too many positional arguments'):
2695 self.call(test, 1, 2)
2696
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002697 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002698 'too many positional arguments'):
2699 self.call(test, 1, 2, bar=2)
2700
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002701 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002702 'too many keyword arguments'):
2703 self.call(test, 1, bar=2, spam='ham')
2704
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002705 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002706 "'bar' parameter lacking default value"):
2707 self.call(test, 1)
2708
2709 def test(foo, *, bar, **bin):
2710 return foo, bar, bin
2711 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2712 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2713 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2714 (1, 2, {'spam': 'ham'}))
2715 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2716 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002717 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002718 "'foo' parameter lacking default value"):
2719 self.call(test, spam='ham', bar=2)
2720 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2721 (1, 2, {'bin': 1, 'spam': 10}))
2722
2723 def test_signature_bind_arguments(self):
2724 def test(a, *args, b, z=100, **kwargs):
2725 pass
2726 sig = inspect.signature(test)
2727 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2728 # we won't have 'z' argument in the bound arguments object, as we didn't
2729 # pass it to the 'bind'
2730 self.assertEqual(tuple(ba.arguments.items()),
2731 (('a', 10), ('args', (20,)), ('b', 30),
2732 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2733 self.assertEqual(ba.kwargs,
2734 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2735 self.assertEqual(ba.args, (10, 20))
2736
2737 def test_signature_bind_positional_only(self):
2738 P = inspect.Parameter
2739
2740 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2741 return a_po, b_po, c_po, foo, bar, kwargs
2742
2743 sig = inspect.signature(test)
2744 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2745 for name in ('a_po', 'b_po', 'c_po'):
2746 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2747 new_sig = sig.replace(parameters=new_params.values())
2748 test.__signature__ = new_sig
2749
2750 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2751 (1, 2, 4, 5, 6, {}))
2752
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002753 self.assertEqual(self.call(test, 1, 2),
2754 (1, 2, 3, 42, 50, {}))
2755
2756 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
2757 (1, 2, 3, 4, 5, {}))
2758
2759 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
2760 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
2761
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002762 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002763 self.call(test, 1, 2, c_po=4)
2764
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002765 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002766 self.call(test, a_po=1, b_po=2)
2767
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002768 def test_signature_bind_with_self_arg(self):
2769 # Issue #17071: one of the parameters is named "self
2770 def test(a, self, b):
2771 pass
2772 sig = inspect.signature(test)
2773 ba = sig.bind(1, 2, 3)
2774 self.assertEqual(ba.args, (1, 2, 3))
2775 ba = sig.bind(1, self=2, b=3)
2776 self.assertEqual(ba.args, (1, 2, 3))
2777
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002778 def test_signature_bind_vararg_name(self):
2779 def test(a, *args):
2780 return a, args
2781 sig = inspect.signature(test)
2782
2783 with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
2784 sig.bind(a=0, args=1)
2785
2786 def test(*args, **kwargs):
2787 return args, kwargs
2788 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
2789
2790 sig = inspect.signature(test)
2791 ba = sig.bind(args=1)
2792 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
2793
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002794
2795class TestBoundArguments(unittest.TestCase):
2796 def test_signature_bound_arguments_unhashable(self):
2797 def foo(a): pass
2798 ba = inspect.signature(foo).bind(1)
2799
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002800 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002801 hash(ba)
2802
2803 def test_signature_bound_arguments_equality(self):
2804 def foo(a): pass
2805 ba = inspect.signature(foo).bind(1)
2806 self.assertEqual(ba, ba)
2807
2808 ba2 = inspect.signature(foo).bind(1)
2809 self.assertEqual(ba, ba2)
2810
2811 ba3 = inspect.signature(foo).bind(2)
2812 self.assertNotEqual(ba, ba3)
2813 ba3.arguments['a'] = 1
2814 self.assertEqual(ba, ba3)
2815
2816 def bar(b): pass
2817 ba4 = inspect.signature(bar).bind(1)
2818 self.assertNotEqual(ba, ba4)
2819
2820
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002821class TestSignaturePrivateHelpers(unittest.TestCase):
2822 def test_signature_get_bound_param(self):
2823 getter = inspect._signature_get_bound_param
2824
2825 self.assertEqual(getter('($self)'), 'self')
2826 self.assertEqual(getter('($self, obj)'), 'self')
2827 self.assertEqual(getter('($cls, /, obj)'), 'cls')
2828
Larry Hastings2623c8c2014-02-08 22:15:29 -08002829 def _strip_non_python_syntax(self, input,
2830 clean_signature, self_parameter, last_positional_only):
2831 computed_clean_signature, \
2832 computed_self_parameter, \
2833 computed_last_positional_only = \
2834 inspect._signature_strip_non_python_syntax(input)
2835 self.assertEqual(computed_clean_signature, clean_signature)
2836 self.assertEqual(computed_self_parameter, self_parameter)
2837 self.assertEqual(computed_last_positional_only, last_positional_only)
2838
2839 def test_signature_strip_non_python_syntax(self):
2840 self._strip_non_python_syntax(
2841 "($module, /, path, mode, *, dir_fd=None, " +
2842 "effective_ids=False,\n follow_symlinks=True)",
2843 "(module, path, mode, *, dir_fd=None, " +
2844 "effective_ids=False, follow_symlinks=True)",
2845 0,
2846 0)
2847
2848 self._strip_non_python_syntax(
2849 "($module, word, salt, /)",
2850 "(module, word, salt)",
2851 0,
2852 2)
2853
2854 self._strip_non_python_syntax(
2855 "(x, y=None, z=None, /)",
2856 "(x, y=None, z=None)",
2857 None,
2858 2)
2859
2860 self._strip_non_python_syntax(
2861 "(x, y=None, z=None)",
2862 "(x, y=None, z=None)",
2863 None,
2864 None)
2865
2866 self._strip_non_python_syntax(
2867 "(x,\n y=None,\n z = None )",
2868 "(x, y=None, z=None)",
2869 None,
2870 None)
2871
2872 self._strip_non_python_syntax(
2873 "",
2874 "",
2875 None,
2876 None)
2877
2878 self._strip_non_python_syntax(
2879 None,
2880 None,
2881 None,
2882 None)
2883
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002884
Nick Coghlane8c45d62013-07-28 20:00:01 +10002885class TestUnwrap(unittest.TestCase):
2886
2887 def test_unwrap_one(self):
2888 def func(a, b):
2889 return a + b
2890 wrapper = functools.lru_cache(maxsize=20)(func)
2891 self.assertIs(inspect.unwrap(wrapper), func)
2892
2893 def test_unwrap_several(self):
2894 def func(a, b):
2895 return a + b
2896 wrapper = func
2897 for __ in range(10):
2898 @functools.wraps(wrapper)
2899 def wrapper():
2900 pass
2901 self.assertIsNot(wrapper.__wrapped__, func)
2902 self.assertIs(inspect.unwrap(wrapper), func)
2903
2904 def test_stop(self):
2905 def func1(a, b):
2906 return a + b
2907 @functools.wraps(func1)
2908 def func2():
2909 pass
2910 @functools.wraps(func2)
2911 def wrapper():
2912 pass
2913 func2.stop_here = 1
2914 unwrapped = inspect.unwrap(wrapper,
2915 stop=(lambda f: hasattr(f, "stop_here")))
2916 self.assertIs(unwrapped, func2)
2917
2918 def test_cycle(self):
2919 def func1(): pass
2920 func1.__wrapped__ = func1
2921 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2922 inspect.unwrap(func1)
2923
2924 def func2(): pass
2925 func2.__wrapped__ = func1
2926 func1.__wrapped__ = func2
2927 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2928 inspect.unwrap(func1)
2929 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2930 inspect.unwrap(func2)
2931
2932 def test_unhashable(self):
2933 def func(): pass
2934 func.__wrapped__ = None
2935 class C:
2936 __hash__ = None
2937 __wrapped__ = func
2938 self.assertIsNone(inspect.unwrap(C()))
2939
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002940class TestMain(unittest.TestCase):
2941 def test_only_source(self):
2942 module = importlib.import_module('unittest')
2943 rc, out, err = assert_python_ok('-m', 'inspect',
2944 'unittest')
2945 lines = out.decode().splitlines()
2946 # ignore the final newline
2947 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
2948 self.assertEqual(err, b'')
2949
Brett Cannon634a8fc2013-10-02 10:25:42 -04002950 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04002951 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002952 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002953 rc, out, err = assert_python_ok('-m', 'inspect',
2954 'concurrent.futures:ThreadPoolExecutor')
2955 lines = out.decode().splitlines()
2956 # ignore the final newline
2957 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04002958 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002959 self.assertEqual(err, b'')
2960
2961 def test_builtins(self):
2962 module = importlib.import_module('unittest')
2963 _, out, err = assert_python_failure('-m', 'inspect',
2964 'sys')
2965 lines = err.decode().splitlines()
2966 self.assertEqual(lines, ["Can't get info for builtin modules."])
2967
2968 def test_details(self):
2969 module = importlib.import_module('unittest')
2970 rc, out, err = assert_python_ok('-m', 'inspect',
2971 'unittest', '--details')
2972 output = out.decode()
2973 # Just a quick sanity check on the output
2974 self.assertIn(module.__name__, output)
2975 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02002976 if not sys.flags.optimize:
2977 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002978 self.assertEqual(err, b'')
2979
2980
2981
Nick Coghlane8c45d62013-07-28 20:00:01 +10002982
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002983def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00002984 run_unittest(
2985 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
2986 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
2987 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00002988 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002989 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002990 TestBoundArguments, TestSignaturePrivateHelpers, TestGetClosureVars,
2991 TestUnwrap, TestMain
Michael Foord95fc51d2010-11-20 15:07:30 +00002992 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00002993
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002994if __name__ == "__main__":
2995 test_main()