8 from UserList
import UserList
9 from UserDict
import UserDict
11 from test
.test_support
import run_unittest
, check_py3k_warnings
13 with
check_py3k_warnings(
14 ("tuple parameter unpacking has been removed", SyntaxWarning),
16 from test
import inspect_fodder
as mod
17 from test
import inspect_fodder2
as mod2
19 # C module for test_findsource_binary
22 # Functions tested in this suite:
23 # ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
24 # isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
25 # getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
26 # getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
27 # currentframe, stack, trace, isdatadescriptor
29 # NOTE: There are some additional tests relating to interaction with
30 # zipimport in the test_zipimport_support test module.
32 modfile
= mod
.__file
__
33 if modfile
.endswith(('c', 'o')):
34 modfile
= modfile
[:-1]
41 tb
= sys
.exc_traceback
45 class IsTestBase(unittest
.TestCase
):
46 predicates
= set([inspect
.isbuiltin
, inspect
.isclass
, inspect
.iscode
,
47 inspect
.isframe
, inspect
.isfunction
, inspect
.ismethod
,
48 inspect
.ismodule
, inspect
.istraceback
,
49 inspect
.isgenerator
, inspect
.isgeneratorfunction
])
51 def istest(self
, predicate
, exp
):
53 self
.assertTrue(predicate(obj
), '%s(%s)' % (predicate
.__name
__, exp
))
55 for other
in self
.predicates
- set([predicate
]):
56 if predicate
== inspect
.isgeneratorfunction
and\
57 other
== inspect
.isfunction
:
59 self
.assertFalse(other(obj
), 'not %s(%s)' % (other
.__name
__, exp
))
61 def generator_function_example(self
):
65 class TestPredicates(IsTestBase
):
66 def test_sixteen(self
):
67 count
= len(filter(lambda x
:x
.startswith('is'), dir(inspect
)))
68 # This test is here for remember you to update Doc/library/inspect.rst
69 # which claims there are 16 such functions
71 err_msg
= "There are %d (not %d) is* functions" % (count
, expected
)
72 self
.assertEqual(count
, expected
, err_msg
)
75 def test_excluding_predicates(self
):
76 self
.istest(inspect
.isbuiltin
, 'sys.exit')
77 self
.istest(inspect
.isbuiltin
, '[].append')
78 self
.istest(inspect
.iscode
, 'mod.spam.func_code')
79 self
.istest(inspect
.isframe
, 'tb.tb_frame')
80 self
.istest(inspect
.isfunction
, 'mod.spam')
81 self
.istest(inspect
.ismethod
, 'mod.StupidGit.abuse')
82 self
.istest(inspect
.ismethod
, 'git.argue')
83 self
.istest(inspect
.ismodule
, 'mod')
84 self
.istest(inspect
.istraceback
, 'tb')
85 self
.istest(inspect
.isdatadescriptor
, '__builtin__.file.closed')
86 self
.istest(inspect
.isdatadescriptor
, '__builtin__.file.softspace')
87 self
.istest(inspect
.isgenerator
, '(x for x in xrange(2))')
88 self
.istest(inspect
.isgeneratorfunction
, 'generator_function_example')
89 if hasattr(types
, 'GetSetDescriptorType'):
90 self
.istest(inspect
.isgetsetdescriptor
,
91 'type(tb.tb_frame).f_locals')
93 self
.assertFalse(inspect
.isgetsetdescriptor(type(tb
.tb_frame
).f_locals
))
94 if hasattr(types
, 'MemberDescriptorType'):
95 self
.istest(inspect
.ismemberdescriptor
, 'datetime.timedelta.days')
97 self
.assertFalse(inspect
.ismemberdescriptor(datetime
.timedelta
.days
))
99 def test_isroutine(self
):
100 self
.assertTrue(inspect
.isroutine(mod
.spam
))
101 self
.assertTrue(inspect
.isroutine([].count
))
103 def test_isclass(self
):
104 self
.istest(inspect
.isclass
, 'mod.StupidGit')
105 self
.assertTrue(inspect
.isclass(list))
107 class newstyle(object): pass
108 self
.assertTrue(inspect
.isclass(newstyle
))
110 class CustomGetattr(object):
111 def __getattr__(self
, attr
):
113 self
.assertFalse(inspect
.isclass(CustomGetattr()))
115 def test_get_slot_members(self
):
117 __slots__
= ("a", "b")
121 members
= dict(inspect
.getmembers(x
))
122 self
.assertIn('a', members
)
123 self
.assertNotIn('b', members
)
125 def test_isabstract(self
):
126 from abc
import ABCMeta
, abstractmethod
128 class AbstractClassExample(object):
129 __metaclass__
= ABCMeta
135 class ClassExample(AbstractClassExample
):
141 # Test general behaviour.
142 self
.assertTrue(inspect
.isabstract(AbstractClassExample
))
143 self
.assertFalse(inspect
.isabstract(ClassExample
))
144 self
.assertFalse(inspect
.isabstract(a
))
145 self
.assertFalse(inspect
.isabstract(int))
146 self
.assertFalse(inspect
.isabstract(5))
149 class TestInterpreterStack(IsTestBase
):
150 def __init__(self
, *args
, **kwargs
):
151 unittest
.TestCase
.__init
__(self
, *args
, **kwargs
)
155 def test_abuse_done(self
):
156 self
.istest(inspect
.istraceback
, 'git.ex[2]')
157 self
.istest(inspect
.isframe
, 'mod.fr')
159 def test_stack(self
):
160 self
.assertTrue(len(mod
.st
) >= 5)
161 self
.assertEqual(mod
.st
[0][1:],
162 (modfile
, 16, 'eggs', [' st = inspect.stack()\n'], 0))
163 self
.assertEqual(mod
.st
[1][1:],
164 (modfile
, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
165 self
.assertEqual(mod
.st
[2][1:],
166 (modfile
, 43, 'argue', [' spam(a, b, c)\n'], 0))
167 self
.assertEqual(mod
.st
[3][1:],
168 (modfile
, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
170 def test_trace(self
):
171 self
.assertEqual(len(git
.tr
), 3)
172 self
.assertEqual(git
.tr
[0][1:], (modfile
, 43, 'argue',
173 [' spam(a, b, c)\n'], 0))
174 self
.assertEqual(git
.tr
[1][1:], (modfile
, 9, 'spam',
175 [' eggs(b + d, c + f)\n'], 0))
176 self
.assertEqual(git
.tr
[2][1:], (modfile
, 18, 'eggs',
177 [' q = y // 0\n'], 0))
179 def test_frame(self
):
180 args
, varargs
, varkw
, locals = inspect
.getargvalues(mod
.fr
)
181 self
.assertEqual(args
, ['x', 'y'])
182 self
.assertEqual(varargs
, None)
183 self
.assertEqual(varkw
, None)
184 self
.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
185 self
.assertEqual(inspect
.formatargvalues(args
, varargs
, varkw
, locals),
188 def test_previous_frame(self
):
189 args
, varargs
, varkw
, locals = inspect
.getargvalues(mod
.fr
.f_back
)
190 self
.assertEqual(args
, ['a', 'b', 'c', 'd', ['e', ['f']]])
191 self
.assertEqual(varargs
, 'g')
192 self
.assertEqual(varkw
, 'h')
193 self
.assertEqual(inspect
.formatargvalues(args
, varargs
, varkw
, locals),
194 '(a=7, b=8, c=9, d=3, (e=4, (f=5,)), *g=(), **h={})')
196 class GetSourceBase(unittest
.TestCase
):
197 # Subclasses must override.
200 def __init__(self
, *args
, **kwargs
):
201 unittest
.TestCase
.__init
__(self
, *args
, **kwargs
)
203 with
open(inspect
.getsourcefile(self
.fodderFile
)) as fp
:
204 self
.source
= fp
.read()
206 def sourcerange(self
, top
, bottom
):
207 lines
= self
.source
.split("\n")
208 return "\n".join(lines
[top
-1:bottom
]) + "\n"
210 def assertSourceEqual(self
, obj
, top
, bottom
):
211 self
.assertEqual(inspect
.getsource(obj
),
212 self
.sourcerange(top
, bottom
))
214 class TestRetrievingSourceCode(GetSourceBase
):
217 def test_getclasses(self
):
218 classes
= inspect
.getmembers(mod
, inspect
.isclass
)
219 self
.assertEqual(classes
,
220 [('FesteringGob', mod
.FesteringGob
),
221 ('MalodorousPervert', mod
.MalodorousPervert
),
222 ('ParrotDroppings', mod
.ParrotDroppings
),
223 ('StupidGit', mod
.StupidGit
)])
224 tree
= inspect
.getclasstree([cls
[1] for cls
in classes
], 1)
225 self
.assertEqual(tree
,
226 [(mod
.ParrotDroppings
, ()),
228 [(mod
.MalodorousPervert
, (mod
.StupidGit
,)),
229 [(mod
.FesteringGob
, (mod
.MalodorousPervert
,
230 mod
.ParrotDroppings
))
235 def test_getfunctions(self
):
236 functions
= inspect
.getmembers(mod
, inspect
.isfunction
)
237 self
.assertEqual(functions
, [('eggs', mod
.eggs
),
240 @unittest.skipIf(sys
.flags
.optimize
>= 2,
241 "Docstrings are omitted with -O2 and above")
242 def test_getdoc(self
):
243 self
.assertEqual(inspect
.getdoc(mod
), 'A module docstring.')
244 self
.assertEqual(inspect
.getdoc(mod
.StupidGit
),
245 'A longer,\n\nindented\n\ndocstring.')
246 self
.assertEqual(inspect
.getdoc(git
.abuse
),
247 'Another\n\ndocstring\n\ncontaining\n\ntabs')
249 def test_cleandoc(self
):
250 self
.assertEqual(inspect
.cleandoc('An\n indented\n docstring.'),
251 'An\nindented\ndocstring.')
253 def test_getcomments(self
):
254 self
.assertEqual(inspect
.getcomments(mod
), '# line 1\n')
255 self
.assertEqual(inspect
.getcomments(mod
.StupidGit
), '# line 20\n')
257 def test_getmodule(self
):
258 # Check actual module
259 self
.assertEqual(inspect
.getmodule(mod
), mod
)
260 # Check class (uses __module__ attribute)
261 self
.assertEqual(inspect
.getmodule(mod
.StupidGit
), mod
)
262 # Check a method (no __module__ attribute, falls back to filename)
263 self
.assertEqual(inspect
.getmodule(mod
.StupidGit
.abuse
), mod
)
264 # Do it again (check the caching isn't broken)
265 self
.assertEqual(inspect
.getmodule(mod
.StupidGit
.abuse
), mod
)
267 self
.assertEqual(inspect
.getmodule(str), sys
.modules
["__builtin__"])
268 # Check filename override
269 self
.assertEqual(inspect
.getmodule(None, modfile
), mod
)
271 def test_getsource(self
):
272 self
.assertSourceEqual(git
.abuse
, 29, 39)
273 self
.assertSourceEqual(mod
.StupidGit
, 21, 46)
275 def test_getsourcefile(self
):
276 self
.assertEqual(inspect
.getsourcefile(mod
.spam
), modfile
)
277 self
.assertEqual(inspect
.getsourcefile(git
.abuse
), modfile
)
278 fn
= "_non_existing_filename_used_for_sourcefile_test.py"
279 co
= compile("None", fn
, "exec")
280 self
.assertEqual(inspect
.getsourcefile(co
), None)
281 linecache
.cache
[co
.co_filename
] = (1, None, "None", co
.co_filename
)
282 self
.assertEqual(inspect
.getsourcefile(co
), fn
)
284 def test_getfile(self
):
285 self
.assertEqual(inspect
.getfile(mod
.StupidGit
), mod
.__file
__)
287 def test_getmodule_recursion(self
):
288 from types
import ModuleType
289 name
= '__inspect_dummy'
290 m
= sys
.modules
[name
] = ModuleType(name
)
291 m
.__file
__ = "<string>" # hopefully not a real filename...
292 m
.__loader
__ = "dummy" # pretend the filename is understood by a loader
293 exec "def x(): pass" in m
.__dict
__
294 self
.assertEqual(inspect
.getsourcefile(m
.x
.func_code
), '<string>')
295 del sys
.modules
[name
]
296 inspect
.getmodule(compile('a=10','','single'))
298 class TestDecorators(GetSourceBase
):
301 def test_wrapped_decorator(self
):
302 self
.assertSourceEqual(mod2
.wrapped
, 14, 17)
304 def test_replacing_decorator(self
):
305 self
.assertSourceEqual(mod2
.gone
, 9, 10)
307 class TestOneliners(GetSourceBase
):
309 def test_oneline_lambda(self
):
310 # Test inspect.getsource with a one-line lambda function.
311 self
.assertSourceEqual(mod2
.oll
, 25, 25)
313 def test_threeline_lambda(self
):
314 # Test inspect.getsource with a three-line lambda function,
315 # where the second and third lines are _not_ indented.
316 self
.assertSourceEqual(mod2
.tll
, 28, 30)
318 def test_twoline_indented_lambda(self
):
319 # Test inspect.getsource with a two-line lambda function,
320 # where the second line _is_ indented.
321 self
.assertSourceEqual(mod2
.tlli
, 33, 34)
323 def test_onelinefunc(self
):
324 # Test inspect.getsource with a regular one-line function.
325 self
.assertSourceEqual(mod2
.onelinefunc
, 37, 37)
327 def test_manyargs(self
):
328 # Test inspect.getsource with a regular function where
329 # the arguments are on two lines and _not_ indented and
330 # the body on the second line with the last arguments.
331 self
.assertSourceEqual(mod2
.manyargs
, 40, 41)
333 def test_twolinefunc(self
):
334 # Test inspect.getsource with a regular function where
335 # the body is on two lines, following the argument list and
336 # continued on the next line by a \\.
337 self
.assertSourceEqual(mod2
.twolinefunc
, 44, 45)
339 def test_lambda_in_list(self
):
340 # Test inspect.getsource with a one-line lambda function
341 # defined in a list, indented.
342 self
.assertSourceEqual(mod2
.a
[1], 49, 49)
344 def test_anonymous(self
):
345 # Test inspect.getsource with a lambda function defined
346 # as argument to another function.
347 self
.assertSourceEqual(mod2
.anonymous
, 55, 55)
349 class TestBuggyCases(GetSourceBase
):
352 def test_with_comment(self
):
353 self
.assertSourceEqual(mod2
.with_comment
, 58, 59)
355 def test_multiline_sig(self
):
356 self
.assertSourceEqual(mod2
.multiline_sig
[0], 63, 64)
358 def test_nested_class(self
):
359 self
.assertSourceEqual(mod2
.func69().func71
, 71, 72)
361 def test_one_liner_followed_by_non_name(self
):
362 self
.assertSourceEqual(mod2
.func77
, 77, 77)
364 def test_one_liner_dedent_non_name(self
):
365 self
.assertSourceEqual(mod2
.cls82
.func83
, 83, 83)
367 def test_with_comment_instead_of_docstring(self
):
368 self
.assertSourceEqual(mod2
.func88
, 88, 90)
370 def test_method_in_dynamic_class(self
):
371 self
.assertSourceEqual(mod2
.method_in_dynamic_class
, 95, 97)
374 not hasattr(unicodedata
, '__file__') or
375 unicodedata
.__file
__[-4:] in (".pyc", ".pyo"),
376 "unicodedata is not an external binary module")
377 def test_findsource_binary(self
):
378 self
.assertRaises(IOError, inspect
.getsource
, unicodedata
)
379 self
.assertRaises(IOError, inspect
.findsource
, unicodedata
)
381 def test_findsource_code_in_linecache(self
):
383 co
= compile(lines
[0], "_dynamically_created_file", "exec")
384 self
.assertRaises(IOError, inspect
.findsource
, co
)
385 self
.assertRaises(IOError, inspect
.getsource
, co
)
386 linecache
.cache
[co
.co_filename
] = (1, None, lines
, co
.co_filename
)
387 self
.assertEquals(inspect
.findsource(co
), (lines
,0))
388 self
.assertEquals(inspect
.getsource(co
), lines
[0])
390 # Helper for testing classify_class_attrs.
391 def attrs_wo_objs(cls
):
392 return [t
[:3] for t
in inspect
.classify_class_attrs(cls
)]
394 class TestClassesAndFunctions(unittest
.TestCase
):
395 def test_classic_mro(self
):
396 # Test classic-class method resolution order.
402 expected
= (D
, B
, A
, C
)
403 got
= inspect
.getmro(D
)
404 self
.assertEqual(expected
, got
)
406 def test_newstyle_mro(self
):
407 # The same w/ new-class MRO.
408 class A(object): pass
413 expected
= (D
, B
, C
, A
, object)
414 got
= inspect
.getmro(D
)
415 self
.assertEqual(expected
, got
)
417 def assertArgSpecEquals(self
, routine
, args_e
, varargs_e
= None,
418 varkw_e
= None, defaults_e
= None,
420 args
, varargs
, varkw
, defaults
= inspect
.getargspec(routine
)
421 self
.assertEqual(args
, args_e
)
422 self
.assertEqual(varargs
, varargs_e
)
423 self
.assertEqual(varkw
, varkw_e
)
424 self
.assertEqual(defaults
, defaults_e
)
425 if formatted
is not None:
426 self
.assertEqual(inspect
.formatargspec(args
, varargs
, varkw
, defaults
),
429 def test_getargspec(self
):
430 self
.assertArgSpecEquals(mod
.eggs
, ['x', 'y'], formatted
= '(x, y)')
432 self
.assertArgSpecEquals(mod
.spam
,
433 ['a', 'b', 'c', 'd', ['e', ['f']]],
434 'g', 'h', (3, (4, (5,))),
435 '(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h)')
437 def test_getargspec_method(self
):
441 self
.assertArgSpecEquals(A
.m
, ['self'])
443 def test_getargspec_sublistofone(self
):
444 with
check_py3k_warnings(
445 ("tuple parameter unpacking has been removed", SyntaxWarning),
446 ("parenthesized argument names are invalid", SyntaxWarning)):
447 exec 'def sublistOfOne((foo,)): return 1'
448 self
.assertArgSpecEquals(sublistOfOne
, [['foo']])
450 exec 'def fakeSublistOfOne((foo)): return 1'
451 self
.assertArgSpecEquals(fakeSublistOfOne
, ['foo'])
454 def _classify_test(self
, newstyle
):
455 """Helper for testing that classify_class_attrs finds a bunch of
456 different kinds of attributes on a given class.
480 attrs
= attrs_wo_objs(A
)
481 self
.assertIn(('s', 'static method', A
), attrs
, 'missing static method')
482 self
.assertIn(('c', 'class method', A
), attrs
, 'missing class method')
483 self
.assertIn(('p', 'property', A
), attrs
, 'missing property')
484 self
.assertIn(('m', 'method', A
), attrs
, 'missing plain method')
485 self
.assertIn(('m1', 'method', A
), attrs
, 'missing plain method')
486 self
.assertIn(('datablob', 'data', A
), attrs
, 'missing data')
491 attrs
= attrs_wo_objs(B
)
492 self
.assertIn(('s', 'static method', A
), attrs
, 'missing static method')
493 self
.assertIn(('c', 'class method', A
), attrs
, 'missing class method')
494 self
.assertIn(('p', 'property', A
), attrs
, 'missing property')
495 self
.assertIn(('m', 'method', B
), attrs
, 'missing plain method')
496 self
.assertIn(('m1', 'method', A
), attrs
, 'missing plain method')
497 self
.assertIn(('datablob', 'data', A
), attrs
, 'missing data')
504 attrs
= attrs_wo_objs(C
)
505 self
.assertIn(('s', 'static method', A
), attrs
, 'missing static method')
506 self
.assertIn(('c', 'method', C
), attrs
, 'missing plain method')
507 self
.assertIn(('p', 'property', A
), attrs
, 'missing property')
508 self
.assertIn(('m', 'method', C
), attrs
, 'missing plain method')
509 self
.assertIn(('m1', 'method', A
), attrs
, 'missing plain method')
510 self
.assertIn(('datablob', 'data', A
), attrs
, 'missing data')
515 attrs
= attrs_wo_objs(D
)
516 self
.assertIn(('s', 'static method', A
), attrs
, 'missing static method')
518 self
.assertIn(('c', 'method', C
), attrs
, 'missing plain method')
520 self
.assertIn(('c', 'class method', A
), attrs
, 'missing class method')
521 self
.assertIn(('p', 'property', A
), attrs
, 'missing property')
522 self
.assertIn(('m', 'method', B
), attrs
, 'missing plain method')
523 self
.assertIn(('m1', 'method', D
), attrs
, 'missing plain method')
524 self
.assertIn(('datablob', 'data', A
), attrs
, 'missing data')
527 def test_classify_oldstyle(self
):
528 """classify_class_attrs finds static methods, class methods,
529 properties, normal methods, and data attributes on an old-style
532 self
._classify
_test
(False)
535 def test_classify_newstyle(self
):
536 """Just like test_classify_oldstyle, but for a new-style class.
538 self
._classify
_test
(True)
542 class TestGetcallargsFunctions(unittest
.TestCase
):
544 # tuple parameters are named '.1', '.2', etc.
545 is_tuplename
= re
.compile(r
'^\.\d+$').match
547 def assertEqualCallArgs(self
, func
, call_params_string
, locs
=None):
548 locs
= dict(locs
or {}, func
=func
)
549 r1
= eval('func(%s)' % call_params_string
, None, locs
)
550 r2
= eval('inspect.getcallargs(func, %s)' % call_params_string
, None,
552 self
.assertEqual(r1
, r2
)
554 def assertEqualException(self
, func
, call_param_string
, locs
=None):
555 locs
= dict(locs
or {}, func
=func
)
557 eval('func(%s)' % call_param_string
, None, locs
)
558 except Exception, ex1
:
561 self
.fail('Exception not raised')
563 eval('inspect.getcallargs(func, %s)' % call_param_string
, None,
565 except Exception, ex2
:
568 self
.fail('Exception not raised')
569 self
.assertIs(type(ex1
), type(ex2
))
570 self
.assertEqual(str(ex1
), str(ex2
))
572 def makeCallable(self
, signature
):
573 """Create a function that returns its locals(), excluding the
574 autogenerated '.1', '.2', etc. tuple param names (if any)."""
575 with
check_py3k_warnings(
576 ("tuple parameter unpacking has been removed", SyntaxWarning),
578 code
= ("lambda %s: dict(i for i in locals().items() "
579 "if not is_tuplename(i[0]))")
580 return eval(code
% signature
, {'is_tuplename' : self
.is_tuplename
})
582 def test_plain(self
):
583 f
= self
.makeCallable('a, b=1')
584 self
.assertEqualCallArgs(f
, '2')
585 self
.assertEqualCallArgs(f
, '2, 3')
586 self
.assertEqualCallArgs(f
, 'a=2')
587 self
.assertEqualCallArgs(f
, 'b=3, a=2')
588 self
.assertEqualCallArgs(f
, '2, b=3')
589 # expand *iterable / **mapping
590 self
.assertEqualCallArgs(f
, '*(2,)')
591 self
.assertEqualCallArgs(f
, '*[2]')
592 self
.assertEqualCallArgs(f
, '*(2, 3)')
593 self
.assertEqualCallArgs(f
, '*[2, 3]')
594 self
.assertEqualCallArgs(f
, '**{"a":2}')
595 self
.assertEqualCallArgs(f
, 'b=3, **{"a":2}')
596 self
.assertEqualCallArgs(f
, '2, **{"b":3}')
597 self
.assertEqualCallArgs(f
, '**{"b":3, "a":2}')
598 # expand UserList / UserDict
599 self
.assertEqualCallArgs(f
, '*UserList([2])')
600 self
.assertEqualCallArgs(f
, '*UserList([2, 3])')
601 self
.assertEqualCallArgs(f
, '**UserDict(a=2)')
602 self
.assertEqualCallArgs(f
, '2, **UserDict(b=3)')
603 self
.assertEqualCallArgs(f
, 'b=2, **UserDict(a=3)')
604 # unicode keyword args
605 self
.assertEqualCallArgs(f
, '**{u"a":2}')
606 self
.assertEqualCallArgs(f
, 'b=3, **{u"a":2}')
607 self
.assertEqualCallArgs(f
, '2, **{u"b":3}')
608 self
.assertEqualCallArgs(f
, '**{u"b":3, u"a":2}')
610 def test_varargs(self
):
611 f
= self
.makeCallable('a, b=1, *c')
612 self
.assertEqualCallArgs(f
, '2')
613 self
.assertEqualCallArgs(f
, '2, 3')
614 self
.assertEqualCallArgs(f
, '2, 3, 4')
615 self
.assertEqualCallArgs(f
, '*(2,3,4)')
616 self
.assertEqualCallArgs(f
, '2, *[3,4]')
617 self
.assertEqualCallArgs(f
, '2, 3, *UserList([4])')
619 def test_varkw(self
):
620 f
= self
.makeCallable('a, b=1, **c')
621 self
.assertEqualCallArgs(f
, 'a=2')
622 self
.assertEqualCallArgs(f
, '2, b=3, c=4')
623 self
.assertEqualCallArgs(f
, 'b=3, a=2, c=4')
624 self
.assertEqualCallArgs(f
, 'c=4, **{"a":2, "b":3}')
625 self
.assertEqualCallArgs(f
, '2, c=4, **{"b":3}')
626 self
.assertEqualCallArgs(f
, 'b=2, **{"a":3, "c":4}')
627 self
.assertEqualCallArgs(f
, '**UserDict(a=2, b=3, c=4)')
628 self
.assertEqualCallArgs(f
, '2, c=4, **UserDict(b=3)')
629 self
.assertEqualCallArgs(f
, 'b=2, **UserDict(a=3, c=4)')
630 # unicode keyword args
631 self
.assertEqualCallArgs(f
, 'c=4, **{u"a":2, u"b":3}')
632 self
.assertEqualCallArgs(f
, '2, c=4, **{u"b":3}')
633 self
.assertEqualCallArgs(f
, 'b=2, **{u"a":3, u"c":4}')
635 def test_tupleargs(self
):
636 f
= self
.makeCallable('(b,c), (d,(e,f))=(0,[1,2])')
637 self
.assertEqualCallArgs(f
, '(2,3)')
638 self
.assertEqualCallArgs(f
, '[2,3]')
639 self
.assertEqualCallArgs(f
, 'UserList([2,3])')
640 self
.assertEqualCallArgs(f
, '(2,3), (4,(5,6))')
641 self
.assertEqualCallArgs(f
, '(2,3), (4,[5,6])')
642 self
.assertEqualCallArgs(f
, '(2,3), [4,UserList([5,6])]')
644 def test_multiple_features(self
):
645 f
= self
.makeCallable('a, b=2, (c,(d,e))=(3,[4,5]), *f, **g')
646 self
.assertEqualCallArgs(f
, '2, 3, (4,[5,6]), 7')
647 self
.assertEqualCallArgs(f
, '2, 3, *[(4,[5,6]), 7], x=8')
648 self
.assertEqualCallArgs(f
, '2, 3, x=8, *[(4,[5,6]), 7]')
649 self
.assertEqualCallArgs(f
, '2, x=8, *[3, (4,[5,6]), 7], y=9')
650 self
.assertEqualCallArgs(f
, 'x=8, *[2, 3, (4,[5,6])], y=9')
651 self
.assertEqualCallArgs(f
, 'x=8, *UserList([2, 3, (4,[5,6])]), '
653 self
.assertEqualCallArgs(f
, '2, x=8, *UserList([3, (4,[5,6])]), '
654 '**UserDict(y=9, z=10)')
656 def test_errors(self
):
657 f0
= self
.makeCallable('')
658 f1
= self
.makeCallable('a, b')
659 f2
= self
.makeCallable('a, b=1')
660 # f0 takes no arguments
661 self
.assertEqualException(f0
, '1')
662 self
.assertEqualException(f0
, 'x=1')
663 self
.assertEqualException(f0
, '1,x=1')
664 # f1 takes exactly 2 arguments
665 self
.assertEqualException(f1
, '')
666 self
.assertEqualException(f1
, '1')
667 self
.assertEqualException(f1
, 'a=2')
668 self
.assertEqualException(f1
, 'b=3')
669 # f2 takes at least 1 argument
670 self
.assertEqualException(f2
, '')
671 self
.assertEqualException(f2
, 'b=3')
673 # f1/f2 takes exactly/at most 2 arguments
674 self
.assertEqualException(f
, '2, 3, 4')
675 self
.assertEqualException(f
, '1, 2, 3, a=1')
676 self
.assertEqualException(f
, '2, 3, 4, c=5')
677 self
.assertEqualException(f
, '2, 3, 4, a=1, c=5')
678 # f got an unexpected keyword argument
679 self
.assertEqualException(f
, 'c=2')
680 self
.assertEqualException(f
, '2, c=3')
681 self
.assertEqualException(f
, '2, 3, c=4')
682 self
.assertEqualException(f
, '2, c=4, b=3')
683 self
.assertEqualException(f
, '**{u"\u03c0\u03b9": 4}')
684 # f got multiple values for keyword argument
685 self
.assertEqualException(f
, '1, a=2')
686 self
.assertEqualException(f
, '1, **{"a":2}')
687 self
.assertEqualException(f
, '1, 2, b=3')
688 # XXX: Python inconsistency
689 # - for functions and bound methods: unexpected keyword 'c'
690 # - for unbound methods: multiple values for keyword 'a'
691 #self.assertEqualException(f, '1, c=3, a=2')
692 f
= self
.makeCallable('(a,b)=(0,1)')
693 self
.assertEqualException(f
, '1')
694 self
.assertEqualException(f
, '[1]')
695 self
.assertEqualException(f
, '(1,2,3)')
697 class TestGetcallargsMethods(TestGetcallargsFunctions
):
705 def makeCallable(self
, signature
):
706 assert 'self' not in signature
707 mk
= super(TestGetcallargsMethods
, self
).makeCallable
708 self
.cls
.method
= mk('self, ' + signature
)
709 return self
.inst
.method
711 class TestGetcallargsUnboundMethods(TestGetcallargsMethods
):
713 def makeCallable(self
, signature
):
714 super(TestGetcallargsUnboundMethods
, self
).makeCallable(signature
)
715 return self
.cls
.method
717 def assertEqualCallArgs(self
, func
, call_params_string
, locs
=None):
718 return super(TestGetcallargsUnboundMethods
, self
).assertEqualCallArgs(
719 *self
._getAssertEqualParams
(func
, call_params_string
, locs
))
721 def assertEqualException(self
, func
, call_params_string
, locs
=None):
722 return super(TestGetcallargsUnboundMethods
, self
).assertEqualException(
723 *self
._getAssertEqualParams
(func
, call_params_string
, locs
))
725 def _getAssertEqualParams(self
, func
, call_params_string
, locs
=None):
726 assert 'inst' not in call_params_string
727 locs
= dict(locs
or {}, inst
=self
.inst
)
728 return (func
, 'inst,' + call_params_string
, locs
)
732 TestDecorators
, TestRetrievingSourceCode
, TestOneliners
, TestBuggyCases
,
733 TestInterpreterStack
, TestClassesAndFunctions
, TestPredicates
,
734 TestGetcallargsFunctions
, TestGetcallargsMethods
,
735 TestGetcallargsUnboundMethods
)
737 if __name__
== "__main__":