]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.2/Lib/test/test_inspect.py
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Lib / test / test_inspect.py
CommitLineData
4710c53d 1import re\r
2import sys\r
3import types\r
4import unittest\r
5import inspect\r
6import linecache\r
7import datetime\r
8from UserList import UserList\r
9from UserDict import UserDict\r
10\r
11from test.test_support import run_unittest, check_py3k_warnings\r
12\r
13with check_py3k_warnings(\r
14 ("tuple parameter unpacking has been removed", SyntaxWarning),\r
15 quiet=True):\r
16 from test import inspect_fodder as mod\r
17 from test import inspect_fodder2 as mod2\r
18\r
19# C module for test_findsource_binary\r
20import unicodedata\r
21\r
22# Functions tested in this suite:\r
23# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,\r
24# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,\r
25# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,\r
26# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,\r
27# currentframe, stack, trace, isdatadescriptor\r
28\r
29# NOTE: There are some additional tests relating to interaction with\r
30# zipimport in the test_zipimport_support test module.\r
31\r
32modfile = mod.__file__\r
33if modfile.endswith(('c', 'o')):\r
34 modfile = modfile[:-1]\r
35\r
36import __builtin__\r
37\r
38try:\r
39 1 // 0\r
40except:\r
41 tb = sys.exc_traceback\r
42\r
43git = mod.StupidGit()\r
44\r
45class IsTestBase(unittest.TestCase):\r
46 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,\r
47 inspect.isframe, inspect.isfunction, inspect.ismethod,\r
48 inspect.ismodule, inspect.istraceback,\r
49 inspect.isgenerator, inspect.isgeneratorfunction])\r
50\r
51 def istest(self, predicate, exp):\r
52 obj = eval(exp)\r
53 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))\r
54\r
55 for other in self.predicates - set([predicate]):\r
56 if predicate == inspect.isgeneratorfunction and\\r
57 other == inspect.isfunction:\r
58 continue\r
59 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))\r
60\r
61def generator_function_example(self):\r
62 for i in xrange(2):\r
63 yield i\r
64\r
65class TestPredicates(IsTestBase):\r
66 def test_sixteen(self):\r
67 count = len(filter(lambda x:x.startswith('is'), dir(inspect)))\r
68 # This test is here for remember you to update Doc/library/inspect.rst\r
69 # which claims there are 16 such functions\r
70 expected = 16\r
71 err_msg = "There are %d (not %d) is* functions" % (count, expected)\r
72 self.assertEqual(count, expected, err_msg)\r
73\r
74\r
75 def test_excluding_predicates(self):\r
76 self.istest(inspect.isbuiltin, 'sys.exit')\r
77 self.istest(inspect.isbuiltin, '[].append')\r
78 self.istest(inspect.iscode, 'mod.spam.func_code')\r
79 self.istest(inspect.isframe, 'tb.tb_frame')\r
80 self.istest(inspect.isfunction, 'mod.spam')\r
81 self.istest(inspect.ismethod, 'mod.StupidGit.abuse')\r
82 self.istest(inspect.ismethod, 'git.argue')\r
83 self.istest(inspect.ismodule, 'mod')\r
84 self.istest(inspect.istraceback, 'tb')\r
85 self.istest(inspect.isdatadescriptor, '__builtin__.file.closed')\r
86 self.istest(inspect.isdatadescriptor, '__builtin__.file.softspace')\r
87 self.istest(inspect.isgenerator, '(x for x in xrange(2))')\r
88 self.istest(inspect.isgeneratorfunction, 'generator_function_example')\r
89 if hasattr(types, 'GetSetDescriptorType'):\r
90 self.istest(inspect.isgetsetdescriptor,\r
91 'type(tb.tb_frame).f_locals')\r
92 else:\r
93 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))\r
94 if hasattr(types, 'MemberDescriptorType'):\r
95 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')\r
96 else:\r
97 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))\r
98\r
99 def test_isroutine(self):\r
100 self.assertTrue(inspect.isroutine(mod.spam))\r
101 self.assertTrue(inspect.isroutine([].count))\r
102\r
103 def test_isclass(self):\r
104 self.istest(inspect.isclass, 'mod.StupidGit')\r
105 self.assertTrue(inspect.isclass(list))\r
106\r
107 class newstyle(object): pass\r
108 self.assertTrue(inspect.isclass(newstyle))\r
109\r
110 class CustomGetattr(object):\r
111 def __getattr__(self, attr):\r
112 return None\r
113 self.assertFalse(inspect.isclass(CustomGetattr()))\r
114\r
115 def test_get_slot_members(self):\r
116 class C(object):\r
117 __slots__ = ("a", "b")\r
118\r
119 x = C()\r
120 x.a = 42\r
121 members = dict(inspect.getmembers(x))\r
122 self.assertIn('a', members)\r
123 self.assertNotIn('b', members)\r
124\r
125 def test_isabstract(self):\r
126 from abc import ABCMeta, abstractmethod\r
127\r
128 class AbstractClassExample(object):\r
129 __metaclass__ = ABCMeta\r
130\r
131 @abstractmethod\r
132 def foo(self):\r
133 pass\r
134\r
135 class ClassExample(AbstractClassExample):\r
136 def foo(self):\r
137 pass\r
138\r
139 a = ClassExample()\r
140\r
141 # Test general behaviour.\r
142 self.assertTrue(inspect.isabstract(AbstractClassExample))\r
143 self.assertFalse(inspect.isabstract(ClassExample))\r
144 self.assertFalse(inspect.isabstract(a))\r
145 self.assertFalse(inspect.isabstract(int))\r
146 self.assertFalse(inspect.isabstract(5))\r
147\r
148\r
149class TestInterpreterStack(IsTestBase):\r
150 def __init__(self, *args, **kwargs):\r
151 unittest.TestCase.__init__(self, *args, **kwargs)\r
152\r
153 git.abuse(7, 8, 9)\r
154\r
155 def test_abuse_done(self):\r
156 self.istest(inspect.istraceback, 'git.ex[2]')\r
157 self.istest(inspect.isframe, 'mod.fr')\r
158\r
159 def test_stack(self):\r
160 self.assertTrue(len(mod.st) >= 5)\r
161 self.assertEqual(mod.st[0][1:],\r
162 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))\r
163 self.assertEqual(mod.st[1][1:],\r
164 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))\r
165 self.assertEqual(mod.st[2][1:],\r
166 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))\r
167 self.assertEqual(mod.st[3][1:],\r
168 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))\r
169\r
170 def test_trace(self):\r
171 self.assertEqual(len(git.tr), 3)\r
172 self.assertEqual(git.tr[0][1:], (modfile, 43, 'argue',\r
173 [' spam(a, b, c)\n'], 0))\r
174 self.assertEqual(git.tr[1][1:], (modfile, 9, 'spam',\r
175 [' eggs(b + d, c + f)\n'], 0))\r
176 self.assertEqual(git.tr[2][1:], (modfile, 18, 'eggs',\r
177 [' q = y // 0\n'], 0))\r
178\r
179 def test_frame(self):\r
180 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)\r
181 self.assertEqual(args, ['x', 'y'])\r
182 self.assertEqual(varargs, None)\r
183 self.assertEqual(varkw, None)\r
184 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})\r
185 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),\r
186 '(x=11, y=14)')\r
187\r
188 def test_previous_frame(self):\r
189 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)\r
190 self.assertEqual(args, ['a', 'b', 'c', 'd', ['e', ['f']]])\r
191 self.assertEqual(varargs, 'g')\r
192 self.assertEqual(varkw, 'h')\r
193 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),\r
194 '(a=7, b=8, c=9, d=3, (e=4, (f=5,)), *g=(), **h={})')\r
195\r
196class GetSourceBase(unittest.TestCase):\r
197 # Subclasses must override.\r
198 fodderFile = None\r
199\r
200 def __init__(self, *args, **kwargs):\r
201 unittest.TestCase.__init__(self, *args, **kwargs)\r
202\r
203 with open(inspect.getsourcefile(self.fodderFile)) as fp:\r
204 self.source = fp.read()\r
205\r
206 def sourcerange(self, top, bottom):\r
207 lines = self.source.split("\n")\r
208 return "\n".join(lines[top-1:bottom]) + "\n"\r
209\r
210 def assertSourceEqual(self, obj, top, bottom):\r
211 self.assertEqual(inspect.getsource(obj),\r
212 self.sourcerange(top, bottom))\r
213\r
214class TestRetrievingSourceCode(GetSourceBase):\r
215 fodderFile = mod\r
216\r
217 def test_getclasses(self):\r
218 classes = inspect.getmembers(mod, inspect.isclass)\r
219 self.assertEqual(classes,\r
220 [('FesteringGob', mod.FesteringGob),\r
221 ('MalodorousPervert', mod.MalodorousPervert),\r
222 ('ParrotDroppings', mod.ParrotDroppings),\r
223 ('StupidGit', mod.StupidGit)])\r
224 tree = inspect.getclasstree([cls[1] for cls in classes], 1)\r
225 self.assertEqual(tree,\r
226 [(mod.ParrotDroppings, ()),\r
227 (mod.StupidGit, ()),\r
228 [(mod.MalodorousPervert, (mod.StupidGit,)),\r
229 [(mod.FesteringGob, (mod.MalodorousPervert,\r
230 mod.ParrotDroppings))\r
231 ]\r
232 ]\r
233 ])\r
234\r
235 def test_getfunctions(self):\r
236 functions = inspect.getmembers(mod, inspect.isfunction)\r
237 self.assertEqual(functions, [('eggs', mod.eggs),\r
238 ('spam', mod.spam)])\r
239\r
240 @unittest.skipIf(sys.flags.optimize >= 2,\r
241 "Docstrings are omitted with -O2 and above")\r
242 def test_getdoc(self):\r
243 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')\r
244 self.assertEqual(inspect.getdoc(mod.StupidGit),\r
245 'A longer,\n\nindented\n\ndocstring.')\r
246 self.assertEqual(inspect.getdoc(git.abuse),\r
247 'Another\n\ndocstring\n\ncontaining\n\ntabs')\r
248\r
249 def test_cleandoc(self):\r
250 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),\r
251 'An\nindented\ndocstring.')\r
252\r
253 def test_getcomments(self):\r
254 self.assertEqual(inspect.getcomments(mod), '# line 1\n')\r
255 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')\r
256\r
257 def test_getmodule(self):\r
258 # Check actual module\r
259 self.assertEqual(inspect.getmodule(mod), mod)\r
260 # Check class (uses __module__ attribute)\r
261 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)\r
262 # Check a method (no __module__ attribute, falls back to filename)\r
263 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)\r
264 # Do it again (check the caching isn't broken)\r
265 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)\r
266 # Check a builtin\r
267 self.assertEqual(inspect.getmodule(str), sys.modules["__builtin__"])\r
268 # Check filename override\r
269 self.assertEqual(inspect.getmodule(None, modfile), mod)\r
270\r
271 def test_getsource(self):\r
272 self.assertSourceEqual(git.abuse, 29, 39)\r
273 self.assertSourceEqual(mod.StupidGit, 21, 46)\r
274\r
275 def test_getsourcefile(self):\r
276 self.assertEqual(inspect.getsourcefile(mod.spam), modfile)\r
277 self.assertEqual(inspect.getsourcefile(git.abuse), modfile)\r
278 fn = "_non_existing_filename_used_for_sourcefile_test.py"\r
279 co = compile("None", fn, "exec")\r
280 self.assertEqual(inspect.getsourcefile(co), None)\r
281 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)\r
282 self.assertEqual(inspect.getsourcefile(co), fn)\r
283\r
284 def test_getfile(self):\r
285 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)\r
286\r
287 def test_getmodule_recursion(self):\r
288 from types import ModuleType\r
289 name = '__inspect_dummy'\r
290 m = sys.modules[name] = ModuleType(name)\r
291 m.__file__ = "<string>" # hopefully not a real filename...\r
292 m.__loader__ = "dummy" # pretend the filename is understood by a loader\r
293 exec "def x(): pass" in m.__dict__\r
294 self.assertEqual(inspect.getsourcefile(m.x.func_code), '<string>')\r
295 del sys.modules[name]\r
296 inspect.getmodule(compile('a=10','','single'))\r
297\r
298class TestDecorators(GetSourceBase):\r
299 fodderFile = mod2\r
300\r
301 def test_wrapped_decorator(self):\r
302 self.assertSourceEqual(mod2.wrapped, 14, 17)\r
303\r
304 def test_replacing_decorator(self):\r
305 self.assertSourceEqual(mod2.gone, 9, 10)\r
306\r
307class TestOneliners(GetSourceBase):\r
308 fodderFile = mod2\r
309 def test_oneline_lambda(self):\r
310 # Test inspect.getsource with a one-line lambda function.\r
311 self.assertSourceEqual(mod2.oll, 25, 25)\r
312\r
313 def test_threeline_lambda(self):\r
314 # Test inspect.getsource with a three-line lambda function,\r
315 # where the second and third lines are _not_ indented.\r
316 self.assertSourceEqual(mod2.tll, 28, 30)\r
317\r
318 def test_twoline_indented_lambda(self):\r
319 # Test inspect.getsource with a two-line lambda function,\r
320 # where the second line _is_ indented.\r
321 self.assertSourceEqual(mod2.tlli, 33, 34)\r
322\r
323 def test_onelinefunc(self):\r
324 # Test inspect.getsource with a regular one-line function.\r
325 self.assertSourceEqual(mod2.onelinefunc, 37, 37)\r
326\r
327 def test_manyargs(self):\r
328 # Test inspect.getsource with a regular function where\r
329 # the arguments are on two lines and _not_ indented and\r
330 # the body on the second line with the last arguments.\r
331 self.assertSourceEqual(mod2.manyargs, 40, 41)\r
332\r
333 def test_twolinefunc(self):\r
334 # Test inspect.getsource with a regular function where\r
335 # the body is on two lines, following the argument list and\r
336 # continued on the next line by a \\.\r
337 self.assertSourceEqual(mod2.twolinefunc, 44, 45)\r
338\r
339 def test_lambda_in_list(self):\r
340 # Test inspect.getsource with a one-line lambda function\r
341 # defined in a list, indented.\r
342 self.assertSourceEqual(mod2.a[1], 49, 49)\r
343\r
344 def test_anonymous(self):\r
345 # Test inspect.getsource with a lambda function defined\r
346 # as argument to another function.\r
347 self.assertSourceEqual(mod2.anonymous, 55, 55)\r
348\r
349class TestBuggyCases(GetSourceBase):\r
350 fodderFile = mod2\r
351\r
352 def test_with_comment(self):\r
353 self.assertSourceEqual(mod2.with_comment, 58, 59)\r
354\r
355 def test_multiline_sig(self):\r
356 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)\r
357\r
358 def test_nested_class(self):\r
359 self.assertSourceEqual(mod2.func69().func71, 71, 72)\r
360\r
361 def test_one_liner_followed_by_non_name(self):\r
362 self.assertSourceEqual(mod2.func77, 77, 77)\r
363\r
364 def test_one_liner_dedent_non_name(self):\r
365 self.assertSourceEqual(mod2.cls82.func83, 83, 83)\r
366\r
367 def test_with_comment_instead_of_docstring(self):\r
368 self.assertSourceEqual(mod2.func88, 88, 90)\r
369\r
370 def test_method_in_dynamic_class(self):\r
371 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)\r
372\r
373 @unittest.skipIf(\r
374 not hasattr(unicodedata, '__file__') or\r
375 unicodedata.__file__[-4:] in (".pyc", ".pyo"),\r
376 "unicodedata is not an external binary module")\r
377 def test_findsource_binary(self):\r
378 self.assertRaises(IOError, inspect.getsource, unicodedata)\r
379 self.assertRaises(IOError, inspect.findsource, unicodedata)\r
380\r
381 def test_findsource_code_in_linecache(self):\r
382 lines = ["x=1"]\r
383 co = compile(lines[0], "_dynamically_created_file", "exec")\r
384 self.assertRaises(IOError, inspect.findsource, co)\r
385 self.assertRaises(IOError, inspect.getsource, co)\r
386 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)\r
387 self.assertEqual(inspect.findsource(co), (lines,0))\r
388 self.assertEqual(inspect.getsource(co), lines[0])\r
389\r
390# Helper for testing classify_class_attrs.\r
391def attrs_wo_objs(cls):\r
392 return [t[:3] for t in inspect.classify_class_attrs(cls)]\r
393\r
394class TestClassesAndFunctions(unittest.TestCase):\r
395 def test_classic_mro(self):\r
396 # Test classic-class method resolution order.\r
397 class A: pass\r
398 class B(A): pass\r
399 class C(A): pass\r
400 class D(B, C): pass\r
401\r
402 expected = (D, B, A, C)\r
403 got = inspect.getmro(D)\r
404 self.assertEqual(expected, got)\r
405\r
406 def test_newstyle_mro(self):\r
407 # The same w/ new-class MRO.\r
408 class A(object): pass\r
409 class B(A): pass\r
410 class C(A): pass\r
411 class D(B, C): pass\r
412\r
413 expected = (D, B, C, A, object)\r
414 got = inspect.getmro(D)\r
415 self.assertEqual(expected, got)\r
416\r
417 def assertArgSpecEquals(self, routine, args_e, varargs_e = None,\r
418 varkw_e = None, defaults_e = None,\r
419 formatted = None):\r
420 args, varargs, varkw, defaults = inspect.getargspec(routine)\r
421 self.assertEqual(args, args_e)\r
422 self.assertEqual(varargs, varargs_e)\r
423 self.assertEqual(varkw, varkw_e)\r
424 self.assertEqual(defaults, defaults_e)\r
425 if formatted is not None:\r
426 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),\r
427 formatted)\r
428\r
429 def test_getargspec(self):\r
430 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted = '(x, y)')\r
431\r
432 self.assertArgSpecEquals(mod.spam,\r
433 ['a', 'b', 'c', 'd', ['e', ['f']]],\r
434 'g', 'h', (3, (4, (5,))),\r
435 '(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h)')\r
436\r
437 def test_getargspec_method(self):\r
438 class A(object):\r
439 def m(self):\r
440 pass\r
441 self.assertArgSpecEquals(A.m, ['self'])\r
442\r
443 def test_getargspec_sublistofone(self):\r
444 with check_py3k_warnings(\r
445 ("tuple parameter unpacking has been removed", SyntaxWarning),\r
446 ("parenthesized argument names are invalid", SyntaxWarning)):\r
447 exec 'def sublistOfOne((foo,)): return 1'\r
448 self.assertArgSpecEquals(sublistOfOne, [['foo']])\r
449\r
450 exec 'def fakeSublistOfOne((foo)): return 1'\r
451 self.assertArgSpecEquals(fakeSublistOfOne, ['foo'])\r
452\r
453\r
454 def _classify_test(self, newstyle):\r
455 """Helper for testing that classify_class_attrs finds a bunch of\r
456 different kinds of attributes on a given class.\r
457 """\r
458 if newstyle:\r
459 base = object\r
460 else:\r
461 class base:\r
462 pass\r
463\r
464 class A(base):\r
465 def s(): pass\r
466 s = staticmethod(s)\r
467\r
468 def c(cls): pass\r
469 c = classmethod(c)\r
470\r
471 def getp(self): pass\r
472 p = property(getp)\r
473\r
474 def m(self): pass\r
475\r
476 def m1(self): pass\r
477\r
478 datablob = '1'\r
479\r
480 attrs = attrs_wo_objs(A)\r
481 self.assertIn(('s', 'static method', A), attrs, 'missing static method')\r
482 self.assertIn(('c', 'class method', A), attrs, 'missing class method')\r
483 self.assertIn(('p', 'property', A), attrs, 'missing property')\r
484 self.assertIn(('m', 'method', A), attrs, 'missing plain method')\r
485 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')\r
486 self.assertIn(('datablob', 'data', A), attrs, 'missing data')\r
487\r
488 class B(A):\r
489 def m(self): pass\r
490\r
491 attrs = attrs_wo_objs(B)\r
492 self.assertIn(('s', 'static method', A), attrs, 'missing static method')\r
493 self.assertIn(('c', 'class method', A), attrs, 'missing class method')\r
494 self.assertIn(('p', 'property', A), attrs, 'missing property')\r
495 self.assertIn(('m', 'method', B), attrs, 'missing plain method')\r
496 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')\r
497 self.assertIn(('datablob', 'data', A), attrs, 'missing data')\r
498\r
499\r
500 class C(A):\r
501 def m(self): pass\r
502 def c(self): pass\r
503\r
504 attrs = attrs_wo_objs(C)\r
505 self.assertIn(('s', 'static method', A), attrs, 'missing static method')\r
506 self.assertIn(('c', 'method', C), attrs, 'missing plain method')\r
507 self.assertIn(('p', 'property', A), attrs, 'missing property')\r
508 self.assertIn(('m', 'method', C), attrs, 'missing plain method')\r
509 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')\r
510 self.assertIn(('datablob', 'data', A), attrs, 'missing data')\r
511\r
512 class D(B, C):\r
513 def m1(self): pass\r
514\r
515 attrs = attrs_wo_objs(D)\r
516 self.assertIn(('s', 'static method', A), attrs, 'missing static method')\r
517 if newstyle:\r
518 self.assertIn(('c', 'method', C), attrs, 'missing plain method')\r
519 else:\r
520 self.assertIn(('c', 'class method', A), attrs, 'missing class method')\r
521 self.assertIn(('p', 'property', A), attrs, 'missing property')\r
522 self.assertIn(('m', 'method', B), attrs, 'missing plain method')\r
523 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')\r
524 self.assertIn(('datablob', 'data', A), attrs, 'missing data')\r
525\r
526\r
527 def test_classify_oldstyle(self):\r
528 """classify_class_attrs finds static methods, class methods,\r
529 properties, normal methods, and data attributes on an old-style\r
530 class.\r
531 """\r
532 self._classify_test(False)\r
533\r
534\r
535 def test_classify_newstyle(self):\r
536 """Just like test_classify_oldstyle, but for a new-style class.\r
537 """\r
538 self._classify_test(True)\r
539\r
540\r
541\r
542class TestGetcallargsFunctions(unittest.TestCase):\r
543\r
544 # tuple parameters are named '.1', '.2', etc.\r
545 is_tuplename = re.compile(r'^\.\d+$').match\r
546\r
547 def assertEqualCallArgs(self, func, call_params_string, locs=None):\r
548 locs = dict(locs or {}, func=func)\r
549 r1 = eval('func(%s)' % call_params_string, None, locs)\r
550 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,\r
551 locs)\r
552 self.assertEqual(r1, r2)\r
553\r
554 def assertEqualException(self, func, call_param_string, locs=None):\r
555 locs = dict(locs or {}, func=func)\r
556 try:\r
557 eval('func(%s)' % call_param_string, None, locs)\r
558 except Exception, ex1:\r
559 pass\r
560 else:\r
561 self.fail('Exception not raised')\r
562 try:\r
563 eval('inspect.getcallargs(func, %s)' % call_param_string, None,\r
564 locs)\r
565 except Exception, ex2:\r
566 pass\r
567 else:\r
568 self.fail('Exception not raised')\r
569 self.assertIs(type(ex1), type(ex2))\r
570 self.assertEqual(str(ex1), str(ex2))\r
571\r
572 def makeCallable(self, signature):\r
573 """Create a function that returns its locals(), excluding the\r
574 autogenerated '.1', '.2', etc. tuple param names (if any)."""\r
575 with check_py3k_warnings(\r
576 ("tuple parameter unpacking has been removed", SyntaxWarning),\r
577 quiet=True):\r
578 code = ("lambda %s: dict(i for i in locals().items() "\r
579 "if not is_tuplename(i[0]))")\r
580 return eval(code % signature, {'is_tuplename' : self.is_tuplename})\r
581\r
582 def test_plain(self):\r
583 f = self.makeCallable('a, b=1')\r
584 self.assertEqualCallArgs(f, '2')\r
585 self.assertEqualCallArgs(f, '2, 3')\r
586 self.assertEqualCallArgs(f, 'a=2')\r
587 self.assertEqualCallArgs(f, 'b=3, a=2')\r
588 self.assertEqualCallArgs(f, '2, b=3')\r
589 # expand *iterable / **mapping\r
590 self.assertEqualCallArgs(f, '*(2,)')\r
591 self.assertEqualCallArgs(f, '*[2]')\r
592 self.assertEqualCallArgs(f, '*(2, 3)')\r
593 self.assertEqualCallArgs(f, '*[2, 3]')\r
594 self.assertEqualCallArgs(f, '**{"a":2}')\r
595 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')\r
596 self.assertEqualCallArgs(f, '2, **{"b":3}')\r
597 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')\r
598 # expand UserList / UserDict\r
599 self.assertEqualCallArgs(f, '*UserList([2])')\r
600 self.assertEqualCallArgs(f, '*UserList([2, 3])')\r
601 self.assertEqualCallArgs(f, '**UserDict(a=2)')\r
602 self.assertEqualCallArgs(f, '2, **UserDict(b=3)')\r
603 self.assertEqualCallArgs(f, 'b=2, **UserDict(a=3)')\r
604 # unicode keyword args\r
605 self.assertEqualCallArgs(f, '**{u"a":2}')\r
606 self.assertEqualCallArgs(f, 'b=3, **{u"a":2}')\r
607 self.assertEqualCallArgs(f, '2, **{u"b":3}')\r
608 self.assertEqualCallArgs(f, '**{u"b":3, u"a":2}')\r
609\r
610 def test_varargs(self):\r
611 f = self.makeCallable('a, b=1, *c')\r
612 self.assertEqualCallArgs(f, '2')\r
613 self.assertEqualCallArgs(f, '2, 3')\r
614 self.assertEqualCallArgs(f, '2, 3, 4')\r
615 self.assertEqualCallArgs(f, '*(2,3,4)')\r
616 self.assertEqualCallArgs(f, '2, *[3,4]')\r
617 self.assertEqualCallArgs(f, '2, 3, *UserList([4])')\r
618\r
619 def test_varkw(self):\r
620 f = self.makeCallable('a, b=1, **c')\r
621 self.assertEqualCallArgs(f, 'a=2')\r
622 self.assertEqualCallArgs(f, '2, b=3, c=4')\r
623 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')\r
624 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')\r
625 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')\r
626 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')\r
627 self.assertEqualCallArgs(f, '**UserDict(a=2, b=3, c=4)')\r
628 self.assertEqualCallArgs(f, '2, c=4, **UserDict(b=3)')\r
629 self.assertEqualCallArgs(f, 'b=2, **UserDict(a=3, c=4)')\r
630 # unicode keyword args\r
631 self.assertEqualCallArgs(f, 'c=4, **{u"a":2, u"b":3}')\r
632 self.assertEqualCallArgs(f, '2, c=4, **{u"b":3}')\r
633 self.assertEqualCallArgs(f, 'b=2, **{u"a":3, u"c":4}')\r
634\r
635 def test_varkw_only(self):\r
636 # issue11256:\r
637 f = self.makeCallable('**c')\r
638 self.assertEqualCallArgs(f, '')\r
639 self.assertEqualCallArgs(f, 'a=1')\r
640 self.assertEqualCallArgs(f, 'a=1, b=2')\r
641 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')\r
642 self.assertEqualCallArgs(f, '**UserDict(a=1, b=2)')\r
643 self.assertEqualCallArgs(f, 'c=3, **UserDict(a=1, b=2)')\r
644\r
645 def test_tupleargs(self):\r
646 f = self.makeCallable('(b,c), (d,(e,f))=(0,[1,2])')\r
647 self.assertEqualCallArgs(f, '(2,3)')\r
648 self.assertEqualCallArgs(f, '[2,3]')\r
649 self.assertEqualCallArgs(f, 'UserList([2,3])')\r
650 self.assertEqualCallArgs(f, '(2,3), (4,(5,6))')\r
651 self.assertEqualCallArgs(f, '(2,3), (4,[5,6])')\r
652 self.assertEqualCallArgs(f, '(2,3), [4,UserList([5,6])]')\r
653\r
654 def test_multiple_features(self):\r
655 f = self.makeCallable('a, b=2, (c,(d,e))=(3,[4,5]), *f, **g')\r
656 self.assertEqualCallArgs(f, '2, 3, (4,[5,6]), 7')\r
657 self.assertEqualCallArgs(f, '2, 3, *[(4,[5,6]), 7], x=8')\r
658 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')\r
659 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')\r
660 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')\r
661 self.assertEqualCallArgs(f, 'x=8, *UserList([2, 3, (4,[5,6])]), '\r
662 '**{"y":9, "z":10}')\r
663 self.assertEqualCallArgs(f, '2, x=8, *UserList([3, (4,[5,6])]), '\r
664 '**UserDict(y=9, z=10)')\r
665\r
666 def test_errors(self):\r
667 f0 = self.makeCallable('')\r
668 f1 = self.makeCallable('a, b')\r
669 f2 = self.makeCallable('a, b=1')\r
670 # f0 takes no arguments\r
671 self.assertEqualException(f0, '1')\r
672 self.assertEqualException(f0, 'x=1')\r
673 self.assertEqualException(f0, '1,x=1')\r
674 # f1 takes exactly 2 arguments\r
675 self.assertEqualException(f1, '')\r
676 self.assertEqualException(f1, '1')\r
677 self.assertEqualException(f1, 'a=2')\r
678 self.assertEqualException(f1, 'b=3')\r
679 # f2 takes at least 1 argument\r
680 self.assertEqualException(f2, '')\r
681 self.assertEqualException(f2, 'b=3')\r
682 for f in f1, f2:\r
683 # f1/f2 takes exactly/at most 2 arguments\r
684 self.assertEqualException(f, '2, 3, 4')\r
685 self.assertEqualException(f, '1, 2, 3, a=1')\r
686 self.assertEqualException(f, '2, 3, 4, c=5')\r
687 self.assertEqualException(f, '2, 3, 4, a=1, c=5')\r
688 # f got an unexpected keyword argument\r
689 self.assertEqualException(f, 'c=2')\r
690 self.assertEqualException(f, '2, c=3')\r
691 self.assertEqualException(f, '2, 3, c=4')\r
692 self.assertEqualException(f, '2, c=4, b=3')\r
693 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')\r
694 # f got multiple values for keyword argument\r
695 self.assertEqualException(f, '1, a=2')\r
696 self.assertEqualException(f, '1, **{"a":2}')\r
697 self.assertEqualException(f, '1, 2, b=3')\r
698 # XXX: Python inconsistency\r
699 # - for functions and bound methods: unexpected keyword 'c'\r
700 # - for unbound methods: multiple values for keyword 'a'\r
701 #self.assertEqualException(f, '1, c=3, a=2')\r
702 f = self.makeCallable('(a,b)=(0,1)')\r
703 self.assertEqualException(f, '1')\r
704 self.assertEqualException(f, '[1]')\r
705 self.assertEqualException(f, '(1,2,3)')\r
706 # issue11256:\r
707 f3 = self.makeCallable('**c')\r
708 self.assertEqualException(f3, '1, 2')\r
709 self.assertEqualException(f3, '1, 2, a=1, b=2')\r
710\r
711class TestGetcallargsMethods(TestGetcallargsFunctions):\r
712\r
713 def setUp(self):\r
714 class Foo(object):\r
715 pass\r
716 self.cls = Foo\r
717 self.inst = Foo()\r
718\r
719 def makeCallable(self, signature):\r
720 assert 'self' not in signature\r
721 mk = super(TestGetcallargsMethods, self).makeCallable\r
722 self.cls.method = mk('self, ' + signature)\r
723 return self.inst.method\r
724\r
725class TestGetcallargsUnboundMethods(TestGetcallargsMethods):\r
726\r
727 def makeCallable(self, signature):\r
728 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)\r
729 return self.cls.method\r
730\r
731 def assertEqualCallArgs(self, func, call_params_string, locs=None):\r
732 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(\r
733 *self._getAssertEqualParams(func, call_params_string, locs))\r
734\r
735 def assertEqualException(self, func, call_params_string, locs=None):\r
736 return super(TestGetcallargsUnboundMethods, self).assertEqualException(\r
737 *self._getAssertEqualParams(func, call_params_string, locs))\r
738\r
739 def _getAssertEqualParams(self, func, call_params_string, locs=None):\r
740 assert 'inst' not in call_params_string\r
741 locs = dict(locs or {}, inst=self.inst)\r
742 return (func, 'inst,' + call_params_string, locs)\r
743\r
744def test_main():\r
745 run_unittest(\r
746 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,\r
747 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,\r
748 TestGetcallargsFunctions, TestGetcallargsMethods,\r
749 TestGetcallargsUnboundMethods)\r
750\r
751if __name__ == "__main__":\r
752 test_main()\r