/Lib/test/test_pyclbr.py

http://unladen-swallow.googlecode.com/ · Python · 193 lines · 133 code · 31 blank · 29 comment · 40 complexity · 116f338b897b4830bf765bf383397298 MD5 · raw file

  1. '''
  2. Test cases for pyclbr.py
  3. Nick Mathewson
  4. '''
  5. from test.test_support import run_unittest
  6. import sys
  7. from types import ClassType, FunctionType, MethodType, BuiltinFunctionType
  8. import pyclbr
  9. from unittest import TestCase
  10. StaticMethodType = type(staticmethod(lambda: None))
  11. ClassMethodType = type(classmethod(lambda c: None))
  12. # This next line triggers an error on old versions of pyclbr.
  13. from commands import getstatus
  14. # Here we test the python class browser code.
  15. #
  16. # The main function in this suite, 'testModule', compares the output
  17. # of pyclbr with the introspected members of a module. Because pyclbr
  18. # is imperfect (as designed), testModule is called with a set of
  19. # members to ignore.
  20. class PyclbrTest(TestCase):
  21. def assertListEq(self, l1, l2, ignore):
  22. ''' succeed iff {l1} - {ignore} == {l2} - {ignore} '''
  23. missing = (set(l1) ^ set(l2)) - set(ignore)
  24. if missing:
  25. print >>sys.stderr, "l1=%r\nl2=%r\nignore=%r" % (l1, l2, ignore)
  26. self.fail("%r missing" % missing.pop())
  27. def assertHasattr(self, obj, attr, ignore):
  28. ''' succeed iff hasattr(obj,attr) or attr in ignore. '''
  29. if attr in ignore: return
  30. if not hasattr(obj, attr): print "???", attr
  31. self.failUnless(hasattr(obj, attr),
  32. 'expected hasattr(%r, %r)' % (obj, attr))
  33. def assertHaskey(self, obj, key, ignore):
  34. ''' succeed iff obj.has_key(key) or key in ignore. '''
  35. if key in ignore: return
  36. if not obj.has_key(key):
  37. print >>sys.stderr, "***",key
  38. self.failUnless(obj.has_key(key))
  39. def assertEqualsOrIgnored(self, a, b, ignore):
  40. ''' succeed iff a == b or a in ignore or b in ignore '''
  41. if a not in ignore and b not in ignore:
  42. self.assertEquals(a, b)
  43. def checkModule(self, moduleName, module=None, ignore=()):
  44. ''' succeed iff pyclbr.readmodule_ex(modulename) corresponds
  45. to the actual module object, module. Any identifiers in
  46. ignore are ignored. If no module is provided, the appropriate
  47. module is loaded with __import__.'''
  48. if module is None:
  49. # Import it.
  50. # ('<silly>' is to work around an API silliness in __import__)
  51. module = __import__(moduleName, globals(), {}, ['<silly>'])
  52. dict = pyclbr.readmodule_ex(moduleName)
  53. def ismethod(oclass, obj, name):
  54. classdict = oclass.__dict__
  55. if isinstance(obj, FunctionType):
  56. if not isinstance(classdict[name], StaticMethodType):
  57. return False
  58. else:
  59. if not isinstance(obj, MethodType):
  60. return False
  61. if obj.im_self is not None:
  62. if (not isinstance(classdict[name], ClassMethodType) or
  63. obj.im_self is not oclass):
  64. return False
  65. else:
  66. if not isinstance(classdict[name], FunctionType):
  67. return False
  68. objname = obj.__name__
  69. if objname.startswith("__") and not objname.endswith("__"):
  70. objname = "_%s%s" % (obj.im_class.__name__, objname)
  71. return objname == name
  72. # Make sure the toplevel functions and classes are the same.
  73. for name, value in dict.items():
  74. if name in ignore:
  75. continue
  76. self.assertHasattr(module, name, ignore)
  77. py_item = getattr(module, name)
  78. if isinstance(value, pyclbr.Function):
  79. self.assert_(isinstance(py_item, (FunctionType, BuiltinFunctionType)))
  80. if py_item.__module__ != moduleName:
  81. continue # skip functions that came from somewhere else
  82. self.assertEquals(py_item.__module__, value.module)
  83. else:
  84. self.failUnless(isinstance(py_item, (ClassType, type)))
  85. if py_item.__module__ != moduleName:
  86. continue # skip classes that came from somewhere else
  87. real_bases = [base.__name__ for base in py_item.__bases__]
  88. pyclbr_bases = [ getattr(base, 'name', base)
  89. for base in value.super ]
  90. try:
  91. self.assertListEq(real_bases, pyclbr_bases, ignore)
  92. except:
  93. print >>sys.stderr, "class=%s" % py_item
  94. raise
  95. actualMethods = []
  96. for m in py_item.__dict__.keys():
  97. if ismethod(py_item, getattr(py_item, m), m):
  98. actualMethods.append(m)
  99. foundMethods = []
  100. for m in value.methods.keys():
  101. if m[:2] == '__' and m[-2:] != '__':
  102. foundMethods.append('_'+name+m)
  103. else:
  104. foundMethods.append(m)
  105. try:
  106. self.assertListEq(foundMethods, actualMethods, ignore)
  107. self.assertEquals(py_item.__module__, value.module)
  108. self.assertEqualsOrIgnored(py_item.__name__, value.name,
  109. ignore)
  110. # can't check file or lineno
  111. except:
  112. print >>sys.stderr, "class=%s" % py_item
  113. raise
  114. # Now check for missing stuff.
  115. def defined_in(item, module):
  116. if isinstance(item, ClassType):
  117. return item.__module__ == module.__name__
  118. if isinstance(item, FunctionType):
  119. return item.func_globals is module.__dict__
  120. return False
  121. for name in dir(module):
  122. item = getattr(module, name)
  123. if isinstance(item, (ClassType, FunctionType)):
  124. if defined_in(item, module):
  125. self.assertHaskey(dict, name, ignore)
  126. def test_easy(self):
  127. self.checkModule('pyclbr')
  128. self.checkModule('doctest')
  129. self.checkModule('rfc822')
  130. self.checkModule('difflib')
  131. def test_decorators(self):
  132. # XXX: See comment in pyclbr_input.py for a test that would fail
  133. # if it were not commented out.
  134. #
  135. self.checkModule('test.pyclbr_input')
  136. def test_others(self):
  137. cm = self.checkModule
  138. # These were once about the 10 longest modules
  139. cm('random', ignore=('Random',)) # from _random import Random as CoreGenerator
  140. cm('cgi', ignore=('log',)) # set with = in module
  141. cm('urllib', ignore=('_CFNumberToInt32',
  142. '_CStringFromCFString',
  143. '_CFSetup',
  144. 'getproxies_registry',
  145. 'proxy_bypass_registry',
  146. 'proxy_bypass_macosx_sysconf',
  147. 'open_https',
  148. 'getproxies_macosx_sysconf',
  149. 'getproxies_internetconfig',)) # not on all platforms
  150. cm('pickle')
  151. cm('aifc', ignore=('openfp',)) # set with = in module
  152. cm('Cookie')
  153. cm('sre_parse', ignore=('dump',)) # from sre_constants import *
  154. cm('pdb')
  155. cm('pydoc')
  156. # Tests for modules inside packages
  157. cm('email.parser')
  158. cm('test.test_pyclbr')
  159. def test_main():
  160. run_unittest(PyclbrTest)
  161. if __name__ == "__main__":
  162. test_main()