blob: 95c1b324fb6bd58b5a52439c3936e8b053584c9e [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
Yury Selivanovd224b6a2014-02-21 01:32:42 -0500646 self.assertFullArgSpecEquals(
647 os.stat,
648 args_e=['path'],
649 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
650 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
651 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
652
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200653 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500654 @unittest.skipIf(MISSING_C_DOCSTRINGS,
655 "Signature information for builtins requires docstrings")
656 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200657 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500658 builtin = _testcapi.docstring_with_signature_with_defaults
659 spec = inspect.getfullargspec(builtin)
660 self.assertEqual(spec.defaults[0], 'avocado')
661
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200662 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500663 @unittest.skipIf(MISSING_C_DOCSTRINGS,
664 "Signature information for builtins requires docstrings")
665 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200666 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500667 builtin = _testcapi.docstring_no_signature
668 with self.assertRaises(TypeError):
669 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000670
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000671 def test_getargspec_method(self):
672 class A(object):
673 def m(self):
674 pass
675 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000676
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000677 def test_classify_newstyle(self):
678 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000679
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000680 def s(): pass
681 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000682
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000683 def c(cls): pass
684 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000685
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000686 def getp(self): pass
687 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000688
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000689 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000690
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000691 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000692
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000693 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000694
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100695 dd = _BrokenDataDescriptor()
696 md = _BrokenMethodDescriptor()
697
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000698 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500699
700 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
701 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
702
Benjamin Peterson577473f2010-01-19 00:09:57 +0000703 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
704 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
705 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000706 self.assertIn(('m', 'method', A), attrs,
707 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000708 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
709 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100710 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
711 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000712
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000713 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000714
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000715 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000716
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000717 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000718 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
719 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
720 self.assertIn(('p', 'property', A), attrs, 'missing property')
721 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
722 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
723 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100724 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
725 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000726
727
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000728 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000729
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000730 def m(self): pass
731 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000732
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000733 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000734 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
735 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
736 self.assertIn(('p', 'property', A), attrs, 'missing property')
737 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
738 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
739 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100740 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
741 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000742
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000743 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000744
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000745 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000746
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000747 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000748 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
749 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
750 self.assertIn(('p', 'property', A), attrs, 'missing property')
751 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
752 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
753 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100754 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
755 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
756
757 def test_classify_builtin_types(self):
758 # Simple sanity check that all built-in types can have their
759 # attributes classified.
760 for name in dir(__builtins__):
761 builtin = getattr(__builtins__, name)
762 if isinstance(builtin, type):
763 inspect.classify_class_attrs(builtin)
764
Ethan Furman63c141c2013-10-18 00:27:39 -0700765 def test_classify_DynamicClassAttribute(self):
766 class Meta(type):
767 def __getattr__(self, name):
768 if name == 'ham':
769 return 'spam'
770 return super().__getattr__(name)
771 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700772 @types.DynamicClassAttribute
773 def ham(self):
774 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700775 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
776 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700777 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700778 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
779
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700780 def test_classify_metaclass_class_attribute(self):
781 class Meta(type):
782 fish = 'slap'
783 def __dir__(self):
784 return ['__class__', '__modules__', '__name__', 'fish']
785 class Class(metaclass=Meta):
786 pass
787 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
788 self.assertIn(should_find, inspect.classify_class_attrs(Class))
789
Ethan Furman63c141c2013-10-18 00:27:39 -0700790 def test_classify_VirtualAttribute(self):
791 class Meta(type):
792 def __dir__(cls):
793 return ['__class__', '__module__', '__name__', 'BOOM']
794 def __getattr__(self, name):
795 if name =='BOOM':
796 return 42
797 return super().__getattr(name)
798 class Class(metaclass=Meta):
799 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700800 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700801 self.assertIn(should_find, inspect.classify_class_attrs(Class))
802
803 def test_classify_VirtualAttribute_multi_classes(self):
804 class Meta1(type):
805 def __dir__(cls):
806 return ['__class__', '__module__', '__name__', 'one']
807 def __getattr__(self, name):
808 if name =='one':
809 return 1
810 return super().__getattr__(name)
811 class Meta2(type):
812 def __dir__(cls):
813 return ['__class__', '__module__', '__name__', 'two']
814 def __getattr__(self, name):
815 if name =='two':
816 return 2
817 return super().__getattr__(name)
818 class Meta3(Meta1, Meta2):
819 def __dir__(cls):
820 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
821 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
822 def __getattr__(self, name):
823 if name =='three':
824 return 3
825 return super().__getattr__(name)
826 class Class1(metaclass=Meta1):
827 pass
828 class Class2(Class1, metaclass=Meta3):
829 pass
830
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700831 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
832 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
833 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700834 cca = inspect.classify_class_attrs(Class2)
835 for sf in (should_find1, should_find2, should_find3):
836 self.assertIn(sf, cca)
837
838 def test_classify_class_attrs_with_buggy_dir(self):
839 class M(type):
840 def __dir__(cls):
841 return ['__class__', '__name__', 'missing']
842 class C(metaclass=M):
843 pass
844 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
845 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700846
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100847 def test_getmembers_descriptors(self):
848 class A(object):
849 dd = _BrokenDataDescriptor()
850 md = _BrokenMethodDescriptor()
851
852 def pred_wrapper(pred):
853 # A quick'n'dirty way to discard standard attributes of new-style
854 # classes.
855 class Empty(object):
856 pass
857 def wrapped(x):
858 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
859 return False
860 return pred(x)
861 return wrapped
862
863 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
864 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
865
866 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
867 [('md', A.__dict__['md'])])
868 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
869 [('dd', A.__dict__['dd'])])
870
871 class B(A):
872 pass
873
874 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
875 [('md', A.__dict__['md'])])
876 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
877 [('dd', A.__dict__['dd'])])
878
Antoine Pitrou0c603812012-01-18 17:40:18 +0100879 def test_getmembers_method(self):
880 class B:
881 def f(self):
882 pass
883
884 self.assertIn(('f', B.f), inspect.getmembers(B))
885 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
886 b = B()
887 self.assertIn(('f', b.f), inspect.getmembers(b))
888 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
889
Ethan Furmane03ea372013-09-25 07:14:41 -0700890 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -0700891 class M(type):
892 def __getattr__(cls, name):
893 if name == 'eggs':
894 return 'scrambled'
895 return super().__getattr__(name)
896 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -0700897 @types.DynamicClassAttribute
898 def eggs(self):
899 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -0700900 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
901 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
902
903 def test_getmembers_with_buggy_dir(self):
904 class M(type):
905 def __dir__(cls):
906 return ['__class__', '__name__', 'missing']
907 class C(metaclass=M):
908 pass
909 attrs = [a[0] for a in inspect.getmembers(C)]
910 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700911
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000912
Nick Coghlan2f92e542012-06-23 19:39:55 +1000913_global_ref = object()
914class TestGetClosureVars(unittest.TestCase):
915
916 def test_name_resolution(self):
917 # Basic test of the 4 different resolution mechanisms
918 def f(nonlocal_ref):
919 def g(local_ref):
920 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
921 return g
922 _arg = object()
923 nonlocal_vars = {"nonlocal_ref": _arg}
924 global_vars = {"_global_ref": _global_ref}
925 builtin_vars = {"print": print}
926 unbound_names = {"unbound_ref"}
927 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
928 builtin_vars, unbound_names)
929 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
930
931 def test_generator_closure(self):
932 def f(nonlocal_ref):
933 def g(local_ref):
934 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
935 yield
936 return g
937 _arg = object()
938 nonlocal_vars = {"nonlocal_ref": _arg}
939 global_vars = {"_global_ref": _global_ref}
940 builtin_vars = {"print": print}
941 unbound_names = {"unbound_ref"}
942 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
943 builtin_vars, unbound_names)
944 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
945
946 def test_method_closure(self):
947 class C:
948 def f(self, nonlocal_ref):
949 def g(local_ref):
950 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
951 return g
952 _arg = object()
953 nonlocal_vars = {"nonlocal_ref": _arg}
954 global_vars = {"_global_ref": _global_ref}
955 builtin_vars = {"print": print}
956 unbound_names = {"unbound_ref"}
957 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
958 builtin_vars, unbound_names)
959 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
960
961 def test_nonlocal_vars(self):
962 # More complex tests of nonlocal resolution
963 def _nonlocal_vars(f):
964 return inspect.getclosurevars(f).nonlocals
965
966 def make_adder(x):
967 def add(y):
968 return x + y
969 return add
970
971 def curry(func, arg1):
972 return lambda arg2: func(arg1, arg2)
973
974 def less_than(a, b):
975 return a < b
976
977 # The infamous Y combinator.
978 def Y(le):
979 def g(f):
980 return le(lambda x: f(f)(x))
981 Y.g_ref = g
982 return g(g)
983
984 def check_y_combinator(func):
985 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
986
987 inc = make_adder(1)
988 add_two = make_adder(2)
989 greater_than_five = curry(less_than, 5)
990
991 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
992 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
993 self.assertEqual(_nonlocal_vars(greater_than_five),
994 {'arg1': 5, 'func': less_than})
995 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
996 {'x': 3})
997 Y(check_y_combinator)
998
999 def test_getclosurevars_empty(self):
1000 def foo(): pass
1001 _empty = inspect.ClosureVars({}, {}, {}, set())
1002 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1003 self.assertEqual(inspect.getclosurevars(foo), _empty)
1004
1005 def test_getclosurevars_error(self):
1006 class T: pass
1007 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1008 self.assertRaises(TypeError, inspect.getclosurevars, list)
1009 self.assertRaises(TypeError, inspect.getclosurevars, {})
1010
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001011 def _private_globals(self):
1012 code = """def f(): print(path)"""
1013 ns = {}
1014 exec(code, ns)
1015 return ns["f"], ns
1016
1017 def test_builtins_fallback(self):
1018 f, ns = self._private_globals()
1019 ns.pop("__builtins__", None)
1020 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1021 self.assertEqual(inspect.getclosurevars(f), expected)
1022
1023 def test_builtins_as_dict(self):
1024 f, ns = self._private_globals()
1025 ns["__builtins__"] = {"path":1}
1026 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1027 self.assertEqual(inspect.getclosurevars(f), expected)
1028
1029 def test_builtins_as_module(self):
1030 f, ns = self._private_globals()
1031 ns["__builtins__"] = os
1032 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1033 self.assertEqual(inspect.getclosurevars(f), expected)
1034
Nick Coghlan2f92e542012-06-23 19:39:55 +10001035
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001036class TestGetcallargsFunctions(unittest.TestCase):
1037
1038 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1039 locs = dict(locs or {}, func=func)
1040 r1 = eval('func(%s)' % call_params_string, None, locs)
1041 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1042 locs)
1043 self.assertEqual(r1, r2)
1044
1045 def assertEqualException(self, func, call_param_string, locs=None):
1046 locs = dict(locs or {}, func=func)
1047 try:
1048 eval('func(%s)' % call_param_string, None, locs)
1049 except Exception as e:
1050 ex1 = e
1051 else:
1052 self.fail('Exception not raised')
1053 try:
1054 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1055 locs)
1056 except Exception as e:
1057 ex2 = e
1058 else:
1059 self.fail('Exception not raised')
1060 self.assertIs(type(ex1), type(ex2))
1061 self.assertEqual(str(ex1), str(ex2))
1062 del ex1, ex2
1063
1064 def makeCallable(self, signature):
1065 """Create a function that returns its locals()"""
1066 code = "lambda %s: locals()"
1067 return eval(code % signature)
1068
1069 def test_plain(self):
1070 f = self.makeCallable('a, b=1')
1071 self.assertEqualCallArgs(f, '2')
1072 self.assertEqualCallArgs(f, '2, 3')
1073 self.assertEqualCallArgs(f, 'a=2')
1074 self.assertEqualCallArgs(f, 'b=3, a=2')
1075 self.assertEqualCallArgs(f, '2, b=3')
1076 # expand *iterable / **mapping
1077 self.assertEqualCallArgs(f, '*(2,)')
1078 self.assertEqualCallArgs(f, '*[2]')
1079 self.assertEqualCallArgs(f, '*(2, 3)')
1080 self.assertEqualCallArgs(f, '*[2, 3]')
1081 self.assertEqualCallArgs(f, '**{"a":2}')
1082 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1083 self.assertEqualCallArgs(f, '2, **{"b":3}')
1084 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1085 # expand UserList / UserDict
1086 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1087 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1088 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1089 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1090 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1091
1092 def test_varargs(self):
1093 f = self.makeCallable('a, b=1, *c')
1094 self.assertEqualCallArgs(f, '2')
1095 self.assertEqualCallArgs(f, '2, 3')
1096 self.assertEqualCallArgs(f, '2, 3, 4')
1097 self.assertEqualCallArgs(f, '*(2,3,4)')
1098 self.assertEqualCallArgs(f, '2, *[3,4]')
1099 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1100
1101 def test_varkw(self):
1102 f = self.makeCallable('a, b=1, **c')
1103 self.assertEqualCallArgs(f, 'a=2')
1104 self.assertEqualCallArgs(f, '2, b=3, c=4')
1105 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1106 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1107 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1108 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1109 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1110 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1111 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1112
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001113 def test_varkw_only(self):
1114 # issue11256:
1115 f = self.makeCallable('**c')
1116 self.assertEqualCallArgs(f, '')
1117 self.assertEqualCallArgs(f, 'a=1')
1118 self.assertEqualCallArgs(f, 'a=1, b=2')
1119 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1120 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1121 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1122
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001123 def test_keyword_only(self):
1124 f = self.makeCallable('a=3, *, c, d=2')
1125 self.assertEqualCallArgs(f, 'c=3')
1126 self.assertEqualCallArgs(f, 'c=3, a=3')
1127 self.assertEqualCallArgs(f, 'a=2, c=4')
1128 self.assertEqualCallArgs(f, '4, c=4')
1129 self.assertEqualException(f, '')
1130 self.assertEqualException(f, '3')
1131 self.assertEqualException(f, 'a=3')
1132 self.assertEqualException(f, 'd=4')
1133
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001134 f = self.makeCallable('*, c, d=2')
1135 self.assertEqualCallArgs(f, 'c=3')
1136 self.assertEqualCallArgs(f, 'c=3, d=4')
1137 self.assertEqualCallArgs(f, 'd=4, c=3')
1138
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001139 def test_multiple_features(self):
1140 f = self.makeCallable('a, b=2, *f, **g')
1141 self.assertEqualCallArgs(f, '2, 3, 7')
1142 self.assertEqualCallArgs(f, '2, 3, x=8')
1143 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1144 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1145 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1146 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1147 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1148 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1149 '(4,[5,6])]), **collections.UserDict('
1150 'y=9, z=10)')
1151
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001152 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1153 self.assertEqualCallArgs(f, '2, 3, x=8')
1154 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1155 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1156 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1157 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1158 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1159 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1160 '(4,[5,6])]), q=0, **collections.UserDict('
1161 'y=9, z=10)')
1162
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001163 def test_errors(self):
1164 f0 = self.makeCallable('')
1165 f1 = self.makeCallable('a, b')
1166 f2 = self.makeCallable('a, b=1')
1167 # f0 takes no arguments
1168 self.assertEqualException(f0, '1')
1169 self.assertEqualException(f0, 'x=1')
1170 self.assertEqualException(f0, '1,x=1')
1171 # f1 takes exactly 2 arguments
1172 self.assertEqualException(f1, '')
1173 self.assertEqualException(f1, '1')
1174 self.assertEqualException(f1, 'a=2')
1175 self.assertEqualException(f1, 'b=3')
1176 # f2 takes at least 1 argument
1177 self.assertEqualException(f2, '')
1178 self.assertEqualException(f2, 'b=3')
1179 for f in f1, f2:
1180 # f1/f2 takes exactly/at most 2 arguments
1181 self.assertEqualException(f, '2, 3, 4')
1182 self.assertEqualException(f, '1, 2, 3, a=1')
1183 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001184 # XXX: success of this one depends on dict order
1185 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001186 # f got an unexpected keyword argument
1187 self.assertEqualException(f, 'c=2')
1188 self.assertEqualException(f, '2, c=3')
1189 self.assertEqualException(f, '2, 3, c=4')
1190 self.assertEqualException(f, '2, c=4, b=3')
1191 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1192 # f got multiple values for keyword argument
1193 self.assertEqualException(f, '1, a=2')
1194 self.assertEqualException(f, '1, **{"a":2}')
1195 self.assertEqualException(f, '1, 2, b=3')
1196 # XXX: Python inconsistency
1197 # - for functions and bound methods: unexpected keyword 'c'
1198 # - for unbound methods: multiple values for keyword 'a'
1199 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001200 # issue11256:
1201 f3 = self.makeCallable('**c')
1202 self.assertEqualException(f3, '1, 2')
1203 self.assertEqualException(f3, '1, 2, a=1, b=2')
1204 f4 = self.makeCallable('*, a, b=0')
1205 self.assertEqualException(f3, '1, 2')
1206 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001207
1208class TestGetcallargsMethods(TestGetcallargsFunctions):
1209
1210 def setUp(self):
1211 class Foo(object):
1212 pass
1213 self.cls = Foo
1214 self.inst = Foo()
1215
1216 def makeCallable(self, signature):
1217 assert 'self' not in signature
1218 mk = super(TestGetcallargsMethods, self).makeCallable
1219 self.cls.method = mk('self, ' + signature)
1220 return self.inst.method
1221
1222class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1223
1224 def makeCallable(self, signature):
1225 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1226 return self.cls.method
1227
1228 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1229 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1230 *self._getAssertEqualParams(func, call_params_string, locs))
1231
1232 def assertEqualException(self, func, call_params_string, locs=None):
1233 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1234 *self._getAssertEqualParams(func, call_params_string, locs))
1235
1236 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1237 assert 'inst' not in call_params_string
1238 locs = dict(locs or {}, inst=self.inst)
1239 return (func, 'inst,' + call_params_string, locs)
1240
Michael Foord95fc51d2010-11-20 15:07:30 +00001241
1242class TestGetattrStatic(unittest.TestCase):
1243
1244 def test_basic(self):
1245 class Thing(object):
1246 x = object()
1247
1248 thing = Thing()
1249 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1250 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1251 with self.assertRaises(AttributeError):
1252 inspect.getattr_static(thing, 'y')
1253
1254 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1255
1256 def test_inherited(self):
1257 class Thing(object):
1258 x = object()
1259 class OtherThing(Thing):
1260 pass
1261
1262 something = OtherThing()
1263 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1264
1265 def test_instance_attr(self):
1266 class Thing(object):
1267 x = 2
1268 def __init__(self, x):
1269 self.x = x
1270 thing = Thing(3)
1271 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1272 del thing.x
1273 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1274
1275 def test_property(self):
1276 class Thing(object):
1277 @property
1278 def x(self):
1279 raise AttributeError("I'm pretending not to exist")
1280 thing = Thing()
1281 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1282
Ezio Melotti75cbd732011-04-28 00:59:29 +03001283 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001284 class descriptor(object):
1285 def __get__(*_):
1286 raise AttributeError("I'm pretending not to exist")
1287 desc = descriptor()
1288 class Thing(object):
1289 x = desc
1290 thing = Thing()
1291 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1292
1293 def test_classAttribute(self):
1294 class Thing(object):
1295 x = object()
1296
1297 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1298
Ethan Furmane03ea372013-09-25 07:14:41 -07001299 def test_classVirtualAttribute(self):
1300 class Thing(object):
1301 @types.DynamicClassAttribute
1302 def x(self):
1303 return self._x
1304 _x = object()
1305
1306 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1307
Michael Foord95fc51d2010-11-20 15:07:30 +00001308 def test_inherited_classattribute(self):
1309 class Thing(object):
1310 x = object()
1311 class OtherThing(Thing):
1312 pass
1313
1314 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1315
1316 def test_slots(self):
1317 class Thing(object):
1318 y = 'bar'
1319 __slots__ = ['x']
1320 def __init__(self):
1321 self.x = 'foo'
1322 thing = Thing()
1323 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1324 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1325
1326 del thing.x
1327 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1328
1329 def test_metaclass(self):
1330 class meta(type):
1331 attr = 'foo'
1332 class Thing(object, metaclass=meta):
1333 pass
1334 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1335
1336 class sub(meta):
1337 pass
1338 class OtherThing(object, metaclass=sub):
1339 x = 3
1340 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1341
1342 class OtherOtherThing(OtherThing):
1343 pass
1344 # this test is odd, but it was added as it exposed a bug
1345 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1346
1347 def test_no_dict_no_slots(self):
1348 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1349 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1350
1351 def test_no_dict_no_slots_instance_member(self):
1352 # returns descriptor
1353 with open(__file__) as handle:
1354 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1355
1356 def test_inherited_slots(self):
1357 # returns descriptor
1358 class Thing(object):
1359 __slots__ = ['x']
1360 def __init__(self):
1361 self.x = 'foo'
1362
1363 class OtherThing(Thing):
1364 pass
1365 # it would be nice if this worked...
1366 # we get the descriptor instead of the instance attribute
1367 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1368
1369 def test_descriptor(self):
1370 class descriptor(object):
1371 def __get__(self, instance, owner):
1372 return 3
1373 class Foo(object):
1374 d = descriptor()
1375
1376 foo = Foo()
1377
1378 # for a non data descriptor we return the instance attribute
1379 foo.__dict__['d'] = 1
1380 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1381
1382 # if the descriptor is a data-desciptor we should return the
1383 # descriptor
1384 descriptor.__set__ = lambda s, i, v: None
1385 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1386
1387
1388 def test_metaclass_with_descriptor(self):
1389 class descriptor(object):
1390 def __get__(self, instance, owner):
1391 return 3
1392 class meta(type):
1393 d = descriptor()
1394 class Thing(object, metaclass=meta):
1395 pass
1396 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1397
1398
Michael Foordcc7ebb82010-11-20 16:20:16 +00001399 def test_class_as_property(self):
1400 class Base(object):
1401 foo = 3
1402
1403 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001404 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001405 @property
1406 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001407 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001408 return object
1409
Michael Foord35184ed2010-11-20 16:58:30 +00001410 instance = Something()
1411 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1412 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001413 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1414
Michael Foorde5162652010-11-20 16:40:44 +00001415 def test_mro_as_property(self):
1416 class Meta(type):
1417 @property
1418 def __mro__(self):
1419 return (object,)
1420
1421 class Base(object):
1422 foo = 3
1423
1424 class Something(Base, metaclass=Meta):
1425 pass
1426
1427 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1428 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1429
Michael Foorddcebe0f2011-03-15 19:20:44 -04001430 def test_dict_as_property(self):
1431 test = self
1432 test.called = False
1433
1434 class Foo(dict):
1435 a = 3
1436 @property
1437 def __dict__(self):
1438 test.called = True
1439 return {}
1440
1441 foo = Foo()
1442 foo.a = 4
1443 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1444 self.assertFalse(test.called)
1445
1446 def test_custom_object_dict(self):
1447 test = self
1448 test.called = False
1449
1450 class Custom(dict):
1451 def get(self, key, default=None):
1452 test.called = True
1453 super().get(key, default)
1454
1455 class Foo(object):
1456 a = 3
1457 foo = Foo()
1458 foo.__dict__ = Custom()
1459 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1460 self.assertFalse(test.called)
1461
1462 def test_metaclass_dict_as_property(self):
1463 class Meta(type):
1464 @property
1465 def __dict__(self):
1466 self.executed = True
1467
1468 class Thing(metaclass=Meta):
1469 executed = False
1470
1471 def __init__(self):
1472 self.spam = 42
1473
1474 instance = Thing()
1475 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1476 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001477
Michael Foorda51623b2011-12-18 22:01:40 +00001478 def test_module(self):
1479 sentinel = object()
1480 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1481 sentinel)
1482
Michael Foord3ba95f82011-12-22 01:13:37 +00001483 def test_metaclass_with_metaclass_with_dict_as_property(self):
1484 class MetaMeta(type):
1485 @property
1486 def __dict__(self):
1487 self.executed = True
1488 return dict(spam=42)
1489
1490 class Meta(type, metaclass=MetaMeta):
1491 executed = False
1492
1493 class Thing(metaclass=Meta):
1494 pass
1495
1496 with self.assertRaises(AttributeError):
1497 inspect.getattr_static(Thing, "spam")
1498 self.assertFalse(Thing.executed)
1499
Nick Coghlane0f04652010-11-21 03:44:04 +00001500class TestGetGeneratorState(unittest.TestCase):
1501
1502 def setUp(self):
1503 def number_generator():
1504 for number in range(5):
1505 yield number
1506 self.generator = number_generator()
1507
1508 def _generatorstate(self):
1509 return inspect.getgeneratorstate(self.generator)
1510
1511 def test_created(self):
1512 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1513
1514 def test_suspended(self):
1515 next(self.generator)
1516 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1517
1518 def test_closed_after_exhaustion(self):
1519 for i in self.generator:
1520 pass
1521 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1522
1523 def test_closed_after_immediate_exception(self):
1524 with self.assertRaises(RuntimeError):
1525 self.generator.throw(RuntimeError)
1526 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1527
1528 def test_running(self):
1529 # As mentioned on issue #10220, checking for the RUNNING state only
1530 # makes sense inside the generator itself.
1531 # The following generator checks for this by using the closure's
1532 # reference to self and the generator state checking helper method
1533 def running_check_generator():
1534 for number in range(5):
1535 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1536 yield number
1537 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1538 self.generator = running_check_generator()
1539 # Running up to the first yield
1540 next(self.generator)
1541 # Running after the first yield
1542 next(self.generator)
1543
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001544 def test_easy_debugging(self):
1545 # repr() and str() of a generator state should contain the state name
1546 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1547 for name in names:
1548 state = getattr(inspect, name)
1549 self.assertIn(name, repr(state))
1550 self.assertIn(name, str(state))
1551
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001552 def test_getgeneratorlocals(self):
1553 def each(lst, a=None):
1554 b=(1, 2, 3)
1555 for v in lst:
1556 if v == 3:
1557 c = 12
1558 yield v
1559
1560 numbers = each([1, 2, 3])
1561 self.assertEqual(inspect.getgeneratorlocals(numbers),
1562 {'a': None, 'lst': [1, 2, 3]})
1563 next(numbers)
1564 self.assertEqual(inspect.getgeneratorlocals(numbers),
1565 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1566 'b': (1, 2, 3)})
1567 next(numbers)
1568 self.assertEqual(inspect.getgeneratorlocals(numbers),
1569 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1570 'b': (1, 2, 3)})
1571 next(numbers)
1572 self.assertEqual(inspect.getgeneratorlocals(numbers),
1573 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1574 'b': (1, 2, 3), 'c': 12})
1575 try:
1576 next(numbers)
1577 except StopIteration:
1578 pass
1579 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1580
1581 def test_getgeneratorlocals_empty(self):
1582 def yield_one():
1583 yield 1
1584 one = yield_one()
1585 self.assertEqual(inspect.getgeneratorlocals(one), {})
1586 try:
1587 next(one)
1588 except StopIteration:
1589 pass
1590 self.assertEqual(inspect.getgeneratorlocals(one), {})
1591
1592 def test_getgeneratorlocals_error(self):
1593 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1594 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1595 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1596 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1597
Nick Coghlane0f04652010-11-21 03:44:04 +00001598
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001599class TestSignatureObject(unittest.TestCase):
1600 @staticmethod
1601 def signature(func):
1602 sig = inspect.signature(func)
1603 return (tuple((param.name,
1604 (... if param.default is param.empty else param.default),
1605 (... if param.annotation is param.empty
1606 else param.annotation),
1607 str(param.kind).lower())
1608 for param in sig.parameters.values()),
1609 (... if sig.return_annotation is sig.empty
1610 else sig.return_annotation))
1611
1612 def test_signature_object(self):
1613 S = inspect.Signature
1614 P = inspect.Parameter
1615
1616 self.assertEqual(str(S()), '()')
1617
Yury Selivanov07a9e452014-01-29 10:58:16 -05001618 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001619 pass
1620 sig = inspect.signature(test)
1621 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001622 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001623 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001624 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001625 args = sig.parameters['args']
1626 ko = sig.parameters['ko']
1627 kwargs = sig.parameters['kwargs']
1628
1629 S((po, pk, args, ko, kwargs))
1630
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001631 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001632 S((pk, po, args, ko, kwargs))
1633
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001634 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001635 S((po, args, pk, ko, kwargs))
1636
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001637 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001638 S((args, po, pk, ko, kwargs))
1639
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001640 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001641 S((po, pk, args, kwargs, ko))
1642
1643 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001644 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001645 S((po, pk, args, kwargs2, ko))
1646
Yury Selivanov07a9e452014-01-29 10:58:16 -05001647 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1648 S((pod, po))
1649
1650 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1651 S((po, pkd, pk))
1652
1653 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1654 S((pkd, pk))
1655
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001656 def test_signature_immutability(self):
1657 def test(a):
1658 pass
1659 sig = inspect.signature(test)
1660
1661 with self.assertRaises(AttributeError):
1662 sig.foo = 'bar'
1663
1664 with self.assertRaises(TypeError):
1665 sig.parameters['a'] = None
1666
1667 def test_signature_on_noarg(self):
1668 def test():
1669 pass
1670 self.assertEqual(self.signature(test), ((), ...))
1671
1672 def test_signature_on_wargs(self):
1673 def test(a, b:'foo') -> 123:
1674 pass
1675 self.assertEqual(self.signature(test),
1676 ((('a', ..., ..., "positional_or_keyword"),
1677 ('b', ..., 'foo', "positional_or_keyword")),
1678 123))
1679
1680 def test_signature_on_wkwonly(self):
1681 def test(*, a:float, b:str) -> int:
1682 pass
1683 self.assertEqual(self.signature(test),
1684 ((('a', ..., float, "keyword_only"),
1685 ('b', ..., str, "keyword_only")),
1686 int))
1687
1688 def test_signature_on_complex_args(self):
1689 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1690 pass
1691 self.assertEqual(self.signature(test),
1692 ((('a', ..., ..., "positional_or_keyword"),
1693 ('b', 10, 'foo', "positional_or_keyword"),
1694 ('args', ..., 'bar', "var_positional"),
1695 ('spam', ..., 'baz', "keyword_only"),
1696 ('ham', 123, ..., "keyword_only"),
1697 ('kwargs', ..., int, "var_keyword")),
1698 ...))
1699
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001700 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001701 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1702 "Signature information for builtins requires docstrings")
1703 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001704 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001705
Larry Hastings5c661892014-01-24 06:17:25 -08001706 def test_unbound_method(o):
1707 """Use this to test unbound methods (things that should have a self)"""
1708 signature = inspect.signature(o)
1709 self.assertTrue(isinstance(signature, inspect.Signature))
1710 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1711 return signature
1712
1713 def test_callable(o):
1714 """Use this to test bound methods or normal callables (things that don't expect self)"""
1715 signature = inspect.signature(o)
1716 self.assertTrue(isinstance(signature, inspect.Signature))
1717 if signature.parameters:
1718 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1719 return signature
1720
1721 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001722 def p(name): return signature.parameters[name].default
1723 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001724 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001725 self.assertEqual(p('d'), 3.14)
1726 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001727 self.assertEqual(p('n'), None)
1728 self.assertEqual(p('t'), True)
1729 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001730 self.assertEqual(p('local'), 3)
1731 self.assertEqual(p('sys'), sys.maxsize)
1732 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001733
Larry Hastings5c661892014-01-24 06:17:25 -08001734 test_callable(object)
1735
1736 # normal method
1737 # (PyMethodDescr_Type, "method_descriptor")
1738 test_unbound_method(_pickle.Pickler.dump)
1739 d = _pickle.Pickler(io.StringIO())
1740 test_callable(d.dump)
1741
1742 # static method
1743 test_callable(str.maketrans)
1744 test_callable('abc'.maketrans)
1745
1746 # class method
1747 test_callable(dict.fromkeys)
1748 test_callable({}.fromkeys)
1749
1750 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1751 test_unbound_method(type.__call__)
1752 test_unbound_method(int.__add__)
1753 test_callable((3).__add__)
1754
1755 # _PyMethodWrapper_Type
1756 # support for 'method-wrapper'
1757 test_callable(min.__call__)
1758
Larry Hastings2623c8c2014-02-08 22:15:29 -08001759 # This doesn't work now.
1760 # (We don't have a valid signature for "type" in 3.4)
1761 with self.assertRaisesRegex(ValueError, "no signature found"):
1762 class ThisWorksNow:
1763 __call__ = type
1764 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08001765
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001766 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05001767 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1768 "Signature information for builtins requires docstrings")
1769 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001770 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05001771 func = _testcapi.docstring_with_signature_with_defaults
1772
1773 def decorator(func):
1774 @functools.wraps(func)
1775 def wrapper(*args, **kwargs) -> int:
1776 return func(*args, **kwargs)
1777 return wrapper
1778
1779 decorated_func = decorator(func)
1780
1781 self.assertEqual(inspect.signature(func),
1782 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08001783
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001784 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08001785 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001786 import _testcapi
Larry Hastings5c661892014-01-24 06:17:25 -08001787 with self.assertRaisesRegex(ValueError, 'no signature found for builtin'):
1788 inspect.signature(_testcapi.docstring_no_signature)
1789
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001790 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001791 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001792 inspect.signature(42)
1793
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001794 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001795 inspect.Signature.from_function(42)
1796
Yury Selivanovb77511d2014-01-29 10:46:14 -05001797 def test_signature_from_builtin_errors(self):
1798 with self.assertRaisesRegex(TypeError, 'is not a Python builtin'):
1799 inspect.Signature.from_builtin(42)
1800
Yury Selivanov63da7c72014-01-31 14:48:37 -05001801 def test_signature_from_functionlike_object(self):
1802 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1803 pass
1804
1805 class funclike:
1806 # Has to be callable, and have correct
1807 # __code__, __annotations__, __defaults__, __name__,
1808 # and __kwdefaults__ attributes
1809
1810 def __init__(self, func):
1811 self.__name__ = func.__name__
1812 self.__code__ = func.__code__
1813 self.__annotations__ = func.__annotations__
1814 self.__defaults__ = func.__defaults__
1815 self.__kwdefaults__ = func.__kwdefaults__
1816 self.func = func
1817
1818 def __call__(self, *args, **kwargs):
1819 return self.func(*args, **kwargs)
1820
1821 sig_func = inspect.Signature.from_function(func)
1822
1823 sig_funclike = inspect.Signature.from_function(funclike(func))
1824 self.assertEqual(sig_funclike, sig_func)
1825
1826 sig_funclike = inspect.signature(funclike(func))
1827 self.assertEqual(sig_funclike, sig_func)
1828
1829 # If object is not a duck type of function, then
1830 # signature will try to get a signature for its '__call__'
1831 # method
1832 fl = funclike(func)
1833 del fl.__defaults__
1834 self.assertEqual(self.signature(fl),
1835 ((('args', ..., ..., "var_positional"),
1836 ('kwargs', ..., ..., "var_keyword")),
1837 ...))
1838
1839 def test_signature_functionlike_class(self):
1840 # We only want to duck type function-like objects,
1841 # not classes.
1842
1843 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1844 pass
1845
1846 class funclike:
1847 def __init__(self, marker):
1848 pass
1849
1850 __name__ = func.__name__
1851 __code__ = func.__code__
1852 __annotations__ = func.__annotations__
1853 __defaults__ = func.__defaults__
1854 __kwdefaults__ = func.__kwdefaults__
1855
1856 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1857 inspect.Signature.from_function(funclike)
1858
1859 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
1860
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001861 def test_signature_on_method(self):
1862 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05001863 def __init__(*args):
1864 pass
1865 def m1(self, arg1, arg2=1) -> int:
1866 pass
1867 def m2(*args):
1868 pass
1869 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001870 pass
1871
Yury Selivanov62560fb2014-01-28 12:26:24 -05001872 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001873 ((('arg1', ..., ..., "positional_or_keyword"),
1874 ('arg2', 1, ..., "positional_or_keyword")),
1875 int))
1876
Yury Selivanov62560fb2014-01-28 12:26:24 -05001877 self.assertEqual(self.signature(Test().m2),
1878 ((('args', ..., ..., "var_positional"),),
1879 ...))
1880
1881 self.assertEqual(self.signature(Test),
1882 ((('args', ..., ..., "var_positional"),),
1883 ...))
1884
1885 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
1886 self.signature(Test())
1887
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001888 def test_signature_on_classmethod(self):
1889 class Test:
1890 @classmethod
1891 def foo(cls, arg1, *, arg2=1):
1892 pass
1893
1894 meth = Test().foo
1895 self.assertEqual(self.signature(meth),
1896 ((('arg1', ..., ..., "positional_or_keyword"),
1897 ('arg2', 1, ..., "keyword_only")),
1898 ...))
1899
1900 meth = Test.foo
1901 self.assertEqual(self.signature(meth),
1902 ((('arg1', ..., ..., "positional_or_keyword"),
1903 ('arg2', 1, ..., "keyword_only")),
1904 ...))
1905
1906 def test_signature_on_staticmethod(self):
1907 class Test:
1908 @staticmethod
1909 def foo(cls, *, arg):
1910 pass
1911
1912 meth = Test().foo
1913 self.assertEqual(self.signature(meth),
1914 ((('cls', ..., ..., "positional_or_keyword"),
1915 ('arg', ..., ..., "keyword_only")),
1916 ...))
1917
1918 meth = Test.foo
1919 self.assertEqual(self.signature(meth),
1920 ((('cls', ..., ..., "positional_or_keyword"),
1921 ('arg', ..., ..., "keyword_only")),
1922 ...))
1923
1924 def test_signature_on_partial(self):
1925 from functools import partial
1926
1927 def test():
1928 pass
1929
1930 self.assertEqual(self.signature(partial(test)), ((), ...))
1931
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001932 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001933 inspect.signature(partial(test, 1))
1934
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001935 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001936 inspect.signature(partial(test, a=1))
1937
1938 def test(a, b, *, c, d):
1939 pass
1940
1941 self.assertEqual(self.signature(partial(test)),
1942 ((('a', ..., ..., "positional_or_keyword"),
1943 ('b', ..., ..., "positional_or_keyword"),
1944 ('c', ..., ..., "keyword_only"),
1945 ('d', ..., ..., "keyword_only")),
1946 ...))
1947
1948 self.assertEqual(self.signature(partial(test, 1)),
1949 ((('b', ..., ..., "positional_or_keyword"),
1950 ('c', ..., ..., "keyword_only"),
1951 ('d', ..., ..., "keyword_only")),
1952 ...))
1953
1954 self.assertEqual(self.signature(partial(test, 1, c=2)),
1955 ((('b', ..., ..., "positional_or_keyword"),
1956 ('c', 2, ..., "keyword_only"),
1957 ('d', ..., ..., "keyword_only")),
1958 ...))
1959
1960 self.assertEqual(self.signature(partial(test, b=1, c=2)),
1961 ((('a', ..., ..., "positional_or_keyword"),
1962 ('b', 1, ..., "positional_or_keyword"),
1963 ('c', 2, ..., "keyword_only"),
1964 ('d', ..., ..., "keyword_only")),
1965 ...))
1966
1967 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
1968 ((('b', 1, ..., "positional_or_keyword"),
1969 ('c', 2, ..., "keyword_only"),
1970 ('d', ..., ..., "keyword_only"),),
1971 ...))
1972
1973 def test(a, *args, b, **kwargs):
1974 pass
1975
1976 self.assertEqual(self.signature(partial(test, 1)),
1977 ((('args', ..., ..., "var_positional"),
1978 ('b', ..., ..., "keyword_only"),
1979 ('kwargs', ..., ..., "var_keyword")),
1980 ...))
1981
1982 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
1983 ((('args', ..., ..., "var_positional"),
1984 ('b', ..., ..., "keyword_only"),
1985 ('kwargs', ..., ..., "var_keyword")),
1986 ...))
1987
1988
1989 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
1990 ((('args', ..., ..., "var_positional"),
1991 ('b', ..., ..., "keyword_only"),
1992 ('kwargs', ..., ..., "var_keyword")),
1993 ...))
1994
1995 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
1996 ((('args', ..., ..., "var_positional"),
1997 ('b', 0, ..., "keyword_only"),
1998 ('kwargs', ..., ..., "var_keyword")),
1999 ...))
2000
2001 self.assertEqual(self.signature(partial(test, b=0)),
2002 ((('a', ..., ..., "positional_or_keyword"),
2003 ('args', ..., ..., "var_positional"),
2004 ('b', 0, ..., "keyword_only"),
2005 ('kwargs', ..., ..., "var_keyword")),
2006 ...))
2007
2008 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2009 ((('a', ..., ..., "positional_or_keyword"),
2010 ('args', ..., ..., "var_positional"),
2011 ('b', 0, ..., "keyword_only"),
2012 ('kwargs', ..., ..., "var_keyword")),
2013 ...))
2014
2015 def test(a, b, c:int) -> 42:
2016 pass
2017
2018 sig = test.__signature__ = inspect.signature(test)
2019
2020 self.assertEqual(self.signature(partial(partial(test, 1))),
2021 ((('b', ..., ..., "positional_or_keyword"),
2022 ('c', ..., int, "positional_or_keyword")),
2023 42))
2024
2025 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2026 ((('c', ..., int, "positional_or_keyword"),),
2027 42))
2028
2029 psig = inspect.signature(partial(partial(test, 1), 2))
2030
2031 def foo(a):
2032 return a
2033 _foo = partial(partial(foo, a=10), a=20)
2034 self.assertEqual(self.signature(_foo),
2035 ((('a', 20, ..., "positional_or_keyword"),),
2036 ...))
2037 # check that we don't have any side-effects in signature(),
2038 # and the partial object is still functioning
2039 self.assertEqual(_foo(), 20)
2040
2041 def foo(a, b, c):
2042 return a, b, c
2043 _foo = partial(partial(foo, 1, b=20), b=30)
2044 self.assertEqual(self.signature(_foo),
2045 ((('b', 30, ..., "positional_or_keyword"),
2046 ('c', ..., ..., "positional_or_keyword")),
2047 ...))
2048 self.assertEqual(_foo(c=10), (1, 30, 10))
2049 _foo = partial(_foo, 2) # now 'b' has two values -
2050 # positional and keyword
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002051 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002052 inspect.signature(_foo)
2053
2054 def foo(a, b, c, *, d):
2055 return a, b, c, d
2056 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2057 self.assertEqual(self.signature(_foo),
2058 ((('a', ..., ..., "positional_or_keyword"),
2059 ('b', 10, ..., "positional_or_keyword"),
2060 ('c', 20, ..., "positional_or_keyword"),
2061 ('d', 30, ..., "keyword_only")),
2062 ...))
2063 ba = inspect.signature(_foo).bind(a=200, b=11)
2064 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2065
2066 def foo(a=1, b=2, c=3):
2067 return a, b, c
2068 _foo = partial(foo, a=10, c=13)
2069 ba = inspect.signature(_foo).bind(11)
2070 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
2071 ba = inspect.signature(_foo).bind(11, 12)
2072 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
2073 ba = inspect.signature(_foo).bind(11, b=12)
2074 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
2075 ba = inspect.signature(_foo).bind(b=12)
2076 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
2077 _foo = partial(_foo, b=10)
2078 ba = inspect.signature(_foo).bind(12, 14)
2079 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
2080
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002081 def test_signature_on_partialmethod(self):
2082 from functools import partialmethod
2083
2084 class Spam:
2085 def test():
2086 pass
2087 ham = partialmethod(test)
2088
2089 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2090 inspect.signature(Spam.ham)
2091
2092 class Spam:
2093 def test(it, a, *, c) -> 'spam':
2094 pass
2095 ham = partialmethod(test, c=1)
2096
2097 self.assertEqual(self.signature(Spam.ham),
2098 ((('it', ..., ..., 'positional_or_keyword'),
2099 ('a', ..., ..., 'positional_or_keyword'),
2100 ('c', 1, ..., 'keyword_only')),
2101 'spam'))
2102
2103 self.assertEqual(self.signature(Spam().ham),
2104 ((('a', ..., ..., 'positional_or_keyword'),
2105 ('c', 1, ..., 'keyword_only')),
2106 'spam'))
2107
Yury Selivanov0486f812014-01-29 12:18:59 -05002108 def test_signature_on_fake_partialmethod(self):
2109 def foo(a): pass
2110 foo._partialmethod = 'spam'
2111 self.assertEqual(str(inspect.signature(foo)), '(a)')
2112
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002113 def test_signature_on_decorated(self):
2114 import functools
2115
2116 def decorator(func):
2117 @functools.wraps(func)
2118 def wrapper(*args, **kwargs) -> int:
2119 return func(*args, **kwargs)
2120 return wrapper
2121
2122 class Foo:
2123 @decorator
2124 def bar(self, a, b):
2125 pass
2126
2127 self.assertEqual(self.signature(Foo.bar),
2128 ((('self', ..., ..., "positional_or_keyword"),
2129 ('a', ..., ..., "positional_or_keyword"),
2130 ('b', ..., ..., "positional_or_keyword")),
2131 ...))
2132
2133 self.assertEqual(self.signature(Foo().bar),
2134 ((('a', ..., ..., "positional_or_keyword"),
2135 ('b', ..., ..., "positional_or_keyword")),
2136 ...))
2137
2138 # Test that we handle method wrappers correctly
2139 def decorator(func):
2140 @functools.wraps(func)
2141 def wrapper(*args, **kwargs) -> int:
2142 return func(42, *args, **kwargs)
2143 sig = inspect.signature(func)
2144 new_params = tuple(sig.parameters.values())[1:]
2145 wrapper.__signature__ = sig.replace(parameters=new_params)
2146 return wrapper
2147
2148 class Foo:
2149 @decorator
2150 def __call__(self, a, b):
2151 pass
2152
2153 self.assertEqual(self.signature(Foo.__call__),
2154 ((('a', ..., ..., "positional_or_keyword"),
2155 ('b', ..., ..., "positional_or_keyword")),
2156 ...))
2157
2158 self.assertEqual(self.signature(Foo().__call__),
2159 ((('b', ..., ..., "positional_or_keyword"),),
2160 ...))
2161
Nick Coghlane8c45d62013-07-28 20:00:01 +10002162 # Test we handle __signature__ partway down the wrapper stack
2163 def wrapped_foo_call():
2164 pass
2165 wrapped_foo_call.__wrapped__ = Foo.__call__
2166
2167 self.assertEqual(self.signature(wrapped_foo_call),
2168 ((('a', ..., ..., "positional_or_keyword"),
2169 ('b', ..., ..., "positional_or_keyword")),
2170 ...))
2171
2172
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002173 def test_signature_on_class(self):
2174 class C:
2175 def __init__(self, a):
2176 pass
2177
2178 self.assertEqual(self.signature(C),
2179 ((('a', ..., ..., "positional_or_keyword"),),
2180 ...))
2181
2182 class CM(type):
2183 def __call__(cls, a):
2184 pass
2185 class C(metaclass=CM):
2186 def __init__(self, b):
2187 pass
2188
2189 self.assertEqual(self.signature(C),
2190 ((('a', ..., ..., "positional_or_keyword"),),
2191 ...))
2192
2193 class CM(type):
2194 def __new__(mcls, name, bases, dct, *, foo=1):
2195 return super().__new__(mcls, name, bases, dct)
2196 class C(metaclass=CM):
2197 def __init__(self, b):
2198 pass
2199
2200 self.assertEqual(self.signature(C),
2201 ((('b', ..., ..., "positional_or_keyword"),),
2202 ...))
2203
2204 self.assertEqual(self.signature(CM),
2205 ((('name', ..., ..., "positional_or_keyword"),
2206 ('bases', ..., ..., "positional_or_keyword"),
2207 ('dct', ..., ..., "positional_or_keyword"),
2208 ('foo', 1, ..., "keyword_only")),
2209 ...))
2210
2211 class CMM(type):
2212 def __new__(mcls, name, bases, dct, *, foo=1):
2213 return super().__new__(mcls, name, bases, dct)
2214 def __call__(cls, nm, bs, dt):
2215 return type(nm, bs, dt)
2216 class CM(type, metaclass=CMM):
2217 def __new__(mcls, name, bases, dct, *, bar=2):
2218 return super().__new__(mcls, name, bases, dct)
2219 class C(metaclass=CM):
2220 def __init__(self, b):
2221 pass
2222
2223 self.assertEqual(self.signature(CMM),
2224 ((('name', ..., ..., "positional_or_keyword"),
2225 ('bases', ..., ..., "positional_or_keyword"),
2226 ('dct', ..., ..., "positional_or_keyword"),
2227 ('foo', 1, ..., "keyword_only")),
2228 ...))
2229
2230 self.assertEqual(self.signature(CM),
2231 ((('nm', ..., ..., "positional_or_keyword"),
2232 ('bs', ..., ..., "positional_or_keyword"),
2233 ('dt', ..., ..., "positional_or_keyword")),
2234 ...))
2235
2236 self.assertEqual(self.signature(C),
2237 ((('b', ..., ..., "positional_or_keyword"),),
2238 ...))
2239
2240 class CM(type):
2241 def __init__(cls, name, bases, dct, *, bar=2):
2242 return super().__init__(name, bases, dct)
2243 class C(metaclass=CM):
2244 def __init__(self, b):
2245 pass
2246
2247 self.assertEqual(self.signature(CM),
2248 ((('name', ..., ..., "positional_or_keyword"),
2249 ('bases', ..., ..., "positional_or_keyword"),
2250 ('dct', ..., ..., "positional_or_keyword"),
2251 ('bar', 2, ..., "keyword_only")),
2252 ...))
2253
Yury Selivanov145dff82014-02-01 13:49:29 -05002254 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2255 "Signature information for builtins requires docstrings")
2256 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002257 # Test classes without user-defined __init__ or __new__
2258 class C: pass
2259 self.assertEqual(str(inspect.signature(C)), '()')
2260 class D(C): pass
2261 self.assertEqual(str(inspect.signature(D)), '()')
2262
2263 # Test meta-classes without user-defined __init__ or __new__
2264 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002265 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002266 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2267 self.assertEqual(inspect.signature(C), None)
2268 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2269 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002270
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002271 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2272 "Signature information for builtins requires docstrings")
2273 def test_signature_on_builtin_class(self):
2274 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2275 '(file, protocol=None, fix_imports=True)')
2276
2277 class P(_pickle.Pickler): pass
2278 class EmptyTrait: pass
2279 class P2(EmptyTrait, P): pass
2280 self.assertEqual(str(inspect.signature(P)),
2281 '(file, protocol=None, fix_imports=True)')
2282 self.assertEqual(str(inspect.signature(P2)),
2283 '(file, protocol=None, fix_imports=True)')
2284
2285 class P3(P2):
2286 def __init__(self, spam):
2287 pass
2288 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2289
2290 class MetaP(type):
2291 def __call__(cls, foo, bar):
2292 pass
2293 class P4(P2, metaclass=MetaP):
2294 pass
2295 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2296
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002297 def test_signature_on_callable_objects(self):
2298 class Foo:
2299 def __call__(self, a):
2300 pass
2301
2302 self.assertEqual(self.signature(Foo()),
2303 ((('a', ..., ..., "positional_or_keyword"),),
2304 ...))
2305
2306 class Spam:
2307 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002308 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002309 inspect.signature(Spam())
2310
2311 class Bar(Spam, Foo):
2312 pass
2313
2314 self.assertEqual(self.signature(Bar()),
2315 ((('a', ..., ..., "positional_or_keyword"),),
2316 ...))
2317
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002318 class Wrapped:
2319 pass
2320 Wrapped.__wrapped__ = lambda a: None
2321 self.assertEqual(self.signature(Wrapped),
2322 ((('a', ..., ..., "positional_or_keyword"),),
2323 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002324 # wrapper loop:
2325 Wrapped.__wrapped__ = Wrapped
2326 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2327 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002328
2329 def test_signature_on_lambdas(self):
2330 self.assertEqual(self.signature((lambda a=10: a)),
2331 ((('a', 10, ..., "positional_or_keyword"),),
2332 ...))
2333
2334 def test_signature_equality(self):
2335 def foo(a, *, b:int) -> float: pass
2336 self.assertNotEqual(inspect.signature(foo), 42)
2337
2338 def bar(a, *, b:int) -> float: pass
2339 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2340
2341 def bar(a, *, b:int) -> int: pass
2342 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2343
2344 def bar(a, *, b:int): pass
2345 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2346
2347 def bar(a, *, b:int=42) -> float: pass
2348 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2349
2350 def bar(a, *, c) -> float: pass
2351 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2352
2353 def bar(a, b:int) -> float: pass
2354 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2355 def spam(b:int, a) -> float: pass
2356 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
2357
2358 def foo(*, a, b, c): pass
2359 def bar(*, c, b, a): pass
2360 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2361
2362 def foo(*, a=1, b, c): pass
2363 def bar(*, c, b, a=1): pass
2364 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2365
2366 def foo(pos, *, a=1, b, c): pass
2367 def bar(pos, *, c, b, a=1): pass
2368 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2369
2370 def foo(pos, *, a, b, c): pass
2371 def bar(pos, *, c, b, a=1): pass
2372 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2373
2374 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2375 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2376 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2377
2378 def test_signature_unhashable(self):
2379 def foo(a): pass
2380 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002381 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002382 hash(sig)
2383
2384 def test_signature_str(self):
2385 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2386 pass
2387 self.assertEqual(str(inspect.signature(foo)),
2388 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2389
2390 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2391 pass
2392 self.assertEqual(str(inspect.signature(foo)),
2393 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2394
2395 def foo():
2396 pass
2397 self.assertEqual(str(inspect.signature(foo)), '()')
2398
2399 def test_signature_str_positional_only(self):
2400 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002401 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002402
2403 def test(a_po, *, b, **kwargs):
2404 return a_po, kwargs
2405
2406 sig = inspect.signature(test)
2407 new_params = list(sig.parameters.values())
2408 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2409 test.__signature__ = sig.replace(parameters=new_params)
2410
2411 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002412 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002413
Yury Selivanov2393dca2014-01-27 15:07:58 -05002414 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2415 '(foo, /)')
2416
2417 self.assertEqual(str(S(parameters=[
2418 P('foo', P.POSITIONAL_ONLY),
2419 P('bar', P.VAR_KEYWORD)])),
2420 '(foo, /, **bar)')
2421
2422 self.assertEqual(str(S(parameters=[
2423 P('foo', P.POSITIONAL_ONLY),
2424 P('bar', P.VAR_POSITIONAL)])),
2425 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002426
2427 def test_signature_replace_anno(self):
2428 def test() -> 42:
2429 pass
2430
2431 sig = inspect.signature(test)
2432 sig = sig.replace(return_annotation=None)
2433 self.assertIs(sig.return_annotation, None)
2434 sig = sig.replace(return_annotation=sig.empty)
2435 self.assertIs(sig.return_annotation, sig.empty)
2436 sig = sig.replace(return_annotation=42)
2437 self.assertEqual(sig.return_annotation, 42)
2438 self.assertEqual(sig, inspect.signature(test))
2439
Yury Selivanov026019f2014-02-18 12:49:41 -05002440 def test_signature_on_mangled_parameters(self):
2441 class Spam:
2442 def foo(self, __p1:1=2, *, __p2:2=3):
2443 pass
2444 class Ham(Spam):
2445 pass
2446
2447 self.assertEqual(self.signature(Spam.foo),
2448 ((('self', ..., ..., "positional_or_keyword"),
2449 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2450 ('_Spam__p2', 3, 2, "keyword_only")),
2451 ...))
2452
2453 self.assertEqual(self.signature(Spam.foo),
2454 self.signature(Ham.foo))
2455
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002456
2457class TestParameterObject(unittest.TestCase):
2458 def test_signature_parameter_kinds(self):
2459 P = inspect.Parameter
2460 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2461 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2462
2463 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2464 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2465
2466 def test_signature_parameter_object(self):
2467 p = inspect.Parameter('foo', default=10,
2468 kind=inspect.Parameter.POSITIONAL_ONLY)
2469 self.assertEqual(p.name, 'foo')
2470 self.assertEqual(p.default, 10)
2471 self.assertIs(p.annotation, p.empty)
2472 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2473
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002474 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002475 inspect.Parameter('foo', default=10, kind='123')
2476
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002477 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002478 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2479
Yury Selivanov2393dca2014-01-27 15:07:58 -05002480 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002481 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2482
Yury Selivanov2393dca2014-01-27 15:07:58 -05002483 with self.assertRaisesRegex(ValueError,
2484 'is not a valid parameter name'):
2485 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2486
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002487 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002488 inspect.Parameter('a', default=42,
2489 kind=inspect.Parameter.VAR_KEYWORD)
2490
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002491 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002492 inspect.Parameter('a', default=42,
2493 kind=inspect.Parameter.VAR_POSITIONAL)
2494
2495 p = inspect.Parameter('a', default=42,
2496 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002497 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002498 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2499
2500 self.assertTrue(repr(p).startswith('<Parameter'))
2501
2502 def test_signature_parameter_equality(self):
2503 P = inspect.Parameter
2504 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2505
2506 self.assertEqual(p, p)
2507 self.assertNotEqual(p, 42)
2508
2509 self.assertEqual(p, P('foo', default=42,
2510 kind=inspect.Parameter.KEYWORD_ONLY))
2511
2512 def test_signature_parameter_unhashable(self):
2513 p = inspect.Parameter('foo', default=42,
2514 kind=inspect.Parameter.KEYWORD_ONLY)
2515
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002516 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002517 hash(p)
2518
2519 def test_signature_parameter_replace(self):
2520 p = inspect.Parameter('foo', default=42,
2521 kind=inspect.Parameter.KEYWORD_ONLY)
2522
2523 self.assertIsNot(p, p.replace())
2524 self.assertEqual(p, p.replace())
2525
2526 p2 = p.replace(annotation=1)
2527 self.assertEqual(p2.annotation, 1)
2528 p2 = p2.replace(annotation=p2.empty)
2529 self.assertEqual(p, p2)
2530
2531 p2 = p2.replace(name='bar')
2532 self.assertEqual(p2.name, 'bar')
2533 self.assertNotEqual(p2, p)
2534
Yury Selivanov2393dca2014-01-27 15:07:58 -05002535 with self.assertRaisesRegex(ValueError,
2536 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002537 p2 = p2.replace(name=p2.empty)
2538
2539 p2 = p2.replace(name='foo', default=None)
2540 self.assertIs(p2.default, None)
2541 self.assertNotEqual(p2, p)
2542
2543 p2 = p2.replace(name='foo', default=p2.empty)
2544 self.assertIs(p2.default, p2.empty)
2545
2546
2547 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2548 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2549 self.assertNotEqual(p2, p)
2550
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002551 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002552 p2 = p2.replace(kind=p2.empty)
2553
2554 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2555 self.assertEqual(p2, p)
2556
2557 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002558 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2559 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002560
2561 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002562 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002563
2564 with self.assertRaises(AttributeError):
2565 p.foo = 'bar'
2566
2567 with self.assertRaises(AttributeError):
2568 p.kind = 123
2569
2570
2571class TestSignatureBind(unittest.TestCase):
2572 @staticmethod
2573 def call(func, *args, **kwargs):
2574 sig = inspect.signature(func)
2575 ba = sig.bind(*args, **kwargs)
2576 return func(*ba.args, **ba.kwargs)
2577
2578 def test_signature_bind_empty(self):
2579 def test():
2580 return 42
2581
2582 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002583 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002584 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002585 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002586 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002587 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002588 self.call(test, spam=1)
2589
2590 def test_signature_bind_var(self):
2591 def test(*args, **kwargs):
2592 return args, kwargs
2593
2594 self.assertEqual(self.call(test), ((), {}))
2595 self.assertEqual(self.call(test, 1), ((1,), {}))
2596 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2597 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2598 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2599 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2600 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2601 ((1, 2), {'foo': 'bar'}))
2602
2603 def test_signature_bind_just_args(self):
2604 def test(a, b, c):
2605 return a, b, c
2606
2607 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2608
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002609 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002610 self.call(test, 1, 2, 3, 4)
2611
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002612 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002613 self.call(test, 1)
2614
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002615 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002616 self.call(test)
2617
2618 def test(a, b, c=10):
2619 return a, b, c
2620 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2621 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2622
2623 def test(a=1, b=2, c=3):
2624 return a, b, c
2625 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2626 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2627 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2628
2629 def test_signature_bind_varargs_order(self):
2630 def test(*args):
2631 return args
2632
2633 self.assertEqual(self.call(test), ())
2634 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2635
2636 def test_signature_bind_args_and_varargs(self):
2637 def test(a, b, c=3, *args):
2638 return a, b, c, args
2639
2640 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2641 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2642 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2643 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2644
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002645 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002646 "multiple values for argument 'c'"):
2647 self.call(test, 1, 2, 3, c=4)
2648
2649 def test_signature_bind_just_kwargs(self):
2650 def test(**kwargs):
2651 return kwargs
2652
2653 self.assertEqual(self.call(test), {})
2654 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2655 {'foo': 'bar', 'spam': 'ham'})
2656
2657 def test_signature_bind_args_and_kwargs(self):
2658 def test(a, b, c=3, **kwargs):
2659 return a, b, c, kwargs
2660
2661 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2662 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2663 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2664 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2665 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2666 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2667 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2668 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2669 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2670 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2671 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2672 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2673 (1, 2, 4, {'foo': 'bar'}))
2674 self.assertEqual(self.call(test, c=5, a=4, b=3),
2675 (4, 3, 5, {}))
2676
2677 def test_signature_bind_kwonly(self):
2678 def test(*, foo):
2679 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002680 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002681 'too many positional arguments'):
2682 self.call(test, 1)
2683 self.assertEqual(self.call(test, foo=1), 1)
2684
2685 def test(a, *, foo=1, bar):
2686 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002687 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002688 "'bar' parameter lacking default value"):
2689 self.call(test, 1)
2690
2691 def test(foo, *, bar):
2692 return foo, bar
2693 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2694 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2695
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002696 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002697 'too many keyword arguments'):
2698 self.call(test, bar=2, foo=1, spam=10)
2699
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002700 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002701 'too many positional arguments'):
2702 self.call(test, 1, 2)
2703
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002704 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002705 'too many positional arguments'):
2706 self.call(test, 1, 2, bar=2)
2707
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002708 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002709 'too many keyword arguments'):
2710 self.call(test, 1, bar=2, spam='ham')
2711
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002712 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002713 "'bar' parameter lacking default value"):
2714 self.call(test, 1)
2715
2716 def test(foo, *, bar, **bin):
2717 return foo, bar, bin
2718 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2719 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2720 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2721 (1, 2, {'spam': 'ham'}))
2722 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2723 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002724 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002725 "'foo' parameter lacking default value"):
2726 self.call(test, spam='ham', bar=2)
2727 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2728 (1, 2, {'bin': 1, 'spam': 10}))
2729
2730 def test_signature_bind_arguments(self):
2731 def test(a, *args, b, z=100, **kwargs):
2732 pass
2733 sig = inspect.signature(test)
2734 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2735 # we won't have 'z' argument in the bound arguments object, as we didn't
2736 # pass it to the 'bind'
2737 self.assertEqual(tuple(ba.arguments.items()),
2738 (('a', 10), ('args', (20,)), ('b', 30),
2739 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2740 self.assertEqual(ba.kwargs,
2741 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2742 self.assertEqual(ba.args, (10, 20))
2743
2744 def test_signature_bind_positional_only(self):
2745 P = inspect.Parameter
2746
2747 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2748 return a_po, b_po, c_po, foo, bar, kwargs
2749
2750 sig = inspect.signature(test)
2751 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2752 for name in ('a_po', 'b_po', 'c_po'):
2753 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2754 new_sig = sig.replace(parameters=new_params.values())
2755 test.__signature__ = new_sig
2756
2757 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2758 (1, 2, 4, 5, 6, {}))
2759
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002760 self.assertEqual(self.call(test, 1, 2),
2761 (1, 2, 3, 42, 50, {}))
2762
2763 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
2764 (1, 2, 3, 4, 5, {}))
2765
2766 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
2767 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
2768
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002769 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002770 self.call(test, 1, 2, c_po=4)
2771
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002772 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002773 self.call(test, a_po=1, b_po=2)
2774
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002775 def test_signature_bind_with_self_arg(self):
2776 # Issue #17071: one of the parameters is named "self
2777 def test(a, self, b):
2778 pass
2779 sig = inspect.signature(test)
2780 ba = sig.bind(1, 2, 3)
2781 self.assertEqual(ba.args, (1, 2, 3))
2782 ba = sig.bind(1, self=2, b=3)
2783 self.assertEqual(ba.args, (1, 2, 3))
2784
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002785 def test_signature_bind_vararg_name(self):
2786 def test(a, *args):
2787 return a, args
2788 sig = inspect.signature(test)
2789
2790 with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
2791 sig.bind(a=0, args=1)
2792
2793 def test(*args, **kwargs):
2794 return args, kwargs
2795 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
2796
2797 sig = inspect.signature(test)
2798 ba = sig.bind(args=1)
2799 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
2800
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002801
2802class TestBoundArguments(unittest.TestCase):
2803 def test_signature_bound_arguments_unhashable(self):
2804 def foo(a): pass
2805 ba = inspect.signature(foo).bind(1)
2806
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002807 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002808 hash(ba)
2809
2810 def test_signature_bound_arguments_equality(self):
2811 def foo(a): pass
2812 ba = inspect.signature(foo).bind(1)
2813 self.assertEqual(ba, ba)
2814
2815 ba2 = inspect.signature(foo).bind(1)
2816 self.assertEqual(ba, ba2)
2817
2818 ba3 = inspect.signature(foo).bind(2)
2819 self.assertNotEqual(ba, ba3)
2820 ba3.arguments['a'] = 1
2821 self.assertEqual(ba, ba3)
2822
2823 def bar(b): pass
2824 ba4 = inspect.signature(bar).bind(1)
2825 self.assertNotEqual(ba, ba4)
2826
2827
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002828class TestSignaturePrivateHelpers(unittest.TestCase):
2829 def test_signature_get_bound_param(self):
2830 getter = inspect._signature_get_bound_param
2831
2832 self.assertEqual(getter('($self)'), 'self')
2833 self.assertEqual(getter('($self, obj)'), 'self')
2834 self.assertEqual(getter('($cls, /, obj)'), 'cls')
2835
Larry Hastings2623c8c2014-02-08 22:15:29 -08002836 def _strip_non_python_syntax(self, input,
2837 clean_signature, self_parameter, last_positional_only):
2838 computed_clean_signature, \
2839 computed_self_parameter, \
2840 computed_last_positional_only = \
2841 inspect._signature_strip_non_python_syntax(input)
2842 self.assertEqual(computed_clean_signature, clean_signature)
2843 self.assertEqual(computed_self_parameter, self_parameter)
2844 self.assertEqual(computed_last_positional_only, last_positional_only)
2845
2846 def test_signature_strip_non_python_syntax(self):
2847 self._strip_non_python_syntax(
2848 "($module, /, path, mode, *, dir_fd=None, " +
2849 "effective_ids=False,\n follow_symlinks=True)",
2850 "(module, path, mode, *, dir_fd=None, " +
2851 "effective_ids=False, follow_symlinks=True)",
2852 0,
2853 0)
2854
2855 self._strip_non_python_syntax(
2856 "($module, word, salt, /)",
2857 "(module, word, salt)",
2858 0,
2859 2)
2860
2861 self._strip_non_python_syntax(
2862 "(x, y=None, z=None, /)",
2863 "(x, y=None, z=None)",
2864 None,
2865 2)
2866
2867 self._strip_non_python_syntax(
2868 "(x, y=None, z=None)",
2869 "(x, y=None, z=None)",
2870 None,
2871 None)
2872
2873 self._strip_non_python_syntax(
2874 "(x,\n y=None,\n z = None )",
2875 "(x, y=None, z=None)",
2876 None,
2877 None)
2878
2879 self._strip_non_python_syntax(
2880 "",
2881 "",
2882 None,
2883 None)
2884
2885 self._strip_non_python_syntax(
2886 None,
2887 None,
2888 None,
2889 None)
2890
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002891
Nick Coghlane8c45d62013-07-28 20:00:01 +10002892class TestUnwrap(unittest.TestCase):
2893
2894 def test_unwrap_one(self):
2895 def func(a, b):
2896 return a + b
2897 wrapper = functools.lru_cache(maxsize=20)(func)
2898 self.assertIs(inspect.unwrap(wrapper), func)
2899
2900 def test_unwrap_several(self):
2901 def func(a, b):
2902 return a + b
2903 wrapper = func
2904 for __ in range(10):
2905 @functools.wraps(wrapper)
2906 def wrapper():
2907 pass
2908 self.assertIsNot(wrapper.__wrapped__, func)
2909 self.assertIs(inspect.unwrap(wrapper), func)
2910
2911 def test_stop(self):
2912 def func1(a, b):
2913 return a + b
2914 @functools.wraps(func1)
2915 def func2():
2916 pass
2917 @functools.wraps(func2)
2918 def wrapper():
2919 pass
2920 func2.stop_here = 1
2921 unwrapped = inspect.unwrap(wrapper,
2922 stop=(lambda f: hasattr(f, "stop_here")))
2923 self.assertIs(unwrapped, func2)
2924
2925 def test_cycle(self):
2926 def func1(): pass
2927 func1.__wrapped__ = func1
2928 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2929 inspect.unwrap(func1)
2930
2931 def func2(): pass
2932 func2.__wrapped__ = func1
2933 func1.__wrapped__ = func2
2934 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2935 inspect.unwrap(func1)
2936 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2937 inspect.unwrap(func2)
2938
2939 def test_unhashable(self):
2940 def func(): pass
2941 func.__wrapped__ = None
2942 class C:
2943 __hash__ = None
2944 __wrapped__ = func
2945 self.assertIsNone(inspect.unwrap(C()))
2946
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002947class TestMain(unittest.TestCase):
2948 def test_only_source(self):
2949 module = importlib.import_module('unittest')
2950 rc, out, err = assert_python_ok('-m', 'inspect',
2951 'unittest')
2952 lines = out.decode().splitlines()
2953 # ignore the final newline
2954 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
2955 self.assertEqual(err, b'')
2956
Brett Cannon634a8fc2013-10-02 10:25:42 -04002957 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04002958 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002959 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002960 rc, out, err = assert_python_ok('-m', 'inspect',
2961 'concurrent.futures:ThreadPoolExecutor')
2962 lines = out.decode().splitlines()
2963 # ignore the final newline
2964 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04002965 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002966 self.assertEqual(err, b'')
2967
2968 def test_builtins(self):
2969 module = importlib.import_module('unittest')
2970 _, out, err = assert_python_failure('-m', 'inspect',
2971 'sys')
2972 lines = err.decode().splitlines()
2973 self.assertEqual(lines, ["Can't get info for builtin modules."])
2974
2975 def test_details(self):
2976 module = importlib.import_module('unittest')
2977 rc, out, err = assert_python_ok('-m', 'inspect',
2978 'unittest', '--details')
2979 output = out.decode()
2980 # Just a quick sanity check on the output
2981 self.assertIn(module.__name__, output)
2982 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02002983 if not sys.flags.optimize:
2984 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002985 self.assertEqual(err, b'')
2986
2987
2988
Nick Coghlane8c45d62013-07-28 20:00:01 +10002989
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002990def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00002991 run_unittest(
2992 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
2993 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
2994 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00002995 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002996 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002997 TestBoundArguments, TestSignaturePrivateHelpers, TestGetClosureVars,
2998 TestUnwrap, TestMain
Michael Foord95fc51d2010-11-20 15:07:30 +00002999 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003000
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003001if __name__ == "__main__":
3002 test_main()