blob: fb6aa6a8aee4838038b924ec7086e8665c3d5e1d [file] [log] [blame]
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001import re
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002import sys
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003import types
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004import unittest
5import inspect
R. David Murraya1b37402010-06-17 02:04:29 +00006import linecache
Thomas Wouters0e3f5912006-08-11 14:57:12 +00007import datetime
Guido van Rossum813b0e52007-05-21 18:11:34 +00008import collections
Alexander Belopolskyf546e702010-12-02 00:10:11 +00009import os
10import shutil
Nick Coghlane8c45d62013-07-28 20:00:01 +100011import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +100012import importlib
Christian Heimesa3538eb2007-11-06 11:44:48 +000013from os.path import normcase
Brett Cannon634a8fc2013-10-02 10:25:42 -040014try:
15 from concurrent.futures import ThreadPoolExecutor
16except ImportError:
17 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000018
Alexander Belopolskyf546e702010-12-02 00:10:11 +000019from test.support import run_unittest, TESTFN, DirsOnSysPath
Nick Coghlanf94a16b2013-09-22 22:46:49 +100020from test.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000021from test import inspect_fodder as mod
22from test import inspect_fodder2 as mod2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000023
R. David Murray74b89242009-05-13 17:33:03 +000024# C module for test_findsource_binary
R. David Murrayb5655772009-05-14 16:17:50 +000025import unicodedata
R. David Murray74b89242009-05-13 17:33:03 +000026
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000027# Functions tested in this suite:
28# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000029# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
30# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
31# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
32# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000033
Nick Coghlanf088e5e2008-12-14 11:50:48 +000034# NOTE: There are some additional tests relating to interaction with
35# zipimport in the test_zipimport_support test module.
36
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000037modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000038if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000039 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000040
Christian Heimesa3538eb2007-11-06 11:44:48 +000041# Normalize file names: on Windows, the case of file names of compiled
42# modules depends on the path used to start the python executable.
43modfile = normcase(modfile)
44
45def revise(filename, *args):
46 return (normcase(filename),) + args
47
Georg Brandl1a3284e2007-12-02 09:40:06 +000048import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000049
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000050git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000051
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000052class IsTestBase(unittest.TestCase):
53 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
54 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000055 inspect.ismodule, inspect.istraceback,
56 inspect.isgenerator, inspect.isgeneratorfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000057
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000058 def istest(self, predicate, exp):
59 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000060 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000061
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000062 for other in self.predicates - set([predicate]):
Christian Heimes7131fd92008-02-19 14:21:46 +000063 if predicate == inspect.isgeneratorfunction and\
64 other == inspect.isfunction:
65 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000066 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000067
Christian Heimes7131fd92008-02-19 14:21:46 +000068def generator_function_example(self):
69 for i in range(2):
70 yield i
71
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000072class TestPredicates(IsTestBase):
Christian Heimes227c8002008-03-03 20:34:40 +000073 def test_sixteen(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +000074 count = len([x for x in dir(inspect) if x.startswith('is')])
Christian Heimes7131fd92008-02-19 14:21:46 +000075 # This test is here for remember you to update Doc/library/inspect.rst
Christian Heimes78644762008-03-04 23:39:23 +000076 # which claims there are 16 such functions
Christian Heimes227c8002008-03-03 20:34:40 +000077 expected = 16
Thomas Wouters0e3f5912006-08-11 14:57:12 +000078 err_msg = "There are %d (not %d) is* functions" % (count, expected)
79 self.assertEqual(count, expected, err_msg)
Tim Peters5a9fb3c2005-01-07 16:01:32 +000080
Christian Heimes7131fd92008-02-19 14:21:46 +000081
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000082 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +020083 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000084 self.istest(inspect.isbuiltin, 'sys.exit')
85 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +000086 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +020087 try:
88 1/0
89 except:
90 tb = sys.exc_info()[2]
91 self.istest(inspect.isframe, 'tb.tb_frame')
92 self.istest(inspect.istraceback, 'tb')
93 if hasattr(types, 'GetSetDescriptorType'):
94 self.istest(inspect.isgetsetdescriptor,
95 'type(tb.tb_frame).f_locals')
96 else:
97 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
98 finally:
99 # Clear traceback and all the frames and local variables hanging to it.
100 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000101 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000102 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000103 self.istest(inspect.ismethod, 'git.argue')
104 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000105 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000106 self.istest(inspect.isgenerator, '(x for x in range(2))')
107 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000108 if hasattr(types, 'MemberDescriptorType'):
109 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
110 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000111 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000112
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000113 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000114 self.assertTrue(inspect.isroutine(mod.spam))
115 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000116
Benjamin Petersonc4656002009-01-17 22:41:18 +0000117 def test_isclass(self):
118 self.istest(inspect.isclass, 'mod.StupidGit')
119 self.assertTrue(inspect.isclass(list))
120
121 class CustomGetattr(object):
122 def __getattr__(self, attr):
123 return None
124 self.assertFalse(inspect.isclass(CustomGetattr()))
125
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000126 def test_get_slot_members(self):
127 class C(object):
128 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000129 x = C()
130 x.a = 42
131 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000132 self.assertIn('a', members)
133 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000134
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000135 def test_isabstract(self):
136 from abc import ABCMeta, abstractmethod
137
138 class AbstractClassExample(metaclass=ABCMeta):
139
140 @abstractmethod
141 def foo(self):
142 pass
143
144 class ClassExample(AbstractClassExample):
145 def foo(self):
146 pass
147
148 a = ClassExample()
149
150 # Test general behaviour.
151 self.assertTrue(inspect.isabstract(AbstractClassExample))
152 self.assertFalse(inspect.isabstract(ClassExample))
153 self.assertFalse(inspect.isabstract(a))
154 self.assertFalse(inspect.isabstract(int))
155 self.assertFalse(inspect.isabstract(5))
156
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000157
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000158class TestInterpreterStack(IsTestBase):
159 def __init__(self, *args, **kwargs):
160 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000161
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000162 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000163
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000164 def test_abuse_done(self):
165 self.istest(inspect.istraceback, 'git.ex[2]')
166 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000167
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000168 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000169 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000170 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000171 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000172 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000173 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000174 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000175 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000176 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000177 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000178
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000179 def test_trace(self):
180 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000181 self.assertEqual(revise(*git.tr[0][1:]),
182 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
183 self.assertEqual(revise(*git.tr[1][1:]),
184 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
185 self.assertEqual(revise(*git.tr[2][1:]),
186 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000187
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000188 def test_frame(self):
189 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
190 self.assertEqual(args, ['x', 'y'])
191 self.assertEqual(varargs, None)
192 self.assertEqual(varkw, None)
193 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
194 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
195 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000196
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000197 def test_previous_frame(self):
198 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000199 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000200 self.assertEqual(varargs, 'g')
201 self.assertEqual(varkw, 'h')
202 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000203 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000204
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000205class GetSourceBase(unittest.TestCase):
206 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000207 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000208
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000209 def __init__(self, *args, **kwargs):
210 unittest.TestCase.__init__(self, *args, **kwargs)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000211
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000212 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000213 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000214
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000215 def sourcerange(self, top, bottom):
216 lines = self.source.split("\n")
217 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000218
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000219 def assertSourceEqual(self, obj, top, bottom):
220 self.assertEqual(inspect.getsource(obj),
221 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000222
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000223class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000224 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000225
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000226 def test_getclasses(self):
227 classes = inspect.getmembers(mod, inspect.isclass)
228 self.assertEqual(classes,
229 [('FesteringGob', mod.FesteringGob),
230 ('MalodorousPervert', mod.MalodorousPervert),
231 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300232 ('StupidGit', mod.StupidGit),
233 ('Tit', mod.MalodorousPervert),
234 ])
235 tree = inspect.getclasstree([cls[1] for cls in classes])
236 self.assertEqual(tree,
237 [(object, ()),
238 [(mod.ParrotDroppings, (object,)),
239 [(mod.FesteringGob, (mod.MalodorousPervert,
240 mod.ParrotDroppings))
241 ],
242 (mod.StupidGit, (object,)),
243 [(mod.MalodorousPervert, (mod.StupidGit,)),
244 [(mod.FesteringGob, (mod.MalodorousPervert,
245 mod.ParrotDroppings))
246 ]
247 ]
248 ]
249 ])
250 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000251 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000252 [(object, ()),
253 [(mod.ParrotDroppings, (object,)),
254 (mod.StupidGit, (object,)),
255 [(mod.MalodorousPervert, (mod.StupidGit,)),
256 [(mod.FesteringGob, (mod.MalodorousPervert,
257 mod.ParrotDroppings))
258 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000259 ]
260 ]
261 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000262
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000263 def test_getfunctions(self):
264 functions = inspect.getmembers(mod, inspect.isfunction)
265 self.assertEqual(functions, [('eggs', mod.eggs),
266 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000267
R. David Murray378c0cf2010-02-24 01:46:21 +0000268 @unittest.skipIf(sys.flags.optimize >= 2,
269 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000270 def test_getdoc(self):
271 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
272 self.assertEqual(inspect.getdoc(mod.StupidGit),
273 'A longer,\n\nindented\n\ndocstring.')
274 self.assertEqual(inspect.getdoc(git.abuse),
275 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000276
Georg Brandl0c77a822008-06-10 16:37:50 +0000277 def test_cleandoc(self):
278 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
279 'An\nindented\ndocstring.')
280
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000281 def test_getcomments(self):
282 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
283 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000284
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000285 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000286 # Check actual module
287 self.assertEqual(inspect.getmodule(mod), mod)
288 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000289 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000290 # Check a method (no __module__ attribute, falls back to filename)
291 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
292 # Do it again (check the caching isn't broken)
293 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
294 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000295 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000296 # Check filename override
297 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000298
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000299 def test_getsource(self):
300 self.assertSourceEqual(git.abuse, 29, 39)
301 self.assertSourceEqual(mod.StupidGit, 21, 46)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000302
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000303 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000304 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
305 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000306 fn = "_non_existing_filename_used_for_sourcefile_test.py"
307 co = compile("None", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000308 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000309 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200310 try:
311 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
312 finally:
313 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000314
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000315 def test_getfile(self):
316 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000317
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000318 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000319 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000320 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000321 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000322 m.__file__ = "<string>" # hopefully not a real filename...
323 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000324 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000325 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000326 del sys.modules[name]
327 inspect.getmodule(compile('a=10','','single'))
328
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500329 def test_proceed_with_fake_filename(self):
330 '''doctest monkeypatches linecache to enable inspection'''
331 fn, source = '<test>', 'def x(): pass\n'
332 getlines = linecache.getlines
333 def monkey(filename, module_globals=None):
334 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300335 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500336 else:
337 return getlines(filename, module_globals)
338 linecache.getlines = monkey
339 try:
340 ns = {}
341 exec(compile(source, fn, 'single'), ns)
342 inspect.getsource(ns["x"])
343 finally:
344 linecache.getlines = getlines
345
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000346class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000347 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000348
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000349 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000350 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000351
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000352 def test_replacing_decorator(self):
353 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000354
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000355class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000356 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000357 def test_oneline_lambda(self):
358 # Test inspect.getsource with a one-line lambda function.
359 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000360
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000361 def test_threeline_lambda(self):
362 # Test inspect.getsource with a three-line lambda function,
363 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000364 self.assertSourceEqual(mod2.tll, 28, 30)
365
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000366 def test_twoline_indented_lambda(self):
367 # Test inspect.getsource with a two-line lambda function,
368 # where the second line _is_ indented.
369 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000370
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000371 def test_onelinefunc(self):
372 # Test inspect.getsource with a regular one-line function.
373 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000374
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000375 def test_manyargs(self):
376 # Test inspect.getsource with a regular function where
377 # the arguments are on two lines and _not_ indented and
378 # the body on the second line with the last arguments.
379 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000380
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000381 def test_twolinefunc(self):
382 # Test inspect.getsource with a regular function where
383 # the body is on two lines, following the argument list and
384 # continued on the next line by a \\.
385 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000386
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000387 def test_lambda_in_list(self):
388 # Test inspect.getsource with a one-line lambda function
389 # defined in a list, indented.
390 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000391
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000392 def test_anonymous(self):
393 # Test inspect.getsource with a lambda function defined
394 # as argument to another function.
395 self.assertSourceEqual(mod2.anonymous, 55, 55)
396
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000397class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000398 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000399
400 def test_with_comment(self):
401 self.assertSourceEqual(mod2.with_comment, 58, 59)
402
403 def test_multiline_sig(self):
404 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
405
Armin Rigodd5c0232005-09-25 11:45:45 +0000406 def test_nested_class(self):
407 self.assertSourceEqual(mod2.func69().func71, 71, 72)
408
409 def test_one_liner_followed_by_non_name(self):
410 self.assertSourceEqual(mod2.func77, 77, 77)
411
412 def test_one_liner_dedent_non_name(self):
413 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
414
415 def test_with_comment_instead_of_docstring(self):
416 self.assertSourceEqual(mod2.func88, 88, 90)
417
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000418 def test_method_in_dynamic_class(self):
419 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
420
R. David Murrayb5655772009-05-14 16:17:50 +0000421 @unittest.skipIf(
422 not hasattr(unicodedata, '__file__') or
423 unicodedata.__file__[-4:] in (".pyc", ".pyo"),
424 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000425 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200426 self.assertRaises(OSError, inspect.getsource, unicodedata)
427 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000428
R. David Murraya1b37402010-06-17 02:04:29 +0000429 def test_findsource_code_in_linecache(self):
430 lines = ["x=1"]
431 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200432 self.assertRaises(OSError, inspect.findsource, co)
433 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000434 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200435 try:
436 self.assertEqual(inspect.findsource(co), (lines,0))
437 self.assertEqual(inspect.getsource(co), lines[0])
438 finally:
439 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000440
Ezio Melotti1b145922013-03-30 05:17:24 +0200441 def test_findsource_without_filename(self):
442 for fname in ['', '<string>']:
443 co = compile('x=1', fname, "exec")
444 self.assertRaises(IOError, inspect.findsource, co)
445 self.assertRaises(IOError, inspect.getsource, co)
446
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000447class TestNoEOL(GetSourceBase):
448 def __init__(self, *args, **kwargs):
449 self.tempdir = TESTFN + '_dir'
450 os.mkdir(self.tempdir)
451 with open(os.path.join(self.tempdir,
452 'inspect_fodder3%spy' % os.extsep), 'w') as f:
453 f.write("class X:\n pass # No EOL")
454 with DirsOnSysPath(self.tempdir):
455 import inspect_fodder3 as mod3
456 self.fodderModule = mod3
457 GetSourceBase.__init__(self, *args, **kwargs)
458
459 def tearDown(self):
460 shutil.rmtree(self.tempdir)
461
462 def test_class(self):
463 self.assertSourceEqual(self.fodderModule.X, 1, 2)
464
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100465
466class _BrokenDataDescriptor(object):
467 """
468 A broken data descriptor. See bug #1785.
469 """
470 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700471 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100472
473 def __set__(*args):
474 raise RuntimeError
475
476 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700477 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100478
479
480class _BrokenMethodDescriptor(object):
481 """
482 A broken method descriptor. See bug #1785.
483 """
484 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700485 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100486
487 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700488 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100489
490
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000491# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000492def attrs_wo_objs(cls):
493 return [t[:3] for t in inspect.classify_class_attrs(cls)]
494
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100495
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000496class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000497 def test_newstyle_mro(self):
498 # The same w/ new-class MRO.
499 class A(object): pass
500 class B(A): pass
501 class C(A): pass
502 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000503
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000504 expected = (D, B, C, A, object)
505 got = inspect.getmro(D)
506 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000507
Christian Heimes3795b532007-11-08 13:48:53 +0000508 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
509 varkw_e=None, defaults_e=None, formatted=None):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000510 args, varargs, varkw, defaults = inspect.getargspec(routine)
511 self.assertEqual(args, args_e)
512 self.assertEqual(varargs, varargs_e)
513 self.assertEqual(varkw, varkw_e)
514 self.assertEqual(defaults, defaults_e)
515 if formatted is not None:
516 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
517 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000518
Christian Heimes3795b532007-11-08 13:48:53 +0000519 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
520 varkw_e=None, defaults_e=None,
521 kwonlyargs_e=[], kwonlydefaults_e=None,
522 ann_e={}, formatted=None):
523 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
524 inspect.getfullargspec(routine)
525 self.assertEqual(args, args_e)
526 self.assertEqual(varargs, varargs_e)
527 self.assertEqual(varkw, varkw_e)
528 self.assertEqual(defaults, defaults_e)
529 self.assertEqual(kwonlyargs, kwonlyargs_e)
530 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
531 self.assertEqual(ann, ann_e)
532 if formatted is not None:
533 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
534 kwonlyargs, kwonlydefaults, ann),
535 formatted)
536
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000537 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000538 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000539
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000540 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000541 ['a', 'b', 'c', 'd', 'e', 'f'],
542 'g', 'h', (3, 4, 5),
543 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000544
Christian Heimes3795b532007-11-08 13:48:53 +0000545 self.assertRaises(ValueError, self.assertArgSpecEquals,
546 mod2.keyworded, [])
547
548 self.assertRaises(ValueError, self.assertArgSpecEquals,
549 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000550 self.assertRaises(ValueError, self.assertArgSpecEquals,
551 mod2.keyword_only_arg, [])
552
Christian Heimes3795b532007-11-08 13:48:53 +0000553
554 def test_getfullargspec(self):
555 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
556 kwonlyargs_e=['arg2'],
557 kwonlydefaults_e={'arg2':1},
558 formatted='(*arg1, arg2=1)')
559
560 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000561 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000562 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000563 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
564 kwonlyargs_e=['arg'],
565 formatted='(*, arg)')
566
Christian Heimes3795b532007-11-08 13:48:53 +0000567
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000568 def test_getargspec_method(self):
569 class A(object):
570 def m(self):
571 pass
572 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000573
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000574 def test_classify_newstyle(self):
575 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000576
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000577 def s(): pass
578 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000579
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000580 def c(cls): pass
581 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000582
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000583 def getp(self): pass
584 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000585
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000586 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000587
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000588 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000589
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000590 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000591
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100592 dd = _BrokenDataDescriptor()
593 md = _BrokenMethodDescriptor()
594
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000595 attrs = attrs_wo_objs(A)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000596 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
597 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
598 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000599 self.assertIn(('m', 'method', A), attrs,
600 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000601 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
602 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100603 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
604 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000605
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000606 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000607
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000608 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000609
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000610 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000611 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
612 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
613 self.assertIn(('p', 'property', A), attrs, 'missing property')
614 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
615 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
616 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100617 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
618 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000619
620
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000621 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000622
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000623 def m(self): pass
624 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000625
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000626 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000627 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
628 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
629 self.assertIn(('p', 'property', A), attrs, 'missing property')
630 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
631 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
632 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100633 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
634 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000635
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000636 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000637
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000638 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000639
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000640 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000641 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
642 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
643 self.assertIn(('p', 'property', A), attrs, 'missing property')
644 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
645 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
646 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100647 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
648 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
649
650 def test_classify_builtin_types(self):
651 # Simple sanity check that all built-in types can have their
652 # attributes classified.
653 for name in dir(__builtins__):
654 builtin = getattr(__builtins__, name)
655 if isinstance(builtin, type):
656 inspect.classify_class_attrs(builtin)
657
Ethan Furman63c141c2013-10-18 00:27:39 -0700658 def test_classify_DynamicClassAttribute(self):
659 class Meta(type):
660 def __getattr__(self, name):
661 if name == 'ham':
662 return 'spam'
663 return super().__getattr__(name)
664 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700665 @types.DynamicClassAttribute
666 def ham(self):
667 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700668 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
669 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
670 should_find_ga = inspect.Attribute('ham', 'data', VA, 'spam')
671 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
672
673 def test_classify_VirtualAttribute(self):
674 class Meta(type):
675 def __dir__(cls):
676 return ['__class__', '__module__', '__name__', 'BOOM']
677 def __getattr__(self, name):
678 if name =='BOOM':
679 return 42
680 return super().__getattr(name)
681 class Class(metaclass=Meta):
682 pass
683 should_find = inspect.Attribute('BOOM', 'data', Class, 42)
684 self.assertIn(should_find, inspect.classify_class_attrs(Class))
685
686 def test_classify_VirtualAttribute_multi_classes(self):
687 class Meta1(type):
688 def __dir__(cls):
689 return ['__class__', '__module__', '__name__', 'one']
690 def __getattr__(self, name):
691 if name =='one':
692 return 1
693 return super().__getattr__(name)
694 class Meta2(type):
695 def __dir__(cls):
696 return ['__class__', '__module__', '__name__', 'two']
697 def __getattr__(self, name):
698 if name =='two':
699 return 2
700 return super().__getattr__(name)
701 class Meta3(Meta1, Meta2):
702 def __dir__(cls):
703 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
704 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
705 def __getattr__(self, name):
706 if name =='three':
707 return 3
708 return super().__getattr__(name)
709 class Class1(metaclass=Meta1):
710 pass
711 class Class2(Class1, metaclass=Meta3):
712 pass
713
714 should_find1 = inspect.Attribute('one', 'data', Class1, 1)
715 should_find2 = inspect.Attribute('two', 'data', Class2, 2)
716 should_find3 = inspect.Attribute('three', 'data', Class2, 3)
717 cca = inspect.classify_class_attrs(Class2)
718 for sf in (should_find1, should_find2, should_find3):
719 self.assertIn(sf, cca)
720
721 def test_classify_class_attrs_with_buggy_dir(self):
722 class M(type):
723 def __dir__(cls):
724 return ['__class__', '__name__', 'missing']
725 class C(metaclass=M):
726 pass
727 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
728 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700729
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100730 def test_getmembers_descriptors(self):
731 class A(object):
732 dd = _BrokenDataDescriptor()
733 md = _BrokenMethodDescriptor()
734
735 def pred_wrapper(pred):
736 # A quick'n'dirty way to discard standard attributes of new-style
737 # classes.
738 class Empty(object):
739 pass
740 def wrapped(x):
741 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
742 return False
743 return pred(x)
744 return wrapped
745
746 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
747 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
748
749 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
750 [('md', A.__dict__['md'])])
751 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
752 [('dd', A.__dict__['dd'])])
753
754 class B(A):
755 pass
756
757 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
758 [('md', A.__dict__['md'])])
759 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
760 [('dd', A.__dict__['dd'])])
761
Antoine Pitrou0c603812012-01-18 17:40:18 +0100762 def test_getmembers_method(self):
763 class B:
764 def f(self):
765 pass
766
767 self.assertIn(('f', B.f), inspect.getmembers(B))
768 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
769 b = B()
770 self.assertIn(('f', b.f), inspect.getmembers(b))
771 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
772
Ethan Furmane03ea372013-09-25 07:14:41 -0700773 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -0700774 class M(type):
775 def __getattr__(cls, name):
776 if name == 'eggs':
777 return 'scrambled'
778 return super().__getattr__(name)
779 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -0700780 @types.DynamicClassAttribute
781 def eggs(self):
782 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -0700783 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
784 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
785
786 def test_getmembers_with_buggy_dir(self):
787 class M(type):
788 def __dir__(cls):
789 return ['__class__', '__name__', 'missing']
790 class C(metaclass=M):
791 pass
792 attrs = [a[0] for a in inspect.getmembers(C)]
793 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700794
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000795
Nick Coghlan2f92e542012-06-23 19:39:55 +1000796_global_ref = object()
797class TestGetClosureVars(unittest.TestCase):
798
799 def test_name_resolution(self):
800 # Basic test of the 4 different resolution mechanisms
801 def f(nonlocal_ref):
802 def g(local_ref):
803 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
804 return g
805 _arg = object()
806 nonlocal_vars = {"nonlocal_ref": _arg}
807 global_vars = {"_global_ref": _global_ref}
808 builtin_vars = {"print": print}
809 unbound_names = {"unbound_ref"}
810 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
811 builtin_vars, unbound_names)
812 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
813
814 def test_generator_closure(self):
815 def f(nonlocal_ref):
816 def g(local_ref):
817 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
818 yield
819 return g
820 _arg = object()
821 nonlocal_vars = {"nonlocal_ref": _arg}
822 global_vars = {"_global_ref": _global_ref}
823 builtin_vars = {"print": print}
824 unbound_names = {"unbound_ref"}
825 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
826 builtin_vars, unbound_names)
827 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
828
829 def test_method_closure(self):
830 class C:
831 def f(self, nonlocal_ref):
832 def g(local_ref):
833 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
834 return g
835 _arg = object()
836 nonlocal_vars = {"nonlocal_ref": _arg}
837 global_vars = {"_global_ref": _global_ref}
838 builtin_vars = {"print": print}
839 unbound_names = {"unbound_ref"}
840 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
841 builtin_vars, unbound_names)
842 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
843
844 def test_nonlocal_vars(self):
845 # More complex tests of nonlocal resolution
846 def _nonlocal_vars(f):
847 return inspect.getclosurevars(f).nonlocals
848
849 def make_adder(x):
850 def add(y):
851 return x + y
852 return add
853
854 def curry(func, arg1):
855 return lambda arg2: func(arg1, arg2)
856
857 def less_than(a, b):
858 return a < b
859
860 # The infamous Y combinator.
861 def Y(le):
862 def g(f):
863 return le(lambda x: f(f)(x))
864 Y.g_ref = g
865 return g(g)
866
867 def check_y_combinator(func):
868 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
869
870 inc = make_adder(1)
871 add_two = make_adder(2)
872 greater_than_five = curry(less_than, 5)
873
874 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
875 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
876 self.assertEqual(_nonlocal_vars(greater_than_five),
877 {'arg1': 5, 'func': less_than})
878 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
879 {'x': 3})
880 Y(check_y_combinator)
881
882 def test_getclosurevars_empty(self):
883 def foo(): pass
884 _empty = inspect.ClosureVars({}, {}, {}, set())
885 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
886 self.assertEqual(inspect.getclosurevars(foo), _empty)
887
888 def test_getclosurevars_error(self):
889 class T: pass
890 self.assertRaises(TypeError, inspect.getclosurevars, 1)
891 self.assertRaises(TypeError, inspect.getclosurevars, list)
892 self.assertRaises(TypeError, inspect.getclosurevars, {})
893
Nick Coghlan6c6e2542012-06-23 20:07:39 +1000894 def _private_globals(self):
895 code = """def f(): print(path)"""
896 ns = {}
897 exec(code, ns)
898 return ns["f"], ns
899
900 def test_builtins_fallback(self):
901 f, ns = self._private_globals()
902 ns.pop("__builtins__", None)
903 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
904 self.assertEqual(inspect.getclosurevars(f), expected)
905
906 def test_builtins_as_dict(self):
907 f, ns = self._private_globals()
908 ns["__builtins__"] = {"path":1}
909 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
910 self.assertEqual(inspect.getclosurevars(f), expected)
911
912 def test_builtins_as_module(self):
913 f, ns = self._private_globals()
914 ns["__builtins__"] = os
915 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
916 self.assertEqual(inspect.getclosurevars(f), expected)
917
Nick Coghlan2f92e542012-06-23 19:39:55 +1000918
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000919class TestGetcallargsFunctions(unittest.TestCase):
920
921 def assertEqualCallArgs(self, func, call_params_string, locs=None):
922 locs = dict(locs or {}, func=func)
923 r1 = eval('func(%s)' % call_params_string, None, locs)
924 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
925 locs)
926 self.assertEqual(r1, r2)
927
928 def assertEqualException(self, func, call_param_string, locs=None):
929 locs = dict(locs or {}, func=func)
930 try:
931 eval('func(%s)' % call_param_string, None, locs)
932 except Exception as e:
933 ex1 = e
934 else:
935 self.fail('Exception not raised')
936 try:
937 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
938 locs)
939 except Exception as e:
940 ex2 = e
941 else:
942 self.fail('Exception not raised')
943 self.assertIs(type(ex1), type(ex2))
944 self.assertEqual(str(ex1), str(ex2))
945 del ex1, ex2
946
947 def makeCallable(self, signature):
948 """Create a function that returns its locals()"""
949 code = "lambda %s: locals()"
950 return eval(code % signature)
951
952 def test_plain(self):
953 f = self.makeCallable('a, b=1')
954 self.assertEqualCallArgs(f, '2')
955 self.assertEqualCallArgs(f, '2, 3')
956 self.assertEqualCallArgs(f, 'a=2')
957 self.assertEqualCallArgs(f, 'b=3, a=2')
958 self.assertEqualCallArgs(f, '2, b=3')
959 # expand *iterable / **mapping
960 self.assertEqualCallArgs(f, '*(2,)')
961 self.assertEqualCallArgs(f, '*[2]')
962 self.assertEqualCallArgs(f, '*(2, 3)')
963 self.assertEqualCallArgs(f, '*[2, 3]')
964 self.assertEqualCallArgs(f, '**{"a":2}')
965 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
966 self.assertEqualCallArgs(f, '2, **{"b":3}')
967 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
968 # expand UserList / UserDict
969 self.assertEqualCallArgs(f, '*collections.UserList([2])')
970 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
971 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
972 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
973 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
974
975 def test_varargs(self):
976 f = self.makeCallable('a, b=1, *c')
977 self.assertEqualCallArgs(f, '2')
978 self.assertEqualCallArgs(f, '2, 3')
979 self.assertEqualCallArgs(f, '2, 3, 4')
980 self.assertEqualCallArgs(f, '*(2,3,4)')
981 self.assertEqualCallArgs(f, '2, *[3,4]')
982 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
983
984 def test_varkw(self):
985 f = self.makeCallable('a, b=1, **c')
986 self.assertEqualCallArgs(f, 'a=2')
987 self.assertEqualCallArgs(f, '2, b=3, c=4')
988 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
989 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
990 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
991 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
992 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
993 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
994 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
995
Benjamin Peterson6a2638b2011-03-28 17:32:31 -0500996 def test_varkw_only(self):
997 # issue11256:
998 f = self.makeCallable('**c')
999 self.assertEqualCallArgs(f, '')
1000 self.assertEqualCallArgs(f, 'a=1')
1001 self.assertEqualCallArgs(f, 'a=1, b=2')
1002 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1003 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1004 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1005
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001006 def test_keyword_only(self):
1007 f = self.makeCallable('a=3, *, c, d=2')
1008 self.assertEqualCallArgs(f, 'c=3')
1009 self.assertEqualCallArgs(f, 'c=3, a=3')
1010 self.assertEqualCallArgs(f, 'a=2, c=4')
1011 self.assertEqualCallArgs(f, '4, c=4')
1012 self.assertEqualException(f, '')
1013 self.assertEqualException(f, '3')
1014 self.assertEqualException(f, 'a=3')
1015 self.assertEqualException(f, 'd=4')
1016
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001017 f = self.makeCallable('*, c, d=2')
1018 self.assertEqualCallArgs(f, 'c=3')
1019 self.assertEqualCallArgs(f, 'c=3, d=4')
1020 self.assertEqualCallArgs(f, 'd=4, c=3')
1021
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001022 def test_multiple_features(self):
1023 f = self.makeCallable('a, b=2, *f, **g')
1024 self.assertEqualCallArgs(f, '2, 3, 7')
1025 self.assertEqualCallArgs(f, '2, 3, x=8')
1026 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1027 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1028 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1029 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1030 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1031 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1032 '(4,[5,6])]), **collections.UserDict('
1033 'y=9, z=10)')
1034
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001035 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1036 self.assertEqualCallArgs(f, '2, 3, x=8')
1037 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1038 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1039 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1040 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1041 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1042 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1043 '(4,[5,6])]), q=0, **collections.UserDict('
1044 'y=9, z=10)')
1045
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001046 def test_errors(self):
1047 f0 = self.makeCallable('')
1048 f1 = self.makeCallable('a, b')
1049 f2 = self.makeCallable('a, b=1')
1050 # f0 takes no arguments
1051 self.assertEqualException(f0, '1')
1052 self.assertEqualException(f0, 'x=1')
1053 self.assertEqualException(f0, '1,x=1')
1054 # f1 takes exactly 2 arguments
1055 self.assertEqualException(f1, '')
1056 self.assertEqualException(f1, '1')
1057 self.assertEqualException(f1, 'a=2')
1058 self.assertEqualException(f1, 'b=3')
1059 # f2 takes at least 1 argument
1060 self.assertEqualException(f2, '')
1061 self.assertEqualException(f2, 'b=3')
1062 for f in f1, f2:
1063 # f1/f2 takes exactly/at most 2 arguments
1064 self.assertEqualException(f, '2, 3, 4')
1065 self.assertEqualException(f, '1, 2, 3, a=1')
1066 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001067 # XXX: success of this one depends on dict order
1068 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001069 # f got an unexpected keyword argument
1070 self.assertEqualException(f, 'c=2')
1071 self.assertEqualException(f, '2, c=3')
1072 self.assertEqualException(f, '2, 3, c=4')
1073 self.assertEqualException(f, '2, c=4, b=3')
1074 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1075 # f got multiple values for keyword argument
1076 self.assertEqualException(f, '1, a=2')
1077 self.assertEqualException(f, '1, **{"a":2}')
1078 self.assertEqualException(f, '1, 2, b=3')
1079 # XXX: Python inconsistency
1080 # - for functions and bound methods: unexpected keyword 'c'
1081 # - for unbound methods: multiple values for keyword 'a'
1082 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001083 # issue11256:
1084 f3 = self.makeCallable('**c')
1085 self.assertEqualException(f3, '1, 2')
1086 self.assertEqualException(f3, '1, 2, a=1, b=2')
1087 f4 = self.makeCallable('*, a, b=0')
1088 self.assertEqualException(f3, '1, 2')
1089 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001090
1091class TestGetcallargsMethods(TestGetcallargsFunctions):
1092
1093 def setUp(self):
1094 class Foo(object):
1095 pass
1096 self.cls = Foo
1097 self.inst = Foo()
1098
1099 def makeCallable(self, signature):
1100 assert 'self' not in signature
1101 mk = super(TestGetcallargsMethods, self).makeCallable
1102 self.cls.method = mk('self, ' + signature)
1103 return self.inst.method
1104
1105class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1106
1107 def makeCallable(self, signature):
1108 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1109 return self.cls.method
1110
1111 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1112 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1113 *self._getAssertEqualParams(func, call_params_string, locs))
1114
1115 def assertEqualException(self, func, call_params_string, locs=None):
1116 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1117 *self._getAssertEqualParams(func, call_params_string, locs))
1118
1119 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1120 assert 'inst' not in call_params_string
1121 locs = dict(locs or {}, inst=self.inst)
1122 return (func, 'inst,' + call_params_string, locs)
1123
Michael Foord95fc51d2010-11-20 15:07:30 +00001124
1125class TestGetattrStatic(unittest.TestCase):
1126
1127 def test_basic(self):
1128 class Thing(object):
1129 x = object()
1130
1131 thing = Thing()
1132 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1133 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1134 with self.assertRaises(AttributeError):
1135 inspect.getattr_static(thing, 'y')
1136
1137 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1138
1139 def test_inherited(self):
1140 class Thing(object):
1141 x = object()
1142 class OtherThing(Thing):
1143 pass
1144
1145 something = OtherThing()
1146 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1147
1148 def test_instance_attr(self):
1149 class Thing(object):
1150 x = 2
1151 def __init__(self, x):
1152 self.x = x
1153 thing = Thing(3)
1154 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1155 del thing.x
1156 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1157
1158 def test_property(self):
1159 class Thing(object):
1160 @property
1161 def x(self):
1162 raise AttributeError("I'm pretending not to exist")
1163 thing = Thing()
1164 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1165
Ezio Melotti75cbd732011-04-28 00:59:29 +03001166 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001167 class descriptor(object):
1168 def __get__(*_):
1169 raise AttributeError("I'm pretending not to exist")
1170 desc = descriptor()
1171 class Thing(object):
1172 x = desc
1173 thing = Thing()
1174 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1175
1176 def test_classAttribute(self):
1177 class Thing(object):
1178 x = object()
1179
1180 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1181
Ethan Furmane03ea372013-09-25 07:14:41 -07001182 def test_classVirtualAttribute(self):
1183 class Thing(object):
1184 @types.DynamicClassAttribute
1185 def x(self):
1186 return self._x
1187 _x = object()
1188
1189 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1190
Michael Foord95fc51d2010-11-20 15:07:30 +00001191 def test_inherited_classattribute(self):
1192 class Thing(object):
1193 x = object()
1194 class OtherThing(Thing):
1195 pass
1196
1197 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1198
1199 def test_slots(self):
1200 class Thing(object):
1201 y = 'bar'
1202 __slots__ = ['x']
1203 def __init__(self):
1204 self.x = 'foo'
1205 thing = Thing()
1206 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1207 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1208
1209 del thing.x
1210 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1211
1212 def test_metaclass(self):
1213 class meta(type):
1214 attr = 'foo'
1215 class Thing(object, metaclass=meta):
1216 pass
1217 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1218
1219 class sub(meta):
1220 pass
1221 class OtherThing(object, metaclass=sub):
1222 x = 3
1223 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1224
1225 class OtherOtherThing(OtherThing):
1226 pass
1227 # this test is odd, but it was added as it exposed a bug
1228 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1229
1230 def test_no_dict_no_slots(self):
1231 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1232 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1233
1234 def test_no_dict_no_slots_instance_member(self):
1235 # returns descriptor
1236 with open(__file__) as handle:
1237 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1238
1239 def test_inherited_slots(self):
1240 # returns descriptor
1241 class Thing(object):
1242 __slots__ = ['x']
1243 def __init__(self):
1244 self.x = 'foo'
1245
1246 class OtherThing(Thing):
1247 pass
1248 # it would be nice if this worked...
1249 # we get the descriptor instead of the instance attribute
1250 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1251
1252 def test_descriptor(self):
1253 class descriptor(object):
1254 def __get__(self, instance, owner):
1255 return 3
1256 class Foo(object):
1257 d = descriptor()
1258
1259 foo = Foo()
1260
1261 # for a non data descriptor we return the instance attribute
1262 foo.__dict__['d'] = 1
1263 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1264
1265 # if the descriptor is a data-desciptor we should return the
1266 # descriptor
1267 descriptor.__set__ = lambda s, i, v: None
1268 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1269
1270
1271 def test_metaclass_with_descriptor(self):
1272 class descriptor(object):
1273 def __get__(self, instance, owner):
1274 return 3
1275 class meta(type):
1276 d = descriptor()
1277 class Thing(object, metaclass=meta):
1278 pass
1279 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1280
1281
Michael Foordcc7ebb82010-11-20 16:20:16 +00001282 def test_class_as_property(self):
1283 class Base(object):
1284 foo = 3
1285
1286 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001287 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001288 @property
1289 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001290 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001291 return object
1292
Michael Foord35184ed2010-11-20 16:58:30 +00001293 instance = Something()
1294 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1295 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001296 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1297
Michael Foorde5162652010-11-20 16:40:44 +00001298 def test_mro_as_property(self):
1299 class Meta(type):
1300 @property
1301 def __mro__(self):
1302 return (object,)
1303
1304 class Base(object):
1305 foo = 3
1306
1307 class Something(Base, metaclass=Meta):
1308 pass
1309
1310 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1311 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1312
Michael Foorddcebe0f2011-03-15 19:20:44 -04001313 def test_dict_as_property(self):
1314 test = self
1315 test.called = False
1316
1317 class Foo(dict):
1318 a = 3
1319 @property
1320 def __dict__(self):
1321 test.called = True
1322 return {}
1323
1324 foo = Foo()
1325 foo.a = 4
1326 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1327 self.assertFalse(test.called)
1328
1329 def test_custom_object_dict(self):
1330 test = self
1331 test.called = False
1332
1333 class Custom(dict):
1334 def get(self, key, default=None):
1335 test.called = True
1336 super().get(key, default)
1337
1338 class Foo(object):
1339 a = 3
1340 foo = Foo()
1341 foo.__dict__ = Custom()
1342 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1343 self.assertFalse(test.called)
1344
1345 def test_metaclass_dict_as_property(self):
1346 class Meta(type):
1347 @property
1348 def __dict__(self):
1349 self.executed = True
1350
1351 class Thing(metaclass=Meta):
1352 executed = False
1353
1354 def __init__(self):
1355 self.spam = 42
1356
1357 instance = Thing()
1358 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1359 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001360
Michael Foorda51623b2011-12-18 22:01:40 +00001361 def test_module(self):
1362 sentinel = object()
1363 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1364 sentinel)
1365
Michael Foord3ba95f82011-12-22 01:13:37 +00001366 def test_metaclass_with_metaclass_with_dict_as_property(self):
1367 class MetaMeta(type):
1368 @property
1369 def __dict__(self):
1370 self.executed = True
1371 return dict(spam=42)
1372
1373 class Meta(type, metaclass=MetaMeta):
1374 executed = False
1375
1376 class Thing(metaclass=Meta):
1377 pass
1378
1379 with self.assertRaises(AttributeError):
1380 inspect.getattr_static(Thing, "spam")
1381 self.assertFalse(Thing.executed)
1382
Nick Coghlane0f04652010-11-21 03:44:04 +00001383class TestGetGeneratorState(unittest.TestCase):
1384
1385 def setUp(self):
1386 def number_generator():
1387 for number in range(5):
1388 yield number
1389 self.generator = number_generator()
1390
1391 def _generatorstate(self):
1392 return inspect.getgeneratorstate(self.generator)
1393
1394 def test_created(self):
1395 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1396
1397 def test_suspended(self):
1398 next(self.generator)
1399 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1400
1401 def test_closed_after_exhaustion(self):
1402 for i in self.generator:
1403 pass
1404 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1405
1406 def test_closed_after_immediate_exception(self):
1407 with self.assertRaises(RuntimeError):
1408 self.generator.throw(RuntimeError)
1409 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1410
1411 def test_running(self):
1412 # As mentioned on issue #10220, checking for the RUNNING state only
1413 # makes sense inside the generator itself.
1414 # The following generator checks for this by using the closure's
1415 # reference to self and the generator state checking helper method
1416 def running_check_generator():
1417 for number in range(5):
1418 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1419 yield number
1420 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1421 self.generator = running_check_generator()
1422 # Running up to the first yield
1423 next(self.generator)
1424 # Running after the first yield
1425 next(self.generator)
1426
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001427 def test_easy_debugging(self):
1428 # repr() and str() of a generator state should contain the state name
1429 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1430 for name in names:
1431 state = getattr(inspect, name)
1432 self.assertIn(name, repr(state))
1433 self.assertIn(name, str(state))
1434
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001435 def test_getgeneratorlocals(self):
1436 def each(lst, a=None):
1437 b=(1, 2, 3)
1438 for v in lst:
1439 if v == 3:
1440 c = 12
1441 yield v
1442
1443 numbers = each([1, 2, 3])
1444 self.assertEqual(inspect.getgeneratorlocals(numbers),
1445 {'a': None, 'lst': [1, 2, 3]})
1446 next(numbers)
1447 self.assertEqual(inspect.getgeneratorlocals(numbers),
1448 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1449 'b': (1, 2, 3)})
1450 next(numbers)
1451 self.assertEqual(inspect.getgeneratorlocals(numbers),
1452 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1453 'b': (1, 2, 3)})
1454 next(numbers)
1455 self.assertEqual(inspect.getgeneratorlocals(numbers),
1456 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1457 'b': (1, 2, 3), 'c': 12})
1458 try:
1459 next(numbers)
1460 except StopIteration:
1461 pass
1462 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1463
1464 def test_getgeneratorlocals_empty(self):
1465 def yield_one():
1466 yield 1
1467 one = yield_one()
1468 self.assertEqual(inspect.getgeneratorlocals(one), {})
1469 try:
1470 next(one)
1471 except StopIteration:
1472 pass
1473 self.assertEqual(inspect.getgeneratorlocals(one), {})
1474
1475 def test_getgeneratorlocals_error(self):
1476 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1477 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1478 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1479 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1480
Nick Coghlane0f04652010-11-21 03:44:04 +00001481
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001482class TestSignatureObject(unittest.TestCase):
1483 @staticmethod
1484 def signature(func):
1485 sig = inspect.signature(func)
1486 return (tuple((param.name,
1487 (... if param.default is param.empty else param.default),
1488 (... if param.annotation is param.empty
1489 else param.annotation),
1490 str(param.kind).lower())
1491 for param in sig.parameters.values()),
1492 (... if sig.return_annotation is sig.empty
1493 else sig.return_annotation))
1494
1495 def test_signature_object(self):
1496 S = inspect.Signature
1497 P = inspect.Parameter
1498
1499 self.assertEqual(str(S()), '()')
1500
1501 def test(po, pk, *args, ko, **kwargs):
1502 pass
1503 sig = inspect.signature(test)
1504 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
1505 pk = sig.parameters['pk']
1506 args = sig.parameters['args']
1507 ko = sig.parameters['ko']
1508 kwargs = sig.parameters['kwargs']
1509
1510 S((po, pk, args, ko, kwargs))
1511
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001512 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001513 S((pk, po, args, ko, kwargs))
1514
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001515 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001516 S((po, args, pk, ko, kwargs))
1517
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001518 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001519 S((args, po, pk, ko, kwargs))
1520
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001521 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001522 S((po, pk, args, kwargs, ko))
1523
1524 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001525 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001526 S((po, pk, args, kwargs2, ko))
1527
1528 def test_signature_immutability(self):
1529 def test(a):
1530 pass
1531 sig = inspect.signature(test)
1532
1533 with self.assertRaises(AttributeError):
1534 sig.foo = 'bar'
1535
1536 with self.assertRaises(TypeError):
1537 sig.parameters['a'] = None
1538
1539 def test_signature_on_noarg(self):
1540 def test():
1541 pass
1542 self.assertEqual(self.signature(test), ((), ...))
1543
1544 def test_signature_on_wargs(self):
1545 def test(a, b:'foo') -> 123:
1546 pass
1547 self.assertEqual(self.signature(test),
1548 ((('a', ..., ..., "positional_or_keyword"),
1549 ('b', ..., 'foo', "positional_or_keyword")),
1550 123))
1551
1552 def test_signature_on_wkwonly(self):
1553 def test(*, a:float, b:str) -> int:
1554 pass
1555 self.assertEqual(self.signature(test),
1556 ((('a', ..., float, "keyword_only"),
1557 ('b', ..., str, "keyword_only")),
1558 int))
1559
1560 def test_signature_on_complex_args(self):
1561 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1562 pass
1563 self.assertEqual(self.signature(test),
1564 ((('a', ..., ..., "positional_or_keyword"),
1565 ('b', 10, 'foo', "positional_or_keyword"),
1566 ('args', ..., 'bar', "var_positional"),
1567 ('spam', ..., 'baz', "keyword_only"),
1568 ('ham', 123, ..., "keyword_only"),
1569 ('kwargs', ..., int, "var_keyword")),
1570 ...))
1571
1572 def test_signature_on_builtin_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001573 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001574 inspect.signature(type)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001575 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001576 # support for 'wrapper_descriptor'
1577 inspect.signature(type.__call__)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001578 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001579 # support for 'method-wrapper'
1580 inspect.signature(min.__call__)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001581 with self.assertRaisesRegex(ValueError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001582 'no signature found for builtin function'):
1583 # support for 'method-wrapper'
1584 inspect.signature(min)
1585
1586 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001587 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001588 inspect.signature(42)
1589
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001590 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001591 inspect.Signature.from_function(42)
1592
1593 def test_signature_on_method(self):
1594 class Test:
1595 def foo(self, arg1, arg2=1) -> int:
1596 pass
1597
1598 meth = Test().foo
1599
1600 self.assertEqual(self.signature(meth),
1601 ((('arg1', ..., ..., "positional_or_keyword"),
1602 ('arg2', 1, ..., "positional_or_keyword")),
1603 int))
1604
1605 def test_signature_on_classmethod(self):
1606 class Test:
1607 @classmethod
1608 def foo(cls, arg1, *, arg2=1):
1609 pass
1610
1611 meth = Test().foo
1612 self.assertEqual(self.signature(meth),
1613 ((('arg1', ..., ..., "positional_or_keyword"),
1614 ('arg2', 1, ..., "keyword_only")),
1615 ...))
1616
1617 meth = Test.foo
1618 self.assertEqual(self.signature(meth),
1619 ((('arg1', ..., ..., "positional_or_keyword"),
1620 ('arg2', 1, ..., "keyword_only")),
1621 ...))
1622
1623 def test_signature_on_staticmethod(self):
1624 class Test:
1625 @staticmethod
1626 def foo(cls, *, arg):
1627 pass
1628
1629 meth = Test().foo
1630 self.assertEqual(self.signature(meth),
1631 ((('cls', ..., ..., "positional_or_keyword"),
1632 ('arg', ..., ..., "keyword_only")),
1633 ...))
1634
1635 meth = Test.foo
1636 self.assertEqual(self.signature(meth),
1637 ((('cls', ..., ..., "positional_or_keyword"),
1638 ('arg', ..., ..., "keyword_only")),
1639 ...))
1640
1641 def test_signature_on_partial(self):
1642 from functools import partial
1643
1644 def test():
1645 pass
1646
1647 self.assertEqual(self.signature(partial(test)), ((), ...))
1648
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001649 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001650 inspect.signature(partial(test, 1))
1651
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001652 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001653 inspect.signature(partial(test, a=1))
1654
1655 def test(a, b, *, c, d):
1656 pass
1657
1658 self.assertEqual(self.signature(partial(test)),
1659 ((('a', ..., ..., "positional_or_keyword"),
1660 ('b', ..., ..., "positional_or_keyword"),
1661 ('c', ..., ..., "keyword_only"),
1662 ('d', ..., ..., "keyword_only")),
1663 ...))
1664
1665 self.assertEqual(self.signature(partial(test, 1)),
1666 ((('b', ..., ..., "positional_or_keyword"),
1667 ('c', ..., ..., "keyword_only"),
1668 ('d', ..., ..., "keyword_only")),
1669 ...))
1670
1671 self.assertEqual(self.signature(partial(test, 1, c=2)),
1672 ((('b', ..., ..., "positional_or_keyword"),
1673 ('c', 2, ..., "keyword_only"),
1674 ('d', ..., ..., "keyword_only")),
1675 ...))
1676
1677 self.assertEqual(self.signature(partial(test, b=1, c=2)),
1678 ((('a', ..., ..., "positional_or_keyword"),
1679 ('b', 1, ..., "positional_or_keyword"),
1680 ('c', 2, ..., "keyword_only"),
1681 ('d', ..., ..., "keyword_only")),
1682 ...))
1683
1684 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
1685 ((('b', 1, ..., "positional_or_keyword"),
1686 ('c', 2, ..., "keyword_only"),
1687 ('d', ..., ..., "keyword_only"),),
1688 ...))
1689
1690 def test(a, *args, b, **kwargs):
1691 pass
1692
1693 self.assertEqual(self.signature(partial(test, 1)),
1694 ((('args', ..., ..., "var_positional"),
1695 ('b', ..., ..., "keyword_only"),
1696 ('kwargs', ..., ..., "var_keyword")),
1697 ...))
1698
1699 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
1700 ((('args', ..., ..., "var_positional"),
1701 ('b', ..., ..., "keyword_only"),
1702 ('kwargs', ..., ..., "var_keyword")),
1703 ...))
1704
1705
1706 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
1707 ((('args', ..., ..., "var_positional"),
1708 ('b', ..., ..., "keyword_only"),
1709 ('kwargs', ..., ..., "var_keyword")),
1710 ...))
1711
1712 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
1713 ((('args', ..., ..., "var_positional"),
1714 ('b', 0, ..., "keyword_only"),
1715 ('kwargs', ..., ..., "var_keyword")),
1716 ...))
1717
1718 self.assertEqual(self.signature(partial(test, b=0)),
1719 ((('a', ..., ..., "positional_or_keyword"),
1720 ('args', ..., ..., "var_positional"),
1721 ('b', 0, ..., "keyword_only"),
1722 ('kwargs', ..., ..., "var_keyword")),
1723 ...))
1724
1725 self.assertEqual(self.signature(partial(test, b=0, test=1)),
1726 ((('a', ..., ..., "positional_or_keyword"),
1727 ('args', ..., ..., "var_positional"),
1728 ('b', 0, ..., "keyword_only"),
1729 ('kwargs', ..., ..., "var_keyword")),
1730 ...))
1731
1732 def test(a, b, c:int) -> 42:
1733 pass
1734
1735 sig = test.__signature__ = inspect.signature(test)
1736
1737 self.assertEqual(self.signature(partial(partial(test, 1))),
1738 ((('b', ..., ..., "positional_or_keyword"),
1739 ('c', ..., int, "positional_or_keyword")),
1740 42))
1741
1742 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
1743 ((('c', ..., int, "positional_or_keyword"),),
1744 42))
1745
1746 psig = inspect.signature(partial(partial(test, 1), 2))
1747
1748 def foo(a):
1749 return a
1750 _foo = partial(partial(foo, a=10), a=20)
1751 self.assertEqual(self.signature(_foo),
1752 ((('a', 20, ..., "positional_or_keyword"),),
1753 ...))
1754 # check that we don't have any side-effects in signature(),
1755 # and the partial object is still functioning
1756 self.assertEqual(_foo(), 20)
1757
1758 def foo(a, b, c):
1759 return a, b, c
1760 _foo = partial(partial(foo, 1, b=20), b=30)
1761 self.assertEqual(self.signature(_foo),
1762 ((('b', 30, ..., "positional_or_keyword"),
1763 ('c', ..., ..., "positional_or_keyword")),
1764 ...))
1765 self.assertEqual(_foo(c=10), (1, 30, 10))
1766 _foo = partial(_foo, 2) # now 'b' has two values -
1767 # positional and keyword
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001768 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001769 inspect.signature(_foo)
1770
1771 def foo(a, b, c, *, d):
1772 return a, b, c, d
1773 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
1774 self.assertEqual(self.signature(_foo),
1775 ((('a', ..., ..., "positional_or_keyword"),
1776 ('b', 10, ..., "positional_or_keyword"),
1777 ('c', 20, ..., "positional_or_keyword"),
1778 ('d', 30, ..., "keyword_only")),
1779 ...))
1780 ba = inspect.signature(_foo).bind(a=200, b=11)
1781 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
1782
1783 def foo(a=1, b=2, c=3):
1784 return a, b, c
1785 _foo = partial(foo, a=10, c=13)
1786 ba = inspect.signature(_foo).bind(11)
1787 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
1788 ba = inspect.signature(_foo).bind(11, 12)
1789 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
1790 ba = inspect.signature(_foo).bind(11, b=12)
1791 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
1792 ba = inspect.signature(_foo).bind(b=12)
1793 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
1794 _foo = partial(_foo, b=10)
1795 ba = inspect.signature(_foo).bind(12, 14)
1796 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
1797
1798 def test_signature_on_decorated(self):
1799 import functools
1800
1801 def decorator(func):
1802 @functools.wraps(func)
1803 def wrapper(*args, **kwargs) -> int:
1804 return func(*args, **kwargs)
1805 return wrapper
1806
1807 class Foo:
1808 @decorator
1809 def bar(self, a, b):
1810 pass
1811
1812 self.assertEqual(self.signature(Foo.bar),
1813 ((('self', ..., ..., "positional_or_keyword"),
1814 ('a', ..., ..., "positional_or_keyword"),
1815 ('b', ..., ..., "positional_or_keyword")),
1816 ...))
1817
1818 self.assertEqual(self.signature(Foo().bar),
1819 ((('a', ..., ..., "positional_or_keyword"),
1820 ('b', ..., ..., "positional_or_keyword")),
1821 ...))
1822
1823 # Test that we handle method wrappers correctly
1824 def decorator(func):
1825 @functools.wraps(func)
1826 def wrapper(*args, **kwargs) -> int:
1827 return func(42, *args, **kwargs)
1828 sig = inspect.signature(func)
1829 new_params = tuple(sig.parameters.values())[1:]
1830 wrapper.__signature__ = sig.replace(parameters=new_params)
1831 return wrapper
1832
1833 class Foo:
1834 @decorator
1835 def __call__(self, a, b):
1836 pass
1837
1838 self.assertEqual(self.signature(Foo.__call__),
1839 ((('a', ..., ..., "positional_or_keyword"),
1840 ('b', ..., ..., "positional_or_keyword")),
1841 ...))
1842
1843 self.assertEqual(self.signature(Foo().__call__),
1844 ((('b', ..., ..., "positional_or_keyword"),),
1845 ...))
1846
Nick Coghlane8c45d62013-07-28 20:00:01 +10001847 # Test we handle __signature__ partway down the wrapper stack
1848 def wrapped_foo_call():
1849 pass
1850 wrapped_foo_call.__wrapped__ = Foo.__call__
1851
1852 self.assertEqual(self.signature(wrapped_foo_call),
1853 ((('a', ..., ..., "positional_or_keyword"),
1854 ('b', ..., ..., "positional_or_keyword")),
1855 ...))
1856
1857
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001858 def test_signature_on_class(self):
1859 class C:
1860 def __init__(self, a):
1861 pass
1862
1863 self.assertEqual(self.signature(C),
1864 ((('a', ..., ..., "positional_or_keyword"),),
1865 ...))
1866
1867 class CM(type):
1868 def __call__(cls, a):
1869 pass
1870 class C(metaclass=CM):
1871 def __init__(self, b):
1872 pass
1873
1874 self.assertEqual(self.signature(C),
1875 ((('a', ..., ..., "positional_or_keyword"),),
1876 ...))
1877
1878 class CM(type):
1879 def __new__(mcls, name, bases, dct, *, foo=1):
1880 return super().__new__(mcls, name, bases, dct)
1881 class C(metaclass=CM):
1882 def __init__(self, b):
1883 pass
1884
1885 self.assertEqual(self.signature(C),
1886 ((('b', ..., ..., "positional_or_keyword"),),
1887 ...))
1888
1889 self.assertEqual(self.signature(CM),
1890 ((('name', ..., ..., "positional_or_keyword"),
1891 ('bases', ..., ..., "positional_or_keyword"),
1892 ('dct', ..., ..., "positional_or_keyword"),
1893 ('foo', 1, ..., "keyword_only")),
1894 ...))
1895
1896 class CMM(type):
1897 def __new__(mcls, name, bases, dct, *, foo=1):
1898 return super().__new__(mcls, name, bases, dct)
1899 def __call__(cls, nm, bs, dt):
1900 return type(nm, bs, dt)
1901 class CM(type, metaclass=CMM):
1902 def __new__(mcls, name, bases, dct, *, bar=2):
1903 return super().__new__(mcls, name, bases, dct)
1904 class C(metaclass=CM):
1905 def __init__(self, b):
1906 pass
1907
1908 self.assertEqual(self.signature(CMM),
1909 ((('name', ..., ..., "positional_or_keyword"),
1910 ('bases', ..., ..., "positional_or_keyword"),
1911 ('dct', ..., ..., "positional_or_keyword"),
1912 ('foo', 1, ..., "keyword_only")),
1913 ...))
1914
1915 self.assertEqual(self.signature(CM),
1916 ((('nm', ..., ..., "positional_or_keyword"),
1917 ('bs', ..., ..., "positional_or_keyword"),
1918 ('dt', ..., ..., "positional_or_keyword")),
1919 ...))
1920
1921 self.assertEqual(self.signature(C),
1922 ((('b', ..., ..., "positional_or_keyword"),),
1923 ...))
1924
1925 class CM(type):
1926 def __init__(cls, name, bases, dct, *, bar=2):
1927 return super().__init__(name, bases, dct)
1928 class C(metaclass=CM):
1929 def __init__(self, b):
1930 pass
1931
1932 self.assertEqual(self.signature(CM),
1933 ((('name', ..., ..., "positional_or_keyword"),
1934 ('bases', ..., ..., "positional_or_keyword"),
1935 ('dct', ..., ..., "positional_or_keyword"),
1936 ('bar', 2, ..., "keyword_only")),
1937 ...))
1938
1939 def test_signature_on_callable_objects(self):
1940 class Foo:
1941 def __call__(self, a):
1942 pass
1943
1944 self.assertEqual(self.signature(Foo()),
1945 ((('a', ..., ..., "positional_or_keyword"),),
1946 ...))
1947
1948 class Spam:
1949 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001950 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001951 inspect.signature(Spam())
1952
1953 class Bar(Spam, Foo):
1954 pass
1955
1956 self.assertEqual(self.signature(Bar()),
1957 ((('a', ..., ..., "positional_or_keyword"),),
1958 ...))
1959
1960 class ToFail:
1961 __call__ = type
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001962 with self.assertRaisesRegex(ValueError, "not supported by signature"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001963 inspect.signature(ToFail())
1964
1965
1966 class Wrapped:
1967 pass
1968 Wrapped.__wrapped__ = lambda a: None
1969 self.assertEqual(self.signature(Wrapped),
1970 ((('a', ..., ..., "positional_or_keyword"),),
1971 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10001972 # wrapper loop:
1973 Wrapped.__wrapped__ = Wrapped
1974 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
1975 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001976
1977 def test_signature_on_lambdas(self):
1978 self.assertEqual(self.signature((lambda a=10: a)),
1979 ((('a', 10, ..., "positional_or_keyword"),),
1980 ...))
1981
1982 def test_signature_equality(self):
1983 def foo(a, *, b:int) -> float: pass
1984 self.assertNotEqual(inspect.signature(foo), 42)
1985
1986 def bar(a, *, b:int) -> float: pass
1987 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1988
1989 def bar(a, *, b:int) -> int: pass
1990 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1991
1992 def bar(a, *, b:int): pass
1993 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1994
1995 def bar(a, *, b:int=42) -> float: pass
1996 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1997
1998 def bar(a, *, c) -> float: pass
1999 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2000
2001 def bar(a, b:int) -> float: pass
2002 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2003 def spam(b:int, a) -> float: pass
2004 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
2005
2006 def foo(*, a, b, c): pass
2007 def bar(*, c, b, a): pass
2008 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2009
2010 def foo(*, a=1, b, c): pass
2011 def bar(*, c, b, a=1): pass
2012 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2013
2014 def foo(pos, *, a=1, b, c): pass
2015 def bar(pos, *, c, b, a=1): pass
2016 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2017
2018 def foo(pos, *, a, b, c): pass
2019 def bar(pos, *, c, b, a=1): pass
2020 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2021
2022 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2023 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2024 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2025
2026 def test_signature_unhashable(self):
2027 def foo(a): pass
2028 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002029 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002030 hash(sig)
2031
2032 def test_signature_str(self):
2033 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2034 pass
2035 self.assertEqual(str(inspect.signature(foo)),
2036 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2037
2038 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2039 pass
2040 self.assertEqual(str(inspect.signature(foo)),
2041 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2042
2043 def foo():
2044 pass
2045 self.assertEqual(str(inspect.signature(foo)), '()')
2046
2047 def test_signature_str_positional_only(self):
2048 P = inspect.Parameter
2049
2050 def test(a_po, *, b, **kwargs):
2051 return a_po, kwargs
2052
2053 sig = inspect.signature(test)
2054 new_params = list(sig.parameters.values())
2055 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2056 test.__signature__ = sig.replace(parameters=new_params)
2057
2058 self.assertEqual(str(inspect.signature(test)),
2059 '(<a_po>, *, b, **kwargs)')
2060
2061 sig = inspect.signature(test)
2062 new_params = list(sig.parameters.values())
2063 new_params[0] = new_params[0].replace(name=None)
2064 test.__signature__ = sig.replace(parameters=new_params)
2065 self.assertEqual(str(inspect.signature(test)),
2066 '(<0>, *, b, **kwargs)')
2067
2068 def test_signature_replace_anno(self):
2069 def test() -> 42:
2070 pass
2071
2072 sig = inspect.signature(test)
2073 sig = sig.replace(return_annotation=None)
2074 self.assertIs(sig.return_annotation, None)
2075 sig = sig.replace(return_annotation=sig.empty)
2076 self.assertIs(sig.return_annotation, sig.empty)
2077 sig = sig.replace(return_annotation=42)
2078 self.assertEqual(sig.return_annotation, 42)
2079 self.assertEqual(sig, inspect.signature(test))
2080
2081
2082class TestParameterObject(unittest.TestCase):
2083 def test_signature_parameter_kinds(self):
2084 P = inspect.Parameter
2085 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2086 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2087
2088 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2089 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2090
2091 def test_signature_parameter_object(self):
2092 p = inspect.Parameter('foo', default=10,
2093 kind=inspect.Parameter.POSITIONAL_ONLY)
2094 self.assertEqual(p.name, 'foo')
2095 self.assertEqual(p.default, 10)
2096 self.assertIs(p.annotation, p.empty)
2097 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2098
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002099 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002100 inspect.Parameter('foo', default=10, kind='123')
2101
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002102 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002103 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2104
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002105 with self.assertRaisesRegex(ValueError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002106 'non-positional-only parameter'):
2107 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2108
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002109 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002110 inspect.Parameter('a', default=42,
2111 kind=inspect.Parameter.VAR_KEYWORD)
2112
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002113 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002114 inspect.Parameter('a', default=42,
2115 kind=inspect.Parameter.VAR_POSITIONAL)
2116
2117 p = inspect.Parameter('a', default=42,
2118 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002119 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002120 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2121
2122 self.assertTrue(repr(p).startswith('<Parameter'))
2123
2124 def test_signature_parameter_equality(self):
2125 P = inspect.Parameter
2126 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2127
2128 self.assertEqual(p, p)
2129 self.assertNotEqual(p, 42)
2130
2131 self.assertEqual(p, P('foo', default=42,
2132 kind=inspect.Parameter.KEYWORD_ONLY))
2133
2134 def test_signature_parameter_unhashable(self):
2135 p = inspect.Parameter('foo', default=42,
2136 kind=inspect.Parameter.KEYWORD_ONLY)
2137
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002138 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002139 hash(p)
2140
2141 def test_signature_parameter_replace(self):
2142 p = inspect.Parameter('foo', default=42,
2143 kind=inspect.Parameter.KEYWORD_ONLY)
2144
2145 self.assertIsNot(p, p.replace())
2146 self.assertEqual(p, p.replace())
2147
2148 p2 = p.replace(annotation=1)
2149 self.assertEqual(p2.annotation, 1)
2150 p2 = p2.replace(annotation=p2.empty)
2151 self.assertEqual(p, p2)
2152
2153 p2 = p2.replace(name='bar')
2154 self.assertEqual(p2.name, 'bar')
2155 self.assertNotEqual(p2, p)
2156
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002157 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002158 p2 = p2.replace(name=p2.empty)
2159
2160 p2 = p2.replace(name='foo', default=None)
2161 self.assertIs(p2.default, None)
2162 self.assertNotEqual(p2, p)
2163
2164 p2 = p2.replace(name='foo', default=p2.empty)
2165 self.assertIs(p2.default, p2.empty)
2166
2167
2168 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2169 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2170 self.assertNotEqual(p2, p)
2171
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002172 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002173 p2 = p2.replace(kind=p2.empty)
2174
2175 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2176 self.assertEqual(p2, p)
2177
2178 def test_signature_parameter_positional_only(self):
2179 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
2180 self.assertEqual(str(p), '<>')
2181
2182 p = p.replace(name='1')
2183 self.assertEqual(str(p), '<1>')
2184
2185 def test_signature_parameter_immutability(self):
2186 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
2187
2188 with self.assertRaises(AttributeError):
2189 p.foo = 'bar'
2190
2191 with self.assertRaises(AttributeError):
2192 p.kind = 123
2193
2194
2195class TestSignatureBind(unittest.TestCase):
2196 @staticmethod
2197 def call(func, *args, **kwargs):
2198 sig = inspect.signature(func)
2199 ba = sig.bind(*args, **kwargs)
2200 return func(*ba.args, **ba.kwargs)
2201
2202 def test_signature_bind_empty(self):
2203 def test():
2204 return 42
2205
2206 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002207 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002208 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002209 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002210 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002211 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002212 self.call(test, spam=1)
2213
2214 def test_signature_bind_var(self):
2215 def test(*args, **kwargs):
2216 return args, kwargs
2217
2218 self.assertEqual(self.call(test), ((), {}))
2219 self.assertEqual(self.call(test, 1), ((1,), {}))
2220 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2221 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2222 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2223 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2224 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2225 ((1, 2), {'foo': 'bar'}))
2226
2227 def test_signature_bind_just_args(self):
2228 def test(a, b, c):
2229 return a, b, c
2230
2231 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2232
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002233 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002234 self.call(test, 1, 2, 3, 4)
2235
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002236 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002237 self.call(test, 1)
2238
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002239 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002240 self.call(test)
2241
2242 def test(a, b, c=10):
2243 return a, b, c
2244 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2245 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2246
2247 def test(a=1, b=2, c=3):
2248 return a, b, c
2249 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2250 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2251 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2252
2253 def test_signature_bind_varargs_order(self):
2254 def test(*args):
2255 return args
2256
2257 self.assertEqual(self.call(test), ())
2258 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2259
2260 def test_signature_bind_args_and_varargs(self):
2261 def test(a, b, c=3, *args):
2262 return a, b, c, args
2263
2264 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2265 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2266 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2267 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2268
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002269 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002270 "multiple values for argument 'c'"):
2271 self.call(test, 1, 2, 3, c=4)
2272
2273 def test_signature_bind_just_kwargs(self):
2274 def test(**kwargs):
2275 return kwargs
2276
2277 self.assertEqual(self.call(test), {})
2278 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2279 {'foo': 'bar', 'spam': 'ham'})
2280
2281 def test_signature_bind_args_and_kwargs(self):
2282 def test(a, b, c=3, **kwargs):
2283 return a, b, c, kwargs
2284
2285 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2286 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2287 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2288 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2289 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2290 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2291 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2292 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2293 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2294 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2295 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2296 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2297 (1, 2, 4, {'foo': 'bar'}))
2298 self.assertEqual(self.call(test, c=5, a=4, b=3),
2299 (4, 3, 5, {}))
2300
2301 def test_signature_bind_kwonly(self):
2302 def test(*, foo):
2303 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002304 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002305 'too many positional arguments'):
2306 self.call(test, 1)
2307 self.assertEqual(self.call(test, foo=1), 1)
2308
2309 def test(a, *, foo=1, bar):
2310 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002311 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002312 "'bar' parameter lacking default value"):
2313 self.call(test, 1)
2314
2315 def test(foo, *, bar):
2316 return foo, bar
2317 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2318 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2319
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002320 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002321 'too many keyword arguments'):
2322 self.call(test, bar=2, foo=1, spam=10)
2323
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002324 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002325 'too many positional arguments'):
2326 self.call(test, 1, 2)
2327
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002328 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002329 'too many positional arguments'):
2330 self.call(test, 1, 2, bar=2)
2331
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002332 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002333 'too many keyword arguments'):
2334 self.call(test, 1, bar=2, spam='ham')
2335
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002336 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002337 "'bar' parameter lacking default value"):
2338 self.call(test, 1)
2339
2340 def test(foo, *, bar, **bin):
2341 return foo, bar, bin
2342 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2343 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2344 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2345 (1, 2, {'spam': 'ham'}))
2346 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2347 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002348 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002349 "'foo' parameter lacking default value"):
2350 self.call(test, spam='ham', bar=2)
2351 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2352 (1, 2, {'bin': 1, 'spam': 10}))
2353
2354 def test_signature_bind_arguments(self):
2355 def test(a, *args, b, z=100, **kwargs):
2356 pass
2357 sig = inspect.signature(test)
2358 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2359 # we won't have 'z' argument in the bound arguments object, as we didn't
2360 # pass it to the 'bind'
2361 self.assertEqual(tuple(ba.arguments.items()),
2362 (('a', 10), ('args', (20,)), ('b', 30),
2363 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2364 self.assertEqual(ba.kwargs,
2365 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2366 self.assertEqual(ba.args, (10, 20))
2367
2368 def test_signature_bind_positional_only(self):
2369 P = inspect.Parameter
2370
2371 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2372 return a_po, b_po, c_po, foo, bar, kwargs
2373
2374 sig = inspect.signature(test)
2375 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2376 for name in ('a_po', 'b_po', 'c_po'):
2377 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2378 new_sig = sig.replace(parameters=new_params.values())
2379 test.__signature__ = new_sig
2380
2381 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2382 (1, 2, 4, 5, 6, {}))
2383
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002384 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002385 self.call(test, 1, 2, c_po=4)
2386
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002387 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002388 self.call(test, a_po=1, b_po=2)
2389
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002390 def test_signature_bind_with_self_arg(self):
2391 # Issue #17071: one of the parameters is named "self
2392 def test(a, self, b):
2393 pass
2394 sig = inspect.signature(test)
2395 ba = sig.bind(1, 2, 3)
2396 self.assertEqual(ba.args, (1, 2, 3))
2397 ba = sig.bind(1, self=2, b=3)
2398 self.assertEqual(ba.args, (1, 2, 3))
2399
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002400
2401class TestBoundArguments(unittest.TestCase):
2402 def test_signature_bound_arguments_unhashable(self):
2403 def foo(a): pass
2404 ba = inspect.signature(foo).bind(1)
2405
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002406 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002407 hash(ba)
2408
2409 def test_signature_bound_arguments_equality(self):
2410 def foo(a): pass
2411 ba = inspect.signature(foo).bind(1)
2412 self.assertEqual(ba, ba)
2413
2414 ba2 = inspect.signature(foo).bind(1)
2415 self.assertEqual(ba, ba2)
2416
2417 ba3 = inspect.signature(foo).bind(2)
2418 self.assertNotEqual(ba, ba3)
2419 ba3.arguments['a'] = 1
2420 self.assertEqual(ba, ba3)
2421
2422 def bar(b): pass
2423 ba4 = inspect.signature(bar).bind(1)
2424 self.assertNotEqual(ba, ba4)
2425
2426
Nick Coghlane8c45d62013-07-28 20:00:01 +10002427class TestUnwrap(unittest.TestCase):
2428
2429 def test_unwrap_one(self):
2430 def func(a, b):
2431 return a + b
2432 wrapper = functools.lru_cache(maxsize=20)(func)
2433 self.assertIs(inspect.unwrap(wrapper), func)
2434
2435 def test_unwrap_several(self):
2436 def func(a, b):
2437 return a + b
2438 wrapper = func
2439 for __ in range(10):
2440 @functools.wraps(wrapper)
2441 def wrapper():
2442 pass
2443 self.assertIsNot(wrapper.__wrapped__, func)
2444 self.assertIs(inspect.unwrap(wrapper), func)
2445
2446 def test_stop(self):
2447 def func1(a, b):
2448 return a + b
2449 @functools.wraps(func1)
2450 def func2():
2451 pass
2452 @functools.wraps(func2)
2453 def wrapper():
2454 pass
2455 func2.stop_here = 1
2456 unwrapped = inspect.unwrap(wrapper,
2457 stop=(lambda f: hasattr(f, "stop_here")))
2458 self.assertIs(unwrapped, func2)
2459
2460 def test_cycle(self):
2461 def func1(): pass
2462 func1.__wrapped__ = func1
2463 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2464 inspect.unwrap(func1)
2465
2466 def func2(): pass
2467 func2.__wrapped__ = func1
2468 func1.__wrapped__ = func2
2469 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2470 inspect.unwrap(func1)
2471 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2472 inspect.unwrap(func2)
2473
2474 def test_unhashable(self):
2475 def func(): pass
2476 func.__wrapped__ = None
2477 class C:
2478 __hash__ = None
2479 __wrapped__ = func
2480 self.assertIsNone(inspect.unwrap(C()))
2481
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002482class TestMain(unittest.TestCase):
2483 def test_only_source(self):
2484 module = importlib.import_module('unittest')
2485 rc, out, err = assert_python_ok('-m', 'inspect',
2486 'unittest')
2487 lines = out.decode().splitlines()
2488 # ignore the final newline
2489 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
2490 self.assertEqual(err, b'')
2491
Brett Cannon634a8fc2013-10-02 10:25:42 -04002492 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04002493 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002494 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002495 rc, out, err = assert_python_ok('-m', 'inspect',
2496 'concurrent.futures:ThreadPoolExecutor')
2497 lines = out.decode().splitlines()
2498 # ignore the final newline
2499 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04002500 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002501 self.assertEqual(err, b'')
2502
2503 def test_builtins(self):
2504 module = importlib.import_module('unittest')
2505 _, out, err = assert_python_failure('-m', 'inspect',
2506 'sys')
2507 lines = err.decode().splitlines()
2508 self.assertEqual(lines, ["Can't get info for builtin modules."])
2509
2510 def test_details(self):
2511 module = importlib.import_module('unittest')
2512 rc, out, err = assert_python_ok('-m', 'inspect',
2513 'unittest', '--details')
2514 output = out.decode()
2515 # Just a quick sanity check on the output
2516 self.assertIn(module.__name__, output)
2517 self.assertIn(module.__file__, output)
2518 self.assertIn(module.__cached__, output)
2519 self.assertEqual(err, b'')
2520
2521
2522
Nick Coghlane8c45d62013-07-28 20:00:01 +10002523
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002524def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00002525 run_unittest(
2526 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
2527 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
2528 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00002529 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002530 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002531 TestBoundArguments, TestGetClosureVars, TestUnwrap, TestMain
Michael Foord95fc51d2010-11-20 15:07:30 +00002532 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00002533
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002534if __name__ == "__main__":
2535 test_main()