diff options
Diffstat (limited to 'Tools')
-rwxr-xr-x | Tools/scripts/findsyms.py | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/Tools/scripts/findsyms.py b/Tools/scripts/findsyms.py new file mode 100755 index 0000000..3b0f709 --- /dev/null +++ b/Tools/scripts/findsyms.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python + +# Released to the public domain by Skip Montanaro, 28 March 2002 + +""" +findsyms.py - try to identify undocumented symbols exported by modules + +Usage: findsyms.py librefdir + +For each lib*.tex file in the libref manual source directory, identify which +module is documented, import the module if possible, then search the LaTeX +source for the symbols global to that module. Report any that don't seem to +be documented. + +Certain exceptions are made to the list of undocumented symbols: + + * don't mention symbols in which all letters are upper case on the + assumption they are manifest constants + + * don't mention symbols that are themselves modules + + * don't mention symbols that match those exported by os, math, string, + types, or __builtin__ modules + +Finally, if a name is exported by the module but fails a getattr() lookup, +that anomaly is reported. +""" + +import __builtin__ +import getopt +import glob +import math +import os +import re +import string +import sys +import types +import warnings + +def usage(): + print >> sys.stderr, """ +usage: %s dir +where 'dir' is the Library Reference Manual source directory. +""" % os.path.basename(sys.argv[0]) + +def main(): + try: + opts, args = getopt.getopt(sys.argv[1:], "") + except getopt.error: + usage() + return + + if not args: + usage() + return + + libdir = args[0] + + warnings.filterwarnings("error") + + pat = re.compile(r"\\declaremodule\s*{[^}]*}\s*{([^}]*)}") + + missing = [] + filelist = glob.glob(os.path.join(libdir, "lib*.tex")) + filelist.sort() + for f in filelist: + mod = f[3:-4] + if not mod: continue + data = open(f).read() + mods = re.findall(pat, data) + if not mods: + print "No module declarations found in", f + continue + for modname in mods: + # skip special modules + if modname.startswith("__"): + continue + try: + mod = __import__(modname) + except ImportError: + missing.append(modname) + continue + except DeprecationWarning: + print "Deprecated module:", modname + continue + if hasattr(mod, "__all__"): + all = mod.__all__ + else: + all = [k for k in dir(mod) if k[0] != "_"] + mentioned = 0 + all.sort() + for name in all: + if data.find(name) == -1: + # certain names are predominantly used for testing + if name in ("main","test","_test"): + continue + # is it some sort of manifest constant? + if name.upper() == name: + continue + try: + item = getattr(mod, name) + except AttributeError: + print " ", name, "exposed, but not an attribute" + continue + # don't care about modules that might be exposed + if type(item) == types.ModuleType: + continue + # check a few modules which tend to be import *'d + isglobal = 0 + for m in (os, math, string, __builtin__, types): + if hasattr(m, name) and item == getattr(m, name): + isglobal = 1 + break + if isglobal: continue + if not mentioned: + print "Not mentioned in", modname, "docs:" + mentioned = 1 + print " ", name + if missing: + missing.sort() + print "Could not import:" + print " ", ", ".join(missing) + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass |