blob: 22c2be861c1f0df96396828ddddf61f6c7da75c3 [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
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000014
Alexander Belopolskyf546e702010-12-02 00:10:11 +000015from test.support import run_unittest, TESTFN, DirsOnSysPath
Nick Coghlanf94a16b2013-09-22 22:46:49 +100016from test.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000017from test import inspect_fodder as mod
18from test import inspect_fodder2 as mod2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000019
R. David Murray74b89242009-05-13 17:33:03 +000020# C module for test_findsource_binary
R. David Murrayb5655772009-05-14 16:17:50 +000021import unicodedata
R. David Murray74b89242009-05-13 17:33:03 +000022
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000023# Functions tested in this suite:
24# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000025# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
26# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
27# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
28# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000029
Nick Coghlanf088e5e2008-12-14 11:50:48 +000030# NOTE: There are some additional tests relating to interaction with
31# zipimport in the test_zipimport_support test module.
32
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000033modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000034if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000035 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000036
Christian Heimesa3538eb2007-11-06 11:44:48 +000037# Normalize file names: on Windows, the case of file names of compiled
38# modules depends on the path used to start the python executable.
39modfile = normcase(modfile)
40
41def revise(filename, *args):
42 return (normcase(filename),) + args
43
Georg Brandl1a3284e2007-12-02 09:40:06 +000044import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000045
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000046git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000047
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000048class IsTestBase(unittest.TestCase):
49 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
50 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000051 inspect.ismodule, inspect.istraceback,
52 inspect.isgenerator, inspect.isgeneratorfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000053
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000054 def istest(self, predicate, exp):
55 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000056 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000057
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000058 for other in self.predicates - set([predicate]):
Christian Heimes7131fd92008-02-19 14:21:46 +000059 if predicate == inspect.isgeneratorfunction and\
60 other == inspect.isfunction:
61 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000062 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000063
Christian Heimes7131fd92008-02-19 14:21:46 +000064def generator_function_example(self):
65 for i in range(2):
66 yield i
67
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000068class TestPredicates(IsTestBase):
Christian Heimes227c8002008-03-03 20:34:40 +000069 def test_sixteen(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +000070 count = len([x for x in dir(inspect) if x.startswith('is')])
Christian Heimes7131fd92008-02-19 14:21:46 +000071 # This test is here for remember you to update Doc/library/inspect.rst
Christian Heimes78644762008-03-04 23:39:23 +000072 # which claims there are 16 such functions
Christian Heimes227c8002008-03-03 20:34:40 +000073 expected = 16
Thomas Wouters0e3f5912006-08-11 14:57:12 +000074 err_msg = "There are %d (not %d) is* functions" % (count, expected)
75 self.assertEqual(count, expected, err_msg)
Tim Peters5a9fb3c2005-01-07 16:01:32 +000076
Christian Heimes7131fd92008-02-19 14:21:46 +000077
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000078 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +020079 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000080 self.istest(inspect.isbuiltin, 'sys.exit')
81 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +000082 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +020083 try:
84 1/0
85 except:
86 tb = sys.exc_info()[2]
87 self.istest(inspect.isframe, 'tb.tb_frame')
88 self.istest(inspect.istraceback, 'tb')
89 if hasattr(types, 'GetSetDescriptorType'):
90 self.istest(inspect.isgetsetdescriptor,
91 'type(tb.tb_frame).f_locals')
92 else:
93 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
94 finally:
95 # Clear traceback and all the frames and local variables hanging to it.
96 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000097 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +000098 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000099 self.istest(inspect.ismethod, 'git.argue')
100 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000101 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000102 self.istest(inspect.isgenerator, '(x for x in range(2))')
103 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000104 if hasattr(types, 'MemberDescriptorType'):
105 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
106 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000107 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000108
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000109 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000110 self.assertTrue(inspect.isroutine(mod.spam))
111 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000112
Benjamin Petersonc4656002009-01-17 22:41:18 +0000113 def test_isclass(self):
114 self.istest(inspect.isclass, 'mod.StupidGit')
115 self.assertTrue(inspect.isclass(list))
116
117 class CustomGetattr(object):
118 def __getattr__(self, attr):
119 return None
120 self.assertFalse(inspect.isclass(CustomGetattr()))
121
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000122 def test_get_slot_members(self):
123 class C(object):
124 __slots__ = ("a", "b")
125
126 x = C()
127 x.a = 42
128 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000129 self.assertIn('a', members)
130 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000131
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000132 def test_isabstract(self):
133 from abc import ABCMeta, abstractmethod
134
135 class AbstractClassExample(metaclass=ABCMeta):
136
137 @abstractmethod
138 def foo(self):
139 pass
140
141 class ClassExample(AbstractClassExample):
142 def foo(self):
143 pass
144
145 a = ClassExample()
146
147 # Test general behaviour.
148 self.assertTrue(inspect.isabstract(AbstractClassExample))
149 self.assertFalse(inspect.isabstract(ClassExample))
150 self.assertFalse(inspect.isabstract(a))
151 self.assertFalse(inspect.isabstract(int))
152 self.assertFalse(inspect.isabstract(5))
153
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000154
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000155class TestInterpreterStack(IsTestBase):
156 def __init__(self, *args, **kwargs):
157 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000158
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000159 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000160
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000161 def test_abuse_done(self):
162 self.istest(inspect.istraceback, 'git.ex[2]')
163 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000164
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000165 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000166 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000167 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000168 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000169 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000170 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000171 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000172 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000173 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000174 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000175
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000176 def test_trace(self):
177 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000178 self.assertEqual(revise(*git.tr[0][1:]),
179 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
180 self.assertEqual(revise(*git.tr[1][1:]),
181 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
182 self.assertEqual(revise(*git.tr[2][1:]),
183 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000184
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000185 def test_frame(self):
186 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
187 self.assertEqual(args, ['x', 'y'])
188 self.assertEqual(varargs, None)
189 self.assertEqual(varkw, None)
190 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
191 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
192 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000193
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000194 def test_previous_frame(self):
195 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000196 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000197 self.assertEqual(varargs, 'g')
198 self.assertEqual(varkw, 'h')
199 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000200 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000201
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000202class GetSourceBase(unittest.TestCase):
203 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000204 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000205
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000206 def __init__(self, *args, **kwargs):
207 unittest.TestCase.__init__(self, *args, **kwargs)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000208
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000209 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000210 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000211
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000212 def sourcerange(self, top, bottom):
213 lines = self.source.split("\n")
214 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000215
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000216 def assertSourceEqual(self, obj, top, bottom):
217 self.assertEqual(inspect.getsource(obj),
218 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000219
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000220class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000221 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000222
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000223 def test_getclasses(self):
224 classes = inspect.getmembers(mod, inspect.isclass)
225 self.assertEqual(classes,
226 [('FesteringGob', mod.FesteringGob),
227 ('MalodorousPervert', mod.MalodorousPervert),
228 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300229 ('StupidGit', mod.StupidGit),
230 ('Tit', mod.MalodorousPervert),
231 ])
232 tree = inspect.getclasstree([cls[1] for cls in classes])
233 self.assertEqual(tree,
234 [(object, ()),
235 [(mod.ParrotDroppings, (object,)),
236 [(mod.FesteringGob, (mod.MalodorousPervert,
237 mod.ParrotDroppings))
238 ],
239 (mod.StupidGit, (object,)),
240 [(mod.MalodorousPervert, (mod.StupidGit,)),
241 [(mod.FesteringGob, (mod.MalodorousPervert,
242 mod.ParrotDroppings))
243 ]
244 ]
245 ]
246 ])
247 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000248 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000249 [(object, ()),
250 [(mod.ParrotDroppings, (object,)),
251 (mod.StupidGit, (object,)),
252 [(mod.MalodorousPervert, (mod.StupidGit,)),
253 [(mod.FesteringGob, (mod.MalodorousPervert,
254 mod.ParrotDroppings))
255 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000256 ]
257 ]
258 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000259
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000260 def test_getfunctions(self):
261 functions = inspect.getmembers(mod, inspect.isfunction)
262 self.assertEqual(functions, [('eggs', mod.eggs),
263 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000264
R. David Murray378c0cf2010-02-24 01:46:21 +0000265 @unittest.skipIf(sys.flags.optimize >= 2,
266 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000267 def test_getdoc(self):
268 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
269 self.assertEqual(inspect.getdoc(mod.StupidGit),
270 'A longer,\n\nindented\n\ndocstring.')
271 self.assertEqual(inspect.getdoc(git.abuse),
272 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000273
Georg Brandl0c77a822008-06-10 16:37:50 +0000274 def test_cleandoc(self):
275 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
276 'An\nindented\ndocstring.')
277
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000278 def test_getcomments(self):
279 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
280 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000281
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000282 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000283 # Check actual module
284 self.assertEqual(inspect.getmodule(mod), mod)
285 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000286 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000287 # Check a method (no __module__ attribute, falls back to filename)
288 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
289 # Do it again (check the caching isn't broken)
290 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
291 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000292 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000293 # Check filename override
294 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000295
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000296 def test_getsource(self):
297 self.assertSourceEqual(git.abuse, 29, 39)
298 self.assertSourceEqual(mod.StupidGit, 21, 46)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000299
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000300 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000301 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
302 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000303 fn = "_non_existing_filename_used_for_sourcefile_test.py"
304 co = compile("None", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000305 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000306 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200307 try:
308 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
309 finally:
310 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000311
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000312 def test_getfile(self):
313 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000314
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000315 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000316 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000317 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000318 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000319 m.__file__ = "<string>" # hopefully not a real filename...
320 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000321 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000322 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000323 del sys.modules[name]
324 inspect.getmodule(compile('a=10','','single'))
325
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500326 def test_proceed_with_fake_filename(self):
327 '''doctest monkeypatches linecache to enable inspection'''
328 fn, source = '<test>', 'def x(): pass\n'
329 getlines = linecache.getlines
330 def monkey(filename, module_globals=None):
331 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300332 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500333 else:
334 return getlines(filename, module_globals)
335 linecache.getlines = monkey
336 try:
337 ns = {}
338 exec(compile(source, fn, 'single'), ns)
339 inspect.getsource(ns["x"])
340 finally:
341 linecache.getlines = getlines
342
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000343class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000344 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000345
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000346 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000347 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000348
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000349 def test_replacing_decorator(self):
350 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000351
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000352class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000353 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000354 def test_oneline_lambda(self):
355 # Test inspect.getsource with a one-line lambda function.
356 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000357
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000358 def test_threeline_lambda(self):
359 # Test inspect.getsource with a three-line lambda function,
360 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000361 self.assertSourceEqual(mod2.tll, 28, 30)
362
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000363 def test_twoline_indented_lambda(self):
364 # Test inspect.getsource with a two-line lambda function,
365 # where the second line _is_ indented.
366 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000367
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000368 def test_onelinefunc(self):
369 # Test inspect.getsource with a regular one-line function.
370 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000371
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000372 def test_manyargs(self):
373 # Test inspect.getsource with a regular function where
374 # the arguments are on two lines and _not_ indented and
375 # the body on the second line with the last arguments.
376 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000377
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000378 def test_twolinefunc(self):
379 # Test inspect.getsource with a regular function where
380 # the body is on two lines, following the argument list and
381 # continued on the next line by a \\.
382 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000383
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000384 def test_lambda_in_list(self):
385 # Test inspect.getsource with a one-line lambda function
386 # defined in a list, indented.
387 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000388
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000389 def test_anonymous(self):
390 # Test inspect.getsource with a lambda function defined
391 # as argument to another function.
392 self.assertSourceEqual(mod2.anonymous, 55, 55)
393
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000394class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000395 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000396
397 def test_with_comment(self):
398 self.assertSourceEqual(mod2.with_comment, 58, 59)
399
400 def test_multiline_sig(self):
401 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
402
Armin Rigodd5c0232005-09-25 11:45:45 +0000403 def test_nested_class(self):
404 self.assertSourceEqual(mod2.func69().func71, 71, 72)
405
406 def test_one_liner_followed_by_non_name(self):
407 self.assertSourceEqual(mod2.func77, 77, 77)
408
409 def test_one_liner_dedent_non_name(self):
410 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
411
412 def test_with_comment_instead_of_docstring(self):
413 self.assertSourceEqual(mod2.func88, 88, 90)
414
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000415 def test_method_in_dynamic_class(self):
416 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
417
R. David Murrayb5655772009-05-14 16:17:50 +0000418 @unittest.skipIf(
419 not hasattr(unicodedata, '__file__') or
420 unicodedata.__file__[-4:] in (".pyc", ".pyo"),
421 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000422 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200423 self.assertRaises(OSError, inspect.getsource, unicodedata)
424 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000425
R. David Murraya1b37402010-06-17 02:04:29 +0000426 def test_findsource_code_in_linecache(self):
427 lines = ["x=1"]
428 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200429 self.assertRaises(OSError, inspect.findsource, co)
430 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000431 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200432 try:
433 self.assertEqual(inspect.findsource(co), (lines,0))
434 self.assertEqual(inspect.getsource(co), lines[0])
435 finally:
436 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000437
Ezio Melotti1b145922013-03-30 05:17:24 +0200438 def test_findsource_without_filename(self):
439 for fname in ['', '<string>']:
440 co = compile('x=1', fname, "exec")
441 self.assertRaises(IOError, inspect.findsource, co)
442 self.assertRaises(IOError, inspect.getsource, co)
443
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000444class TestNoEOL(GetSourceBase):
445 def __init__(self, *args, **kwargs):
446 self.tempdir = TESTFN + '_dir'
447 os.mkdir(self.tempdir)
448 with open(os.path.join(self.tempdir,
449 'inspect_fodder3%spy' % os.extsep), 'w') as f:
450 f.write("class X:\n pass # No EOL")
451 with DirsOnSysPath(self.tempdir):
452 import inspect_fodder3 as mod3
453 self.fodderModule = mod3
454 GetSourceBase.__init__(self, *args, **kwargs)
455
456 def tearDown(self):
457 shutil.rmtree(self.tempdir)
458
459 def test_class(self):
460 self.assertSourceEqual(self.fodderModule.X, 1, 2)
461
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100462
463class _BrokenDataDescriptor(object):
464 """
465 A broken data descriptor. See bug #1785.
466 """
467 def __get__(*args):
468 raise AssertionError("should not __get__ data descriptors")
469
470 def __set__(*args):
471 raise RuntimeError
472
473 def __getattr__(*args):
474 raise AssertionError("should not __getattr__ data descriptors")
475
476
477class _BrokenMethodDescriptor(object):
478 """
479 A broken method descriptor. See bug #1785.
480 """
481 def __get__(*args):
482 raise AssertionError("should not __get__ method descriptors")
483
484 def __getattr__(*args):
485 raise AssertionError("should not __getattr__ method descriptors")
486
487
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000488# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000489def attrs_wo_objs(cls):
490 return [t[:3] for t in inspect.classify_class_attrs(cls)]
491
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100492
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000493class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000494 def test_newstyle_mro(self):
495 # The same w/ new-class MRO.
496 class A(object): pass
497 class B(A): pass
498 class C(A): pass
499 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000500
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000501 expected = (D, B, C, A, object)
502 got = inspect.getmro(D)
503 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000504
Christian Heimes3795b532007-11-08 13:48:53 +0000505 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
506 varkw_e=None, defaults_e=None, formatted=None):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000507 args, varargs, varkw, defaults = inspect.getargspec(routine)
508 self.assertEqual(args, args_e)
509 self.assertEqual(varargs, varargs_e)
510 self.assertEqual(varkw, varkw_e)
511 self.assertEqual(defaults, defaults_e)
512 if formatted is not None:
513 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
514 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000515
Christian Heimes3795b532007-11-08 13:48:53 +0000516 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
517 varkw_e=None, defaults_e=None,
518 kwonlyargs_e=[], kwonlydefaults_e=None,
519 ann_e={}, formatted=None):
520 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
521 inspect.getfullargspec(routine)
522 self.assertEqual(args, args_e)
523 self.assertEqual(varargs, varargs_e)
524 self.assertEqual(varkw, varkw_e)
525 self.assertEqual(defaults, defaults_e)
526 self.assertEqual(kwonlyargs, kwonlyargs_e)
527 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
528 self.assertEqual(ann, ann_e)
529 if formatted is not None:
530 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
531 kwonlyargs, kwonlydefaults, ann),
532 formatted)
533
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000534 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000535 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000536
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000537 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000538 ['a', 'b', 'c', 'd', 'e', 'f'],
539 'g', 'h', (3, 4, 5),
540 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000541
Christian Heimes3795b532007-11-08 13:48:53 +0000542 self.assertRaises(ValueError, self.assertArgSpecEquals,
543 mod2.keyworded, [])
544
545 self.assertRaises(ValueError, self.assertArgSpecEquals,
546 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000547 self.assertRaises(ValueError, self.assertArgSpecEquals,
548 mod2.keyword_only_arg, [])
549
Christian Heimes3795b532007-11-08 13:48:53 +0000550
551 def test_getfullargspec(self):
552 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
553 kwonlyargs_e=['arg2'],
554 kwonlydefaults_e={'arg2':1},
555 formatted='(*arg1, arg2=1)')
556
557 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000558 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000559 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000560 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
561 kwonlyargs_e=['arg'],
562 formatted='(*, arg)')
563
Christian Heimes3795b532007-11-08 13:48:53 +0000564
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000565 def test_getargspec_method(self):
566 class A(object):
567 def m(self):
568 pass
569 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000570
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000571 def test_classify_newstyle(self):
572 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000573
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000574 def s(): pass
575 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000576
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000577 def c(cls): pass
578 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000579
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000580 def getp(self): pass
581 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000582
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000583 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000584
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000585 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000586
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000587 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000588
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100589 dd = _BrokenDataDescriptor()
590 md = _BrokenMethodDescriptor()
591
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000592 attrs = attrs_wo_objs(A)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000593 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
594 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
595 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000596 self.assertIn(('m', 'method', A), attrs,
597 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000598 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
599 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100600 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
601 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000602
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000603 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000604
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000605 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000606
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000607 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000608 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
609 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
610 self.assertIn(('p', 'property', A), attrs, 'missing property')
611 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
612 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
613 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100614 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
615 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000616
617
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000618 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000619
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000620 def m(self): pass
621 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000622
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000623 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000624 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
625 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
626 self.assertIn(('p', 'property', A), attrs, 'missing property')
627 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
628 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
629 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100630 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
631 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000632
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000633 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000634
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000635 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000636
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000637 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000638 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
639 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
640 self.assertIn(('p', 'property', A), attrs, 'missing property')
641 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
642 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
643 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100644 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
645 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
646
647 def test_classify_builtin_types(self):
648 # Simple sanity check that all built-in types can have their
649 # attributes classified.
650 for name in dir(__builtins__):
651 builtin = getattr(__builtins__, name)
652 if isinstance(builtin, type):
653 inspect.classify_class_attrs(builtin)
654
Ethan Furmane03ea372013-09-25 07:14:41 -0700655 def test_classify_VirtualAttribute(self):
656 class VA:
657 @types.DynamicClassAttribute
658 def ham(self):
659 return 'eggs'
660 should_find = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
661 self.assertIn(should_find, inspect.classify_class_attrs(VA))
662
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100663 def test_getmembers_descriptors(self):
664 class A(object):
665 dd = _BrokenDataDescriptor()
666 md = _BrokenMethodDescriptor()
667
668 def pred_wrapper(pred):
669 # A quick'n'dirty way to discard standard attributes of new-style
670 # classes.
671 class Empty(object):
672 pass
673 def wrapped(x):
674 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
675 return False
676 return pred(x)
677 return wrapped
678
679 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
680 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
681
682 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
683 [('md', A.__dict__['md'])])
684 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
685 [('dd', A.__dict__['dd'])])
686
687 class B(A):
688 pass
689
690 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
691 [('md', A.__dict__['md'])])
692 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
693 [('dd', A.__dict__['dd'])])
694
Antoine Pitrou0c603812012-01-18 17:40:18 +0100695 def test_getmembers_method(self):
696 class B:
697 def f(self):
698 pass
699
700 self.assertIn(('f', B.f), inspect.getmembers(B))
701 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
702 b = B()
703 self.assertIn(('f', b.f), inspect.getmembers(b))
704 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
705
Ethan Furmane03ea372013-09-25 07:14:41 -0700706 def test_getmembers_VirtualAttribute(self):
707 class A:
708 @types.DynamicClassAttribute
709 def eggs(self):
710 return 'spam'
711 self.assertIn(('eggs', A.__dict__['eggs']), inspect.getmembers(A))
712
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000713
Nick Coghlan2f92e542012-06-23 19:39:55 +1000714_global_ref = object()
715class TestGetClosureVars(unittest.TestCase):
716
717 def test_name_resolution(self):
718 # Basic test of the 4 different resolution mechanisms
719 def f(nonlocal_ref):
720 def g(local_ref):
721 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
722 return g
723 _arg = object()
724 nonlocal_vars = {"nonlocal_ref": _arg}
725 global_vars = {"_global_ref": _global_ref}
726 builtin_vars = {"print": print}
727 unbound_names = {"unbound_ref"}
728 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
729 builtin_vars, unbound_names)
730 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
731
732 def test_generator_closure(self):
733 def f(nonlocal_ref):
734 def g(local_ref):
735 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
736 yield
737 return g
738 _arg = object()
739 nonlocal_vars = {"nonlocal_ref": _arg}
740 global_vars = {"_global_ref": _global_ref}
741 builtin_vars = {"print": print}
742 unbound_names = {"unbound_ref"}
743 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
744 builtin_vars, unbound_names)
745 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
746
747 def test_method_closure(self):
748 class C:
749 def f(self, nonlocal_ref):
750 def g(local_ref):
751 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
752 return g
753 _arg = object()
754 nonlocal_vars = {"nonlocal_ref": _arg}
755 global_vars = {"_global_ref": _global_ref}
756 builtin_vars = {"print": print}
757 unbound_names = {"unbound_ref"}
758 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
759 builtin_vars, unbound_names)
760 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
761
762 def test_nonlocal_vars(self):
763 # More complex tests of nonlocal resolution
764 def _nonlocal_vars(f):
765 return inspect.getclosurevars(f).nonlocals
766
767 def make_adder(x):
768 def add(y):
769 return x + y
770 return add
771
772 def curry(func, arg1):
773 return lambda arg2: func(arg1, arg2)
774
775 def less_than(a, b):
776 return a < b
777
778 # The infamous Y combinator.
779 def Y(le):
780 def g(f):
781 return le(lambda x: f(f)(x))
782 Y.g_ref = g
783 return g(g)
784
785 def check_y_combinator(func):
786 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
787
788 inc = make_adder(1)
789 add_two = make_adder(2)
790 greater_than_five = curry(less_than, 5)
791
792 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
793 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
794 self.assertEqual(_nonlocal_vars(greater_than_five),
795 {'arg1': 5, 'func': less_than})
796 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
797 {'x': 3})
798 Y(check_y_combinator)
799
800 def test_getclosurevars_empty(self):
801 def foo(): pass
802 _empty = inspect.ClosureVars({}, {}, {}, set())
803 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
804 self.assertEqual(inspect.getclosurevars(foo), _empty)
805
806 def test_getclosurevars_error(self):
807 class T: pass
808 self.assertRaises(TypeError, inspect.getclosurevars, 1)
809 self.assertRaises(TypeError, inspect.getclosurevars, list)
810 self.assertRaises(TypeError, inspect.getclosurevars, {})
811
Nick Coghlan6c6e2542012-06-23 20:07:39 +1000812 def _private_globals(self):
813 code = """def f(): print(path)"""
814 ns = {}
815 exec(code, ns)
816 return ns["f"], ns
817
818 def test_builtins_fallback(self):
819 f, ns = self._private_globals()
820 ns.pop("__builtins__", None)
821 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
822 self.assertEqual(inspect.getclosurevars(f), expected)
823
824 def test_builtins_as_dict(self):
825 f, ns = self._private_globals()
826 ns["__builtins__"] = {"path":1}
827 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
828 self.assertEqual(inspect.getclosurevars(f), expected)
829
830 def test_builtins_as_module(self):
831 f, ns = self._private_globals()
832 ns["__builtins__"] = os
833 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
834 self.assertEqual(inspect.getclosurevars(f), expected)
835
Nick Coghlan2f92e542012-06-23 19:39:55 +1000836
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000837class TestGetcallargsFunctions(unittest.TestCase):
838
839 def assertEqualCallArgs(self, func, call_params_string, locs=None):
840 locs = dict(locs or {}, func=func)
841 r1 = eval('func(%s)' % call_params_string, None, locs)
842 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
843 locs)
844 self.assertEqual(r1, r2)
845
846 def assertEqualException(self, func, call_param_string, locs=None):
847 locs = dict(locs or {}, func=func)
848 try:
849 eval('func(%s)' % call_param_string, None, locs)
850 except Exception as e:
851 ex1 = e
852 else:
853 self.fail('Exception not raised')
854 try:
855 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
856 locs)
857 except Exception as e:
858 ex2 = e
859 else:
860 self.fail('Exception not raised')
861 self.assertIs(type(ex1), type(ex2))
862 self.assertEqual(str(ex1), str(ex2))
863 del ex1, ex2
864
865 def makeCallable(self, signature):
866 """Create a function that returns its locals()"""
867 code = "lambda %s: locals()"
868 return eval(code % signature)
869
870 def test_plain(self):
871 f = self.makeCallable('a, b=1')
872 self.assertEqualCallArgs(f, '2')
873 self.assertEqualCallArgs(f, '2, 3')
874 self.assertEqualCallArgs(f, 'a=2')
875 self.assertEqualCallArgs(f, 'b=3, a=2')
876 self.assertEqualCallArgs(f, '2, b=3')
877 # expand *iterable / **mapping
878 self.assertEqualCallArgs(f, '*(2,)')
879 self.assertEqualCallArgs(f, '*[2]')
880 self.assertEqualCallArgs(f, '*(2, 3)')
881 self.assertEqualCallArgs(f, '*[2, 3]')
882 self.assertEqualCallArgs(f, '**{"a":2}')
883 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
884 self.assertEqualCallArgs(f, '2, **{"b":3}')
885 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
886 # expand UserList / UserDict
887 self.assertEqualCallArgs(f, '*collections.UserList([2])')
888 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
889 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
890 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
891 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
892
893 def test_varargs(self):
894 f = self.makeCallable('a, b=1, *c')
895 self.assertEqualCallArgs(f, '2')
896 self.assertEqualCallArgs(f, '2, 3')
897 self.assertEqualCallArgs(f, '2, 3, 4')
898 self.assertEqualCallArgs(f, '*(2,3,4)')
899 self.assertEqualCallArgs(f, '2, *[3,4]')
900 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
901
902 def test_varkw(self):
903 f = self.makeCallable('a, b=1, **c')
904 self.assertEqualCallArgs(f, 'a=2')
905 self.assertEqualCallArgs(f, '2, b=3, c=4')
906 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
907 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
908 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
909 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
910 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
911 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
912 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
913
Benjamin Peterson6a2638b2011-03-28 17:32:31 -0500914 def test_varkw_only(self):
915 # issue11256:
916 f = self.makeCallable('**c')
917 self.assertEqualCallArgs(f, '')
918 self.assertEqualCallArgs(f, 'a=1')
919 self.assertEqualCallArgs(f, 'a=1, b=2')
920 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
921 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
922 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
923
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000924 def test_keyword_only(self):
925 f = self.makeCallable('a=3, *, c, d=2')
926 self.assertEqualCallArgs(f, 'c=3')
927 self.assertEqualCallArgs(f, 'c=3, a=3')
928 self.assertEqualCallArgs(f, 'a=2, c=4')
929 self.assertEqualCallArgs(f, '4, c=4')
930 self.assertEqualException(f, '')
931 self.assertEqualException(f, '3')
932 self.assertEqualException(f, 'a=3')
933 self.assertEqualException(f, 'd=4')
934
Benjamin Peterson6a2638b2011-03-28 17:32:31 -0500935 f = self.makeCallable('*, c, d=2')
936 self.assertEqualCallArgs(f, 'c=3')
937 self.assertEqualCallArgs(f, 'c=3, d=4')
938 self.assertEqualCallArgs(f, 'd=4, c=3')
939
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000940 def test_multiple_features(self):
941 f = self.makeCallable('a, b=2, *f, **g')
942 self.assertEqualCallArgs(f, '2, 3, 7')
943 self.assertEqualCallArgs(f, '2, 3, x=8')
944 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
945 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
946 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
947 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
948 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
949 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
950 '(4,[5,6])]), **collections.UserDict('
951 'y=9, z=10)')
952
Benjamin Peterson6a2638b2011-03-28 17:32:31 -0500953 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
954 self.assertEqualCallArgs(f, '2, 3, x=8')
955 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
956 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
957 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
958 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
959 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
960 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
961 '(4,[5,6])]), q=0, **collections.UserDict('
962 'y=9, z=10)')
963
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000964 def test_errors(self):
965 f0 = self.makeCallable('')
966 f1 = self.makeCallable('a, b')
967 f2 = self.makeCallable('a, b=1')
968 # f0 takes no arguments
969 self.assertEqualException(f0, '1')
970 self.assertEqualException(f0, 'x=1')
971 self.assertEqualException(f0, '1,x=1')
972 # f1 takes exactly 2 arguments
973 self.assertEqualException(f1, '')
974 self.assertEqualException(f1, '1')
975 self.assertEqualException(f1, 'a=2')
976 self.assertEqualException(f1, 'b=3')
977 # f2 takes at least 1 argument
978 self.assertEqualException(f2, '')
979 self.assertEqualException(f2, 'b=3')
980 for f in f1, f2:
981 # f1/f2 takes exactly/at most 2 arguments
982 self.assertEqualException(f, '2, 3, 4')
983 self.assertEqualException(f, '1, 2, 3, a=1')
984 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +0100985 # XXX: success of this one depends on dict order
986 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000987 # f got an unexpected keyword argument
988 self.assertEqualException(f, 'c=2')
989 self.assertEqualException(f, '2, c=3')
990 self.assertEqualException(f, '2, 3, c=4')
991 self.assertEqualException(f, '2, c=4, b=3')
992 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
993 # f got multiple values for keyword argument
994 self.assertEqualException(f, '1, a=2')
995 self.assertEqualException(f, '1, **{"a":2}')
996 self.assertEqualException(f, '1, 2, b=3')
997 # XXX: Python inconsistency
998 # - for functions and bound methods: unexpected keyword 'c'
999 # - for unbound methods: multiple values for keyword 'a'
1000 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001001 # issue11256:
1002 f3 = self.makeCallable('**c')
1003 self.assertEqualException(f3, '1, 2')
1004 self.assertEqualException(f3, '1, 2, a=1, b=2')
1005 f4 = self.makeCallable('*, a, b=0')
1006 self.assertEqualException(f3, '1, 2')
1007 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001008
1009class TestGetcallargsMethods(TestGetcallargsFunctions):
1010
1011 def setUp(self):
1012 class Foo(object):
1013 pass
1014 self.cls = Foo
1015 self.inst = Foo()
1016
1017 def makeCallable(self, signature):
1018 assert 'self' not in signature
1019 mk = super(TestGetcallargsMethods, self).makeCallable
1020 self.cls.method = mk('self, ' + signature)
1021 return self.inst.method
1022
1023class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1024
1025 def makeCallable(self, signature):
1026 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1027 return self.cls.method
1028
1029 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1030 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1031 *self._getAssertEqualParams(func, call_params_string, locs))
1032
1033 def assertEqualException(self, func, call_params_string, locs=None):
1034 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1035 *self._getAssertEqualParams(func, call_params_string, locs))
1036
1037 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1038 assert 'inst' not in call_params_string
1039 locs = dict(locs or {}, inst=self.inst)
1040 return (func, 'inst,' + call_params_string, locs)
1041
Michael Foord95fc51d2010-11-20 15:07:30 +00001042
1043class TestGetattrStatic(unittest.TestCase):
1044
1045 def test_basic(self):
1046 class Thing(object):
1047 x = object()
1048
1049 thing = Thing()
1050 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1051 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1052 with self.assertRaises(AttributeError):
1053 inspect.getattr_static(thing, 'y')
1054
1055 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1056
1057 def test_inherited(self):
1058 class Thing(object):
1059 x = object()
1060 class OtherThing(Thing):
1061 pass
1062
1063 something = OtherThing()
1064 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1065
1066 def test_instance_attr(self):
1067 class Thing(object):
1068 x = 2
1069 def __init__(self, x):
1070 self.x = x
1071 thing = Thing(3)
1072 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1073 del thing.x
1074 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1075
1076 def test_property(self):
1077 class Thing(object):
1078 @property
1079 def x(self):
1080 raise AttributeError("I'm pretending not to exist")
1081 thing = Thing()
1082 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1083
Ezio Melotti75cbd732011-04-28 00:59:29 +03001084 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001085 class descriptor(object):
1086 def __get__(*_):
1087 raise AttributeError("I'm pretending not to exist")
1088 desc = descriptor()
1089 class Thing(object):
1090 x = desc
1091 thing = Thing()
1092 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1093
1094 def test_classAttribute(self):
1095 class Thing(object):
1096 x = object()
1097
1098 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1099
Ethan Furmane03ea372013-09-25 07:14:41 -07001100 def test_classVirtualAttribute(self):
1101 class Thing(object):
1102 @types.DynamicClassAttribute
1103 def x(self):
1104 return self._x
1105 _x = object()
1106
1107 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1108
Michael Foord95fc51d2010-11-20 15:07:30 +00001109 def test_inherited_classattribute(self):
1110 class Thing(object):
1111 x = object()
1112 class OtherThing(Thing):
1113 pass
1114
1115 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1116
1117 def test_slots(self):
1118 class Thing(object):
1119 y = 'bar'
1120 __slots__ = ['x']
1121 def __init__(self):
1122 self.x = 'foo'
1123 thing = Thing()
1124 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1125 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1126
1127 del thing.x
1128 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1129
1130 def test_metaclass(self):
1131 class meta(type):
1132 attr = 'foo'
1133 class Thing(object, metaclass=meta):
1134 pass
1135 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1136
1137 class sub(meta):
1138 pass
1139 class OtherThing(object, metaclass=sub):
1140 x = 3
1141 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1142
1143 class OtherOtherThing(OtherThing):
1144 pass
1145 # this test is odd, but it was added as it exposed a bug
1146 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1147
1148 def test_no_dict_no_slots(self):
1149 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1150 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1151
1152 def test_no_dict_no_slots_instance_member(self):
1153 # returns descriptor
1154 with open(__file__) as handle:
1155 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1156
1157 def test_inherited_slots(self):
1158 # returns descriptor
1159 class Thing(object):
1160 __slots__ = ['x']
1161 def __init__(self):
1162 self.x = 'foo'
1163
1164 class OtherThing(Thing):
1165 pass
1166 # it would be nice if this worked...
1167 # we get the descriptor instead of the instance attribute
1168 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1169
1170 def test_descriptor(self):
1171 class descriptor(object):
1172 def __get__(self, instance, owner):
1173 return 3
1174 class Foo(object):
1175 d = descriptor()
1176
1177 foo = Foo()
1178
1179 # for a non data descriptor we return the instance attribute
1180 foo.__dict__['d'] = 1
1181 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1182
1183 # if the descriptor is a data-desciptor we should return the
1184 # descriptor
1185 descriptor.__set__ = lambda s, i, v: None
1186 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1187
1188
1189 def test_metaclass_with_descriptor(self):
1190 class descriptor(object):
1191 def __get__(self, instance, owner):
1192 return 3
1193 class meta(type):
1194 d = descriptor()
1195 class Thing(object, metaclass=meta):
1196 pass
1197 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1198
1199
Michael Foordcc7ebb82010-11-20 16:20:16 +00001200 def test_class_as_property(self):
1201 class Base(object):
1202 foo = 3
1203
1204 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001205 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001206 @property
1207 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001208 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001209 return object
1210
Michael Foord35184ed2010-11-20 16:58:30 +00001211 instance = Something()
1212 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1213 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001214 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1215
Michael Foorde5162652010-11-20 16:40:44 +00001216 def test_mro_as_property(self):
1217 class Meta(type):
1218 @property
1219 def __mro__(self):
1220 return (object,)
1221
1222 class Base(object):
1223 foo = 3
1224
1225 class Something(Base, metaclass=Meta):
1226 pass
1227
1228 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1229 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1230
Michael Foorddcebe0f2011-03-15 19:20:44 -04001231 def test_dict_as_property(self):
1232 test = self
1233 test.called = False
1234
1235 class Foo(dict):
1236 a = 3
1237 @property
1238 def __dict__(self):
1239 test.called = True
1240 return {}
1241
1242 foo = Foo()
1243 foo.a = 4
1244 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1245 self.assertFalse(test.called)
1246
1247 def test_custom_object_dict(self):
1248 test = self
1249 test.called = False
1250
1251 class Custom(dict):
1252 def get(self, key, default=None):
1253 test.called = True
1254 super().get(key, default)
1255
1256 class Foo(object):
1257 a = 3
1258 foo = Foo()
1259 foo.__dict__ = Custom()
1260 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1261 self.assertFalse(test.called)
1262
1263 def test_metaclass_dict_as_property(self):
1264 class Meta(type):
1265 @property
1266 def __dict__(self):
1267 self.executed = True
1268
1269 class Thing(metaclass=Meta):
1270 executed = False
1271
1272 def __init__(self):
1273 self.spam = 42
1274
1275 instance = Thing()
1276 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1277 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001278
Michael Foorda51623b2011-12-18 22:01:40 +00001279 def test_module(self):
1280 sentinel = object()
1281 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1282 sentinel)
1283
Michael Foord3ba95f82011-12-22 01:13:37 +00001284 def test_metaclass_with_metaclass_with_dict_as_property(self):
1285 class MetaMeta(type):
1286 @property
1287 def __dict__(self):
1288 self.executed = True
1289 return dict(spam=42)
1290
1291 class Meta(type, metaclass=MetaMeta):
1292 executed = False
1293
1294 class Thing(metaclass=Meta):
1295 pass
1296
1297 with self.assertRaises(AttributeError):
1298 inspect.getattr_static(Thing, "spam")
1299 self.assertFalse(Thing.executed)
1300
Nick Coghlane0f04652010-11-21 03:44:04 +00001301class TestGetGeneratorState(unittest.TestCase):
1302
1303 def setUp(self):
1304 def number_generator():
1305 for number in range(5):
1306 yield number
1307 self.generator = number_generator()
1308
1309 def _generatorstate(self):
1310 return inspect.getgeneratorstate(self.generator)
1311
1312 def test_created(self):
1313 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1314
1315 def test_suspended(self):
1316 next(self.generator)
1317 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1318
1319 def test_closed_after_exhaustion(self):
1320 for i in self.generator:
1321 pass
1322 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1323
1324 def test_closed_after_immediate_exception(self):
1325 with self.assertRaises(RuntimeError):
1326 self.generator.throw(RuntimeError)
1327 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1328
1329 def test_running(self):
1330 # As mentioned on issue #10220, checking for the RUNNING state only
1331 # makes sense inside the generator itself.
1332 # The following generator checks for this by using the closure's
1333 # reference to self and the generator state checking helper method
1334 def running_check_generator():
1335 for number in range(5):
1336 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1337 yield number
1338 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1339 self.generator = running_check_generator()
1340 # Running up to the first yield
1341 next(self.generator)
1342 # Running after the first yield
1343 next(self.generator)
1344
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001345 def test_easy_debugging(self):
1346 # repr() and str() of a generator state should contain the state name
1347 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1348 for name in names:
1349 state = getattr(inspect, name)
1350 self.assertIn(name, repr(state))
1351 self.assertIn(name, str(state))
1352
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001353 def test_getgeneratorlocals(self):
1354 def each(lst, a=None):
1355 b=(1, 2, 3)
1356 for v in lst:
1357 if v == 3:
1358 c = 12
1359 yield v
1360
1361 numbers = each([1, 2, 3])
1362 self.assertEqual(inspect.getgeneratorlocals(numbers),
1363 {'a': None, 'lst': [1, 2, 3]})
1364 next(numbers)
1365 self.assertEqual(inspect.getgeneratorlocals(numbers),
1366 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1367 'b': (1, 2, 3)})
1368 next(numbers)
1369 self.assertEqual(inspect.getgeneratorlocals(numbers),
1370 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1371 'b': (1, 2, 3)})
1372 next(numbers)
1373 self.assertEqual(inspect.getgeneratorlocals(numbers),
1374 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1375 'b': (1, 2, 3), 'c': 12})
1376 try:
1377 next(numbers)
1378 except StopIteration:
1379 pass
1380 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1381
1382 def test_getgeneratorlocals_empty(self):
1383 def yield_one():
1384 yield 1
1385 one = yield_one()
1386 self.assertEqual(inspect.getgeneratorlocals(one), {})
1387 try:
1388 next(one)
1389 except StopIteration:
1390 pass
1391 self.assertEqual(inspect.getgeneratorlocals(one), {})
1392
1393 def test_getgeneratorlocals_error(self):
1394 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1395 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1396 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1397 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1398
Nick Coghlane0f04652010-11-21 03:44:04 +00001399
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001400class TestSignatureObject(unittest.TestCase):
1401 @staticmethod
1402 def signature(func):
1403 sig = inspect.signature(func)
1404 return (tuple((param.name,
1405 (... if param.default is param.empty else param.default),
1406 (... if param.annotation is param.empty
1407 else param.annotation),
1408 str(param.kind).lower())
1409 for param in sig.parameters.values()),
1410 (... if sig.return_annotation is sig.empty
1411 else sig.return_annotation))
1412
1413 def test_signature_object(self):
1414 S = inspect.Signature
1415 P = inspect.Parameter
1416
1417 self.assertEqual(str(S()), '()')
1418
1419 def test(po, pk, *args, ko, **kwargs):
1420 pass
1421 sig = inspect.signature(test)
1422 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
1423 pk = sig.parameters['pk']
1424 args = sig.parameters['args']
1425 ko = sig.parameters['ko']
1426 kwargs = sig.parameters['kwargs']
1427
1428 S((po, pk, args, ko, kwargs))
1429
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001430 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001431 S((pk, po, args, ko, kwargs))
1432
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001433 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001434 S((po, args, pk, ko, kwargs))
1435
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001436 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001437 S((args, po, pk, ko, kwargs))
1438
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001439 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001440 S((po, pk, args, kwargs, ko))
1441
1442 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001443 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001444 S((po, pk, args, kwargs2, ko))
1445
1446 def test_signature_immutability(self):
1447 def test(a):
1448 pass
1449 sig = inspect.signature(test)
1450
1451 with self.assertRaises(AttributeError):
1452 sig.foo = 'bar'
1453
1454 with self.assertRaises(TypeError):
1455 sig.parameters['a'] = None
1456
1457 def test_signature_on_noarg(self):
1458 def test():
1459 pass
1460 self.assertEqual(self.signature(test), ((), ...))
1461
1462 def test_signature_on_wargs(self):
1463 def test(a, b:'foo') -> 123:
1464 pass
1465 self.assertEqual(self.signature(test),
1466 ((('a', ..., ..., "positional_or_keyword"),
1467 ('b', ..., 'foo', "positional_or_keyword")),
1468 123))
1469
1470 def test_signature_on_wkwonly(self):
1471 def test(*, a:float, b:str) -> int:
1472 pass
1473 self.assertEqual(self.signature(test),
1474 ((('a', ..., float, "keyword_only"),
1475 ('b', ..., str, "keyword_only")),
1476 int))
1477
1478 def test_signature_on_complex_args(self):
1479 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1480 pass
1481 self.assertEqual(self.signature(test),
1482 ((('a', ..., ..., "positional_or_keyword"),
1483 ('b', 10, 'foo', "positional_or_keyword"),
1484 ('args', ..., 'bar', "var_positional"),
1485 ('spam', ..., 'baz', "keyword_only"),
1486 ('ham', 123, ..., "keyword_only"),
1487 ('kwargs', ..., int, "var_keyword")),
1488 ...))
1489
1490 def test_signature_on_builtin_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001491 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001492 inspect.signature(type)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001493 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001494 # support for 'wrapper_descriptor'
1495 inspect.signature(type.__call__)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001496 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001497 # support for 'method-wrapper'
1498 inspect.signature(min.__call__)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001499 with self.assertRaisesRegex(ValueError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001500 'no signature found for builtin function'):
1501 # support for 'method-wrapper'
1502 inspect.signature(min)
1503
1504 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001505 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001506 inspect.signature(42)
1507
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001508 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001509 inspect.Signature.from_function(42)
1510
1511 def test_signature_on_method(self):
1512 class Test:
1513 def foo(self, arg1, arg2=1) -> int:
1514 pass
1515
1516 meth = Test().foo
1517
1518 self.assertEqual(self.signature(meth),
1519 ((('arg1', ..., ..., "positional_or_keyword"),
1520 ('arg2', 1, ..., "positional_or_keyword")),
1521 int))
1522
1523 def test_signature_on_classmethod(self):
1524 class Test:
1525 @classmethod
1526 def foo(cls, arg1, *, arg2=1):
1527 pass
1528
1529 meth = Test().foo
1530 self.assertEqual(self.signature(meth),
1531 ((('arg1', ..., ..., "positional_or_keyword"),
1532 ('arg2', 1, ..., "keyword_only")),
1533 ...))
1534
1535 meth = Test.foo
1536 self.assertEqual(self.signature(meth),
1537 ((('arg1', ..., ..., "positional_or_keyword"),
1538 ('arg2', 1, ..., "keyword_only")),
1539 ...))
1540
1541 def test_signature_on_staticmethod(self):
1542 class Test:
1543 @staticmethod
1544 def foo(cls, *, arg):
1545 pass
1546
1547 meth = Test().foo
1548 self.assertEqual(self.signature(meth),
1549 ((('cls', ..., ..., "positional_or_keyword"),
1550 ('arg', ..., ..., "keyword_only")),
1551 ...))
1552
1553 meth = Test.foo
1554 self.assertEqual(self.signature(meth),
1555 ((('cls', ..., ..., "positional_or_keyword"),
1556 ('arg', ..., ..., "keyword_only")),
1557 ...))
1558
1559 def test_signature_on_partial(self):
1560 from functools import partial
1561
1562 def test():
1563 pass
1564
1565 self.assertEqual(self.signature(partial(test)), ((), ...))
1566
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001567 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001568 inspect.signature(partial(test, 1))
1569
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001570 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001571 inspect.signature(partial(test, a=1))
1572
1573 def test(a, b, *, c, d):
1574 pass
1575
1576 self.assertEqual(self.signature(partial(test)),
1577 ((('a', ..., ..., "positional_or_keyword"),
1578 ('b', ..., ..., "positional_or_keyword"),
1579 ('c', ..., ..., "keyword_only"),
1580 ('d', ..., ..., "keyword_only")),
1581 ...))
1582
1583 self.assertEqual(self.signature(partial(test, 1)),
1584 ((('b', ..., ..., "positional_or_keyword"),
1585 ('c', ..., ..., "keyword_only"),
1586 ('d', ..., ..., "keyword_only")),
1587 ...))
1588
1589 self.assertEqual(self.signature(partial(test, 1, c=2)),
1590 ((('b', ..., ..., "positional_or_keyword"),
1591 ('c', 2, ..., "keyword_only"),
1592 ('d', ..., ..., "keyword_only")),
1593 ...))
1594
1595 self.assertEqual(self.signature(partial(test, b=1, c=2)),
1596 ((('a', ..., ..., "positional_or_keyword"),
1597 ('b', 1, ..., "positional_or_keyword"),
1598 ('c', 2, ..., "keyword_only"),
1599 ('d', ..., ..., "keyword_only")),
1600 ...))
1601
1602 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
1603 ((('b', 1, ..., "positional_or_keyword"),
1604 ('c', 2, ..., "keyword_only"),
1605 ('d', ..., ..., "keyword_only"),),
1606 ...))
1607
1608 def test(a, *args, b, **kwargs):
1609 pass
1610
1611 self.assertEqual(self.signature(partial(test, 1)),
1612 ((('args', ..., ..., "var_positional"),
1613 ('b', ..., ..., "keyword_only"),
1614 ('kwargs', ..., ..., "var_keyword")),
1615 ...))
1616
1617 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
1618 ((('args', ..., ..., "var_positional"),
1619 ('b', ..., ..., "keyword_only"),
1620 ('kwargs', ..., ..., "var_keyword")),
1621 ...))
1622
1623
1624 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
1625 ((('args', ..., ..., "var_positional"),
1626 ('b', ..., ..., "keyword_only"),
1627 ('kwargs', ..., ..., "var_keyword")),
1628 ...))
1629
1630 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
1631 ((('args', ..., ..., "var_positional"),
1632 ('b', 0, ..., "keyword_only"),
1633 ('kwargs', ..., ..., "var_keyword")),
1634 ...))
1635
1636 self.assertEqual(self.signature(partial(test, b=0)),
1637 ((('a', ..., ..., "positional_or_keyword"),
1638 ('args', ..., ..., "var_positional"),
1639 ('b', 0, ..., "keyword_only"),
1640 ('kwargs', ..., ..., "var_keyword")),
1641 ...))
1642
1643 self.assertEqual(self.signature(partial(test, b=0, test=1)),
1644 ((('a', ..., ..., "positional_or_keyword"),
1645 ('args', ..., ..., "var_positional"),
1646 ('b', 0, ..., "keyword_only"),
1647 ('kwargs', ..., ..., "var_keyword")),
1648 ...))
1649
1650 def test(a, b, c:int) -> 42:
1651 pass
1652
1653 sig = test.__signature__ = inspect.signature(test)
1654
1655 self.assertEqual(self.signature(partial(partial(test, 1))),
1656 ((('b', ..., ..., "positional_or_keyword"),
1657 ('c', ..., int, "positional_or_keyword")),
1658 42))
1659
1660 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
1661 ((('c', ..., int, "positional_or_keyword"),),
1662 42))
1663
1664 psig = inspect.signature(partial(partial(test, 1), 2))
1665
1666 def foo(a):
1667 return a
1668 _foo = partial(partial(foo, a=10), a=20)
1669 self.assertEqual(self.signature(_foo),
1670 ((('a', 20, ..., "positional_or_keyword"),),
1671 ...))
1672 # check that we don't have any side-effects in signature(),
1673 # and the partial object is still functioning
1674 self.assertEqual(_foo(), 20)
1675
1676 def foo(a, b, c):
1677 return a, b, c
1678 _foo = partial(partial(foo, 1, b=20), b=30)
1679 self.assertEqual(self.signature(_foo),
1680 ((('b', 30, ..., "positional_or_keyword"),
1681 ('c', ..., ..., "positional_or_keyword")),
1682 ...))
1683 self.assertEqual(_foo(c=10), (1, 30, 10))
1684 _foo = partial(_foo, 2) # now 'b' has two values -
1685 # positional and keyword
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001686 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001687 inspect.signature(_foo)
1688
1689 def foo(a, b, c, *, d):
1690 return a, b, c, d
1691 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
1692 self.assertEqual(self.signature(_foo),
1693 ((('a', ..., ..., "positional_or_keyword"),
1694 ('b', 10, ..., "positional_or_keyword"),
1695 ('c', 20, ..., "positional_or_keyword"),
1696 ('d', 30, ..., "keyword_only")),
1697 ...))
1698 ba = inspect.signature(_foo).bind(a=200, b=11)
1699 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
1700
1701 def foo(a=1, b=2, c=3):
1702 return a, b, c
1703 _foo = partial(foo, a=10, c=13)
1704 ba = inspect.signature(_foo).bind(11)
1705 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
1706 ba = inspect.signature(_foo).bind(11, 12)
1707 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
1708 ba = inspect.signature(_foo).bind(11, b=12)
1709 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
1710 ba = inspect.signature(_foo).bind(b=12)
1711 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
1712 _foo = partial(_foo, b=10)
1713 ba = inspect.signature(_foo).bind(12, 14)
1714 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
1715
1716 def test_signature_on_decorated(self):
1717 import functools
1718
1719 def decorator(func):
1720 @functools.wraps(func)
1721 def wrapper(*args, **kwargs) -> int:
1722 return func(*args, **kwargs)
1723 return wrapper
1724
1725 class Foo:
1726 @decorator
1727 def bar(self, a, b):
1728 pass
1729
1730 self.assertEqual(self.signature(Foo.bar),
1731 ((('self', ..., ..., "positional_or_keyword"),
1732 ('a', ..., ..., "positional_or_keyword"),
1733 ('b', ..., ..., "positional_or_keyword")),
1734 ...))
1735
1736 self.assertEqual(self.signature(Foo().bar),
1737 ((('a', ..., ..., "positional_or_keyword"),
1738 ('b', ..., ..., "positional_or_keyword")),
1739 ...))
1740
1741 # Test that we handle method wrappers correctly
1742 def decorator(func):
1743 @functools.wraps(func)
1744 def wrapper(*args, **kwargs) -> int:
1745 return func(42, *args, **kwargs)
1746 sig = inspect.signature(func)
1747 new_params = tuple(sig.parameters.values())[1:]
1748 wrapper.__signature__ = sig.replace(parameters=new_params)
1749 return wrapper
1750
1751 class Foo:
1752 @decorator
1753 def __call__(self, a, b):
1754 pass
1755
1756 self.assertEqual(self.signature(Foo.__call__),
1757 ((('a', ..., ..., "positional_or_keyword"),
1758 ('b', ..., ..., "positional_or_keyword")),
1759 ...))
1760
1761 self.assertEqual(self.signature(Foo().__call__),
1762 ((('b', ..., ..., "positional_or_keyword"),),
1763 ...))
1764
Nick Coghlane8c45d62013-07-28 20:00:01 +10001765 # Test we handle __signature__ partway down the wrapper stack
1766 def wrapped_foo_call():
1767 pass
1768 wrapped_foo_call.__wrapped__ = Foo.__call__
1769
1770 self.assertEqual(self.signature(wrapped_foo_call),
1771 ((('a', ..., ..., "positional_or_keyword"),
1772 ('b', ..., ..., "positional_or_keyword")),
1773 ...))
1774
1775
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001776 def test_signature_on_class(self):
1777 class C:
1778 def __init__(self, a):
1779 pass
1780
1781 self.assertEqual(self.signature(C),
1782 ((('a', ..., ..., "positional_or_keyword"),),
1783 ...))
1784
1785 class CM(type):
1786 def __call__(cls, a):
1787 pass
1788 class C(metaclass=CM):
1789 def __init__(self, b):
1790 pass
1791
1792 self.assertEqual(self.signature(C),
1793 ((('a', ..., ..., "positional_or_keyword"),),
1794 ...))
1795
1796 class CM(type):
1797 def __new__(mcls, name, bases, dct, *, foo=1):
1798 return super().__new__(mcls, name, bases, dct)
1799 class C(metaclass=CM):
1800 def __init__(self, b):
1801 pass
1802
1803 self.assertEqual(self.signature(C),
1804 ((('b', ..., ..., "positional_or_keyword"),),
1805 ...))
1806
1807 self.assertEqual(self.signature(CM),
1808 ((('name', ..., ..., "positional_or_keyword"),
1809 ('bases', ..., ..., "positional_or_keyword"),
1810 ('dct', ..., ..., "positional_or_keyword"),
1811 ('foo', 1, ..., "keyword_only")),
1812 ...))
1813
1814 class CMM(type):
1815 def __new__(mcls, name, bases, dct, *, foo=1):
1816 return super().__new__(mcls, name, bases, dct)
1817 def __call__(cls, nm, bs, dt):
1818 return type(nm, bs, dt)
1819 class CM(type, metaclass=CMM):
1820 def __new__(mcls, name, bases, dct, *, bar=2):
1821 return super().__new__(mcls, name, bases, dct)
1822 class C(metaclass=CM):
1823 def __init__(self, b):
1824 pass
1825
1826 self.assertEqual(self.signature(CMM),
1827 ((('name', ..., ..., "positional_or_keyword"),
1828 ('bases', ..., ..., "positional_or_keyword"),
1829 ('dct', ..., ..., "positional_or_keyword"),
1830 ('foo', 1, ..., "keyword_only")),
1831 ...))
1832
1833 self.assertEqual(self.signature(CM),
1834 ((('nm', ..., ..., "positional_or_keyword"),
1835 ('bs', ..., ..., "positional_or_keyword"),
1836 ('dt', ..., ..., "positional_or_keyword")),
1837 ...))
1838
1839 self.assertEqual(self.signature(C),
1840 ((('b', ..., ..., "positional_or_keyword"),),
1841 ...))
1842
1843 class CM(type):
1844 def __init__(cls, name, bases, dct, *, bar=2):
1845 return super().__init__(name, bases, dct)
1846 class C(metaclass=CM):
1847 def __init__(self, b):
1848 pass
1849
1850 self.assertEqual(self.signature(CM),
1851 ((('name', ..., ..., "positional_or_keyword"),
1852 ('bases', ..., ..., "positional_or_keyword"),
1853 ('dct', ..., ..., "positional_or_keyword"),
1854 ('bar', 2, ..., "keyword_only")),
1855 ...))
1856
1857 def test_signature_on_callable_objects(self):
1858 class Foo:
1859 def __call__(self, a):
1860 pass
1861
1862 self.assertEqual(self.signature(Foo()),
1863 ((('a', ..., ..., "positional_or_keyword"),),
1864 ...))
1865
1866 class Spam:
1867 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001868 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001869 inspect.signature(Spam())
1870
1871 class Bar(Spam, Foo):
1872 pass
1873
1874 self.assertEqual(self.signature(Bar()),
1875 ((('a', ..., ..., "positional_or_keyword"),),
1876 ...))
1877
1878 class ToFail:
1879 __call__ = type
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001880 with self.assertRaisesRegex(ValueError, "not supported by signature"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001881 inspect.signature(ToFail())
1882
1883
1884 class Wrapped:
1885 pass
1886 Wrapped.__wrapped__ = lambda a: None
1887 self.assertEqual(self.signature(Wrapped),
1888 ((('a', ..., ..., "positional_or_keyword"),),
1889 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10001890 # wrapper loop:
1891 Wrapped.__wrapped__ = Wrapped
1892 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
1893 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001894
1895 def test_signature_on_lambdas(self):
1896 self.assertEqual(self.signature((lambda a=10: a)),
1897 ((('a', 10, ..., "positional_or_keyword"),),
1898 ...))
1899
1900 def test_signature_equality(self):
1901 def foo(a, *, b:int) -> float: pass
1902 self.assertNotEqual(inspect.signature(foo), 42)
1903
1904 def bar(a, *, b:int) -> float: pass
1905 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1906
1907 def bar(a, *, b:int) -> int: pass
1908 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1909
1910 def bar(a, *, b:int): pass
1911 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1912
1913 def bar(a, *, b:int=42) -> float: pass
1914 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1915
1916 def bar(a, *, c) -> float: pass
1917 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1918
1919 def bar(a, b:int) -> float: pass
1920 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1921 def spam(b:int, a) -> float: pass
1922 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
1923
1924 def foo(*, a, b, c): pass
1925 def bar(*, c, b, a): pass
1926 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1927
1928 def foo(*, a=1, b, c): pass
1929 def bar(*, c, b, a=1): pass
1930 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1931
1932 def foo(pos, *, a=1, b, c): pass
1933 def bar(pos, *, c, b, a=1): pass
1934 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1935
1936 def foo(pos, *, a, b, c): pass
1937 def bar(pos, *, c, b, a=1): pass
1938 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1939
1940 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
1941 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
1942 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1943
1944 def test_signature_unhashable(self):
1945 def foo(a): pass
1946 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001947 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001948 hash(sig)
1949
1950 def test_signature_str(self):
1951 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
1952 pass
1953 self.assertEqual(str(inspect.signature(foo)),
1954 '(a:int=1, *, b, c=None, **kwargs) -> 42')
1955
1956 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
1957 pass
1958 self.assertEqual(str(inspect.signature(foo)),
1959 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
1960
1961 def foo():
1962 pass
1963 self.assertEqual(str(inspect.signature(foo)), '()')
1964
1965 def test_signature_str_positional_only(self):
1966 P = inspect.Parameter
1967
1968 def test(a_po, *, b, **kwargs):
1969 return a_po, kwargs
1970
1971 sig = inspect.signature(test)
1972 new_params = list(sig.parameters.values())
1973 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
1974 test.__signature__ = sig.replace(parameters=new_params)
1975
1976 self.assertEqual(str(inspect.signature(test)),
1977 '(<a_po>, *, b, **kwargs)')
1978
1979 sig = inspect.signature(test)
1980 new_params = list(sig.parameters.values())
1981 new_params[0] = new_params[0].replace(name=None)
1982 test.__signature__ = sig.replace(parameters=new_params)
1983 self.assertEqual(str(inspect.signature(test)),
1984 '(<0>, *, b, **kwargs)')
1985
1986 def test_signature_replace_anno(self):
1987 def test() -> 42:
1988 pass
1989
1990 sig = inspect.signature(test)
1991 sig = sig.replace(return_annotation=None)
1992 self.assertIs(sig.return_annotation, None)
1993 sig = sig.replace(return_annotation=sig.empty)
1994 self.assertIs(sig.return_annotation, sig.empty)
1995 sig = sig.replace(return_annotation=42)
1996 self.assertEqual(sig.return_annotation, 42)
1997 self.assertEqual(sig, inspect.signature(test))
1998
1999
2000class TestParameterObject(unittest.TestCase):
2001 def test_signature_parameter_kinds(self):
2002 P = inspect.Parameter
2003 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2004 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2005
2006 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2007 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2008
2009 def test_signature_parameter_object(self):
2010 p = inspect.Parameter('foo', default=10,
2011 kind=inspect.Parameter.POSITIONAL_ONLY)
2012 self.assertEqual(p.name, 'foo')
2013 self.assertEqual(p.default, 10)
2014 self.assertIs(p.annotation, p.empty)
2015 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2016
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002017 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002018 inspect.Parameter('foo', default=10, kind='123')
2019
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002020 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002021 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2022
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002023 with self.assertRaisesRegex(ValueError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002024 'non-positional-only parameter'):
2025 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2026
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002027 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002028 inspect.Parameter('a', default=42,
2029 kind=inspect.Parameter.VAR_KEYWORD)
2030
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002031 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002032 inspect.Parameter('a', default=42,
2033 kind=inspect.Parameter.VAR_POSITIONAL)
2034
2035 p = inspect.Parameter('a', default=42,
2036 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002037 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002038 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2039
2040 self.assertTrue(repr(p).startswith('<Parameter'))
2041
2042 def test_signature_parameter_equality(self):
2043 P = inspect.Parameter
2044 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2045
2046 self.assertEqual(p, p)
2047 self.assertNotEqual(p, 42)
2048
2049 self.assertEqual(p, P('foo', default=42,
2050 kind=inspect.Parameter.KEYWORD_ONLY))
2051
2052 def test_signature_parameter_unhashable(self):
2053 p = inspect.Parameter('foo', default=42,
2054 kind=inspect.Parameter.KEYWORD_ONLY)
2055
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002056 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002057 hash(p)
2058
2059 def test_signature_parameter_replace(self):
2060 p = inspect.Parameter('foo', default=42,
2061 kind=inspect.Parameter.KEYWORD_ONLY)
2062
2063 self.assertIsNot(p, p.replace())
2064 self.assertEqual(p, p.replace())
2065
2066 p2 = p.replace(annotation=1)
2067 self.assertEqual(p2.annotation, 1)
2068 p2 = p2.replace(annotation=p2.empty)
2069 self.assertEqual(p, p2)
2070
2071 p2 = p2.replace(name='bar')
2072 self.assertEqual(p2.name, 'bar')
2073 self.assertNotEqual(p2, p)
2074
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002075 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002076 p2 = p2.replace(name=p2.empty)
2077
2078 p2 = p2.replace(name='foo', default=None)
2079 self.assertIs(p2.default, None)
2080 self.assertNotEqual(p2, p)
2081
2082 p2 = p2.replace(name='foo', default=p2.empty)
2083 self.assertIs(p2.default, p2.empty)
2084
2085
2086 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2087 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2088 self.assertNotEqual(p2, p)
2089
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002090 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002091 p2 = p2.replace(kind=p2.empty)
2092
2093 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2094 self.assertEqual(p2, p)
2095
2096 def test_signature_parameter_positional_only(self):
2097 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
2098 self.assertEqual(str(p), '<>')
2099
2100 p = p.replace(name='1')
2101 self.assertEqual(str(p), '<1>')
2102
2103 def test_signature_parameter_immutability(self):
2104 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
2105
2106 with self.assertRaises(AttributeError):
2107 p.foo = 'bar'
2108
2109 with self.assertRaises(AttributeError):
2110 p.kind = 123
2111
2112
2113class TestSignatureBind(unittest.TestCase):
2114 @staticmethod
2115 def call(func, *args, **kwargs):
2116 sig = inspect.signature(func)
2117 ba = sig.bind(*args, **kwargs)
2118 return func(*ba.args, **ba.kwargs)
2119
2120 def test_signature_bind_empty(self):
2121 def test():
2122 return 42
2123
2124 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002125 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002126 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002127 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002128 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002129 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002130 self.call(test, spam=1)
2131
2132 def test_signature_bind_var(self):
2133 def test(*args, **kwargs):
2134 return args, kwargs
2135
2136 self.assertEqual(self.call(test), ((), {}))
2137 self.assertEqual(self.call(test, 1), ((1,), {}))
2138 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2139 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2140 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2141 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2142 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2143 ((1, 2), {'foo': 'bar'}))
2144
2145 def test_signature_bind_just_args(self):
2146 def test(a, b, c):
2147 return a, b, c
2148
2149 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2150
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002151 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002152 self.call(test, 1, 2, 3, 4)
2153
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002154 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002155 self.call(test, 1)
2156
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002157 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002158 self.call(test)
2159
2160 def test(a, b, c=10):
2161 return a, b, c
2162 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2163 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2164
2165 def test(a=1, b=2, c=3):
2166 return a, b, c
2167 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2168 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2169 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2170
2171 def test_signature_bind_varargs_order(self):
2172 def test(*args):
2173 return args
2174
2175 self.assertEqual(self.call(test), ())
2176 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2177
2178 def test_signature_bind_args_and_varargs(self):
2179 def test(a, b, c=3, *args):
2180 return a, b, c, args
2181
2182 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2183 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2184 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2185 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2186
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002187 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002188 "multiple values for argument 'c'"):
2189 self.call(test, 1, 2, 3, c=4)
2190
2191 def test_signature_bind_just_kwargs(self):
2192 def test(**kwargs):
2193 return kwargs
2194
2195 self.assertEqual(self.call(test), {})
2196 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2197 {'foo': 'bar', 'spam': 'ham'})
2198
2199 def test_signature_bind_args_and_kwargs(self):
2200 def test(a, b, c=3, **kwargs):
2201 return a, b, c, kwargs
2202
2203 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2204 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2205 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2206 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2207 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2208 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2209 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2210 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2211 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2212 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2213 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2214 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2215 (1, 2, 4, {'foo': 'bar'}))
2216 self.assertEqual(self.call(test, c=5, a=4, b=3),
2217 (4, 3, 5, {}))
2218
2219 def test_signature_bind_kwonly(self):
2220 def test(*, foo):
2221 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002222 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002223 'too many positional arguments'):
2224 self.call(test, 1)
2225 self.assertEqual(self.call(test, foo=1), 1)
2226
2227 def test(a, *, foo=1, bar):
2228 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002229 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002230 "'bar' parameter lacking default value"):
2231 self.call(test, 1)
2232
2233 def test(foo, *, bar):
2234 return foo, bar
2235 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2236 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2237
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002238 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002239 'too many keyword arguments'):
2240 self.call(test, bar=2, foo=1, spam=10)
2241
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002242 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002243 'too many positional arguments'):
2244 self.call(test, 1, 2)
2245
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002246 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002247 'too many positional arguments'):
2248 self.call(test, 1, 2, bar=2)
2249
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002250 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002251 'too many keyword arguments'):
2252 self.call(test, 1, bar=2, spam='ham')
2253
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002254 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002255 "'bar' parameter lacking default value"):
2256 self.call(test, 1)
2257
2258 def test(foo, *, bar, **bin):
2259 return foo, bar, bin
2260 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2261 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2262 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2263 (1, 2, {'spam': 'ham'}))
2264 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2265 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002266 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002267 "'foo' parameter lacking default value"):
2268 self.call(test, spam='ham', bar=2)
2269 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2270 (1, 2, {'bin': 1, 'spam': 10}))
2271
2272 def test_signature_bind_arguments(self):
2273 def test(a, *args, b, z=100, **kwargs):
2274 pass
2275 sig = inspect.signature(test)
2276 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2277 # we won't have 'z' argument in the bound arguments object, as we didn't
2278 # pass it to the 'bind'
2279 self.assertEqual(tuple(ba.arguments.items()),
2280 (('a', 10), ('args', (20,)), ('b', 30),
2281 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2282 self.assertEqual(ba.kwargs,
2283 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2284 self.assertEqual(ba.args, (10, 20))
2285
2286 def test_signature_bind_positional_only(self):
2287 P = inspect.Parameter
2288
2289 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2290 return a_po, b_po, c_po, foo, bar, kwargs
2291
2292 sig = inspect.signature(test)
2293 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2294 for name in ('a_po', 'b_po', 'c_po'):
2295 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2296 new_sig = sig.replace(parameters=new_params.values())
2297 test.__signature__ = new_sig
2298
2299 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2300 (1, 2, 4, 5, 6, {}))
2301
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002302 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002303 self.call(test, 1, 2, c_po=4)
2304
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002305 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002306 self.call(test, a_po=1, b_po=2)
2307
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002308 def test_signature_bind_with_self_arg(self):
2309 # Issue #17071: one of the parameters is named "self
2310 def test(a, self, b):
2311 pass
2312 sig = inspect.signature(test)
2313 ba = sig.bind(1, 2, 3)
2314 self.assertEqual(ba.args, (1, 2, 3))
2315 ba = sig.bind(1, self=2, b=3)
2316 self.assertEqual(ba.args, (1, 2, 3))
2317
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002318
2319class TestBoundArguments(unittest.TestCase):
2320 def test_signature_bound_arguments_unhashable(self):
2321 def foo(a): pass
2322 ba = inspect.signature(foo).bind(1)
2323
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002324 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002325 hash(ba)
2326
2327 def test_signature_bound_arguments_equality(self):
2328 def foo(a): pass
2329 ba = inspect.signature(foo).bind(1)
2330 self.assertEqual(ba, ba)
2331
2332 ba2 = inspect.signature(foo).bind(1)
2333 self.assertEqual(ba, ba2)
2334
2335 ba3 = inspect.signature(foo).bind(2)
2336 self.assertNotEqual(ba, ba3)
2337 ba3.arguments['a'] = 1
2338 self.assertEqual(ba, ba3)
2339
2340 def bar(b): pass
2341 ba4 = inspect.signature(bar).bind(1)
2342 self.assertNotEqual(ba, ba4)
2343
2344
Nick Coghlane8c45d62013-07-28 20:00:01 +10002345class TestUnwrap(unittest.TestCase):
2346
2347 def test_unwrap_one(self):
2348 def func(a, b):
2349 return a + b
2350 wrapper = functools.lru_cache(maxsize=20)(func)
2351 self.assertIs(inspect.unwrap(wrapper), func)
2352
2353 def test_unwrap_several(self):
2354 def func(a, b):
2355 return a + b
2356 wrapper = func
2357 for __ in range(10):
2358 @functools.wraps(wrapper)
2359 def wrapper():
2360 pass
2361 self.assertIsNot(wrapper.__wrapped__, func)
2362 self.assertIs(inspect.unwrap(wrapper), func)
2363
2364 def test_stop(self):
2365 def func1(a, b):
2366 return a + b
2367 @functools.wraps(func1)
2368 def func2():
2369 pass
2370 @functools.wraps(func2)
2371 def wrapper():
2372 pass
2373 func2.stop_here = 1
2374 unwrapped = inspect.unwrap(wrapper,
2375 stop=(lambda f: hasattr(f, "stop_here")))
2376 self.assertIs(unwrapped, func2)
2377
2378 def test_cycle(self):
2379 def func1(): pass
2380 func1.__wrapped__ = func1
2381 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2382 inspect.unwrap(func1)
2383
2384 def func2(): pass
2385 func2.__wrapped__ = func1
2386 func1.__wrapped__ = func2
2387 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2388 inspect.unwrap(func1)
2389 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2390 inspect.unwrap(func2)
2391
2392 def test_unhashable(self):
2393 def func(): pass
2394 func.__wrapped__ = None
2395 class C:
2396 __hash__ = None
2397 __wrapped__ = func
2398 self.assertIsNone(inspect.unwrap(C()))
2399
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002400class TestMain(unittest.TestCase):
2401 def test_only_source(self):
2402 module = importlib.import_module('unittest')
2403 rc, out, err = assert_python_ok('-m', 'inspect',
2404 'unittest')
2405 lines = out.decode().splitlines()
2406 # ignore the final newline
2407 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
2408 self.assertEqual(err, b'')
2409
2410 def test_qualname_source(self):
2411 module = importlib.import_module('concurrent.futures')
2412 member = getattr(module, 'ThreadPoolExecutor')
2413 rc, out, err = assert_python_ok('-m', 'inspect',
2414 'concurrent.futures:ThreadPoolExecutor')
2415 lines = out.decode().splitlines()
2416 # ignore the final newline
2417 self.assertEqual(lines[:-1],
2418 inspect.getsource(member).splitlines())
2419 self.assertEqual(err, b'')
2420
2421 def test_builtins(self):
2422 module = importlib.import_module('unittest')
2423 _, out, err = assert_python_failure('-m', 'inspect',
2424 'sys')
2425 lines = err.decode().splitlines()
2426 self.assertEqual(lines, ["Can't get info for builtin modules."])
2427
2428 def test_details(self):
2429 module = importlib.import_module('unittest')
2430 rc, out, err = assert_python_ok('-m', 'inspect',
2431 'unittest', '--details')
2432 output = out.decode()
2433 # Just a quick sanity check on the output
2434 self.assertIn(module.__name__, output)
2435 self.assertIn(module.__file__, output)
2436 self.assertIn(module.__cached__, output)
2437 self.assertEqual(err, b'')
2438
2439
2440
Nick Coghlane8c45d62013-07-28 20:00:01 +10002441
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002442def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00002443 run_unittest(
2444 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
2445 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
2446 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00002447 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002448 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002449 TestBoundArguments, TestGetClosureVars, TestUnwrap, TestMain
Michael Foord95fc51d2010-11-20 15:07:30 +00002450 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00002451
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002452if __name__ == "__main__":
2453 test_main()