blob: 9d3490449acdc7d0ac651a409d3a372dcfe89dab [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))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700670 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700671 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
672
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700673 def test_classify_metaclass_class_attribute(self):
674 class Meta(type):
675 fish = 'slap'
676 def __dir__(self):
677 return ['__class__', '__modules__', '__name__', 'fish']
678 class Class(metaclass=Meta):
679 pass
680 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
681 self.assertIn(should_find, inspect.classify_class_attrs(Class))
682
Ethan Furman63c141c2013-10-18 00:27:39 -0700683 def test_classify_VirtualAttribute(self):
684 class Meta(type):
685 def __dir__(cls):
686 return ['__class__', '__module__', '__name__', 'BOOM']
687 def __getattr__(self, name):
688 if name =='BOOM':
689 return 42
690 return super().__getattr(name)
691 class Class(metaclass=Meta):
692 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700693 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700694 self.assertIn(should_find, inspect.classify_class_attrs(Class))
695
696 def test_classify_VirtualAttribute_multi_classes(self):
697 class Meta1(type):
698 def __dir__(cls):
699 return ['__class__', '__module__', '__name__', 'one']
700 def __getattr__(self, name):
701 if name =='one':
702 return 1
703 return super().__getattr__(name)
704 class Meta2(type):
705 def __dir__(cls):
706 return ['__class__', '__module__', '__name__', 'two']
707 def __getattr__(self, name):
708 if name =='two':
709 return 2
710 return super().__getattr__(name)
711 class Meta3(Meta1, Meta2):
712 def __dir__(cls):
713 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
714 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
715 def __getattr__(self, name):
716 if name =='three':
717 return 3
718 return super().__getattr__(name)
719 class Class1(metaclass=Meta1):
720 pass
721 class Class2(Class1, metaclass=Meta3):
722 pass
723
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700724 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
725 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
726 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700727 cca = inspect.classify_class_attrs(Class2)
728 for sf in (should_find1, should_find2, should_find3):
729 self.assertIn(sf, cca)
730
731 def test_classify_class_attrs_with_buggy_dir(self):
732 class M(type):
733 def __dir__(cls):
734 return ['__class__', '__name__', 'missing']
735 class C(metaclass=M):
736 pass
737 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
738 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700739
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100740 def test_getmembers_descriptors(self):
741 class A(object):
742 dd = _BrokenDataDescriptor()
743 md = _BrokenMethodDescriptor()
744
745 def pred_wrapper(pred):
746 # A quick'n'dirty way to discard standard attributes of new-style
747 # classes.
748 class Empty(object):
749 pass
750 def wrapped(x):
751 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
752 return False
753 return pred(x)
754 return wrapped
755
756 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
757 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
758
759 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
760 [('md', A.__dict__['md'])])
761 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
762 [('dd', A.__dict__['dd'])])
763
764 class B(A):
765 pass
766
767 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
768 [('md', A.__dict__['md'])])
769 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
770 [('dd', A.__dict__['dd'])])
771
Antoine Pitrou0c603812012-01-18 17:40:18 +0100772 def test_getmembers_method(self):
773 class B:
774 def f(self):
775 pass
776
777 self.assertIn(('f', B.f), inspect.getmembers(B))
778 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
779 b = B()
780 self.assertIn(('f', b.f), inspect.getmembers(b))
781 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
782
Ethan Furmane03ea372013-09-25 07:14:41 -0700783 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -0700784 class M(type):
785 def __getattr__(cls, name):
786 if name == 'eggs':
787 return 'scrambled'
788 return super().__getattr__(name)
789 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -0700790 @types.DynamicClassAttribute
791 def eggs(self):
792 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -0700793 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
794 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
795
796 def test_getmembers_with_buggy_dir(self):
797 class M(type):
798 def __dir__(cls):
799 return ['__class__', '__name__', 'missing']
800 class C(metaclass=M):
801 pass
802 attrs = [a[0] for a in inspect.getmembers(C)]
803 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700804
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000805
Nick Coghlan2f92e542012-06-23 19:39:55 +1000806_global_ref = object()
807class TestGetClosureVars(unittest.TestCase):
808
809 def test_name_resolution(self):
810 # Basic test of the 4 different resolution mechanisms
811 def f(nonlocal_ref):
812 def g(local_ref):
813 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
814 return g
815 _arg = object()
816 nonlocal_vars = {"nonlocal_ref": _arg}
817 global_vars = {"_global_ref": _global_ref}
818 builtin_vars = {"print": print}
819 unbound_names = {"unbound_ref"}
820 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
821 builtin_vars, unbound_names)
822 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
823
824 def test_generator_closure(self):
825 def f(nonlocal_ref):
826 def g(local_ref):
827 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
828 yield
829 return g
830 _arg = object()
831 nonlocal_vars = {"nonlocal_ref": _arg}
832 global_vars = {"_global_ref": _global_ref}
833 builtin_vars = {"print": print}
834 unbound_names = {"unbound_ref"}
835 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
836 builtin_vars, unbound_names)
837 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
838
839 def test_method_closure(self):
840 class C:
841 def f(self, nonlocal_ref):
842 def g(local_ref):
843 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
844 return g
845 _arg = object()
846 nonlocal_vars = {"nonlocal_ref": _arg}
847 global_vars = {"_global_ref": _global_ref}
848 builtin_vars = {"print": print}
849 unbound_names = {"unbound_ref"}
850 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
851 builtin_vars, unbound_names)
852 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
853
854 def test_nonlocal_vars(self):
855 # More complex tests of nonlocal resolution
856 def _nonlocal_vars(f):
857 return inspect.getclosurevars(f).nonlocals
858
859 def make_adder(x):
860 def add(y):
861 return x + y
862 return add
863
864 def curry(func, arg1):
865 return lambda arg2: func(arg1, arg2)
866
867 def less_than(a, b):
868 return a < b
869
870 # The infamous Y combinator.
871 def Y(le):
872 def g(f):
873 return le(lambda x: f(f)(x))
874 Y.g_ref = g
875 return g(g)
876
877 def check_y_combinator(func):
878 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
879
880 inc = make_adder(1)
881 add_two = make_adder(2)
882 greater_than_five = curry(less_than, 5)
883
884 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
885 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
886 self.assertEqual(_nonlocal_vars(greater_than_five),
887 {'arg1': 5, 'func': less_than})
888 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
889 {'x': 3})
890 Y(check_y_combinator)
891
892 def test_getclosurevars_empty(self):
893 def foo(): pass
894 _empty = inspect.ClosureVars({}, {}, {}, set())
895 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
896 self.assertEqual(inspect.getclosurevars(foo), _empty)
897
898 def test_getclosurevars_error(self):
899 class T: pass
900 self.assertRaises(TypeError, inspect.getclosurevars, 1)
901 self.assertRaises(TypeError, inspect.getclosurevars, list)
902 self.assertRaises(TypeError, inspect.getclosurevars, {})
903
Nick Coghlan6c6e2542012-06-23 20:07:39 +1000904 def _private_globals(self):
905 code = """def f(): print(path)"""
906 ns = {}
907 exec(code, ns)
908 return ns["f"], ns
909
910 def test_builtins_fallback(self):
911 f, ns = self._private_globals()
912 ns.pop("__builtins__", None)
913 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
914 self.assertEqual(inspect.getclosurevars(f), expected)
915
916 def test_builtins_as_dict(self):
917 f, ns = self._private_globals()
918 ns["__builtins__"] = {"path":1}
919 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
920 self.assertEqual(inspect.getclosurevars(f), expected)
921
922 def test_builtins_as_module(self):
923 f, ns = self._private_globals()
924 ns["__builtins__"] = os
925 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
926 self.assertEqual(inspect.getclosurevars(f), expected)
927
Nick Coghlan2f92e542012-06-23 19:39:55 +1000928
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000929class TestGetcallargsFunctions(unittest.TestCase):
930
931 def assertEqualCallArgs(self, func, call_params_string, locs=None):
932 locs = dict(locs or {}, func=func)
933 r1 = eval('func(%s)' % call_params_string, None, locs)
934 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
935 locs)
936 self.assertEqual(r1, r2)
937
938 def assertEqualException(self, func, call_param_string, locs=None):
939 locs = dict(locs or {}, func=func)
940 try:
941 eval('func(%s)' % call_param_string, None, locs)
942 except Exception as e:
943 ex1 = e
944 else:
945 self.fail('Exception not raised')
946 try:
947 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
948 locs)
949 except Exception as e:
950 ex2 = e
951 else:
952 self.fail('Exception not raised')
953 self.assertIs(type(ex1), type(ex2))
954 self.assertEqual(str(ex1), str(ex2))
955 del ex1, ex2
956
957 def makeCallable(self, signature):
958 """Create a function that returns its locals()"""
959 code = "lambda %s: locals()"
960 return eval(code % signature)
961
962 def test_plain(self):
963 f = self.makeCallable('a, b=1')
964 self.assertEqualCallArgs(f, '2')
965 self.assertEqualCallArgs(f, '2, 3')
966 self.assertEqualCallArgs(f, 'a=2')
967 self.assertEqualCallArgs(f, 'b=3, a=2')
968 self.assertEqualCallArgs(f, '2, b=3')
969 # expand *iterable / **mapping
970 self.assertEqualCallArgs(f, '*(2,)')
971 self.assertEqualCallArgs(f, '*[2]')
972 self.assertEqualCallArgs(f, '*(2, 3)')
973 self.assertEqualCallArgs(f, '*[2, 3]')
974 self.assertEqualCallArgs(f, '**{"a":2}')
975 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
976 self.assertEqualCallArgs(f, '2, **{"b":3}')
977 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
978 # expand UserList / UserDict
979 self.assertEqualCallArgs(f, '*collections.UserList([2])')
980 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
981 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
982 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
983 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
984
985 def test_varargs(self):
986 f = self.makeCallable('a, b=1, *c')
987 self.assertEqualCallArgs(f, '2')
988 self.assertEqualCallArgs(f, '2, 3')
989 self.assertEqualCallArgs(f, '2, 3, 4')
990 self.assertEqualCallArgs(f, '*(2,3,4)')
991 self.assertEqualCallArgs(f, '2, *[3,4]')
992 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
993
994 def test_varkw(self):
995 f = self.makeCallable('a, b=1, **c')
996 self.assertEqualCallArgs(f, 'a=2')
997 self.assertEqualCallArgs(f, '2, b=3, c=4')
998 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
999 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1000 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1001 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1002 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1003 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1004 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1005
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001006 def test_varkw_only(self):
1007 # issue11256:
1008 f = self.makeCallable('**c')
1009 self.assertEqualCallArgs(f, '')
1010 self.assertEqualCallArgs(f, 'a=1')
1011 self.assertEqualCallArgs(f, 'a=1, b=2')
1012 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1013 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1014 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1015
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001016 def test_keyword_only(self):
1017 f = self.makeCallable('a=3, *, c, d=2')
1018 self.assertEqualCallArgs(f, 'c=3')
1019 self.assertEqualCallArgs(f, 'c=3, a=3')
1020 self.assertEqualCallArgs(f, 'a=2, c=4')
1021 self.assertEqualCallArgs(f, '4, c=4')
1022 self.assertEqualException(f, '')
1023 self.assertEqualException(f, '3')
1024 self.assertEqualException(f, 'a=3')
1025 self.assertEqualException(f, 'd=4')
1026
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001027 f = self.makeCallable('*, c, d=2')
1028 self.assertEqualCallArgs(f, 'c=3')
1029 self.assertEqualCallArgs(f, 'c=3, d=4')
1030 self.assertEqualCallArgs(f, 'd=4, c=3')
1031
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001032 def test_multiple_features(self):
1033 f = self.makeCallable('a, b=2, *f, **g')
1034 self.assertEqualCallArgs(f, '2, 3, 7')
1035 self.assertEqualCallArgs(f, '2, 3, x=8')
1036 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1037 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1038 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1039 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1040 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1041 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1042 '(4,[5,6])]), **collections.UserDict('
1043 'y=9, z=10)')
1044
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001045 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1046 self.assertEqualCallArgs(f, '2, 3, x=8')
1047 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1048 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1049 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1050 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1051 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1052 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1053 '(4,[5,6])]), q=0, **collections.UserDict('
1054 'y=9, z=10)')
1055
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001056 def test_errors(self):
1057 f0 = self.makeCallable('')
1058 f1 = self.makeCallable('a, b')
1059 f2 = self.makeCallable('a, b=1')
1060 # f0 takes no arguments
1061 self.assertEqualException(f0, '1')
1062 self.assertEqualException(f0, 'x=1')
1063 self.assertEqualException(f0, '1,x=1')
1064 # f1 takes exactly 2 arguments
1065 self.assertEqualException(f1, '')
1066 self.assertEqualException(f1, '1')
1067 self.assertEqualException(f1, 'a=2')
1068 self.assertEqualException(f1, 'b=3')
1069 # f2 takes at least 1 argument
1070 self.assertEqualException(f2, '')
1071 self.assertEqualException(f2, 'b=3')
1072 for f in f1, f2:
1073 # f1/f2 takes exactly/at most 2 arguments
1074 self.assertEqualException(f, '2, 3, 4')
1075 self.assertEqualException(f, '1, 2, 3, a=1')
1076 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001077 # XXX: success of this one depends on dict order
1078 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001079 # f got an unexpected keyword argument
1080 self.assertEqualException(f, 'c=2')
1081 self.assertEqualException(f, '2, c=3')
1082 self.assertEqualException(f, '2, 3, c=4')
1083 self.assertEqualException(f, '2, c=4, b=3')
1084 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1085 # f got multiple values for keyword argument
1086 self.assertEqualException(f, '1, a=2')
1087 self.assertEqualException(f, '1, **{"a":2}')
1088 self.assertEqualException(f, '1, 2, b=3')
1089 # XXX: Python inconsistency
1090 # - for functions and bound methods: unexpected keyword 'c'
1091 # - for unbound methods: multiple values for keyword 'a'
1092 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001093 # issue11256:
1094 f3 = self.makeCallable('**c')
1095 self.assertEqualException(f3, '1, 2')
1096 self.assertEqualException(f3, '1, 2, a=1, b=2')
1097 f4 = self.makeCallable('*, a, b=0')
1098 self.assertEqualException(f3, '1, 2')
1099 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001100
1101class TestGetcallargsMethods(TestGetcallargsFunctions):
1102
1103 def setUp(self):
1104 class Foo(object):
1105 pass
1106 self.cls = Foo
1107 self.inst = Foo()
1108
1109 def makeCallable(self, signature):
1110 assert 'self' not in signature
1111 mk = super(TestGetcallargsMethods, self).makeCallable
1112 self.cls.method = mk('self, ' + signature)
1113 return self.inst.method
1114
1115class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1116
1117 def makeCallable(self, signature):
1118 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1119 return self.cls.method
1120
1121 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1122 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1123 *self._getAssertEqualParams(func, call_params_string, locs))
1124
1125 def assertEqualException(self, func, call_params_string, locs=None):
1126 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1127 *self._getAssertEqualParams(func, call_params_string, locs))
1128
1129 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1130 assert 'inst' not in call_params_string
1131 locs = dict(locs or {}, inst=self.inst)
1132 return (func, 'inst,' + call_params_string, locs)
1133
Michael Foord95fc51d2010-11-20 15:07:30 +00001134
1135class TestGetattrStatic(unittest.TestCase):
1136
1137 def test_basic(self):
1138 class Thing(object):
1139 x = object()
1140
1141 thing = Thing()
1142 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1143 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1144 with self.assertRaises(AttributeError):
1145 inspect.getattr_static(thing, 'y')
1146
1147 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1148
1149 def test_inherited(self):
1150 class Thing(object):
1151 x = object()
1152 class OtherThing(Thing):
1153 pass
1154
1155 something = OtherThing()
1156 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1157
1158 def test_instance_attr(self):
1159 class Thing(object):
1160 x = 2
1161 def __init__(self, x):
1162 self.x = x
1163 thing = Thing(3)
1164 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1165 del thing.x
1166 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1167
1168 def test_property(self):
1169 class Thing(object):
1170 @property
1171 def x(self):
1172 raise AttributeError("I'm pretending not to exist")
1173 thing = Thing()
1174 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1175
Ezio Melotti75cbd732011-04-28 00:59:29 +03001176 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001177 class descriptor(object):
1178 def __get__(*_):
1179 raise AttributeError("I'm pretending not to exist")
1180 desc = descriptor()
1181 class Thing(object):
1182 x = desc
1183 thing = Thing()
1184 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1185
1186 def test_classAttribute(self):
1187 class Thing(object):
1188 x = object()
1189
1190 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1191
Ethan Furmane03ea372013-09-25 07:14:41 -07001192 def test_classVirtualAttribute(self):
1193 class Thing(object):
1194 @types.DynamicClassAttribute
1195 def x(self):
1196 return self._x
1197 _x = object()
1198
1199 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1200
Michael Foord95fc51d2010-11-20 15:07:30 +00001201 def test_inherited_classattribute(self):
1202 class Thing(object):
1203 x = object()
1204 class OtherThing(Thing):
1205 pass
1206
1207 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1208
1209 def test_slots(self):
1210 class Thing(object):
1211 y = 'bar'
1212 __slots__ = ['x']
1213 def __init__(self):
1214 self.x = 'foo'
1215 thing = Thing()
1216 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1217 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1218
1219 del thing.x
1220 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1221
1222 def test_metaclass(self):
1223 class meta(type):
1224 attr = 'foo'
1225 class Thing(object, metaclass=meta):
1226 pass
1227 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1228
1229 class sub(meta):
1230 pass
1231 class OtherThing(object, metaclass=sub):
1232 x = 3
1233 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1234
1235 class OtherOtherThing(OtherThing):
1236 pass
1237 # this test is odd, but it was added as it exposed a bug
1238 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1239
1240 def test_no_dict_no_slots(self):
1241 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1242 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1243
1244 def test_no_dict_no_slots_instance_member(self):
1245 # returns descriptor
1246 with open(__file__) as handle:
1247 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1248
1249 def test_inherited_slots(self):
1250 # returns descriptor
1251 class Thing(object):
1252 __slots__ = ['x']
1253 def __init__(self):
1254 self.x = 'foo'
1255
1256 class OtherThing(Thing):
1257 pass
1258 # it would be nice if this worked...
1259 # we get the descriptor instead of the instance attribute
1260 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1261
1262 def test_descriptor(self):
1263 class descriptor(object):
1264 def __get__(self, instance, owner):
1265 return 3
1266 class Foo(object):
1267 d = descriptor()
1268
1269 foo = Foo()
1270
1271 # for a non data descriptor we return the instance attribute
1272 foo.__dict__['d'] = 1
1273 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1274
1275 # if the descriptor is a data-desciptor we should return the
1276 # descriptor
1277 descriptor.__set__ = lambda s, i, v: None
1278 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1279
1280
1281 def test_metaclass_with_descriptor(self):
1282 class descriptor(object):
1283 def __get__(self, instance, owner):
1284 return 3
1285 class meta(type):
1286 d = descriptor()
1287 class Thing(object, metaclass=meta):
1288 pass
1289 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1290
1291
Michael Foordcc7ebb82010-11-20 16:20:16 +00001292 def test_class_as_property(self):
1293 class Base(object):
1294 foo = 3
1295
1296 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001297 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001298 @property
1299 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001300 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001301 return object
1302
Michael Foord35184ed2010-11-20 16:58:30 +00001303 instance = Something()
1304 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1305 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001306 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1307
Michael Foorde5162652010-11-20 16:40:44 +00001308 def test_mro_as_property(self):
1309 class Meta(type):
1310 @property
1311 def __mro__(self):
1312 return (object,)
1313
1314 class Base(object):
1315 foo = 3
1316
1317 class Something(Base, metaclass=Meta):
1318 pass
1319
1320 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1321 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1322
Michael Foorddcebe0f2011-03-15 19:20:44 -04001323 def test_dict_as_property(self):
1324 test = self
1325 test.called = False
1326
1327 class Foo(dict):
1328 a = 3
1329 @property
1330 def __dict__(self):
1331 test.called = True
1332 return {}
1333
1334 foo = Foo()
1335 foo.a = 4
1336 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1337 self.assertFalse(test.called)
1338
1339 def test_custom_object_dict(self):
1340 test = self
1341 test.called = False
1342
1343 class Custom(dict):
1344 def get(self, key, default=None):
1345 test.called = True
1346 super().get(key, default)
1347
1348 class Foo(object):
1349 a = 3
1350 foo = Foo()
1351 foo.__dict__ = Custom()
1352 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1353 self.assertFalse(test.called)
1354
1355 def test_metaclass_dict_as_property(self):
1356 class Meta(type):
1357 @property
1358 def __dict__(self):
1359 self.executed = True
1360
1361 class Thing(metaclass=Meta):
1362 executed = False
1363
1364 def __init__(self):
1365 self.spam = 42
1366
1367 instance = Thing()
1368 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1369 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001370
Michael Foorda51623b2011-12-18 22:01:40 +00001371 def test_module(self):
1372 sentinel = object()
1373 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1374 sentinel)
1375
Michael Foord3ba95f82011-12-22 01:13:37 +00001376 def test_metaclass_with_metaclass_with_dict_as_property(self):
1377 class MetaMeta(type):
1378 @property
1379 def __dict__(self):
1380 self.executed = True
1381 return dict(spam=42)
1382
1383 class Meta(type, metaclass=MetaMeta):
1384 executed = False
1385
1386 class Thing(metaclass=Meta):
1387 pass
1388
1389 with self.assertRaises(AttributeError):
1390 inspect.getattr_static(Thing, "spam")
1391 self.assertFalse(Thing.executed)
1392
Nick Coghlane0f04652010-11-21 03:44:04 +00001393class TestGetGeneratorState(unittest.TestCase):
1394
1395 def setUp(self):
1396 def number_generator():
1397 for number in range(5):
1398 yield number
1399 self.generator = number_generator()
1400
1401 def _generatorstate(self):
1402 return inspect.getgeneratorstate(self.generator)
1403
1404 def test_created(self):
1405 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1406
1407 def test_suspended(self):
1408 next(self.generator)
1409 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1410
1411 def test_closed_after_exhaustion(self):
1412 for i in self.generator:
1413 pass
1414 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1415
1416 def test_closed_after_immediate_exception(self):
1417 with self.assertRaises(RuntimeError):
1418 self.generator.throw(RuntimeError)
1419 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1420
1421 def test_running(self):
1422 # As mentioned on issue #10220, checking for the RUNNING state only
1423 # makes sense inside the generator itself.
1424 # The following generator checks for this by using the closure's
1425 # reference to self and the generator state checking helper method
1426 def running_check_generator():
1427 for number in range(5):
1428 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1429 yield number
1430 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1431 self.generator = running_check_generator()
1432 # Running up to the first yield
1433 next(self.generator)
1434 # Running after the first yield
1435 next(self.generator)
1436
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001437 def test_easy_debugging(self):
1438 # repr() and str() of a generator state should contain the state name
1439 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1440 for name in names:
1441 state = getattr(inspect, name)
1442 self.assertIn(name, repr(state))
1443 self.assertIn(name, str(state))
1444
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001445 def test_getgeneratorlocals(self):
1446 def each(lst, a=None):
1447 b=(1, 2, 3)
1448 for v in lst:
1449 if v == 3:
1450 c = 12
1451 yield v
1452
1453 numbers = each([1, 2, 3])
1454 self.assertEqual(inspect.getgeneratorlocals(numbers),
1455 {'a': None, 'lst': [1, 2, 3]})
1456 next(numbers)
1457 self.assertEqual(inspect.getgeneratorlocals(numbers),
1458 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1459 'b': (1, 2, 3)})
1460 next(numbers)
1461 self.assertEqual(inspect.getgeneratorlocals(numbers),
1462 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1463 'b': (1, 2, 3)})
1464 next(numbers)
1465 self.assertEqual(inspect.getgeneratorlocals(numbers),
1466 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1467 'b': (1, 2, 3), 'c': 12})
1468 try:
1469 next(numbers)
1470 except StopIteration:
1471 pass
1472 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1473
1474 def test_getgeneratorlocals_empty(self):
1475 def yield_one():
1476 yield 1
1477 one = yield_one()
1478 self.assertEqual(inspect.getgeneratorlocals(one), {})
1479 try:
1480 next(one)
1481 except StopIteration:
1482 pass
1483 self.assertEqual(inspect.getgeneratorlocals(one), {})
1484
1485 def test_getgeneratorlocals_error(self):
1486 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1487 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1488 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1489 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1490
Nick Coghlane0f04652010-11-21 03:44:04 +00001491
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001492class TestSignatureObject(unittest.TestCase):
1493 @staticmethod
1494 def signature(func):
1495 sig = inspect.signature(func)
1496 return (tuple((param.name,
1497 (... if param.default is param.empty else param.default),
1498 (... if param.annotation is param.empty
1499 else param.annotation),
1500 str(param.kind).lower())
1501 for param in sig.parameters.values()),
1502 (... if sig.return_annotation is sig.empty
1503 else sig.return_annotation))
1504
1505 def test_signature_object(self):
1506 S = inspect.Signature
1507 P = inspect.Parameter
1508
1509 self.assertEqual(str(S()), '()')
1510
1511 def test(po, pk, *args, ko, **kwargs):
1512 pass
1513 sig = inspect.signature(test)
1514 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
1515 pk = sig.parameters['pk']
1516 args = sig.parameters['args']
1517 ko = sig.parameters['ko']
1518 kwargs = sig.parameters['kwargs']
1519
1520 S((po, pk, args, ko, kwargs))
1521
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001522 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001523 S((pk, po, args, ko, kwargs))
1524
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001525 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001526 S((po, args, pk, ko, kwargs))
1527
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001528 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001529 S((args, po, pk, ko, kwargs))
1530
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001531 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001532 S((po, pk, args, kwargs, ko))
1533
1534 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001535 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001536 S((po, pk, args, kwargs2, ko))
1537
1538 def test_signature_immutability(self):
1539 def test(a):
1540 pass
1541 sig = inspect.signature(test)
1542
1543 with self.assertRaises(AttributeError):
1544 sig.foo = 'bar'
1545
1546 with self.assertRaises(TypeError):
1547 sig.parameters['a'] = None
1548
1549 def test_signature_on_noarg(self):
1550 def test():
1551 pass
1552 self.assertEqual(self.signature(test), ((), ...))
1553
1554 def test_signature_on_wargs(self):
1555 def test(a, b:'foo') -> 123:
1556 pass
1557 self.assertEqual(self.signature(test),
1558 ((('a', ..., ..., "positional_or_keyword"),
1559 ('b', ..., 'foo', "positional_or_keyword")),
1560 123))
1561
1562 def test_signature_on_wkwonly(self):
1563 def test(*, a:float, b:str) -> int:
1564 pass
1565 self.assertEqual(self.signature(test),
1566 ((('a', ..., float, "keyword_only"),
1567 ('b', ..., str, "keyword_only")),
1568 int))
1569
1570 def test_signature_on_complex_args(self):
1571 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1572 pass
1573 self.assertEqual(self.signature(test),
1574 ((('a', ..., ..., "positional_or_keyword"),
1575 ('b', 10, 'foo', "positional_or_keyword"),
1576 ('args', ..., 'bar', "var_positional"),
1577 ('spam', ..., 'baz', "keyword_only"),
1578 ('ham', 123, ..., "keyword_only"),
1579 ('kwargs', ..., int, "var_keyword")),
1580 ...))
1581
1582 def test_signature_on_builtin_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001583 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001584 inspect.signature(type)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001585 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001586 # support for 'wrapper_descriptor'
1587 inspect.signature(type.__call__)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001588 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001589 # support for 'method-wrapper'
1590 inspect.signature(min.__call__)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001591 with self.assertRaisesRegex(ValueError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001592 'no signature found for builtin function'):
1593 # support for 'method-wrapper'
1594 inspect.signature(min)
1595
1596 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001597 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001598 inspect.signature(42)
1599
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001600 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001601 inspect.Signature.from_function(42)
1602
1603 def test_signature_on_method(self):
1604 class Test:
1605 def foo(self, arg1, arg2=1) -> int:
1606 pass
1607
1608 meth = Test().foo
1609
1610 self.assertEqual(self.signature(meth),
1611 ((('arg1', ..., ..., "positional_or_keyword"),
1612 ('arg2', 1, ..., "positional_or_keyword")),
1613 int))
1614
1615 def test_signature_on_classmethod(self):
1616 class Test:
1617 @classmethod
1618 def foo(cls, arg1, *, arg2=1):
1619 pass
1620
1621 meth = Test().foo
1622 self.assertEqual(self.signature(meth),
1623 ((('arg1', ..., ..., "positional_or_keyword"),
1624 ('arg2', 1, ..., "keyword_only")),
1625 ...))
1626
1627 meth = Test.foo
1628 self.assertEqual(self.signature(meth),
1629 ((('arg1', ..., ..., "positional_or_keyword"),
1630 ('arg2', 1, ..., "keyword_only")),
1631 ...))
1632
1633 def test_signature_on_staticmethod(self):
1634 class Test:
1635 @staticmethod
1636 def foo(cls, *, arg):
1637 pass
1638
1639 meth = Test().foo
1640 self.assertEqual(self.signature(meth),
1641 ((('cls', ..., ..., "positional_or_keyword"),
1642 ('arg', ..., ..., "keyword_only")),
1643 ...))
1644
1645 meth = Test.foo
1646 self.assertEqual(self.signature(meth),
1647 ((('cls', ..., ..., "positional_or_keyword"),
1648 ('arg', ..., ..., "keyword_only")),
1649 ...))
1650
1651 def test_signature_on_partial(self):
1652 from functools import partial
1653
1654 def test():
1655 pass
1656
1657 self.assertEqual(self.signature(partial(test)), ((), ...))
1658
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001659 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001660 inspect.signature(partial(test, 1))
1661
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001662 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001663 inspect.signature(partial(test, a=1))
1664
1665 def test(a, b, *, c, d):
1666 pass
1667
1668 self.assertEqual(self.signature(partial(test)),
1669 ((('a', ..., ..., "positional_or_keyword"),
1670 ('b', ..., ..., "positional_or_keyword"),
1671 ('c', ..., ..., "keyword_only"),
1672 ('d', ..., ..., "keyword_only")),
1673 ...))
1674
1675 self.assertEqual(self.signature(partial(test, 1)),
1676 ((('b', ..., ..., "positional_or_keyword"),
1677 ('c', ..., ..., "keyword_only"),
1678 ('d', ..., ..., "keyword_only")),
1679 ...))
1680
1681 self.assertEqual(self.signature(partial(test, 1, c=2)),
1682 ((('b', ..., ..., "positional_or_keyword"),
1683 ('c', 2, ..., "keyword_only"),
1684 ('d', ..., ..., "keyword_only")),
1685 ...))
1686
1687 self.assertEqual(self.signature(partial(test, b=1, c=2)),
1688 ((('a', ..., ..., "positional_or_keyword"),
1689 ('b', 1, ..., "positional_or_keyword"),
1690 ('c', 2, ..., "keyword_only"),
1691 ('d', ..., ..., "keyword_only")),
1692 ...))
1693
1694 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
1695 ((('b', 1, ..., "positional_or_keyword"),
1696 ('c', 2, ..., "keyword_only"),
1697 ('d', ..., ..., "keyword_only"),),
1698 ...))
1699
1700 def test(a, *args, b, **kwargs):
1701 pass
1702
1703 self.assertEqual(self.signature(partial(test, 1)),
1704 ((('args', ..., ..., "var_positional"),
1705 ('b', ..., ..., "keyword_only"),
1706 ('kwargs', ..., ..., "var_keyword")),
1707 ...))
1708
1709 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
1710 ((('args', ..., ..., "var_positional"),
1711 ('b', ..., ..., "keyword_only"),
1712 ('kwargs', ..., ..., "var_keyword")),
1713 ...))
1714
1715
1716 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
1717 ((('args', ..., ..., "var_positional"),
1718 ('b', ..., ..., "keyword_only"),
1719 ('kwargs', ..., ..., "var_keyword")),
1720 ...))
1721
1722 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
1723 ((('args', ..., ..., "var_positional"),
1724 ('b', 0, ..., "keyword_only"),
1725 ('kwargs', ..., ..., "var_keyword")),
1726 ...))
1727
1728 self.assertEqual(self.signature(partial(test, b=0)),
1729 ((('a', ..., ..., "positional_or_keyword"),
1730 ('args', ..., ..., "var_positional"),
1731 ('b', 0, ..., "keyword_only"),
1732 ('kwargs', ..., ..., "var_keyword")),
1733 ...))
1734
1735 self.assertEqual(self.signature(partial(test, b=0, test=1)),
1736 ((('a', ..., ..., "positional_or_keyword"),
1737 ('args', ..., ..., "var_positional"),
1738 ('b', 0, ..., "keyword_only"),
1739 ('kwargs', ..., ..., "var_keyword")),
1740 ...))
1741
1742 def test(a, b, c:int) -> 42:
1743 pass
1744
1745 sig = test.__signature__ = inspect.signature(test)
1746
1747 self.assertEqual(self.signature(partial(partial(test, 1))),
1748 ((('b', ..., ..., "positional_or_keyword"),
1749 ('c', ..., int, "positional_or_keyword")),
1750 42))
1751
1752 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
1753 ((('c', ..., int, "positional_or_keyword"),),
1754 42))
1755
1756 psig = inspect.signature(partial(partial(test, 1), 2))
1757
1758 def foo(a):
1759 return a
1760 _foo = partial(partial(foo, a=10), a=20)
1761 self.assertEqual(self.signature(_foo),
1762 ((('a', 20, ..., "positional_or_keyword"),),
1763 ...))
1764 # check that we don't have any side-effects in signature(),
1765 # and the partial object is still functioning
1766 self.assertEqual(_foo(), 20)
1767
1768 def foo(a, b, c):
1769 return a, b, c
1770 _foo = partial(partial(foo, 1, b=20), b=30)
1771 self.assertEqual(self.signature(_foo),
1772 ((('b', 30, ..., "positional_or_keyword"),
1773 ('c', ..., ..., "positional_or_keyword")),
1774 ...))
1775 self.assertEqual(_foo(c=10), (1, 30, 10))
1776 _foo = partial(_foo, 2) # now 'b' has two values -
1777 # positional and keyword
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001778 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001779 inspect.signature(_foo)
1780
1781 def foo(a, b, c, *, d):
1782 return a, b, c, d
1783 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
1784 self.assertEqual(self.signature(_foo),
1785 ((('a', ..., ..., "positional_or_keyword"),
1786 ('b', 10, ..., "positional_or_keyword"),
1787 ('c', 20, ..., "positional_or_keyword"),
1788 ('d', 30, ..., "keyword_only")),
1789 ...))
1790 ba = inspect.signature(_foo).bind(a=200, b=11)
1791 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
1792
1793 def foo(a=1, b=2, c=3):
1794 return a, b, c
1795 _foo = partial(foo, a=10, c=13)
1796 ba = inspect.signature(_foo).bind(11)
1797 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
1798 ba = inspect.signature(_foo).bind(11, 12)
1799 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
1800 ba = inspect.signature(_foo).bind(11, b=12)
1801 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
1802 ba = inspect.signature(_foo).bind(b=12)
1803 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
1804 _foo = partial(_foo, b=10)
1805 ba = inspect.signature(_foo).bind(12, 14)
1806 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
1807
1808 def test_signature_on_decorated(self):
1809 import functools
1810
1811 def decorator(func):
1812 @functools.wraps(func)
1813 def wrapper(*args, **kwargs) -> int:
1814 return func(*args, **kwargs)
1815 return wrapper
1816
1817 class Foo:
1818 @decorator
1819 def bar(self, a, b):
1820 pass
1821
1822 self.assertEqual(self.signature(Foo.bar),
1823 ((('self', ..., ..., "positional_or_keyword"),
1824 ('a', ..., ..., "positional_or_keyword"),
1825 ('b', ..., ..., "positional_or_keyword")),
1826 ...))
1827
1828 self.assertEqual(self.signature(Foo().bar),
1829 ((('a', ..., ..., "positional_or_keyword"),
1830 ('b', ..., ..., "positional_or_keyword")),
1831 ...))
1832
1833 # Test that we handle method wrappers correctly
1834 def decorator(func):
1835 @functools.wraps(func)
1836 def wrapper(*args, **kwargs) -> int:
1837 return func(42, *args, **kwargs)
1838 sig = inspect.signature(func)
1839 new_params = tuple(sig.parameters.values())[1:]
1840 wrapper.__signature__ = sig.replace(parameters=new_params)
1841 return wrapper
1842
1843 class Foo:
1844 @decorator
1845 def __call__(self, a, b):
1846 pass
1847
1848 self.assertEqual(self.signature(Foo.__call__),
1849 ((('a', ..., ..., "positional_or_keyword"),
1850 ('b', ..., ..., "positional_or_keyword")),
1851 ...))
1852
1853 self.assertEqual(self.signature(Foo().__call__),
1854 ((('b', ..., ..., "positional_or_keyword"),),
1855 ...))
1856
Nick Coghlane8c45d62013-07-28 20:00:01 +10001857 # Test we handle __signature__ partway down the wrapper stack
1858 def wrapped_foo_call():
1859 pass
1860 wrapped_foo_call.__wrapped__ = Foo.__call__
1861
1862 self.assertEqual(self.signature(wrapped_foo_call),
1863 ((('a', ..., ..., "positional_or_keyword"),
1864 ('b', ..., ..., "positional_or_keyword")),
1865 ...))
1866
1867
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001868 def test_signature_on_class(self):
1869 class C:
1870 def __init__(self, a):
1871 pass
1872
1873 self.assertEqual(self.signature(C),
1874 ((('a', ..., ..., "positional_or_keyword"),),
1875 ...))
1876
1877 class CM(type):
1878 def __call__(cls, a):
1879 pass
1880 class C(metaclass=CM):
1881 def __init__(self, b):
1882 pass
1883
1884 self.assertEqual(self.signature(C),
1885 ((('a', ..., ..., "positional_or_keyword"),),
1886 ...))
1887
1888 class CM(type):
1889 def __new__(mcls, name, bases, dct, *, foo=1):
1890 return super().__new__(mcls, name, bases, dct)
1891 class C(metaclass=CM):
1892 def __init__(self, b):
1893 pass
1894
1895 self.assertEqual(self.signature(C),
1896 ((('b', ..., ..., "positional_or_keyword"),),
1897 ...))
1898
1899 self.assertEqual(self.signature(CM),
1900 ((('name', ..., ..., "positional_or_keyword"),
1901 ('bases', ..., ..., "positional_or_keyword"),
1902 ('dct', ..., ..., "positional_or_keyword"),
1903 ('foo', 1, ..., "keyword_only")),
1904 ...))
1905
1906 class CMM(type):
1907 def __new__(mcls, name, bases, dct, *, foo=1):
1908 return super().__new__(mcls, name, bases, dct)
1909 def __call__(cls, nm, bs, dt):
1910 return type(nm, bs, dt)
1911 class CM(type, metaclass=CMM):
1912 def __new__(mcls, name, bases, dct, *, bar=2):
1913 return super().__new__(mcls, name, bases, dct)
1914 class C(metaclass=CM):
1915 def __init__(self, b):
1916 pass
1917
1918 self.assertEqual(self.signature(CMM),
1919 ((('name', ..., ..., "positional_or_keyword"),
1920 ('bases', ..., ..., "positional_or_keyword"),
1921 ('dct', ..., ..., "positional_or_keyword"),
1922 ('foo', 1, ..., "keyword_only")),
1923 ...))
1924
1925 self.assertEqual(self.signature(CM),
1926 ((('nm', ..., ..., "positional_or_keyword"),
1927 ('bs', ..., ..., "positional_or_keyword"),
1928 ('dt', ..., ..., "positional_or_keyword")),
1929 ...))
1930
1931 self.assertEqual(self.signature(C),
1932 ((('b', ..., ..., "positional_or_keyword"),),
1933 ...))
1934
1935 class CM(type):
1936 def __init__(cls, name, bases, dct, *, bar=2):
1937 return super().__init__(name, bases, dct)
1938 class C(metaclass=CM):
1939 def __init__(self, b):
1940 pass
1941
1942 self.assertEqual(self.signature(CM),
1943 ((('name', ..., ..., "positional_or_keyword"),
1944 ('bases', ..., ..., "positional_or_keyword"),
1945 ('dct', ..., ..., "positional_or_keyword"),
1946 ('bar', 2, ..., "keyword_only")),
1947 ...))
1948
1949 def test_signature_on_callable_objects(self):
1950 class Foo:
1951 def __call__(self, a):
1952 pass
1953
1954 self.assertEqual(self.signature(Foo()),
1955 ((('a', ..., ..., "positional_or_keyword"),),
1956 ...))
1957
1958 class Spam:
1959 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001960 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001961 inspect.signature(Spam())
1962
1963 class Bar(Spam, Foo):
1964 pass
1965
1966 self.assertEqual(self.signature(Bar()),
1967 ((('a', ..., ..., "positional_or_keyword"),),
1968 ...))
1969
1970 class ToFail:
1971 __call__ = type
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001972 with self.assertRaisesRegex(ValueError, "not supported by signature"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001973 inspect.signature(ToFail())
1974
1975
1976 class Wrapped:
1977 pass
1978 Wrapped.__wrapped__ = lambda a: None
1979 self.assertEqual(self.signature(Wrapped),
1980 ((('a', ..., ..., "positional_or_keyword"),),
1981 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10001982 # wrapper loop:
1983 Wrapped.__wrapped__ = Wrapped
1984 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
1985 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001986
1987 def test_signature_on_lambdas(self):
1988 self.assertEqual(self.signature((lambda a=10: a)),
1989 ((('a', 10, ..., "positional_or_keyword"),),
1990 ...))
1991
1992 def test_signature_equality(self):
1993 def foo(a, *, b:int) -> float: pass
1994 self.assertNotEqual(inspect.signature(foo), 42)
1995
1996 def bar(a, *, b:int) -> float: pass
1997 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1998
1999 def bar(a, *, b:int) -> int: pass
2000 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2001
2002 def bar(a, *, b:int): pass
2003 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2004
2005 def bar(a, *, b:int=42) -> float: pass
2006 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2007
2008 def bar(a, *, c) -> float: pass
2009 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2010
2011 def bar(a, b:int) -> float: pass
2012 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2013 def spam(b:int, a) -> float: pass
2014 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
2015
2016 def foo(*, a, b, c): pass
2017 def bar(*, c, b, a): pass
2018 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2019
2020 def foo(*, a=1, b, c): pass
2021 def bar(*, c, b, a=1): pass
2022 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2023
2024 def foo(pos, *, a=1, b, c): pass
2025 def bar(pos, *, c, b, a=1): pass
2026 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2027
2028 def foo(pos, *, a, b, c): pass
2029 def bar(pos, *, c, b, a=1): pass
2030 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2031
2032 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2033 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2034 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2035
2036 def test_signature_unhashable(self):
2037 def foo(a): pass
2038 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002039 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002040 hash(sig)
2041
2042 def test_signature_str(self):
2043 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2044 pass
2045 self.assertEqual(str(inspect.signature(foo)),
2046 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2047
2048 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2049 pass
2050 self.assertEqual(str(inspect.signature(foo)),
2051 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2052
2053 def foo():
2054 pass
2055 self.assertEqual(str(inspect.signature(foo)), '()')
2056
2057 def test_signature_str_positional_only(self):
2058 P = inspect.Parameter
2059
2060 def test(a_po, *, b, **kwargs):
2061 return a_po, kwargs
2062
2063 sig = inspect.signature(test)
2064 new_params = list(sig.parameters.values())
2065 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2066 test.__signature__ = sig.replace(parameters=new_params)
2067
2068 self.assertEqual(str(inspect.signature(test)),
2069 '(<a_po>, *, b, **kwargs)')
2070
2071 sig = inspect.signature(test)
2072 new_params = list(sig.parameters.values())
2073 new_params[0] = new_params[0].replace(name=None)
2074 test.__signature__ = sig.replace(parameters=new_params)
2075 self.assertEqual(str(inspect.signature(test)),
2076 '(<0>, *, b, **kwargs)')
2077
2078 def test_signature_replace_anno(self):
2079 def test() -> 42:
2080 pass
2081
2082 sig = inspect.signature(test)
2083 sig = sig.replace(return_annotation=None)
2084 self.assertIs(sig.return_annotation, None)
2085 sig = sig.replace(return_annotation=sig.empty)
2086 self.assertIs(sig.return_annotation, sig.empty)
2087 sig = sig.replace(return_annotation=42)
2088 self.assertEqual(sig.return_annotation, 42)
2089 self.assertEqual(sig, inspect.signature(test))
2090
2091
2092class TestParameterObject(unittest.TestCase):
2093 def test_signature_parameter_kinds(self):
2094 P = inspect.Parameter
2095 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2096 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2097
2098 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2099 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2100
2101 def test_signature_parameter_object(self):
2102 p = inspect.Parameter('foo', default=10,
2103 kind=inspect.Parameter.POSITIONAL_ONLY)
2104 self.assertEqual(p.name, 'foo')
2105 self.assertEqual(p.default, 10)
2106 self.assertIs(p.annotation, p.empty)
2107 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2108
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002109 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002110 inspect.Parameter('foo', default=10, kind='123')
2111
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002112 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002113 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2114
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002115 with self.assertRaisesRegex(ValueError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002116 'non-positional-only parameter'):
2117 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2118
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002119 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002120 inspect.Parameter('a', default=42,
2121 kind=inspect.Parameter.VAR_KEYWORD)
2122
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002123 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002124 inspect.Parameter('a', default=42,
2125 kind=inspect.Parameter.VAR_POSITIONAL)
2126
2127 p = inspect.Parameter('a', default=42,
2128 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002129 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002130 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2131
2132 self.assertTrue(repr(p).startswith('<Parameter'))
2133
2134 def test_signature_parameter_equality(self):
2135 P = inspect.Parameter
2136 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2137
2138 self.assertEqual(p, p)
2139 self.assertNotEqual(p, 42)
2140
2141 self.assertEqual(p, P('foo', default=42,
2142 kind=inspect.Parameter.KEYWORD_ONLY))
2143
2144 def test_signature_parameter_unhashable(self):
2145 p = inspect.Parameter('foo', default=42,
2146 kind=inspect.Parameter.KEYWORD_ONLY)
2147
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002148 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002149 hash(p)
2150
2151 def test_signature_parameter_replace(self):
2152 p = inspect.Parameter('foo', default=42,
2153 kind=inspect.Parameter.KEYWORD_ONLY)
2154
2155 self.assertIsNot(p, p.replace())
2156 self.assertEqual(p, p.replace())
2157
2158 p2 = p.replace(annotation=1)
2159 self.assertEqual(p2.annotation, 1)
2160 p2 = p2.replace(annotation=p2.empty)
2161 self.assertEqual(p, p2)
2162
2163 p2 = p2.replace(name='bar')
2164 self.assertEqual(p2.name, 'bar')
2165 self.assertNotEqual(p2, p)
2166
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002167 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002168 p2 = p2.replace(name=p2.empty)
2169
2170 p2 = p2.replace(name='foo', default=None)
2171 self.assertIs(p2.default, None)
2172 self.assertNotEqual(p2, p)
2173
2174 p2 = p2.replace(name='foo', default=p2.empty)
2175 self.assertIs(p2.default, p2.empty)
2176
2177
2178 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2179 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2180 self.assertNotEqual(p2, p)
2181
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002182 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002183 p2 = p2.replace(kind=p2.empty)
2184
2185 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2186 self.assertEqual(p2, p)
2187
2188 def test_signature_parameter_positional_only(self):
2189 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
2190 self.assertEqual(str(p), '<>')
2191
2192 p = p.replace(name='1')
2193 self.assertEqual(str(p), '<1>')
2194
2195 def test_signature_parameter_immutability(self):
2196 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
2197
2198 with self.assertRaises(AttributeError):
2199 p.foo = 'bar'
2200
2201 with self.assertRaises(AttributeError):
2202 p.kind = 123
2203
2204
2205class TestSignatureBind(unittest.TestCase):
2206 @staticmethod
2207 def call(func, *args, **kwargs):
2208 sig = inspect.signature(func)
2209 ba = sig.bind(*args, **kwargs)
2210 return func(*ba.args, **ba.kwargs)
2211
2212 def test_signature_bind_empty(self):
2213 def test():
2214 return 42
2215
2216 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002217 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002218 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002219 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002220 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002221 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002222 self.call(test, spam=1)
2223
2224 def test_signature_bind_var(self):
2225 def test(*args, **kwargs):
2226 return args, kwargs
2227
2228 self.assertEqual(self.call(test), ((), {}))
2229 self.assertEqual(self.call(test, 1), ((1,), {}))
2230 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2231 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2232 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2233 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2234 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2235 ((1, 2), {'foo': 'bar'}))
2236
2237 def test_signature_bind_just_args(self):
2238 def test(a, b, c):
2239 return a, b, c
2240
2241 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2242
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002243 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002244 self.call(test, 1, 2, 3, 4)
2245
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002246 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002247 self.call(test, 1)
2248
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002249 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002250 self.call(test)
2251
2252 def test(a, b, c=10):
2253 return a, b, c
2254 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2255 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2256
2257 def test(a=1, b=2, c=3):
2258 return a, b, c
2259 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2260 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2261 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2262
2263 def test_signature_bind_varargs_order(self):
2264 def test(*args):
2265 return args
2266
2267 self.assertEqual(self.call(test), ())
2268 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2269
2270 def test_signature_bind_args_and_varargs(self):
2271 def test(a, b, c=3, *args):
2272 return a, b, c, args
2273
2274 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2275 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2276 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2277 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2278
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002279 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002280 "multiple values for argument 'c'"):
2281 self.call(test, 1, 2, 3, c=4)
2282
2283 def test_signature_bind_just_kwargs(self):
2284 def test(**kwargs):
2285 return kwargs
2286
2287 self.assertEqual(self.call(test), {})
2288 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2289 {'foo': 'bar', 'spam': 'ham'})
2290
2291 def test_signature_bind_args_and_kwargs(self):
2292 def test(a, b, c=3, **kwargs):
2293 return a, b, c, kwargs
2294
2295 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2296 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2297 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2298 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2299 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2300 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2301 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2302 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2303 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2304 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2305 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2306 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2307 (1, 2, 4, {'foo': 'bar'}))
2308 self.assertEqual(self.call(test, c=5, a=4, b=3),
2309 (4, 3, 5, {}))
2310
2311 def test_signature_bind_kwonly(self):
2312 def test(*, foo):
2313 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002314 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002315 'too many positional arguments'):
2316 self.call(test, 1)
2317 self.assertEqual(self.call(test, foo=1), 1)
2318
2319 def test(a, *, foo=1, bar):
2320 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002321 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002322 "'bar' parameter lacking default value"):
2323 self.call(test, 1)
2324
2325 def test(foo, *, bar):
2326 return foo, bar
2327 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2328 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2329
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002330 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002331 'too many keyword arguments'):
2332 self.call(test, bar=2, foo=1, spam=10)
2333
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002334 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002335 'too many positional arguments'):
2336 self.call(test, 1, 2)
2337
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002338 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002339 'too many positional arguments'):
2340 self.call(test, 1, 2, bar=2)
2341
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002342 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002343 'too many keyword arguments'):
2344 self.call(test, 1, bar=2, spam='ham')
2345
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002346 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002347 "'bar' parameter lacking default value"):
2348 self.call(test, 1)
2349
2350 def test(foo, *, bar, **bin):
2351 return foo, bar, bin
2352 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2353 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2354 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2355 (1, 2, {'spam': 'ham'}))
2356 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2357 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002358 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002359 "'foo' parameter lacking default value"):
2360 self.call(test, spam='ham', bar=2)
2361 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2362 (1, 2, {'bin': 1, 'spam': 10}))
2363
2364 def test_signature_bind_arguments(self):
2365 def test(a, *args, b, z=100, **kwargs):
2366 pass
2367 sig = inspect.signature(test)
2368 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2369 # we won't have 'z' argument in the bound arguments object, as we didn't
2370 # pass it to the 'bind'
2371 self.assertEqual(tuple(ba.arguments.items()),
2372 (('a', 10), ('args', (20,)), ('b', 30),
2373 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2374 self.assertEqual(ba.kwargs,
2375 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2376 self.assertEqual(ba.args, (10, 20))
2377
2378 def test_signature_bind_positional_only(self):
2379 P = inspect.Parameter
2380
2381 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2382 return a_po, b_po, c_po, foo, bar, kwargs
2383
2384 sig = inspect.signature(test)
2385 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2386 for name in ('a_po', 'b_po', 'c_po'):
2387 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2388 new_sig = sig.replace(parameters=new_params.values())
2389 test.__signature__ = new_sig
2390
2391 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2392 (1, 2, 4, 5, 6, {}))
2393
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002394 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002395 self.call(test, 1, 2, c_po=4)
2396
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002397 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002398 self.call(test, a_po=1, b_po=2)
2399
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002400 def test_signature_bind_with_self_arg(self):
2401 # Issue #17071: one of the parameters is named "self
2402 def test(a, self, b):
2403 pass
2404 sig = inspect.signature(test)
2405 ba = sig.bind(1, 2, 3)
2406 self.assertEqual(ba.args, (1, 2, 3))
2407 ba = sig.bind(1, self=2, b=3)
2408 self.assertEqual(ba.args, (1, 2, 3))
2409
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002410
2411class TestBoundArguments(unittest.TestCase):
2412 def test_signature_bound_arguments_unhashable(self):
2413 def foo(a): pass
2414 ba = inspect.signature(foo).bind(1)
2415
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002416 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002417 hash(ba)
2418
2419 def test_signature_bound_arguments_equality(self):
2420 def foo(a): pass
2421 ba = inspect.signature(foo).bind(1)
2422 self.assertEqual(ba, ba)
2423
2424 ba2 = inspect.signature(foo).bind(1)
2425 self.assertEqual(ba, ba2)
2426
2427 ba3 = inspect.signature(foo).bind(2)
2428 self.assertNotEqual(ba, ba3)
2429 ba3.arguments['a'] = 1
2430 self.assertEqual(ba, ba3)
2431
2432 def bar(b): pass
2433 ba4 = inspect.signature(bar).bind(1)
2434 self.assertNotEqual(ba, ba4)
2435
2436
Nick Coghlane8c45d62013-07-28 20:00:01 +10002437class TestUnwrap(unittest.TestCase):
2438
2439 def test_unwrap_one(self):
2440 def func(a, b):
2441 return a + b
2442 wrapper = functools.lru_cache(maxsize=20)(func)
2443 self.assertIs(inspect.unwrap(wrapper), func)
2444
2445 def test_unwrap_several(self):
2446 def func(a, b):
2447 return a + b
2448 wrapper = func
2449 for __ in range(10):
2450 @functools.wraps(wrapper)
2451 def wrapper():
2452 pass
2453 self.assertIsNot(wrapper.__wrapped__, func)
2454 self.assertIs(inspect.unwrap(wrapper), func)
2455
2456 def test_stop(self):
2457 def func1(a, b):
2458 return a + b
2459 @functools.wraps(func1)
2460 def func2():
2461 pass
2462 @functools.wraps(func2)
2463 def wrapper():
2464 pass
2465 func2.stop_here = 1
2466 unwrapped = inspect.unwrap(wrapper,
2467 stop=(lambda f: hasattr(f, "stop_here")))
2468 self.assertIs(unwrapped, func2)
2469
2470 def test_cycle(self):
2471 def func1(): pass
2472 func1.__wrapped__ = func1
2473 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2474 inspect.unwrap(func1)
2475
2476 def func2(): pass
2477 func2.__wrapped__ = func1
2478 func1.__wrapped__ = func2
2479 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2480 inspect.unwrap(func1)
2481 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2482 inspect.unwrap(func2)
2483
2484 def test_unhashable(self):
2485 def func(): pass
2486 func.__wrapped__ = None
2487 class C:
2488 __hash__ = None
2489 __wrapped__ = func
2490 self.assertIsNone(inspect.unwrap(C()))
2491
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002492class TestMain(unittest.TestCase):
2493 def test_only_source(self):
2494 module = importlib.import_module('unittest')
2495 rc, out, err = assert_python_ok('-m', 'inspect',
2496 'unittest')
2497 lines = out.decode().splitlines()
2498 # ignore the final newline
2499 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
2500 self.assertEqual(err, b'')
2501
Brett Cannon634a8fc2013-10-02 10:25:42 -04002502 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04002503 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002504 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002505 rc, out, err = assert_python_ok('-m', 'inspect',
2506 'concurrent.futures:ThreadPoolExecutor')
2507 lines = out.decode().splitlines()
2508 # ignore the final newline
2509 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04002510 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002511 self.assertEqual(err, b'')
2512
2513 def test_builtins(self):
2514 module = importlib.import_module('unittest')
2515 _, out, err = assert_python_failure('-m', 'inspect',
2516 'sys')
2517 lines = err.decode().splitlines()
2518 self.assertEqual(lines, ["Can't get info for builtin modules."])
2519
2520 def test_details(self):
2521 module = importlib.import_module('unittest')
2522 rc, out, err = assert_python_ok('-m', 'inspect',
2523 'unittest', '--details')
2524 output = out.decode()
2525 # Just a quick sanity check on the output
2526 self.assertIn(module.__name__, output)
2527 self.assertIn(module.__file__, output)
2528 self.assertIn(module.__cached__, output)
2529 self.assertEqual(err, b'')
2530
2531
2532
Nick Coghlane8c45d62013-07-28 20:00:01 +10002533
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002534def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00002535 run_unittest(
2536 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
2537 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
2538 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00002539 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002540 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002541 TestBoundArguments, TestGetClosureVars, TestUnwrap, TestMain
Michael Foord95fc51d2010-11-20 15:07:30 +00002542 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00002543
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002544if __name__ == "__main__":
2545 test_main()