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