Exceptions raised during renaming in rotating file handlers are now passed to handleE...
[python.git] / Doc / tools / listmodules
blob03e7b5dc0843b96c5fd14b06294da519e74efd12
1 #! /usr/bin/env python
2 # -*- Python -*-
4 # This script can be used to identify undocumented modules in the Python
5 # standard library. Use it like this:
7 # .../Doc/tools/listmodules --ignore-from .../Doc/paper-<paper>/modlib.idx
9 """%(program)s - list modules in the Python standard library
11 -a, --annotate Annotate the module names with the subdirectory they
12 live in
13 -c, --categorize Group the modules by subdirectory
14 -i <file>,
16 --ignore-from <file> Ignore the modules listed in <file>. <file> may
17 contain a list of module names or a module index file
18 as produced when formatting the Python documentation
19 (.idx or .html flavor).
21 If neither -a nor -c are given, the modules are listed in alphabetical
22 order.
24 Note that -a and -c are mutually exclusive.
26 Limitation: Modules loadable as shared objects may not be listed,
27 though this script attempts to locate such modules.
29 """
31 __version__ = '$Revision$'
33 import getopt
34 import glob
35 import os
36 import re
37 import string
38 import sys
41 REMOVE_DIRS = ["dos-8x3", "encodings", "distutils",
42 "lib-old", "lib-stdwin", "test"]
45 def main():
46 args = sys.argv[1:]
47 annotate = 0
48 builtin = 0
49 categorize = 0
50 ignore_dict = {}
51 ignore = ignore_dict.has_key
52 try:
53 opts, args = getopt.getopt(
54 args, "abchi:",
55 ["annotate", "built-in", "categorize", "help", "ignore-from="])
56 except getopt.error, msg:
57 sys.stdout = sys.stderr
58 print msg
59 print
60 usage()
61 sys.exit(2)
62 for opt, arg in opts:
63 if opt in ("-a", "--annotate"):
64 annotate = 1
65 elif opt in ("-b", "--built-in"):
66 builtin = 1
67 elif opt in ("-c", "--categorize"):
68 categorize = 1
69 elif opt in ("-h", "--help"):
70 usage()
71 sys.exit()
72 elif opt in ("-i", "--ignore-from"):
73 data = open(arg).read()
74 if data[:1] == "\\":
75 ignore_from_idx(data, ignore_dict)
76 else:
77 ignore_from_modulelist(data, ignore_dict)
78 if args or (annotate and categorize):
79 usage()
80 sys.exit(2)
82 # Populate the database:
84 srcdir = os.path.normpath(os.path.join(
85 os.path.dirname(sys.argv[0]), os.pardir, os.pardir))
86 os.chdir(srcdir)
87 modules_by_name = {}
88 modules_by_dir = {}
89 if builtin:
90 l = []
91 modules_by_dir["<builtin>"] = l
92 for name in sys.builtin_module_names:
93 if not ignore(name):
94 modules_by_name[name] = "<built-in>"
95 l.append(name)
96 rx = re.compile("Lib/plat-[a-zA-Z0-9]*/")
97 fp = os.popen("find Lib -name \*.py -print", "r")
98 while 1:
99 line = fp.readline()
100 if not line:
101 break
102 m = rx.match(line)
103 if m:
104 line = "Lib/plat-*/" + line[m.end():]
105 line = line[4:-4] # strip off 'Lib/' and '.py\n'
106 dir, name = os.path.split(line)
107 dir = dir or "<standard>"
108 if ignore(name):
109 continue
110 if dir not in REMOVE_DIRS:
111 modules_by_name[name] = dir
112 l = modules_by_dir.get(dir, [])
113 modules_by_dir[dir] = l
114 if name not in l:
115 l.append(name)
116 # load up extension modules:
117 pwd = os.getcwd()
118 try:
119 os.chdir("Modules")
120 dir = "<extension>"
121 for line in glob.glob("*module.c"):
122 name = line[:-8]
123 if ignore(name) or modules_by_name.has_key(name) or name == "xx":
124 continue
125 modules_by_name[name] = dir
126 l = modules_by_dir.get(dir, [])
127 modules_by_dir[dir] = l
128 if name not in l:
129 l.append(name)
130 finally:
131 os.chdir(pwd)
133 # Dump the results:
135 if annotate:
136 modules = modules_by_name.items()
137 modules.sort()
138 width = max(map(len, modules_by_name.keys()))
139 format = "%%-%ds %%s" % width
140 for name, dir in modules:
141 if dir and dir[0] != "<":
142 print format % (name, dir)
143 else:
144 print name
145 elif categorize:
146 modules = modules_by_dir.items()
147 modules.sort()
148 width = max(map(len, modules_by_dir.keys()))
149 format = "%%-%ds %%s" % width
150 for dir, names in modules:
151 names.sort()
152 print format % (dir, names[0])
153 for name in names[1:]:
154 print format % ('', name)
155 print
156 else:
157 modules = modules_by_name.keys()
158 modules.sort()
159 print string.join(modules, "\n")
162 def ignore_from_modulelist(data, ignore_dict):
163 for name in string.split(data):
164 ignore_dict[name] = name
166 def ignore_from_idx(data, ignore_dict):
167 data = string.replace(data, r"\hackscore {}", "_")
168 rx = re.compile(r"\\indexentry\s*{([^@]*)@")
169 for line in string.split(data, "\n"):
170 m = rx.match(line)
171 if m:
172 name = m.group(1)
173 ignore_dict[name] = name
176 def usage():
177 vars = {}
178 vars["program"] = os.path.basename(sys.argv[0])
179 print __doc__ % vars
182 if __name__ == "__main__":
183 main()