#!/usr/bin/env python
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
"""This is a test on a package level that find all modules,
classes, methods and functions that do not have a doc string
and lists them in individual log files.
Currently, methods with leading and trailing double underscores
are skipped.
"""
from reportlab.lib.testutils import setOutDir,SecureTestCase,GlobDirectoryWalker,outputfile,printLocation
setOutDir(__name__)
import os, sys, glob, string, re, unittest
from types import ModuleType,ClassType,MethodType,FunctionType
import reportlab
def getModuleObjects(folder, rootName, typ, pattern='*.py'):
"Get a list of all objects defined *somewhere* in a package."
# Define some abbreviations.
find = string.find
split = string.split
replace = string.replace
objects = []
lookup = {}
for file in GlobDirectoryWalker(folder, pattern):
folder = os.path.dirname(file)
if os.path.basename(file) == '__init__.py':
continue
## if os.path.exists(os.path.join(folder, '__init__.py')):
#### print 'skipping', os.path.join(folder, '__init__.py')
## continue
sys.path.insert(0, folder)
cwd = os.getcwd()
os.chdir(folder)
modName = os.path.splitext(os.path.basename(file))[0]
prefix = folder[find(folder, rootName):]
prefix = replace(prefix, os.sep, '.')
mName = prefix + '.' + modName
try:
module = __import__(mName)
except ImportError:
# Restore sys.path and working directory.
os.chdir(cwd)
del sys.path[0]
continue
# Get the 'real' (leaf) module
# (__import__ loads only the top-level one).
if find(mName, '.') != -1:
for part in split(mName, '.')[1:]:
module = getattr(module, part)
# Find the objects in the module's content.
modContentNames = dir(module)
# Handle modules.
if typ == ModuleType:
if find(module.__name__, 'reportlab') > -1:
objects.append((mName, module))
continue
for n in modContentNames:
obj = eval(mName + '.' + n)
# Handle functions and classes.
if typ in (FunctionType, ClassType):
if type(obj) == typ and not lookup.has_key(obj):
if typ == ClassType:
if find(obj.__module__, rootName) != 0:
continue
objects.append((mName, obj))
lookup[obj] = 1
# Handle methods.
elif typ == MethodType:
if type(obj) == ClassType:
for m in dir(obj):
a = getattr(obj, m)
if type(a) == typ and not lookup.has_key(a):
if find(a.im_class.__module__, rootName) != 0:
continue
cName = obj.__name__
objects.append((mName, a))
lookup[a] = 1
# Restore sys.path and working directory.
os.chdir(cwd)
del sys.path[0]
return objects
class DocstringTestCase(SecureTestCase):
"Testing if objects in the ReportLab package have docstrings."
def _writeLogFile(self, objType):
"Write log file for different kind of documentable objects."
cwd = os.getcwd()
from reportlab.lib.testutils import RL_HOME
objects = getModuleObjects(RL_HOME, 'reportlab', objType)
objects.sort()
os.chdir(cwd)
expl = {FunctionType:'functions',
ClassType:'classes',
MethodType:'methods',
ModuleType:'modules'}[objType]
path = outputfile("test_docstrings-%s.log" % expl)
file = open(path, 'w')
file.write('No doc strings found for the following %s below.\n\n' % expl)
p = re.compile('__.+__')
lines = []
for name, obj in objects:
if objType == MethodType:
n = obj.__name__
# Skip names with leading and trailing double underscores.
if p.match(n):
continue
if objType == FunctionType:
if not obj.__doc__ or len(obj.__doc__) == 0:
lines.append("%s.%s\n" % (name, obj.__name__))
else:
if not obj.__doc__ or len(obj.__doc__) == 0:
if objType == ClassType:
lines.append("%s.%s\n" % (obj.__module__, obj.__name__))
elif objType == MethodType:
lines.append("%s.%s\n" % (obj.im_class, obj.__name__))
else:
lines.append("%s\n" % (obj.__name__))
lines.sort()
for line in lines:
file.write(line)
file.close()
def test0(self):
"Test if functions have a doc string."
self._writeLogFile(FunctionType)
def test1(self):
"Test if classes have a doc string."
self._writeLogFile(ClassType)
def test2(self):
"Test if methods have a doc string."
self._writeLogFile(MethodType)
def test3(self):
"Test if modules have a doc string."
self._writeLogFile(ModuleType)
def makeSuite():
suite = unittest.TestSuite()
loader = unittest.TestLoader()
if sys.platform[:4] != 'java': suite.addTest(loader.loadTestsFromTestCase(DocstringTestCase))
return suite
#noruntests
if __name__ == "__main__":
unittest.TextTestRunner().run(makeSuite())
printLocation()
|