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 live in
12 -c, --categorize Group the modules by subdirectory
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).
18 If neither -a nor -c are given, the modules are listed in alphabetical order.
20 Note that -a and -c are mutually exclusive.
22 Limitation: Modules loadable as shared objects are not listed.
25 __version__
= '$Revision$'
35 REMOVE_DIRS
= ["dos-8x3", "lib-old", "lib-stdwin", "test"]
44 ignore
= ignore_dict
.has_key
46 opts
, args
= getopt
.getopt(
48 ["annotate", "built-in", "categorize", "help", "ignore-from="])
49 except getopt
.error
, msg
:
50 sys
.stdout
= sys
.stderr
56 if opt
in ("-a", "--annotate"):
58 elif opt
in ("-b", "--built-in"):
60 elif opt
in ("-c", "--categorize"):
62 elif opt
in ("-h", "--help"):
65 elif opt
in ("-i", "--ignore-from"):
66 data
= open(arg
).read()
68 ignore_from_idx(data
, ignore_dict
)
70 ignore_from_modulelist(data
, ignore_dict
)
71 if args
or (annotate
and categorize
):
75 # Populate the database:
77 srcdir
= os
.path
.normpath(os
.path
.join(
78 os
.path
.dirname(sys
.argv
[0]), os
.pardir
, os
.pardir
))
84 modules_by_dir
["<builtin>"] = l
85 for name
in sys
.builtin_module_names
:
87 modules_by_name
[name
] = "<built-in>"
89 rx
= re
.compile("Lib/plat-[a-z0-9]*/", re
.IGNORECASE
)
90 fp
= os
.popen("find Lib -name \*.py -print", "r")
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>"
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
109 # load up extension modules:
114 for line
in glob
.glob("*module.c"):
116 if ignore(name
) or modules_by_name
.has_key(name
) or name
== "xx":
118 modules_by_name
[name
] = dir
119 l
= modules_by_dir
.get(dir, [])
120 modules_by_dir
[dir] = l
129 modules
= modules_by_name
.items()
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)
139 modules
= modules_by_dir
.items()
141 width
= max(map(len, modules_by_dir
.keys()))
142 format
= "%%-%ds %%s" % width
143 for dir, names
in modules
:
145 print format
% (dir, names
[0])
146 for name
in names
[1:]:
147 print format
% ('', name
)
150 modules
= modules_by_name
.keys()
152 print string
.join(modules
, "\n")
155 def ignore_from_modulelist(data
, ignore_dict
):
156 for name
in string
.split(data
):
157 ignore_dict
[name
] = name
159 def ignore_from_idx(data
, ignore_dict
):
160 data
= string
.replace(data
, r
"\hackscore {}", "_")
161 rx
= re
.compile(r
"\\indexentry\s*{([^@]*)@")
162 for line
in string
.split(data
, "\n"):
166 ignore_dict
[name
] = name
171 vars["program"] = os
.path
.basename(sys
.argv
[0])
175 if __name__
== "__main__":