summaryrefslogtreecommitdiffstats
path: root/Tools
diff options
context:
space:
mode:
Diffstat (limited to 'Tools')
-rwxr-xr-xTools/scripts/findsyms.py128
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