0001 ''' 0002 Test cases for pyclbr.py 0003 Nick Mathewson 0004 ''' 0005 from test.test_support import run_unittest 0006 import unittest, sys 0007 from types import ClassType, FunctionType, MethodType, BuiltinFunctionType 0008 import pyclbr 0009 from unittest import TestCase 0010 0011 StaticMethodType = type(staticmethod(lambda: None)) 0012 ClassMethodType = type(classmethod(lambda c: None)) 0013 0014 # This next line triggers an error on old versions of pyclbr. 0015 0016 from commands import getstatus 0017 0018 # Here we test the python class browser code. 0019 # 0020 # The main function in this suite, 'testModule', compares the output 0021 # of pyclbr with the introspected members of a module. Because pyclbr 0022 # is imperfect (as designed), testModule is called with a set of 0023 # members to ignore. 0024 0025 class PyclbrTest(TestCase): 0026 0027 def assertListEq(self, l1, l2, ignore): 0028 ''' succeed iff {l1} - {ignore} == {l2} - {ignore} ''' 0029 missing = (set(l1) ^ set(l2)) - set(ignore) 0030 if missing: 0031 print >>sys.stderr, "l1=%r\nl2=%r\nignore=%r" % (l1, l2, ignore) 0032 self.fail("%r missing" % missing.pop()) 0033 0034 def assertHasattr(self, obj, attr, ignore): 0035 ''' succeed iff hasattr(obj,attr) or attr in ignore. ''' 0036 if attr in ignore: return 0037 if not hasattr(obj, attr): print "???", attr 0038 self.failUnless(hasattr(obj, attr), 0039 'expected hasattr(%r, %r)' % (obj, attr)) 0040 0041 0042 def assertHaskey(self, obj, key, ignore): 0043 ''' succeed iff obj.has_key(key) or key in ignore. ''' 0044 if key in ignore: return 0045 if not obj.has_key(key): 0046 print >>sys.stderr, "***",key 0047 self.failUnless(obj.has_key(key)) 0048 0049 def assertEqualsOrIgnored(self, a, b, ignore): 0050 ''' succeed iff a == b or a in ignore or b in ignore ''' 0051 if a not in ignore and b not in ignore: 0052 self.assertEquals(a, b) 0053 0054 def checkModule(self, moduleName, module=None, ignore=()): 0055 ''' succeed iff pyclbr.readmodule_ex(modulename) corresponds 0056 to the actual module object, module. Any identifiers in 0057 ignore are ignored. If no module is provided, the appropriate 0058 module is loaded with __import__.''' 0059 0060 if module == None: 0061 # Import it. 0062 # ('<silly>' is to work around an API silliness in __import__) 0063 module = __import__(moduleName, globals(), {}, ['<silly>']) 0064 0065 dict = pyclbr.readmodule_ex(moduleName) 0066 0067 def ismethod(oclass, obj, name): 0068 classdict = oclass.__dict__ 0069 if isinstance(obj, FunctionType): 0070 if not isinstance(classdict[name], StaticMethodType): 0071 return False 0072 else: 0073 if not isinstance(obj, MethodType): 0074 return False 0075 if obj.im_self is not None: 0076 if (not isinstance(classdict[name], ClassMethodType) or 0077 obj.im_self is not oclass): 0078 return False 0079 else: 0080 if not isinstance(classdict[name], FunctionType): 0081 return False 0082 0083 objname = obj.__name__ 0084 if objname.startswith("__") and not objname.endswith("__"): 0085 objname = "_%s%s" % (obj.im_class.__name__, objname) 0086 return objname == name 0087 0088 # Make sure the toplevel functions and classes are the same. 0089 for name, value in dict.items(): 0090 if name in ignore: 0091 continue 0092 self.assertHasattr(module, name, ignore) 0093 py_item = getattr(module, name) 0094 if isinstance(value, pyclbr.Function): 0095 self.assert_(isinstance(py_item, (FunctionType, BuiltinFunctionType))) 0096 else: 0097 self.failUnless(isinstance(py_item, (ClassType, type))) 0098 real_bases = [base.__name__ for base in py_item.__bases__] 0099 pyclbr_bases = [ getattr(base, 'name', base) 0100 for base in value.super ] 0101 0102 try: 0103 self.assertListEq(real_bases, pyclbr_bases, ignore) 0104 except: 0105 print >>sys.stderr, "class=%s" % py_item 0106 raise 0107 0108 actualMethods = [] 0109 for m in py_item.__dict__.keys(): 0110 if ismethod(py_item, getattr(py_item, m), m): 0111 actualMethods.append(m) 0112 foundMethods = [] 0113 for m in value.methods.keys(): 0114 if m[:2] == '__' and m[-2:] != '__': 0115 foundMethods.append('_'+name+m) 0116 else: 0117 foundMethods.append(m) 0118 0119 try: 0120 self.assertListEq(foundMethods, actualMethods, ignore) 0121 self.assertEquals(py_item.__module__, value.module) 0122 0123 self.assertEqualsOrIgnored(py_item.__name__, value.name, 0124 ignore) 0125 # can't check file or lineno 0126 except: 0127 print >>sys.stderr, "class=%s" % py_item 0128 raise 0129 0130 # Now check for missing stuff. 0131 def defined_in(item, module): 0132 if isinstance(item, ClassType): 0133 return item.__module__ == module.__name__ 0134 if isinstance(item, FunctionType): 0135 return item.func_globals is module.__dict__ 0136 return False 0137 for name in dir(module): 0138 item = getattr(module, name) 0139 if isinstance(item, (ClassType, FunctionType)): 0140 if defined_in(item, module): 0141 self.assertHaskey(dict, name, ignore) 0142 0143 def test_easy(self): 0144 self.checkModule('pyclbr') 0145 self.checkModule('doctest') 0146 self.checkModule('rfc822') 0147 self.checkModule('difflib') 0148 0149 def test_decorators(self): 0150 # XXX: See comment in pyclbr_input.py for a test that would fail 0151 # if it were not commented out. 0152 # 0153 self.checkModule('test.pyclbr_input') 0154 0155 def test_others(self): 0156 cm = self.checkModule 0157 0158 # These were once about the 10 longest modules 0159 cm('random', ignore=('Random',)) # from _random import Random as CoreGenerator 0160 cm('cgi', ignore=('log',)) # set with = in module 0161 cm('mhlib') 0162 cm('urllib', ignore=('getproxies_registry', 0163 'open_https', 0164 'getproxies_internetconfig',)) # not on all platforms 0165 cm('pickle') 0166 cm('aifc', ignore=('openfp',)) # set with = in module 0167 cm('Cookie') 0168 cm('sre_parse', ignore=('dump',)) # from sre_constants import * 0169 cm('pdb') 0170 cm('pydoc') 0171 0172 # Tests for modules inside packages 0173 cm('email.Parser') 0174 cm('test.test_pyclbr') 0175 0176 0177 def test_main(): 0178 run_unittest(PyclbrTest) 0179 0180 0181 if __name__ == "__main__": 0182 test_main() 0183
Generated by PyXR 0.9.4