Exceptions raised during renaming in rotating file handlers are now passed to handleE...
[python.git] / Doc / tools / findsyms
blob3b0f70991c079b529d8f1cabbb03defac71aa3ba
1 #!/usr/bin/env python
3 # Released to the public domain by Skip Montanaro, 28 March 2002
5 """
6 findsyms.py - try to identify undocumented symbols exported by modules
8 Usage: findsyms.py librefdir
10 For each lib*.tex file in the libref manual source directory, identify which
11 module is documented, import the module if possible, then search the LaTeX
12 source for the symbols global to that module. Report any that don't seem to
13 be documented.
15 Certain exceptions are made to the list of undocumented symbols:
17 * don't mention symbols in which all letters are upper case on the
18 assumption they are manifest constants
20 * don't mention symbols that are themselves modules
22 * don't mention symbols that match those exported by os, math, string,
23 types, or __builtin__ modules
25 Finally, if a name is exported by the module but fails a getattr() lookup,
26 that anomaly is reported.
27 """
29 import __builtin__
30 import getopt
31 import glob
32 import math
33 import os
34 import re
35 import string
36 import sys
37 import types
38 import warnings
40 def usage():
41 print >> sys.stderr, """
42 usage: %s dir
43 where 'dir' is the Library Reference Manual source directory.
44 """ % os.path.basename(sys.argv[0])
46 def main():
47 try:
48 opts, args = getopt.getopt(sys.argv[1:], "")
49 except getopt.error:
50 usage()
51 return
53 if not args:
54 usage()
55 return
57 libdir = args[0]
59 warnings.filterwarnings("error")
61 pat = re.compile(r"\\declaremodule\s*{[^}]*}\s*{([^}]*)}")
63 missing = []
64 filelist = glob.glob(os.path.join(libdir, "lib*.tex"))
65 filelist.sort()
66 for f in filelist:
67 mod = f[3:-4]
68 if not mod: continue
69 data = open(f).read()
70 mods = re.findall(pat, data)
71 if not mods:
72 print "No module declarations found in", f
73 continue
74 for modname in mods:
75 # skip special modules
76 if modname.startswith("__"):
77 continue
78 try:
79 mod = __import__(modname)
80 except ImportError:
81 missing.append(modname)
82 continue
83 except DeprecationWarning:
84 print "Deprecated module:", modname
85 continue
86 if hasattr(mod, "__all__"):
87 all = mod.__all__
88 else:
89 all = [k for k in dir(mod) if k[0] != "_"]
90 mentioned = 0
91 all.sort()
92 for name in all:
93 if data.find(name) == -1:
94 # certain names are predominantly used for testing
95 if name in ("main","test","_test"):
96 continue
97 # is it some sort of manifest constant?
98 if name.upper() == name:
99 continue
100 try:
101 item = getattr(mod, name)
102 except AttributeError:
103 print " ", name, "exposed, but not an attribute"
104 continue
105 # don't care about modules that might be exposed
106 if type(item) == types.ModuleType:
107 continue
108 # check a few modules which tend to be import *'d
109 isglobal = 0
110 for m in (os, math, string, __builtin__, types):
111 if hasattr(m, name) and item == getattr(m, name):
112 isglobal = 1
113 break
114 if isglobal: continue
115 if not mentioned:
116 print "Not mentioned in", modname, "docs:"
117 mentioned = 1
118 print " ", name
119 if missing:
120 missing.sort()
121 print "Could not import:"
122 print " ", ", ".join(missing)
124 if __name__ == "__main__":
125 try:
126 main()
127 except KeyboardInterrupt:
128 pass