blob: a34a418ccab41706a9c92642bb90e73652ff6a16 [file] [log] [blame]
Guido van Rossum813b0e52007-05-21 18:11:34 +00001import collections
Larry Hastings5c661892014-01-24 06:17:25 -08002import datetime
Nick Coghlane8c45d62013-07-28 20:00:01 +10003import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004import importlib
Larry Hastings5c661892014-01-24 06:17:25 -08005import inspect
6import io
7import linecache
8import os
Christian Heimesa3538eb2007-11-06 11:44:48 +00009from os.path import normcase
Larry Hastings5c661892014-01-24 06:17:25 -080010import _pickle
11import re
12import shutil
13import sys
14import types
15import unicodedata
16import unittest
17
Brett Cannon634a8fc2013-10-02 10:25:42 -040018try:
19 from concurrent.futures import ThreadPoolExecutor
20except ImportError:
21 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000022
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020023from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -080024from test.support import MISSING_C_DOCSTRINGS
Nick Coghlanf94a16b2013-09-22 22:46:49 +100025from test.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000026from test import inspect_fodder as mod
27from test import inspect_fodder2 as mod2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000028
R. David Murray74b89242009-05-13 17:33:03 +000029
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000030# Functions tested in this suite:
31# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000032# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
33# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
34# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
35# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000036
Nick Coghlanf088e5e2008-12-14 11:50:48 +000037# NOTE: There are some additional tests relating to interaction with
38# zipimport in the test_zipimport_support test module.
39
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000040modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000041if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000042 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000043
Christian Heimesa3538eb2007-11-06 11:44:48 +000044# Normalize file names: on Windows, the case of file names of compiled
45# modules depends on the path used to start the python executable.
46modfile = normcase(modfile)
47
48def revise(filename, *args):
49 return (normcase(filename),) + args
50
Georg Brandl1a3284e2007-12-02 09:40:06 +000051import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000052
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000053git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000054
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000055class IsTestBase(unittest.TestCase):
56 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
57 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000058 inspect.ismodule, inspect.istraceback,
59 inspect.isgenerator, inspect.isgeneratorfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000060
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000061 def istest(self, predicate, exp):
62 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000063 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000064
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000065 for other in self.predicates - set([predicate]):
Christian Heimes7131fd92008-02-19 14:21:46 +000066 if predicate == inspect.isgeneratorfunction and\
67 other == inspect.isfunction:
68 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000069 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000070
Christian Heimes7131fd92008-02-19 14:21:46 +000071def generator_function_example(self):
72 for i in range(2):
73 yield i
74
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000075class TestPredicates(IsTestBase):
Christian Heimes227c8002008-03-03 20:34:40 +000076 def test_sixteen(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +000077 count = len([x for x in dir(inspect) if x.startswith('is')])
Christian Heimes7131fd92008-02-19 14:21:46 +000078 # This test is here for remember you to update Doc/library/inspect.rst
Christian Heimes78644762008-03-04 23:39:23 +000079 # which claims there are 16 such functions
Christian Heimes227c8002008-03-03 20:34:40 +000080 expected = 16
Thomas Wouters0e3f5912006-08-11 14:57:12 +000081 err_msg = "There are %d (not %d) is* functions" % (count, expected)
82 self.assertEqual(count, expected, err_msg)
Tim Peters5a9fb3c2005-01-07 16:01:32 +000083
Christian Heimes7131fd92008-02-19 14:21:46 +000084
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000085 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +020086 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000087 self.istest(inspect.isbuiltin, 'sys.exit')
88 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +000089 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +020090 try:
91 1/0
92 except:
93 tb = sys.exc_info()[2]
94 self.istest(inspect.isframe, 'tb.tb_frame')
95 self.istest(inspect.istraceback, 'tb')
96 if hasattr(types, 'GetSetDescriptorType'):
97 self.istest(inspect.isgetsetdescriptor,
98 'type(tb.tb_frame).f_locals')
99 else:
100 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
101 finally:
102 # Clear traceback and all the frames and local variables hanging to it.
103 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000104 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000105 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000106 self.istest(inspect.ismethod, 'git.argue')
107 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000108 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000109 self.istest(inspect.isgenerator, '(x for x in range(2))')
110 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000111 if hasattr(types, 'MemberDescriptorType'):
112 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
113 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000114 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000115
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000116 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000117 self.assertTrue(inspect.isroutine(mod.spam))
118 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000119
Benjamin Petersonc4656002009-01-17 22:41:18 +0000120 def test_isclass(self):
121 self.istest(inspect.isclass, 'mod.StupidGit')
122 self.assertTrue(inspect.isclass(list))
123
124 class CustomGetattr(object):
125 def __getattr__(self, attr):
126 return None
127 self.assertFalse(inspect.isclass(CustomGetattr()))
128
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000129 def test_get_slot_members(self):
130 class C(object):
131 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000132 x = C()
133 x.a = 42
134 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000135 self.assertIn('a', members)
136 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000137
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000138 def test_isabstract(self):
139 from abc import ABCMeta, abstractmethod
140
141 class AbstractClassExample(metaclass=ABCMeta):
142
143 @abstractmethod
144 def foo(self):
145 pass
146
147 class ClassExample(AbstractClassExample):
148 def foo(self):
149 pass
150
151 a = ClassExample()
152
153 # Test general behaviour.
154 self.assertTrue(inspect.isabstract(AbstractClassExample))
155 self.assertFalse(inspect.isabstract(ClassExample))
156 self.assertFalse(inspect.isabstract(a))
157 self.assertFalse(inspect.isabstract(int))
158 self.assertFalse(inspect.isabstract(5))
159
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000160
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000161class TestInterpreterStack(IsTestBase):
162 def __init__(self, *args, **kwargs):
163 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000164
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000165 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000166
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000167 def test_abuse_done(self):
168 self.istest(inspect.istraceback, 'git.ex[2]')
169 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000170
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000171 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000172 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000173 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000174 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000175 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000176 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000177 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000178 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000179 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000180 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000181
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000182 def test_trace(self):
183 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000184 self.assertEqual(revise(*git.tr[0][1:]),
185 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
186 self.assertEqual(revise(*git.tr[1][1:]),
187 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
188 self.assertEqual(revise(*git.tr[2][1:]),
189 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000190
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000191 def test_frame(self):
192 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
193 self.assertEqual(args, ['x', 'y'])
194 self.assertEqual(varargs, None)
195 self.assertEqual(varkw, None)
196 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
197 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
198 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000199
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000200 def test_previous_frame(self):
201 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000202 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000203 self.assertEqual(varargs, 'g')
204 self.assertEqual(varkw, 'h')
205 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000206 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000207
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000208class GetSourceBase(unittest.TestCase):
209 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000210 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000211
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000212 def __init__(self, *args, **kwargs):
213 unittest.TestCase.__init__(self, *args, **kwargs)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000214
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000215 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000216 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000217
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000218 def sourcerange(self, top, bottom):
219 lines = self.source.split("\n")
220 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000221
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000222 def assertSourceEqual(self, obj, top, bottom):
223 self.assertEqual(inspect.getsource(obj),
224 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000225
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000226class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000227 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000228
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000229 def test_getclasses(self):
230 classes = inspect.getmembers(mod, inspect.isclass)
231 self.assertEqual(classes,
232 [('FesteringGob', mod.FesteringGob),
233 ('MalodorousPervert', mod.MalodorousPervert),
234 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300235 ('StupidGit', mod.StupidGit),
236 ('Tit', mod.MalodorousPervert),
237 ])
238 tree = inspect.getclasstree([cls[1] for cls in classes])
239 self.assertEqual(tree,
240 [(object, ()),
241 [(mod.ParrotDroppings, (object,)),
242 [(mod.FesteringGob, (mod.MalodorousPervert,
243 mod.ParrotDroppings))
244 ],
245 (mod.StupidGit, (object,)),
246 [(mod.MalodorousPervert, (mod.StupidGit,)),
247 [(mod.FesteringGob, (mod.MalodorousPervert,
248 mod.ParrotDroppings))
249 ]
250 ]
251 ]
252 ])
253 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000254 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000255 [(object, ()),
256 [(mod.ParrotDroppings, (object,)),
257 (mod.StupidGit, (object,)),
258 [(mod.MalodorousPervert, (mod.StupidGit,)),
259 [(mod.FesteringGob, (mod.MalodorousPervert,
260 mod.ParrotDroppings))
261 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000262 ]
263 ]
264 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000265
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000266 def test_getfunctions(self):
267 functions = inspect.getmembers(mod, inspect.isfunction)
268 self.assertEqual(functions, [('eggs', mod.eggs),
269 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000270
R. David Murray378c0cf2010-02-24 01:46:21 +0000271 @unittest.skipIf(sys.flags.optimize >= 2,
272 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000273 def test_getdoc(self):
274 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
275 self.assertEqual(inspect.getdoc(mod.StupidGit),
276 'A longer,\n\nindented\n\ndocstring.')
277 self.assertEqual(inspect.getdoc(git.abuse),
278 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000279
Georg Brandl0c77a822008-06-10 16:37:50 +0000280 def test_cleandoc(self):
281 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
282 'An\nindented\ndocstring.')
283
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000284 def test_getcomments(self):
285 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
286 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000287
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000288 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000289 # Check actual module
290 self.assertEqual(inspect.getmodule(mod), mod)
291 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000292 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000293 # Check a method (no __module__ attribute, falls back to filename)
294 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
295 # Do it again (check the caching isn't broken)
296 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
297 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000298 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000299 # Check filename override
300 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000301
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000302 def test_getsource(self):
303 self.assertSourceEqual(git.abuse, 29, 39)
304 self.assertSourceEqual(mod.StupidGit, 21, 46)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000305
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000306 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000307 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
308 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000309 fn = "_non_existing_filename_used_for_sourcefile_test.py"
310 co = compile("None", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000311 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000312 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200313 try:
314 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
315 finally:
316 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000317
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000318 def test_getfile(self):
319 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000320
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500321 def test_getfile_class_without_module(self):
322 class CM(type):
323 @property
324 def __module__(cls):
325 raise AttributeError
326 class C(metaclass=CM):
327 pass
328 with self.assertRaises(TypeError):
329 inspect.getfile(C)
330
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000331 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000332 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000333 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000334 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000335 m.__file__ = "<string>" # hopefully not a real filename...
336 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000337 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000338 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000339 del sys.modules[name]
340 inspect.getmodule(compile('a=10','','single'))
341
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500342 def test_proceed_with_fake_filename(self):
343 '''doctest monkeypatches linecache to enable inspection'''
344 fn, source = '<test>', 'def x(): pass\n'
345 getlines = linecache.getlines
346 def monkey(filename, module_globals=None):
347 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300348 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500349 else:
350 return getlines(filename, module_globals)
351 linecache.getlines = monkey
352 try:
353 ns = {}
354 exec(compile(source, fn, 'single'), ns)
355 inspect.getsource(ns["x"])
356 finally:
357 linecache.getlines = getlines
358
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000359class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000360 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000361
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000362 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000363 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000364
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000365 def test_replacing_decorator(self):
366 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000367
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000368class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000369 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000370 def test_oneline_lambda(self):
371 # Test inspect.getsource with a one-line lambda function.
372 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000373
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000374 def test_threeline_lambda(self):
375 # Test inspect.getsource with a three-line lambda function,
376 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000377 self.assertSourceEqual(mod2.tll, 28, 30)
378
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000379 def test_twoline_indented_lambda(self):
380 # Test inspect.getsource with a two-line lambda function,
381 # where the second line _is_ indented.
382 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000383
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000384 def test_onelinefunc(self):
385 # Test inspect.getsource with a regular one-line function.
386 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000387
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000388 def test_manyargs(self):
389 # Test inspect.getsource with a regular function where
390 # the arguments are on two lines and _not_ indented and
391 # the body on the second line with the last arguments.
392 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000393
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000394 def test_twolinefunc(self):
395 # Test inspect.getsource with a regular function where
396 # the body is on two lines, following the argument list and
397 # continued on the next line by a \\.
398 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000399
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000400 def test_lambda_in_list(self):
401 # Test inspect.getsource with a one-line lambda function
402 # defined in a list, indented.
403 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000404
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000405 def test_anonymous(self):
406 # Test inspect.getsource with a lambda function defined
407 # as argument to another function.
408 self.assertSourceEqual(mod2.anonymous, 55, 55)
409
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000410class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000411 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000412
413 def test_with_comment(self):
414 self.assertSourceEqual(mod2.with_comment, 58, 59)
415
416 def test_multiline_sig(self):
417 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
418
Armin Rigodd5c0232005-09-25 11:45:45 +0000419 def test_nested_class(self):
420 self.assertSourceEqual(mod2.func69().func71, 71, 72)
421
422 def test_one_liner_followed_by_non_name(self):
423 self.assertSourceEqual(mod2.func77, 77, 77)
424
425 def test_one_liner_dedent_non_name(self):
426 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
427
428 def test_with_comment_instead_of_docstring(self):
429 self.assertSourceEqual(mod2.func88, 88, 90)
430
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000431 def test_method_in_dynamic_class(self):
432 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
433
R. David Murrayb5655772009-05-14 16:17:50 +0000434 @unittest.skipIf(
435 not hasattr(unicodedata, '__file__') or
436 unicodedata.__file__[-4:] in (".pyc", ".pyo"),
437 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000438 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200439 self.assertRaises(OSError, inspect.getsource, unicodedata)
440 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000441
R. David Murraya1b37402010-06-17 02:04:29 +0000442 def test_findsource_code_in_linecache(self):
443 lines = ["x=1"]
444 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200445 self.assertRaises(OSError, inspect.findsource, co)
446 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000447 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200448 try:
449 self.assertEqual(inspect.findsource(co), (lines,0))
450 self.assertEqual(inspect.getsource(co), lines[0])
451 finally:
452 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000453
Ezio Melotti1b145922013-03-30 05:17:24 +0200454 def test_findsource_without_filename(self):
455 for fname in ['', '<string>']:
456 co = compile('x=1', fname, "exec")
457 self.assertRaises(IOError, inspect.findsource, co)
458 self.assertRaises(IOError, inspect.getsource, co)
459
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000460class TestNoEOL(GetSourceBase):
461 def __init__(self, *args, **kwargs):
462 self.tempdir = TESTFN + '_dir'
463 os.mkdir(self.tempdir)
464 with open(os.path.join(self.tempdir,
465 'inspect_fodder3%spy' % os.extsep), 'w') as f:
466 f.write("class X:\n pass # No EOL")
467 with DirsOnSysPath(self.tempdir):
468 import inspect_fodder3 as mod3
469 self.fodderModule = mod3
470 GetSourceBase.__init__(self, *args, **kwargs)
471
472 def tearDown(self):
473 shutil.rmtree(self.tempdir)
474
475 def test_class(self):
476 self.assertSourceEqual(self.fodderModule.X, 1, 2)
477
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100478
479class _BrokenDataDescriptor(object):
480 """
481 A broken data descriptor. See bug #1785.
482 """
483 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700484 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100485
486 def __set__(*args):
487 raise RuntimeError
488
489 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700490 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100491
492
493class _BrokenMethodDescriptor(object):
494 """
495 A broken method descriptor. See bug #1785.
496 """
497 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700498 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100499
500 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700501 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100502
503
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000504# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000505def attrs_wo_objs(cls):
506 return [t[:3] for t in inspect.classify_class_attrs(cls)]
507
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100508
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000509class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000510 def test_newstyle_mro(self):
511 # The same w/ new-class MRO.
512 class A(object): pass
513 class B(A): pass
514 class C(A): pass
515 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000516
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000517 expected = (D, B, C, A, object)
518 got = inspect.getmro(D)
519 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000520
Christian Heimes3795b532007-11-08 13:48:53 +0000521 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
522 varkw_e=None, defaults_e=None, formatted=None):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000523 args, varargs, varkw, defaults = inspect.getargspec(routine)
524 self.assertEqual(args, args_e)
525 self.assertEqual(varargs, varargs_e)
526 self.assertEqual(varkw, varkw_e)
527 self.assertEqual(defaults, defaults_e)
528 if formatted is not None:
529 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
530 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000531
Christian Heimes3795b532007-11-08 13:48:53 +0000532 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
533 varkw_e=None, defaults_e=None,
534 kwonlyargs_e=[], kwonlydefaults_e=None,
535 ann_e={}, formatted=None):
536 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
537 inspect.getfullargspec(routine)
538 self.assertEqual(args, args_e)
539 self.assertEqual(varargs, varargs_e)
540 self.assertEqual(varkw, varkw_e)
541 self.assertEqual(defaults, defaults_e)
542 self.assertEqual(kwonlyargs, kwonlyargs_e)
543 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
544 self.assertEqual(ann, ann_e)
545 if formatted is not None:
546 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
547 kwonlyargs, kwonlydefaults, ann),
548 formatted)
549
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000550 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000551 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000552
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000553 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000554 ['a', 'b', 'c', 'd', 'e', 'f'],
555 'g', 'h', (3, 4, 5),
556 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000557
Christian Heimes3795b532007-11-08 13:48:53 +0000558 self.assertRaises(ValueError, self.assertArgSpecEquals,
559 mod2.keyworded, [])
560
561 self.assertRaises(ValueError, self.assertArgSpecEquals,
562 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000563 self.assertRaises(ValueError, self.assertArgSpecEquals,
564 mod2.keyword_only_arg, [])
565
Christian Heimes3795b532007-11-08 13:48:53 +0000566
567 def test_getfullargspec(self):
568 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
569 kwonlyargs_e=['arg2'],
570 kwonlydefaults_e={'arg2':1},
571 formatted='(*arg1, arg2=1)')
572
573 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000574 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000575 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000576 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
577 kwonlyargs_e=['arg'],
578 formatted='(*, arg)')
579
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500580 def test_getfullargspec_signature_attr(self):
581 def test():
582 pass
583 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
584 test.__signature__ = inspect.Signature(parameters=(spam_param,))
585
586 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
587
Yury Selivanov4cb93912014-01-29 11:54:12 -0500588 def test_getfullargspec_signature_annos(self):
589 def test(a:'spam') -> 'ham': pass
590 spec = inspect.getfullargspec(test)
591 self.assertEqual(test.__annotations__, spec.annotations)
592
593 def test(): pass
594 spec = inspect.getfullargspec(test)
595 self.assertEqual(test.__annotations__, spec.annotations)
596
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500597 @unittest.skipIf(MISSING_C_DOCSTRINGS,
598 "Signature information for builtins requires docstrings")
599 def test_getfullargspec_builtin_methods(self):
600 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
601 args_e=['self', 'obj'], formatted='(self, obj)')
602
603 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
604 args_e=['self', 'obj'], formatted='(self, obj)')
605
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200606 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500607 @unittest.skipIf(MISSING_C_DOCSTRINGS,
608 "Signature information for builtins requires docstrings")
609 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200610 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500611 builtin = _testcapi.docstring_with_signature_with_defaults
612 spec = inspect.getfullargspec(builtin)
613 self.assertEqual(spec.defaults[0], 'avocado')
614
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200615 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500616 @unittest.skipIf(MISSING_C_DOCSTRINGS,
617 "Signature information for builtins requires docstrings")
618 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200619 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500620 builtin = _testcapi.docstring_no_signature
621 with self.assertRaises(TypeError):
622 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000623
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000624 def test_getargspec_method(self):
625 class A(object):
626 def m(self):
627 pass
628 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000629
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000630 def test_classify_newstyle(self):
631 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000632
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000633 def s(): pass
634 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000635
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000636 def c(cls): pass
637 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000638
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000639 def getp(self): pass
640 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000641
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000642 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000643
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000644 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000645
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000646 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000647
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100648 dd = _BrokenDataDescriptor()
649 md = _BrokenMethodDescriptor()
650
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000651 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500652
653 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
654 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
655
Benjamin Peterson577473f2010-01-19 00:09:57 +0000656 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
657 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
658 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000659 self.assertIn(('m', 'method', A), attrs,
660 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000661 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
662 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100663 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
664 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000665
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000666 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000667
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000668 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000669
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000670 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000671 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
672 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
673 self.assertIn(('p', 'property', A), attrs, 'missing property')
674 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
675 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
676 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100677 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
678 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000679
680
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000681 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000682
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000683 def m(self): pass
684 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000685
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000686 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000687 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
688 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
689 self.assertIn(('p', 'property', A), attrs, 'missing property')
690 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
691 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
692 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100693 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
694 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000695
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000696 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000697
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000698 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000699
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000700 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000701 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
702 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
703 self.assertIn(('p', 'property', A), attrs, 'missing property')
704 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
705 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
706 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100707 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
708 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
709
710 def test_classify_builtin_types(self):
711 # Simple sanity check that all built-in types can have their
712 # attributes classified.
713 for name in dir(__builtins__):
714 builtin = getattr(__builtins__, name)
715 if isinstance(builtin, type):
716 inspect.classify_class_attrs(builtin)
717
Ethan Furman63c141c2013-10-18 00:27:39 -0700718 def test_classify_DynamicClassAttribute(self):
719 class Meta(type):
720 def __getattr__(self, name):
721 if name == 'ham':
722 return 'spam'
723 return super().__getattr__(name)
724 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700725 @types.DynamicClassAttribute
726 def ham(self):
727 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700728 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
729 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700730 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700731 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
732
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700733 def test_classify_metaclass_class_attribute(self):
734 class Meta(type):
735 fish = 'slap'
736 def __dir__(self):
737 return ['__class__', '__modules__', '__name__', 'fish']
738 class Class(metaclass=Meta):
739 pass
740 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
741 self.assertIn(should_find, inspect.classify_class_attrs(Class))
742
Ethan Furman63c141c2013-10-18 00:27:39 -0700743 def test_classify_VirtualAttribute(self):
744 class Meta(type):
745 def __dir__(cls):
746 return ['__class__', '__module__', '__name__', 'BOOM']
747 def __getattr__(self, name):
748 if name =='BOOM':
749 return 42
750 return super().__getattr(name)
751 class Class(metaclass=Meta):
752 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700753 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700754 self.assertIn(should_find, inspect.classify_class_attrs(Class))
755
756 def test_classify_VirtualAttribute_multi_classes(self):
757 class Meta1(type):
758 def __dir__(cls):
759 return ['__class__', '__module__', '__name__', 'one']
760 def __getattr__(self, name):
761 if name =='one':
762 return 1
763 return super().__getattr__(name)
764 class Meta2(type):
765 def __dir__(cls):
766 return ['__class__', '__module__', '__name__', 'two']
767 def __getattr__(self, name):
768 if name =='two':
769 return 2
770 return super().__getattr__(name)
771 class Meta3(Meta1, Meta2):
772 def __dir__(cls):
773 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
774 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
775 def __getattr__(self, name):
776 if name =='three':
777 return 3
778 return super().__getattr__(name)
779 class Class1(metaclass=Meta1):
780 pass
781 class Class2(Class1, metaclass=Meta3):
782 pass
783
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700784 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
785 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
786 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700787 cca = inspect.classify_class_attrs(Class2)
788 for sf in (should_find1, should_find2, should_find3):
789 self.assertIn(sf, cca)
790
791 def test_classify_class_attrs_with_buggy_dir(self):
792 class M(type):
793 def __dir__(cls):
794 return ['__class__', '__name__', 'missing']
795 class C(metaclass=M):
796 pass
797 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
798 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700799
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100800 def test_getmembers_descriptors(self):
801 class A(object):
802 dd = _BrokenDataDescriptor()
803 md = _BrokenMethodDescriptor()
804
805 def pred_wrapper(pred):
806 # A quick'n'dirty way to discard standard attributes of new-style
807 # classes.
808 class Empty(object):
809 pass
810 def wrapped(x):
811 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
812 return False
813 return pred(x)
814 return wrapped
815
816 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
817 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
818
819 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
820 [('md', A.__dict__['md'])])
821 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
822 [('dd', A.__dict__['dd'])])
823
824 class B(A):
825 pass
826
827 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
828 [('md', A.__dict__['md'])])
829 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
830 [('dd', A.__dict__['dd'])])
831
Antoine Pitrou0c603812012-01-18 17:40:18 +0100832 def test_getmembers_method(self):
833 class B:
834 def f(self):
835 pass
836
837 self.assertIn(('f', B.f), inspect.getmembers(B))
838 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
839 b = B()
840 self.assertIn(('f', b.f), inspect.getmembers(b))
841 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
842
Ethan Furmane03ea372013-09-25 07:14:41 -0700843 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -0700844 class M(type):
845 def __getattr__(cls, name):
846 if name == 'eggs':
847 return 'scrambled'
848 return super().__getattr__(name)
849 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -0700850 @types.DynamicClassAttribute
851 def eggs(self):
852 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -0700853 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
854 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
855
856 def test_getmembers_with_buggy_dir(self):
857 class M(type):
858 def __dir__(cls):
859 return ['__class__', '__name__', 'missing']
860 class C(metaclass=M):
861 pass
862 attrs = [a[0] for a in inspect.getmembers(C)]
863 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700864
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000865
Nick Coghlan2f92e542012-06-23 19:39:55 +1000866_global_ref = object()
867class TestGetClosureVars(unittest.TestCase):
868
869 def test_name_resolution(self):
870 # Basic test of the 4 different resolution mechanisms
871 def f(nonlocal_ref):
872 def g(local_ref):
873 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
874 return g
875 _arg = object()
876 nonlocal_vars = {"nonlocal_ref": _arg}
877 global_vars = {"_global_ref": _global_ref}
878 builtin_vars = {"print": print}
879 unbound_names = {"unbound_ref"}
880 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
881 builtin_vars, unbound_names)
882 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
883
884 def test_generator_closure(self):
885 def f(nonlocal_ref):
886 def g(local_ref):
887 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
888 yield
889 return g
890 _arg = object()
891 nonlocal_vars = {"nonlocal_ref": _arg}
892 global_vars = {"_global_ref": _global_ref}
893 builtin_vars = {"print": print}
894 unbound_names = {"unbound_ref"}
895 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
896 builtin_vars, unbound_names)
897 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
898
899 def test_method_closure(self):
900 class C:
901 def f(self, nonlocal_ref):
902 def g(local_ref):
903 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
904 return g
905 _arg = object()
906 nonlocal_vars = {"nonlocal_ref": _arg}
907 global_vars = {"_global_ref": _global_ref}
908 builtin_vars = {"print": print}
909 unbound_names = {"unbound_ref"}
910 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
911 builtin_vars, unbound_names)
912 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
913
914 def test_nonlocal_vars(self):
915 # More complex tests of nonlocal resolution
916 def _nonlocal_vars(f):
917 return inspect.getclosurevars(f).nonlocals
918
919 def make_adder(x):
920 def add(y):
921 return x + y
922 return add
923
924 def curry(func, arg1):
925 return lambda arg2: func(arg1, arg2)
926
927 def less_than(a, b):
928 return a < b
929
930 # The infamous Y combinator.
931 def Y(le):
932 def g(f):
933 return le(lambda x: f(f)(x))
934 Y.g_ref = g
935 return g(g)
936
937 def check_y_combinator(func):
938 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
939
940 inc = make_adder(1)
941 add_two = make_adder(2)
942 greater_than_five = curry(less_than, 5)
943
944 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
945 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
946 self.assertEqual(_nonlocal_vars(greater_than_five),
947 {'arg1': 5, 'func': less_than})
948 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
949 {'x': 3})
950 Y(check_y_combinator)
951
952 def test_getclosurevars_empty(self):
953 def foo(): pass
954 _empty = inspect.ClosureVars({}, {}, {}, set())
955 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
956 self.assertEqual(inspect.getclosurevars(foo), _empty)
957
958 def test_getclosurevars_error(self):
959 class T: pass
960 self.assertRaises(TypeError, inspect.getclosurevars, 1)
961 self.assertRaises(TypeError, inspect.getclosurevars, list)
962 self.assertRaises(TypeError, inspect.getclosurevars, {})
963
Nick Coghlan6c6e2542012-06-23 20:07:39 +1000964 def _private_globals(self):
965 code = """def f(): print(path)"""
966 ns = {}
967 exec(code, ns)
968 return ns["f"], ns
969
970 def test_builtins_fallback(self):
971 f, ns = self._private_globals()
972 ns.pop("__builtins__", None)
973 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
974 self.assertEqual(inspect.getclosurevars(f), expected)
975
976 def test_builtins_as_dict(self):
977 f, ns = self._private_globals()
978 ns["__builtins__"] = {"path":1}
979 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
980 self.assertEqual(inspect.getclosurevars(f), expected)
981
982 def test_builtins_as_module(self):
983 f, ns = self._private_globals()
984 ns["__builtins__"] = os
985 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
986 self.assertEqual(inspect.getclosurevars(f), expected)
987
Nick Coghlan2f92e542012-06-23 19:39:55 +1000988
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000989class TestGetcallargsFunctions(unittest.TestCase):
990
991 def assertEqualCallArgs(self, func, call_params_string, locs=None):
992 locs = dict(locs or {}, func=func)
993 r1 = eval('func(%s)' % call_params_string, None, locs)
994 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
995 locs)
996 self.assertEqual(r1, r2)
997
998 def assertEqualException(self, func, call_param_string, locs=None):
999 locs = dict(locs or {}, func=func)
1000 try:
1001 eval('func(%s)' % call_param_string, None, locs)
1002 except Exception as e:
1003 ex1 = e
1004 else:
1005 self.fail('Exception not raised')
1006 try:
1007 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1008 locs)
1009 except Exception as e:
1010 ex2 = e
1011 else:
1012 self.fail('Exception not raised')
1013 self.assertIs(type(ex1), type(ex2))
1014 self.assertEqual(str(ex1), str(ex2))
1015 del ex1, ex2
1016
1017 def makeCallable(self, signature):
1018 """Create a function that returns its locals()"""
1019 code = "lambda %s: locals()"
1020 return eval(code % signature)
1021
1022 def test_plain(self):
1023 f = self.makeCallable('a, b=1')
1024 self.assertEqualCallArgs(f, '2')
1025 self.assertEqualCallArgs(f, '2, 3')
1026 self.assertEqualCallArgs(f, 'a=2')
1027 self.assertEqualCallArgs(f, 'b=3, a=2')
1028 self.assertEqualCallArgs(f, '2, b=3')
1029 # expand *iterable / **mapping
1030 self.assertEqualCallArgs(f, '*(2,)')
1031 self.assertEqualCallArgs(f, '*[2]')
1032 self.assertEqualCallArgs(f, '*(2, 3)')
1033 self.assertEqualCallArgs(f, '*[2, 3]')
1034 self.assertEqualCallArgs(f, '**{"a":2}')
1035 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1036 self.assertEqualCallArgs(f, '2, **{"b":3}')
1037 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1038 # expand UserList / UserDict
1039 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1040 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1041 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1042 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1043 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1044
1045 def test_varargs(self):
1046 f = self.makeCallable('a, b=1, *c')
1047 self.assertEqualCallArgs(f, '2')
1048 self.assertEqualCallArgs(f, '2, 3')
1049 self.assertEqualCallArgs(f, '2, 3, 4')
1050 self.assertEqualCallArgs(f, '*(2,3,4)')
1051 self.assertEqualCallArgs(f, '2, *[3,4]')
1052 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1053
1054 def test_varkw(self):
1055 f = self.makeCallable('a, b=1, **c')
1056 self.assertEqualCallArgs(f, 'a=2')
1057 self.assertEqualCallArgs(f, '2, b=3, c=4')
1058 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1059 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1060 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1061 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1062 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1063 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1064 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1065
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001066 def test_varkw_only(self):
1067 # issue11256:
1068 f = self.makeCallable('**c')
1069 self.assertEqualCallArgs(f, '')
1070 self.assertEqualCallArgs(f, 'a=1')
1071 self.assertEqualCallArgs(f, 'a=1, b=2')
1072 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1073 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1074 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1075
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001076 def test_keyword_only(self):
1077 f = self.makeCallable('a=3, *, c, d=2')
1078 self.assertEqualCallArgs(f, 'c=3')
1079 self.assertEqualCallArgs(f, 'c=3, a=3')
1080 self.assertEqualCallArgs(f, 'a=2, c=4')
1081 self.assertEqualCallArgs(f, '4, c=4')
1082 self.assertEqualException(f, '')
1083 self.assertEqualException(f, '3')
1084 self.assertEqualException(f, 'a=3')
1085 self.assertEqualException(f, 'd=4')
1086
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001087 f = self.makeCallable('*, c, d=2')
1088 self.assertEqualCallArgs(f, 'c=3')
1089 self.assertEqualCallArgs(f, 'c=3, d=4')
1090 self.assertEqualCallArgs(f, 'd=4, c=3')
1091
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001092 def test_multiple_features(self):
1093 f = self.makeCallable('a, b=2, *f, **g')
1094 self.assertEqualCallArgs(f, '2, 3, 7')
1095 self.assertEqualCallArgs(f, '2, 3, x=8')
1096 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1097 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1098 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1099 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1100 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1101 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1102 '(4,[5,6])]), **collections.UserDict('
1103 'y=9, z=10)')
1104
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001105 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1106 self.assertEqualCallArgs(f, '2, 3, x=8')
1107 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1108 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1109 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1110 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1111 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1112 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1113 '(4,[5,6])]), q=0, **collections.UserDict('
1114 'y=9, z=10)')
1115
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001116 def test_errors(self):
1117 f0 = self.makeCallable('')
1118 f1 = self.makeCallable('a, b')
1119 f2 = self.makeCallable('a, b=1')
1120 # f0 takes no arguments
1121 self.assertEqualException(f0, '1')
1122 self.assertEqualException(f0, 'x=1')
1123 self.assertEqualException(f0, '1,x=1')
1124 # f1 takes exactly 2 arguments
1125 self.assertEqualException(f1, '')
1126 self.assertEqualException(f1, '1')
1127 self.assertEqualException(f1, 'a=2')
1128 self.assertEqualException(f1, 'b=3')
1129 # f2 takes at least 1 argument
1130 self.assertEqualException(f2, '')
1131 self.assertEqualException(f2, 'b=3')
1132 for f in f1, f2:
1133 # f1/f2 takes exactly/at most 2 arguments
1134 self.assertEqualException(f, '2, 3, 4')
1135 self.assertEqualException(f, '1, 2, 3, a=1')
1136 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001137 # XXX: success of this one depends on dict order
1138 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001139 # f got an unexpected keyword argument
1140 self.assertEqualException(f, 'c=2')
1141 self.assertEqualException(f, '2, c=3')
1142 self.assertEqualException(f, '2, 3, c=4')
1143 self.assertEqualException(f, '2, c=4, b=3')
1144 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1145 # f got multiple values for keyword argument
1146 self.assertEqualException(f, '1, a=2')
1147 self.assertEqualException(f, '1, **{"a":2}')
1148 self.assertEqualException(f, '1, 2, b=3')
1149 # XXX: Python inconsistency
1150 # - for functions and bound methods: unexpected keyword 'c'
1151 # - for unbound methods: multiple values for keyword 'a'
1152 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001153 # issue11256:
1154 f3 = self.makeCallable('**c')
1155 self.assertEqualException(f3, '1, 2')
1156 self.assertEqualException(f3, '1, 2, a=1, b=2')
1157 f4 = self.makeCallable('*, a, b=0')
1158 self.assertEqualException(f3, '1, 2')
1159 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001160
1161class TestGetcallargsMethods(TestGetcallargsFunctions):
1162
1163 def setUp(self):
1164 class Foo(object):
1165 pass
1166 self.cls = Foo
1167 self.inst = Foo()
1168
1169 def makeCallable(self, signature):
1170 assert 'self' not in signature
1171 mk = super(TestGetcallargsMethods, self).makeCallable
1172 self.cls.method = mk('self, ' + signature)
1173 return self.inst.method
1174
1175class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1176
1177 def makeCallable(self, signature):
1178 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1179 return self.cls.method
1180
1181 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1182 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1183 *self._getAssertEqualParams(func, call_params_string, locs))
1184
1185 def assertEqualException(self, func, call_params_string, locs=None):
1186 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1187 *self._getAssertEqualParams(func, call_params_string, locs))
1188
1189 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1190 assert 'inst' not in call_params_string
1191 locs = dict(locs or {}, inst=self.inst)
1192 return (func, 'inst,' + call_params_string, locs)
1193
Michael Foord95fc51d2010-11-20 15:07:30 +00001194
1195class TestGetattrStatic(unittest.TestCase):
1196
1197 def test_basic(self):
1198 class Thing(object):
1199 x = object()
1200
1201 thing = Thing()
1202 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1203 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1204 with self.assertRaises(AttributeError):
1205 inspect.getattr_static(thing, 'y')
1206
1207 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1208
1209 def test_inherited(self):
1210 class Thing(object):
1211 x = object()
1212 class OtherThing(Thing):
1213 pass
1214
1215 something = OtherThing()
1216 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1217
1218 def test_instance_attr(self):
1219 class Thing(object):
1220 x = 2
1221 def __init__(self, x):
1222 self.x = x
1223 thing = Thing(3)
1224 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1225 del thing.x
1226 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1227
1228 def test_property(self):
1229 class Thing(object):
1230 @property
1231 def x(self):
1232 raise AttributeError("I'm pretending not to exist")
1233 thing = Thing()
1234 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1235
Ezio Melotti75cbd732011-04-28 00:59:29 +03001236 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001237 class descriptor(object):
1238 def __get__(*_):
1239 raise AttributeError("I'm pretending not to exist")
1240 desc = descriptor()
1241 class Thing(object):
1242 x = desc
1243 thing = Thing()
1244 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1245
1246 def test_classAttribute(self):
1247 class Thing(object):
1248 x = object()
1249
1250 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1251
Ethan Furmane03ea372013-09-25 07:14:41 -07001252 def test_classVirtualAttribute(self):
1253 class Thing(object):
1254 @types.DynamicClassAttribute
1255 def x(self):
1256 return self._x
1257 _x = object()
1258
1259 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1260
Michael Foord95fc51d2010-11-20 15:07:30 +00001261 def test_inherited_classattribute(self):
1262 class Thing(object):
1263 x = object()
1264 class OtherThing(Thing):
1265 pass
1266
1267 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1268
1269 def test_slots(self):
1270 class Thing(object):
1271 y = 'bar'
1272 __slots__ = ['x']
1273 def __init__(self):
1274 self.x = 'foo'
1275 thing = Thing()
1276 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1277 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1278
1279 del thing.x
1280 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1281
1282 def test_metaclass(self):
1283 class meta(type):
1284 attr = 'foo'
1285 class Thing(object, metaclass=meta):
1286 pass
1287 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1288
1289 class sub(meta):
1290 pass
1291 class OtherThing(object, metaclass=sub):
1292 x = 3
1293 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1294
1295 class OtherOtherThing(OtherThing):
1296 pass
1297 # this test is odd, but it was added as it exposed a bug
1298 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1299
1300 def test_no_dict_no_slots(self):
1301 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1302 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1303
1304 def test_no_dict_no_slots_instance_member(self):
1305 # returns descriptor
1306 with open(__file__) as handle:
1307 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1308
1309 def test_inherited_slots(self):
1310 # returns descriptor
1311 class Thing(object):
1312 __slots__ = ['x']
1313 def __init__(self):
1314 self.x = 'foo'
1315
1316 class OtherThing(Thing):
1317 pass
1318 # it would be nice if this worked...
1319 # we get the descriptor instead of the instance attribute
1320 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1321
1322 def test_descriptor(self):
1323 class descriptor(object):
1324 def __get__(self, instance, owner):
1325 return 3
1326 class Foo(object):
1327 d = descriptor()
1328
1329 foo = Foo()
1330
1331 # for a non data descriptor we return the instance attribute
1332 foo.__dict__['d'] = 1
1333 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1334
1335 # if the descriptor is a data-desciptor we should return the
1336 # descriptor
1337 descriptor.__set__ = lambda s, i, v: None
1338 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1339
1340
1341 def test_metaclass_with_descriptor(self):
1342 class descriptor(object):
1343 def __get__(self, instance, owner):
1344 return 3
1345 class meta(type):
1346 d = descriptor()
1347 class Thing(object, metaclass=meta):
1348 pass
1349 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1350
1351
Michael Foordcc7ebb82010-11-20 16:20:16 +00001352 def test_class_as_property(self):
1353 class Base(object):
1354 foo = 3
1355
1356 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001357 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001358 @property
1359 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001360 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001361 return object
1362
Michael Foord35184ed2010-11-20 16:58:30 +00001363 instance = Something()
1364 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1365 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001366 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1367
Michael Foorde5162652010-11-20 16:40:44 +00001368 def test_mro_as_property(self):
1369 class Meta(type):
1370 @property
1371 def __mro__(self):
1372 return (object,)
1373
1374 class Base(object):
1375 foo = 3
1376
1377 class Something(Base, metaclass=Meta):
1378 pass
1379
1380 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1381 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1382
Michael Foorddcebe0f2011-03-15 19:20:44 -04001383 def test_dict_as_property(self):
1384 test = self
1385 test.called = False
1386
1387 class Foo(dict):
1388 a = 3
1389 @property
1390 def __dict__(self):
1391 test.called = True
1392 return {}
1393
1394 foo = Foo()
1395 foo.a = 4
1396 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1397 self.assertFalse(test.called)
1398
1399 def test_custom_object_dict(self):
1400 test = self
1401 test.called = False
1402
1403 class Custom(dict):
1404 def get(self, key, default=None):
1405 test.called = True
1406 super().get(key, default)
1407
1408 class Foo(object):
1409 a = 3
1410 foo = Foo()
1411 foo.__dict__ = Custom()
1412 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1413 self.assertFalse(test.called)
1414
1415 def test_metaclass_dict_as_property(self):
1416 class Meta(type):
1417 @property
1418 def __dict__(self):
1419 self.executed = True
1420
1421 class Thing(metaclass=Meta):
1422 executed = False
1423
1424 def __init__(self):
1425 self.spam = 42
1426
1427 instance = Thing()
1428 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1429 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001430
Michael Foorda51623b2011-12-18 22:01:40 +00001431 def test_module(self):
1432 sentinel = object()
1433 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1434 sentinel)
1435
Michael Foord3ba95f82011-12-22 01:13:37 +00001436 def test_metaclass_with_metaclass_with_dict_as_property(self):
1437 class MetaMeta(type):
1438 @property
1439 def __dict__(self):
1440 self.executed = True
1441 return dict(spam=42)
1442
1443 class Meta(type, metaclass=MetaMeta):
1444 executed = False
1445
1446 class Thing(metaclass=Meta):
1447 pass
1448
1449 with self.assertRaises(AttributeError):
1450 inspect.getattr_static(Thing, "spam")
1451 self.assertFalse(Thing.executed)
1452
Nick Coghlane0f04652010-11-21 03:44:04 +00001453class TestGetGeneratorState(unittest.TestCase):
1454
1455 def setUp(self):
1456 def number_generator():
1457 for number in range(5):
1458 yield number
1459 self.generator = number_generator()
1460
1461 def _generatorstate(self):
1462 return inspect.getgeneratorstate(self.generator)
1463
1464 def test_created(self):
1465 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1466
1467 def test_suspended(self):
1468 next(self.generator)
1469 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1470
1471 def test_closed_after_exhaustion(self):
1472 for i in self.generator:
1473 pass
1474 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1475
1476 def test_closed_after_immediate_exception(self):
1477 with self.assertRaises(RuntimeError):
1478 self.generator.throw(RuntimeError)
1479 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1480
1481 def test_running(self):
1482 # As mentioned on issue #10220, checking for the RUNNING state only
1483 # makes sense inside the generator itself.
1484 # The following generator checks for this by using the closure's
1485 # reference to self and the generator state checking helper method
1486 def running_check_generator():
1487 for number in range(5):
1488 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1489 yield number
1490 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1491 self.generator = running_check_generator()
1492 # Running up to the first yield
1493 next(self.generator)
1494 # Running after the first yield
1495 next(self.generator)
1496
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001497 def test_easy_debugging(self):
1498 # repr() and str() of a generator state should contain the state name
1499 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1500 for name in names:
1501 state = getattr(inspect, name)
1502 self.assertIn(name, repr(state))
1503 self.assertIn(name, str(state))
1504
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001505 def test_getgeneratorlocals(self):
1506 def each(lst, a=None):
1507 b=(1, 2, 3)
1508 for v in lst:
1509 if v == 3:
1510 c = 12
1511 yield v
1512
1513 numbers = each([1, 2, 3])
1514 self.assertEqual(inspect.getgeneratorlocals(numbers),
1515 {'a': None, 'lst': [1, 2, 3]})
1516 next(numbers)
1517 self.assertEqual(inspect.getgeneratorlocals(numbers),
1518 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1519 'b': (1, 2, 3)})
1520 next(numbers)
1521 self.assertEqual(inspect.getgeneratorlocals(numbers),
1522 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1523 'b': (1, 2, 3)})
1524 next(numbers)
1525 self.assertEqual(inspect.getgeneratorlocals(numbers),
1526 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1527 'b': (1, 2, 3), 'c': 12})
1528 try:
1529 next(numbers)
1530 except StopIteration:
1531 pass
1532 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1533
1534 def test_getgeneratorlocals_empty(self):
1535 def yield_one():
1536 yield 1
1537 one = yield_one()
1538 self.assertEqual(inspect.getgeneratorlocals(one), {})
1539 try:
1540 next(one)
1541 except StopIteration:
1542 pass
1543 self.assertEqual(inspect.getgeneratorlocals(one), {})
1544
1545 def test_getgeneratorlocals_error(self):
1546 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1547 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1548 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1549 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1550
Nick Coghlane0f04652010-11-21 03:44:04 +00001551
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001552class TestSignatureObject(unittest.TestCase):
1553 @staticmethod
1554 def signature(func):
1555 sig = inspect.signature(func)
1556 return (tuple((param.name,
1557 (... if param.default is param.empty else param.default),
1558 (... if param.annotation is param.empty
1559 else param.annotation),
1560 str(param.kind).lower())
1561 for param in sig.parameters.values()),
1562 (... if sig.return_annotation is sig.empty
1563 else sig.return_annotation))
1564
1565 def test_signature_object(self):
1566 S = inspect.Signature
1567 P = inspect.Parameter
1568
1569 self.assertEqual(str(S()), '()')
1570
Yury Selivanov07a9e452014-01-29 10:58:16 -05001571 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001572 pass
1573 sig = inspect.signature(test)
1574 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001575 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001576 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001577 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001578 args = sig.parameters['args']
1579 ko = sig.parameters['ko']
1580 kwargs = sig.parameters['kwargs']
1581
1582 S((po, pk, args, ko, kwargs))
1583
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001584 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001585 S((pk, po, args, ko, kwargs))
1586
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001587 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001588 S((po, args, pk, ko, kwargs))
1589
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001590 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001591 S((args, po, pk, ko, kwargs))
1592
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001593 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001594 S((po, pk, args, kwargs, ko))
1595
1596 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001597 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001598 S((po, pk, args, kwargs2, ko))
1599
Yury Selivanov07a9e452014-01-29 10:58:16 -05001600 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1601 S((pod, po))
1602
1603 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1604 S((po, pkd, pk))
1605
1606 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1607 S((pkd, pk))
1608
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001609 def test_signature_immutability(self):
1610 def test(a):
1611 pass
1612 sig = inspect.signature(test)
1613
1614 with self.assertRaises(AttributeError):
1615 sig.foo = 'bar'
1616
1617 with self.assertRaises(TypeError):
1618 sig.parameters['a'] = None
1619
1620 def test_signature_on_noarg(self):
1621 def test():
1622 pass
1623 self.assertEqual(self.signature(test), ((), ...))
1624
1625 def test_signature_on_wargs(self):
1626 def test(a, b:'foo') -> 123:
1627 pass
1628 self.assertEqual(self.signature(test),
1629 ((('a', ..., ..., "positional_or_keyword"),
1630 ('b', ..., 'foo', "positional_or_keyword")),
1631 123))
1632
1633 def test_signature_on_wkwonly(self):
1634 def test(*, a:float, b:str) -> int:
1635 pass
1636 self.assertEqual(self.signature(test),
1637 ((('a', ..., float, "keyword_only"),
1638 ('b', ..., str, "keyword_only")),
1639 int))
1640
1641 def test_signature_on_complex_args(self):
1642 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1643 pass
1644 self.assertEqual(self.signature(test),
1645 ((('a', ..., ..., "positional_or_keyword"),
1646 ('b', 10, 'foo', "positional_or_keyword"),
1647 ('args', ..., 'bar', "var_positional"),
1648 ('spam', ..., 'baz', "keyword_only"),
1649 ('ham', 123, ..., "keyword_only"),
1650 ('kwargs', ..., int, "var_keyword")),
1651 ...))
1652
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001653 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001654 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1655 "Signature information for builtins requires docstrings")
1656 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001657 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001658
Larry Hastings5c661892014-01-24 06:17:25 -08001659 def test_unbound_method(o):
1660 """Use this to test unbound methods (things that should have a self)"""
1661 signature = inspect.signature(o)
1662 self.assertTrue(isinstance(signature, inspect.Signature))
1663 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1664 return signature
1665
1666 def test_callable(o):
1667 """Use this to test bound methods or normal callables (things that don't expect self)"""
1668 signature = inspect.signature(o)
1669 self.assertTrue(isinstance(signature, inspect.Signature))
1670 if signature.parameters:
1671 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1672 return signature
1673
1674 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001675 def p(name): return signature.parameters[name].default
1676 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001677 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001678 self.assertEqual(p('d'), 3.14)
1679 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001680 self.assertEqual(p('n'), None)
1681 self.assertEqual(p('t'), True)
1682 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001683 self.assertEqual(p('local'), 3)
1684 self.assertEqual(p('sys'), sys.maxsize)
1685 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001686
Larry Hastings5c661892014-01-24 06:17:25 -08001687 test_callable(object)
1688
1689 # normal method
1690 # (PyMethodDescr_Type, "method_descriptor")
1691 test_unbound_method(_pickle.Pickler.dump)
1692 d = _pickle.Pickler(io.StringIO())
1693 test_callable(d.dump)
1694
1695 # static method
1696 test_callable(str.maketrans)
1697 test_callable('abc'.maketrans)
1698
1699 # class method
1700 test_callable(dict.fromkeys)
1701 test_callable({}.fromkeys)
1702
1703 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1704 test_unbound_method(type.__call__)
1705 test_unbound_method(int.__add__)
1706 test_callable((3).__add__)
1707
1708 # _PyMethodWrapper_Type
1709 # support for 'method-wrapper'
1710 test_callable(min.__call__)
1711
Larry Hastings2623c8c2014-02-08 22:15:29 -08001712 # This doesn't work now.
1713 # (We don't have a valid signature for "type" in 3.4)
1714 with self.assertRaisesRegex(ValueError, "no signature found"):
1715 class ThisWorksNow:
1716 __call__ = type
1717 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08001718
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001719 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05001720 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1721 "Signature information for builtins requires docstrings")
1722 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001723 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05001724 func = _testcapi.docstring_with_signature_with_defaults
1725
1726 def decorator(func):
1727 @functools.wraps(func)
1728 def wrapper(*args, **kwargs) -> int:
1729 return func(*args, **kwargs)
1730 return wrapper
1731
1732 decorated_func = decorator(func)
1733
1734 self.assertEqual(inspect.signature(func),
1735 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08001736
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001737 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08001738 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001739 import _testcapi
Larry Hastings5c661892014-01-24 06:17:25 -08001740 with self.assertRaisesRegex(ValueError, 'no signature found for builtin'):
1741 inspect.signature(_testcapi.docstring_no_signature)
1742
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001743 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001744 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001745 inspect.signature(42)
1746
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001747 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001748 inspect.Signature.from_function(42)
1749
Yury Selivanovb77511d2014-01-29 10:46:14 -05001750 def test_signature_from_builtin_errors(self):
1751 with self.assertRaisesRegex(TypeError, 'is not a Python builtin'):
1752 inspect.Signature.from_builtin(42)
1753
Yury Selivanov63da7c72014-01-31 14:48:37 -05001754 def test_signature_from_functionlike_object(self):
1755 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1756 pass
1757
1758 class funclike:
1759 # Has to be callable, and have correct
1760 # __code__, __annotations__, __defaults__, __name__,
1761 # and __kwdefaults__ attributes
1762
1763 def __init__(self, func):
1764 self.__name__ = func.__name__
1765 self.__code__ = func.__code__
1766 self.__annotations__ = func.__annotations__
1767 self.__defaults__ = func.__defaults__
1768 self.__kwdefaults__ = func.__kwdefaults__
1769 self.func = func
1770
1771 def __call__(self, *args, **kwargs):
1772 return self.func(*args, **kwargs)
1773
1774 sig_func = inspect.Signature.from_function(func)
1775
1776 sig_funclike = inspect.Signature.from_function(funclike(func))
1777 self.assertEqual(sig_funclike, sig_func)
1778
1779 sig_funclike = inspect.signature(funclike(func))
1780 self.assertEqual(sig_funclike, sig_func)
1781
1782 # If object is not a duck type of function, then
1783 # signature will try to get a signature for its '__call__'
1784 # method
1785 fl = funclike(func)
1786 del fl.__defaults__
1787 self.assertEqual(self.signature(fl),
1788 ((('args', ..., ..., "var_positional"),
1789 ('kwargs', ..., ..., "var_keyword")),
1790 ...))
1791
1792 def test_signature_functionlike_class(self):
1793 # We only want to duck type function-like objects,
1794 # not classes.
1795
1796 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1797 pass
1798
1799 class funclike:
1800 def __init__(self, marker):
1801 pass
1802
1803 __name__ = func.__name__
1804 __code__ = func.__code__
1805 __annotations__ = func.__annotations__
1806 __defaults__ = func.__defaults__
1807 __kwdefaults__ = func.__kwdefaults__
1808
1809 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1810 inspect.Signature.from_function(funclike)
1811
1812 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
1813
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001814 def test_signature_on_method(self):
1815 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05001816 def __init__(*args):
1817 pass
1818 def m1(self, arg1, arg2=1) -> int:
1819 pass
1820 def m2(*args):
1821 pass
1822 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001823 pass
1824
Yury Selivanov62560fb2014-01-28 12:26:24 -05001825 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001826 ((('arg1', ..., ..., "positional_or_keyword"),
1827 ('arg2', 1, ..., "positional_or_keyword")),
1828 int))
1829
Yury Selivanov62560fb2014-01-28 12:26:24 -05001830 self.assertEqual(self.signature(Test().m2),
1831 ((('args', ..., ..., "var_positional"),),
1832 ...))
1833
1834 self.assertEqual(self.signature(Test),
1835 ((('args', ..., ..., "var_positional"),),
1836 ...))
1837
1838 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
1839 self.signature(Test())
1840
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001841 def test_signature_on_classmethod(self):
1842 class Test:
1843 @classmethod
1844 def foo(cls, arg1, *, arg2=1):
1845 pass
1846
1847 meth = Test().foo
1848 self.assertEqual(self.signature(meth),
1849 ((('arg1', ..., ..., "positional_or_keyword"),
1850 ('arg2', 1, ..., "keyword_only")),
1851 ...))
1852
1853 meth = Test.foo
1854 self.assertEqual(self.signature(meth),
1855 ((('arg1', ..., ..., "positional_or_keyword"),
1856 ('arg2', 1, ..., "keyword_only")),
1857 ...))
1858
1859 def test_signature_on_staticmethod(self):
1860 class Test:
1861 @staticmethod
1862 def foo(cls, *, arg):
1863 pass
1864
1865 meth = Test().foo
1866 self.assertEqual(self.signature(meth),
1867 ((('cls', ..., ..., "positional_or_keyword"),
1868 ('arg', ..., ..., "keyword_only")),
1869 ...))
1870
1871 meth = Test.foo
1872 self.assertEqual(self.signature(meth),
1873 ((('cls', ..., ..., "positional_or_keyword"),
1874 ('arg', ..., ..., "keyword_only")),
1875 ...))
1876
1877 def test_signature_on_partial(self):
1878 from functools import partial
1879
1880 def test():
1881 pass
1882
1883 self.assertEqual(self.signature(partial(test)), ((), ...))
1884
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001885 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001886 inspect.signature(partial(test, 1))
1887
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001888 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001889 inspect.signature(partial(test, a=1))
1890
1891 def test(a, b, *, c, d):
1892 pass
1893
1894 self.assertEqual(self.signature(partial(test)),
1895 ((('a', ..., ..., "positional_or_keyword"),
1896 ('b', ..., ..., "positional_or_keyword"),
1897 ('c', ..., ..., "keyword_only"),
1898 ('d', ..., ..., "keyword_only")),
1899 ...))
1900
1901 self.assertEqual(self.signature(partial(test, 1)),
1902 ((('b', ..., ..., "positional_or_keyword"),
1903 ('c', ..., ..., "keyword_only"),
1904 ('d', ..., ..., "keyword_only")),
1905 ...))
1906
1907 self.assertEqual(self.signature(partial(test, 1, c=2)),
1908 ((('b', ..., ..., "positional_or_keyword"),
1909 ('c', 2, ..., "keyword_only"),
1910 ('d', ..., ..., "keyword_only")),
1911 ...))
1912
1913 self.assertEqual(self.signature(partial(test, b=1, c=2)),
1914 ((('a', ..., ..., "positional_or_keyword"),
1915 ('b', 1, ..., "positional_or_keyword"),
1916 ('c', 2, ..., "keyword_only"),
1917 ('d', ..., ..., "keyword_only")),
1918 ...))
1919
1920 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
1921 ((('b', 1, ..., "positional_or_keyword"),
1922 ('c', 2, ..., "keyword_only"),
1923 ('d', ..., ..., "keyword_only"),),
1924 ...))
1925
1926 def test(a, *args, b, **kwargs):
1927 pass
1928
1929 self.assertEqual(self.signature(partial(test, 1)),
1930 ((('args', ..., ..., "var_positional"),
1931 ('b', ..., ..., "keyword_only"),
1932 ('kwargs', ..., ..., "var_keyword")),
1933 ...))
1934
1935 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
1936 ((('args', ..., ..., "var_positional"),
1937 ('b', ..., ..., "keyword_only"),
1938 ('kwargs', ..., ..., "var_keyword")),
1939 ...))
1940
1941
1942 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
1943 ((('args', ..., ..., "var_positional"),
1944 ('b', ..., ..., "keyword_only"),
1945 ('kwargs', ..., ..., "var_keyword")),
1946 ...))
1947
1948 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
1949 ((('args', ..., ..., "var_positional"),
1950 ('b', 0, ..., "keyword_only"),
1951 ('kwargs', ..., ..., "var_keyword")),
1952 ...))
1953
1954 self.assertEqual(self.signature(partial(test, b=0)),
1955 ((('a', ..., ..., "positional_or_keyword"),
1956 ('args', ..., ..., "var_positional"),
1957 ('b', 0, ..., "keyword_only"),
1958 ('kwargs', ..., ..., "var_keyword")),
1959 ...))
1960
1961 self.assertEqual(self.signature(partial(test, b=0, test=1)),
1962 ((('a', ..., ..., "positional_or_keyword"),
1963 ('args', ..., ..., "var_positional"),
1964 ('b', 0, ..., "keyword_only"),
1965 ('kwargs', ..., ..., "var_keyword")),
1966 ...))
1967
1968 def test(a, b, c:int) -> 42:
1969 pass
1970
1971 sig = test.__signature__ = inspect.signature(test)
1972
1973 self.assertEqual(self.signature(partial(partial(test, 1))),
1974 ((('b', ..., ..., "positional_or_keyword"),
1975 ('c', ..., int, "positional_or_keyword")),
1976 42))
1977
1978 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
1979 ((('c', ..., int, "positional_or_keyword"),),
1980 42))
1981
1982 psig = inspect.signature(partial(partial(test, 1), 2))
1983
1984 def foo(a):
1985 return a
1986 _foo = partial(partial(foo, a=10), a=20)
1987 self.assertEqual(self.signature(_foo),
1988 ((('a', 20, ..., "positional_or_keyword"),),
1989 ...))
1990 # check that we don't have any side-effects in signature(),
1991 # and the partial object is still functioning
1992 self.assertEqual(_foo(), 20)
1993
1994 def foo(a, b, c):
1995 return a, b, c
1996 _foo = partial(partial(foo, 1, b=20), b=30)
1997 self.assertEqual(self.signature(_foo),
1998 ((('b', 30, ..., "positional_or_keyword"),
1999 ('c', ..., ..., "positional_or_keyword")),
2000 ...))
2001 self.assertEqual(_foo(c=10), (1, 30, 10))
2002 _foo = partial(_foo, 2) # now 'b' has two values -
2003 # positional and keyword
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002004 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002005 inspect.signature(_foo)
2006
2007 def foo(a, b, c, *, d):
2008 return a, b, c, d
2009 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2010 self.assertEqual(self.signature(_foo),
2011 ((('a', ..., ..., "positional_or_keyword"),
2012 ('b', 10, ..., "positional_or_keyword"),
2013 ('c', 20, ..., "positional_or_keyword"),
2014 ('d', 30, ..., "keyword_only")),
2015 ...))
2016 ba = inspect.signature(_foo).bind(a=200, b=11)
2017 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2018
2019 def foo(a=1, b=2, c=3):
2020 return a, b, c
2021 _foo = partial(foo, a=10, c=13)
2022 ba = inspect.signature(_foo).bind(11)
2023 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
2024 ba = inspect.signature(_foo).bind(11, 12)
2025 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
2026 ba = inspect.signature(_foo).bind(11, b=12)
2027 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
2028 ba = inspect.signature(_foo).bind(b=12)
2029 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
2030 _foo = partial(_foo, b=10)
2031 ba = inspect.signature(_foo).bind(12, 14)
2032 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
2033
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002034 def test_signature_on_partialmethod(self):
2035 from functools import partialmethod
2036
2037 class Spam:
2038 def test():
2039 pass
2040 ham = partialmethod(test)
2041
2042 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2043 inspect.signature(Spam.ham)
2044
2045 class Spam:
2046 def test(it, a, *, c) -> 'spam':
2047 pass
2048 ham = partialmethod(test, c=1)
2049
2050 self.assertEqual(self.signature(Spam.ham),
2051 ((('it', ..., ..., 'positional_or_keyword'),
2052 ('a', ..., ..., 'positional_or_keyword'),
2053 ('c', 1, ..., 'keyword_only')),
2054 'spam'))
2055
2056 self.assertEqual(self.signature(Spam().ham),
2057 ((('a', ..., ..., 'positional_or_keyword'),
2058 ('c', 1, ..., 'keyword_only')),
2059 'spam'))
2060
Yury Selivanov0486f812014-01-29 12:18:59 -05002061 def test_signature_on_fake_partialmethod(self):
2062 def foo(a): pass
2063 foo._partialmethod = 'spam'
2064 self.assertEqual(str(inspect.signature(foo)), '(a)')
2065
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002066 def test_signature_on_decorated(self):
2067 import functools
2068
2069 def decorator(func):
2070 @functools.wraps(func)
2071 def wrapper(*args, **kwargs) -> int:
2072 return func(*args, **kwargs)
2073 return wrapper
2074
2075 class Foo:
2076 @decorator
2077 def bar(self, a, b):
2078 pass
2079
2080 self.assertEqual(self.signature(Foo.bar),
2081 ((('self', ..., ..., "positional_or_keyword"),
2082 ('a', ..., ..., "positional_or_keyword"),
2083 ('b', ..., ..., "positional_or_keyword")),
2084 ...))
2085
2086 self.assertEqual(self.signature(Foo().bar),
2087 ((('a', ..., ..., "positional_or_keyword"),
2088 ('b', ..., ..., "positional_or_keyword")),
2089 ...))
2090
2091 # Test that we handle method wrappers correctly
2092 def decorator(func):
2093 @functools.wraps(func)
2094 def wrapper(*args, **kwargs) -> int:
2095 return func(42, *args, **kwargs)
2096 sig = inspect.signature(func)
2097 new_params = tuple(sig.parameters.values())[1:]
2098 wrapper.__signature__ = sig.replace(parameters=new_params)
2099 return wrapper
2100
2101 class Foo:
2102 @decorator
2103 def __call__(self, a, b):
2104 pass
2105
2106 self.assertEqual(self.signature(Foo.__call__),
2107 ((('a', ..., ..., "positional_or_keyword"),
2108 ('b', ..., ..., "positional_or_keyword")),
2109 ...))
2110
2111 self.assertEqual(self.signature(Foo().__call__),
2112 ((('b', ..., ..., "positional_or_keyword"),),
2113 ...))
2114
Nick Coghlane8c45d62013-07-28 20:00:01 +10002115 # Test we handle __signature__ partway down the wrapper stack
2116 def wrapped_foo_call():
2117 pass
2118 wrapped_foo_call.__wrapped__ = Foo.__call__
2119
2120 self.assertEqual(self.signature(wrapped_foo_call),
2121 ((('a', ..., ..., "positional_or_keyword"),
2122 ('b', ..., ..., "positional_or_keyword")),
2123 ...))
2124
2125
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002126 def test_signature_on_class(self):
2127 class C:
2128 def __init__(self, a):
2129 pass
2130
2131 self.assertEqual(self.signature(C),
2132 ((('a', ..., ..., "positional_or_keyword"),),
2133 ...))
2134
2135 class CM(type):
2136 def __call__(cls, a):
2137 pass
2138 class C(metaclass=CM):
2139 def __init__(self, b):
2140 pass
2141
2142 self.assertEqual(self.signature(C),
2143 ((('a', ..., ..., "positional_or_keyword"),),
2144 ...))
2145
2146 class CM(type):
2147 def __new__(mcls, name, bases, dct, *, foo=1):
2148 return super().__new__(mcls, name, bases, dct)
2149 class C(metaclass=CM):
2150 def __init__(self, b):
2151 pass
2152
2153 self.assertEqual(self.signature(C),
2154 ((('b', ..., ..., "positional_or_keyword"),),
2155 ...))
2156
2157 self.assertEqual(self.signature(CM),
2158 ((('name', ..., ..., "positional_or_keyword"),
2159 ('bases', ..., ..., "positional_or_keyword"),
2160 ('dct', ..., ..., "positional_or_keyword"),
2161 ('foo', 1, ..., "keyword_only")),
2162 ...))
2163
2164 class CMM(type):
2165 def __new__(mcls, name, bases, dct, *, foo=1):
2166 return super().__new__(mcls, name, bases, dct)
2167 def __call__(cls, nm, bs, dt):
2168 return type(nm, bs, dt)
2169 class CM(type, metaclass=CMM):
2170 def __new__(mcls, name, bases, dct, *, bar=2):
2171 return super().__new__(mcls, name, bases, dct)
2172 class C(metaclass=CM):
2173 def __init__(self, b):
2174 pass
2175
2176 self.assertEqual(self.signature(CMM),
2177 ((('name', ..., ..., "positional_or_keyword"),
2178 ('bases', ..., ..., "positional_or_keyword"),
2179 ('dct', ..., ..., "positional_or_keyword"),
2180 ('foo', 1, ..., "keyword_only")),
2181 ...))
2182
2183 self.assertEqual(self.signature(CM),
2184 ((('nm', ..., ..., "positional_or_keyword"),
2185 ('bs', ..., ..., "positional_or_keyword"),
2186 ('dt', ..., ..., "positional_or_keyword")),
2187 ...))
2188
2189 self.assertEqual(self.signature(C),
2190 ((('b', ..., ..., "positional_or_keyword"),),
2191 ...))
2192
2193 class CM(type):
2194 def __init__(cls, name, bases, dct, *, bar=2):
2195 return super().__init__(name, bases, dct)
2196 class C(metaclass=CM):
2197 def __init__(self, b):
2198 pass
2199
2200 self.assertEqual(self.signature(CM),
2201 ((('name', ..., ..., "positional_or_keyword"),
2202 ('bases', ..., ..., "positional_or_keyword"),
2203 ('dct', ..., ..., "positional_or_keyword"),
2204 ('bar', 2, ..., "keyword_only")),
2205 ...))
2206
Yury Selivanov145dff82014-02-01 13:49:29 -05002207 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2208 "Signature information for builtins requires docstrings")
2209 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002210 # Test classes without user-defined __init__ or __new__
2211 class C: pass
2212 self.assertEqual(str(inspect.signature(C)), '()')
2213 class D(C): pass
2214 self.assertEqual(str(inspect.signature(D)), '()')
2215
2216 # Test meta-classes without user-defined __init__ or __new__
2217 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002218 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002219 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2220 self.assertEqual(inspect.signature(C), None)
2221 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2222 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002223
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002224 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2225 "Signature information for builtins requires docstrings")
2226 def test_signature_on_builtin_class(self):
2227 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2228 '(file, protocol=None, fix_imports=True)')
2229
2230 class P(_pickle.Pickler): pass
2231 class EmptyTrait: pass
2232 class P2(EmptyTrait, P): pass
2233 self.assertEqual(str(inspect.signature(P)),
2234 '(file, protocol=None, fix_imports=True)')
2235 self.assertEqual(str(inspect.signature(P2)),
2236 '(file, protocol=None, fix_imports=True)')
2237
2238 class P3(P2):
2239 def __init__(self, spam):
2240 pass
2241 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2242
2243 class MetaP(type):
2244 def __call__(cls, foo, bar):
2245 pass
2246 class P4(P2, metaclass=MetaP):
2247 pass
2248 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2249
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002250 def test_signature_on_callable_objects(self):
2251 class Foo:
2252 def __call__(self, a):
2253 pass
2254
2255 self.assertEqual(self.signature(Foo()),
2256 ((('a', ..., ..., "positional_or_keyword"),),
2257 ...))
2258
2259 class Spam:
2260 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002261 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002262 inspect.signature(Spam())
2263
2264 class Bar(Spam, Foo):
2265 pass
2266
2267 self.assertEqual(self.signature(Bar()),
2268 ((('a', ..., ..., "positional_or_keyword"),),
2269 ...))
2270
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002271 class Wrapped:
2272 pass
2273 Wrapped.__wrapped__ = lambda a: None
2274 self.assertEqual(self.signature(Wrapped),
2275 ((('a', ..., ..., "positional_or_keyword"),),
2276 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002277 # wrapper loop:
2278 Wrapped.__wrapped__ = Wrapped
2279 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2280 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002281
2282 def test_signature_on_lambdas(self):
2283 self.assertEqual(self.signature((lambda a=10: a)),
2284 ((('a', 10, ..., "positional_or_keyword"),),
2285 ...))
2286
2287 def test_signature_equality(self):
2288 def foo(a, *, b:int) -> float: pass
2289 self.assertNotEqual(inspect.signature(foo), 42)
2290
2291 def bar(a, *, b:int) -> float: pass
2292 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2293
2294 def bar(a, *, b:int) -> int: pass
2295 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2296
2297 def bar(a, *, b:int): pass
2298 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2299
2300 def bar(a, *, b:int=42) -> float: pass
2301 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2302
2303 def bar(a, *, c) -> float: pass
2304 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2305
2306 def bar(a, b:int) -> float: pass
2307 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2308 def spam(b:int, a) -> float: pass
2309 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
2310
2311 def foo(*, a, b, c): pass
2312 def bar(*, c, b, a): pass
2313 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2314
2315 def foo(*, a=1, b, c): pass
2316 def bar(*, c, b, a=1): pass
2317 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2318
2319 def foo(pos, *, a=1, b, c): pass
2320 def bar(pos, *, c, b, a=1): pass
2321 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2322
2323 def foo(pos, *, a, b, c): pass
2324 def bar(pos, *, c, b, a=1): pass
2325 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2326
2327 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2328 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2329 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2330
2331 def test_signature_unhashable(self):
2332 def foo(a): pass
2333 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002334 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002335 hash(sig)
2336
2337 def test_signature_str(self):
2338 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2339 pass
2340 self.assertEqual(str(inspect.signature(foo)),
2341 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2342
2343 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2344 pass
2345 self.assertEqual(str(inspect.signature(foo)),
2346 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2347
2348 def foo():
2349 pass
2350 self.assertEqual(str(inspect.signature(foo)), '()')
2351
2352 def test_signature_str_positional_only(self):
2353 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002354 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002355
2356 def test(a_po, *, b, **kwargs):
2357 return a_po, kwargs
2358
2359 sig = inspect.signature(test)
2360 new_params = list(sig.parameters.values())
2361 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2362 test.__signature__ = sig.replace(parameters=new_params)
2363
2364 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002365 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002366
Yury Selivanov2393dca2014-01-27 15:07:58 -05002367 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2368 '(foo, /)')
2369
2370 self.assertEqual(str(S(parameters=[
2371 P('foo', P.POSITIONAL_ONLY),
2372 P('bar', P.VAR_KEYWORD)])),
2373 '(foo, /, **bar)')
2374
2375 self.assertEqual(str(S(parameters=[
2376 P('foo', P.POSITIONAL_ONLY),
2377 P('bar', P.VAR_POSITIONAL)])),
2378 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002379
2380 def test_signature_replace_anno(self):
2381 def test() -> 42:
2382 pass
2383
2384 sig = inspect.signature(test)
2385 sig = sig.replace(return_annotation=None)
2386 self.assertIs(sig.return_annotation, None)
2387 sig = sig.replace(return_annotation=sig.empty)
2388 self.assertIs(sig.return_annotation, sig.empty)
2389 sig = sig.replace(return_annotation=42)
2390 self.assertEqual(sig.return_annotation, 42)
2391 self.assertEqual(sig, inspect.signature(test))
2392
Yury Selivanov026019f2014-02-18 12:49:41 -05002393 def test_signature_on_mangled_parameters(self):
2394 class Spam:
2395 def foo(self, __p1:1=2, *, __p2:2=3):
2396 pass
2397 class Ham(Spam):
2398 pass
2399
2400 self.assertEqual(self.signature(Spam.foo),
2401 ((('self', ..., ..., "positional_or_keyword"),
2402 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2403 ('_Spam__p2', 3, 2, "keyword_only")),
2404 ...))
2405
2406 self.assertEqual(self.signature(Spam.foo),
2407 self.signature(Ham.foo))
2408
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002409
2410class TestParameterObject(unittest.TestCase):
2411 def test_signature_parameter_kinds(self):
2412 P = inspect.Parameter
2413 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2414 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2415
2416 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2417 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2418
2419 def test_signature_parameter_object(self):
2420 p = inspect.Parameter('foo', default=10,
2421 kind=inspect.Parameter.POSITIONAL_ONLY)
2422 self.assertEqual(p.name, 'foo')
2423 self.assertEqual(p.default, 10)
2424 self.assertIs(p.annotation, p.empty)
2425 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2426
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002427 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002428 inspect.Parameter('foo', default=10, kind='123')
2429
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002430 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002431 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2432
Yury Selivanov2393dca2014-01-27 15:07:58 -05002433 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002434 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2435
Yury Selivanov2393dca2014-01-27 15:07:58 -05002436 with self.assertRaisesRegex(ValueError,
2437 'is not a valid parameter name'):
2438 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2439
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002440 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002441 inspect.Parameter('a', default=42,
2442 kind=inspect.Parameter.VAR_KEYWORD)
2443
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002444 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002445 inspect.Parameter('a', default=42,
2446 kind=inspect.Parameter.VAR_POSITIONAL)
2447
2448 p = inspect.Parameter('a', default=42,
2449 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002450 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002451 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2452
2453 self.assertTrue(repr(p).startswith('<Parameter'))
2454
2455 def test_signature_parameter_equality(self):
2456 P = inspect.Parameter
2457 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2458
2459 self.assertEqual(p, p)
2460 self.assertNotEqual(p, 42)
2461
2462 self.assertEqual(p, P('foo', default=42,
2463 kind=inspect.Parameter.KEYWORD_ONLY))
2464
2465 def test_signature_parameter_unhashable(self):
2466 p = inspect.Parameter('foo', default=42,
2467 kind=inspect.Parameter.KEYWORD_ONLY)
2468
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002469 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002470 hash(p)
2471
2472 def test_signature_parameter_replace(self):
2473 p = inspect.Parameter('foo', default=42,
2474 kind=inspect.Parameter.KEYWORD_ONLY)
2475
2476 self.assertIsNot(p, p.replace())
2477 self.assertEqual(p, p.replace())
2478
2479 p2 = p.replace(annotation=1)
2480 self.assertEqual(p2.annotation, 1)
2481 p2 = p2.replace(annotation=p2.empty)
2482 self.assertEqual(p, p2)
2483
2484 p2 = p2.replace(name='bar')
2485 self.assertEqual(p2.name, 'bar')
2486 self.assertNotEqual(p2, p)
2487
Yury Selivanov2393dca2014-01-27 15:07:58 -05002488 with self.assertRaisesRegex(ValueError,
2489 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002490 p2 = p2.replace(name=p2.empty)
2491
2492 p2 = p2.replace(name='foo', default=None)
2493 self.assertIs(p2.default, None)
2494 self.assertNotEqual(p2, p)
2495
2496 p2 = p2.replace(name='foo', default=p2.empty)
2497 self.assertIs(p2.default, p2.empty)
2498
2499
2500 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2501 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2502 self.assertNotEqual(p2, p)
2503
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002504 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002505 p2 = p2.replace(kind=p2.empty)
2506
2507 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2508 self.assertEqual(p2, p)
2509
2510 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002511 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2512 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002513
2514 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002515 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002516
2517 with self.assertRaises(AttributeError):
2518 p.foo = 'bar'
2519
2520 with self.assertRaises(AttributeError):
2521 p.kind = 123
2522
2523
2524class TestSignatureBind(unittest.TestCase):
2525 @staticmethod
2526 def call(func, *args, **kwargs):
2527 sig = inspect.signature(func)
2528 ba = sig.bind(*args, **kwargs)
2529 return func(*ba.args, **ba.kwargs)
2530
2531 def test_signature_bind_empty(self):
2532 def test():
2533 return 42
2534
2535 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002536 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002537 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002538 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002539 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002540 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002541 self.call(test, spam=1)
2542
2543 def test_signature_bind_var(self):
2544 def test(*args, **kwargs):
2545 return args, kwargs
2546
2547 self.assertEqual(self.call(test), ((), {}))
2548 self.assertEqual(self.call(test, 1), ((1,), {}))
2549 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2550 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2551 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2552 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2553 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2554 ((1, 2), {'foo': 'bar'}))
2555
2556 def test_signature_bind_just_args(self):
2557 def test(a, b, c):
2558 return a, b, c
2559
2560 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2561
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002562 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002563 self.call(test, 1, 2, 3, 4)
2564
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002565 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002566 self.call(test, 1)
2567
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002568 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002569 self.call(test)
2570
2571 def test(a, b, c=10):
2572 return a, b, c
2573 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2574 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2575
2576 def test(a=1, b=2, c=3):
2577 return a, b, c
2578 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2579 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2580 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2581
2582 def test_signature_bind_varargs_order(self):
2583 def test(*args):
2584 return args
2585
2586 self.assertEqual(self.call(test), ())
2587 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2588
2589 def test_signature_bind_args_and_varargs(self):
2590 def test(a, b, c=3, *args):
2591 return a, b, c, args
2592
2593 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2594 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2595 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2596 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2597
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002598 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002599 "multiple values for argument 'c'"):
2600 self.call(test, 1, 2, 3, c=4)
2601
2602 def test_signature_bind_just_kwargs(self):
2603 def test(**kwargs):
2604 return kwargs
2605
2606 self.assertEqual(self.call(test), {})
2607 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2608 {'foo': 'bar', 'spam': 'ham'})
2609
2610 def test_signature_bind_args_and_kwargs(self):
2611 def test(a, b, c=3, **kwargs):
2612 return a, b, c, kwargs
2613
2614 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2615 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2616 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2617 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2618 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2619 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2620 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2621 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2622 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2623 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2624 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2625 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2626 (1, 2, 4, {'foo': 'bar'}))
2627 self.assertEqual(self.call(test, c=5, a=4, b=3),
2628 (4, 3, 5, {}))
2629
2630 def test_signature_bind_kwonly(self):
2631 def test(*, foo):
2632 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002633 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002634 'too many positional arguments'):
2635 self.call(test, 1)
2636 self.assertEqual(self.call(test, foo=1), 1)
2637
2638 def test(a, *, foo=1, bar):
2639 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002640 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002641 "'bar' parameter lacking default value"):
2642 self.call(test, 1)
2643
2644 def test(foo, *, bar):
2645 return foo, bar
2646 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2647 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2648
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002649 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002650 'too many keyword arguments'):
2651 self.call(test, bar=2, foo=1, spam=10)
2652
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002653 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002654 'too many positional arguments'):
2655 self.call(test, 1, 2)
2656
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002657 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002658 'too many positional arguments'):
2659 self.call(test, 1, 2, bar=2)
2660
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002661 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002662 'too many keyword arguments'):
2663 self.call(test, 1, bar=2, spam='ham')
2664
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002665 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002666 "'bar' parameter lacking default value"):
2667 self.call(test, 1)
2668
2669 def test(foo, *, bar, **bin):
2670 return foo, bar, bin
2671 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2672 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2673 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2674 (1, 2, {'spam': 'ham'}))
2675 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2676 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002677 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002678 "'foo' parameter lacking default value"):
2679 self.call(test, spam='ham', bar=2)
2680 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2681 (1, 2, {'bin': 1, 'spam': 10}))
2682
2683 def test_signature_bind_arguments(self):
2684 def test(a, *args, b, z=100, **kwargs):
2685 pass
2686 sig = inspect.signature(test)
2687 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2688 # we won't have 'z' argument in the bound arguments object, as we didn't
2689 # pass it to the 'bind'
2690 self.assertEqual(tuple(ba.arguments.items()),
2691 (('a', 10), ('args', (20,)), ('b', 30),
2692 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2693 self.assertEqual(ba.kwargs,
2694 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2695 self.assertEqual(ba.args, (10, 20))
2696
2697 def test_signature_bind_positional_only(self):
2698 P = inspect.Parameter
2699
2700 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2701 return a_po, b_po, c_po, foo, bar, kwargs
2702
2703 sig = inspect.signature(test)
2704 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2705 for name in ('a_po', 'b_po', 'c_po'):
2706 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2707 new_sig = sig.replace(parameters=new_params.values())
2708 test.__signature__ = new_sig
2709
2710 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2711 (1, 2, 4, 5, 6, {}))
2712
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002713 self.assertEqual(self.call(test, 1, 2),
2714 (1, 2, 3, 42, 50, {}))
2715
2716 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
2717 (1, 2, 3, 4, 5, {}))
2718
2719 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
2720 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
2721
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002722 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002723 self.call(test, 1, 2, c_po=4)
2724
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002725 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002726 self.call(test, a_po=1, b_po=2)
2727
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002728 def test_signature_bind_with_self_arg(self):
2729 # Issue #17071: one of the parameters is named "self
2730 def test(a, self, b):
2731 pass
2732 sig = inspect.signature(test)
2733 ba = sig.bind(1, 2, 3)
2734 self.assertEqual(ba.args, (1, 2, 3))
2735 ba = sig.bind(1, self=2, b=3)
2736 self.assertEqual(ba.args, (1, 2, 3))
2737
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002738 def test_signature_bind_vararg_name(self):
2739 def test(a, *args):
2740 return a, args
2741 sig = inspect.signature(test)
2742
2743 with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
2744 sig.bind(a=0, args=1)
2745
2746 def test(*args, **kwargs):
2747 return args, kwargs
2748 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
2749
2750 sig = inspect.signature(test)
2751 ba = sig.bind(args=1)
2752 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
2753
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002754
2755class TestBoundArguments(unittest.TestCase):
2756 def test_signature_bound_arguments_unhashable(self):
2757 def foo(a): pass
2758 ba = inspect.signature(foo).bind(1)
2759
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002760 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002761 hash(ba)
2762
2763 def test_signature_bound_arguments_equality(self):
2764 def foo(a): pass
2765 ba = inspect.signature(foo).bind(1)
2766 self.assertEqual(ba, ba)
2767
2768 ba2 = inspect.signature(foo).bind(1)
2769 self.assertEqual(ba, ba2)
2770
2771 ba3 = inspect.signature(foo).bind(2)
2772 self.assertNotEqual(ba, ba3)
2773 ba3.arguments['a'] = 1
2774 self.assertEqual(ba, ba3)
2775
2776 def bar(b): pass
2777 ba4 = inspect.signature(bar).bind(1)
2778 self.assertNotEqual(ba, ba4)
2779
2780
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002781class TestSignaturePrivateHelpers(unittest.TestCase):
2782 def test_signature_get_bound_param(self):
2783 getter = inspect._signature_get_bound_param
2784
2785 self.assertEqual(getter('($self)'), 'self')
2786 self.assertEqual(getter('($self, obj)'), 'self')
2787 self.assertEqual(getter('($cls, /, obj)'), 'cls')
2788
Larry Hastings2623c8c2014-02-08 22:15:29 -08002789 def _strip_non_python_syntax(self, input,
2790 clean_signature, self_parameter, last_positional_only):
2791 computed_clean_signature, \
2792 computed_self_parameter, \
2793 computed_last_positional_only = \
2794 inspect._signature_strip_non_python_syntax(input)
2795 self.assertEqual(computed_clean_signature, clean_signature)
2796 self.assertEqual(computed_self_parameter, self_parameter)
2797 self.assertEqual(computed_last_positional_only, last_positional_only)
2798
2799 def test_signature_strip_non_python_syntax(self):
2800 self._strip_non_python_syntax(
2801 "($module, /, path, mode, *, dir_fd=None, " +
2802 "effective_ids=False,\n follow_symlinks=True)",
2803 "(module, path, mode, *, dir_fd=None, " +
2804 "effective_ids=False, follow_symlinks=True)",
2805 0,
2806 0)
2807
2808 self._strip_non_python_syntax(
2809 "($module, word, salt, /)",
2810 "(module, word, salt)",
2811 0,
2812 2)
2813
2814 self._strip_non_python_syntax(
2815 "(x, y=None, z=None, /)",
2816 "(x, y=None, z=None)",
2817 None,
2818 2)
2819
2820 self._strip_non_python_syntax(
2821 "(x, y=None, z=None)",
2822 "(x, y=None, z=None)",
2823 None,
2824 None)
2825
2826 self._strip_non_python_syntax(
2827 "(x,\n y=None,\n z = None )",
2828 "(x, y=None, z=None)",
2829 None,
2830 None)
2831
2832 self._strip_non_python_syntax(
2833 "",
2834 "",
2835 None,
2836 None)
2837
2838 self._strip_non_python_syntax(
2839 None,
2840 None,
2841 None,
2842 None)
2843
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002844
Nick Coghlane8c45d62013-07-28 20:00:01 +10002845class TestUnwrap(unittest.TestCase):
2846
2847 def test_unwrap_one(self):
2848 def func(a, b):
2849 return a + b
2850 wrapper = functools.lru_cache(maxsize=20)(func)
2851 self.assertIs(inspect.unwrap(wrapper), func)
2852
2853 def test_unwrap_several(self):
2854 def func(a, b):
2855 return a + b
2856 wrapper = func
2857 for __ in range(10):
2858 @functools.wraps(wrapper)
2859 def wrapper():
2860 pass
2861 self.assertIsNot(wrapper.__wrapped__, func)
2862 self.assertIs(inspect.unwrap(wrapper), func)
2863
2864 def test_stop(self):
2865 def func1(a, b):
2866 return a + b
2867 @functools.wraps(func1)
2868 def func2():
2869 pass
2870 @functools.wraps(func2)
2871 def wrapper():
2872 pass
2873 func2.stop_here = 1
2874 unwrapped = inspect.unwrap(wrapper,
2875 stop=(lambda f: hasattr(f, "stop_here")))
2876 self.assertIs(unwrapped, func2)
2877
2878 def test_cycle(self):
2879 def func1(): pass
2880 func1.__wrapped__ = func1
2881 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2882 inspect.unwrap(func1)
2883
2884 def func2(): pass
2885 func2.__wrapped__ = func1
2886 func1.__wrapped__ = func2
2887 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2888 inspect.unwrap(func1)
2889 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2890 inspect.unwrap(func2)
2891
2892 def test_unhashable(self):
2893 def func(): pass
2894 func.__wrapped__ = None
2895 class C:
2896 __hash__ = None
2897 __wrapped__ = func
2898 self.assertIsNone(inspect.unwrap(C()))
2899
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002900class TestMain(unittest.TestCase):
2901 def test_only_source(self):
2902 module = importlib.import_module('unittest')
2903 rc, out, err = assert_python_ok('-m', 'inspect',
2904 'unittest')
2905 lines = out.decode().splitlines()
2906 # ignore the final newline
2907 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
2908 self.assertEqual(err, b'')
2909
Brett Cannon634a8fc2013-10-02 10:25:42 -04002910 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04002911 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002912 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002913 rc, out, err = assert_python_ok('-m', 'inspect',
2914 'concurrent.futures:ThreadPoolExecutor')
2915 lines = out.decode().splitlines()
2916 # ignore the final newline
2917 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04002918 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002919 self.assertEqual(err, b'')
2920
2921 def test_builtins(self):
2922 module = importlib.import_module('unittest')
2923 _, out, err = assert_python_failure('-m', 'inspect',
2924 'sys')
2925 lines = err.decode().splitlines()
2926 self.assertEqual(lines, ["Can't get info for builtin modules."])
2927
2928 def test_details(self):
2929 module = importlib.import_module('unittest')
2930 rc, out, err = assert_python_ok('-m', 'inspect',
2931 'unittest', '--details')
2932 output = out.decode()
2933 # Just a quick sanity check on the output
2934 self.assertIn(module.__name__, output)
2935 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02002936 if not sys.flags.optimize:
2937 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10002938 self.assertEqual(err, b'')
2939
2940
2941
Nick Coghlane8c45d62013-07-28 20:00:01 +10002942
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002943def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00002944 run_unittest(
2945 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
2946 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
2947 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00002948 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002949 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002950 TestBoundArguments, TestSignaturePrivateHelpers, TestGetClosureVars,
2951 TestUnwrap, TestMain
Michael Foord95fc51d2010-11-20 15:07:30 +00002952 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00002953
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002954if __name__ == "__main__":
2955 test_main()