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