1999-02-23 23:07:48 +00:00
|
|
|
#! /usr/bin/env python
|
|
|
|
# -*- Python -*-
|
|
|
|
#
|
|
|
|
# This script can be used to identify undocumented modules in the Python
|
|
|
|
# standard library. Use it like this:
|
|
|
|
#
|
|
|
|
# .../Doc/tools/listmodules --ignore-from .../Doc/paper-<paper>/modlib.idx
|
|
|
|
|
|
|
|
"""%(program)s - list modules in the Python standard library
|
|
|
|
|
|
|
|
-a, --annotate Annotate the module names with the subdirectory they live in
|
|
|
|
-c, --categorize Group the modules by subdirectory
|
|
|
|
-i <file>,
|
|
|
|
--ignore-from <file> Ignore the modules listed in <file>. <file> may contain
|
|
|
|
a list of module names or a module index file as produced
|
|
|
|
when formatting the Python documentation (.idx flavor).
|
|
|
|
|
|
|
|
If neither -a nor -c are given, the modules are listed in alphabetical order.
|
|
|
|
|
|
|
|
Note that -a and -c are mutually exclusive.
|
|
|
|
|
|
|
|
Limitation: Modules loadable as shared objects are not listed.
|
|
|
|
"""
|
|
|
|
|
|
|
|
__version__ = '$Revision$'
|
|
|
|
|
|
|
|
import getopt
|
1999-06-17 18:49:18 +00:00
|
|
|
import glob
|
1999-02-23 23:07:48 +00:00
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import string
|
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
|
|
REMOVE_DIRS = ["dos-8x3", "lib-old", "lib-stdwin", "test"]
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
args = sys.argv[1:]
|
|
|
|
annotate = 0
|
|
|
|
builtin = 0
|
|
|
|
categorize = 0
|
|
|
|
ignore_dict = {}
|
|
|
|
ignore = ignore_dict.has_key
|
|
|
|
try:
|
|
|
|
opts, args = getopt.getopt(
|
|
|
|
args, "abchi:",
|
|
|
|
["annotate", "built-in", "categorize", "help", "ignore-from="])
|
|
|
|
except getopt.error, msg:
|
|
|
|
sys.stdout = sys.stderr
|
|
|
|
print msg
|
|
|
|
print
|
|
|
|
usage()
|
|
|
|
sys.exit(2)
|
|
|
|
for opt, arg in opts:
|
|
|
|
if opt in ("-a", "--annotate"):
|
|
|
|
annotate = 1
|
|
|
|
elif opt in ("-b", "--built-in"):
|
|
|
|
builtin = 1
|
|
|
|
elif opt in ("-c", "--categorize"):
|
|
|
|
categorize = 1
|
|
|
|
elif opt in ("-h", "--help"):
|
|
|
|
usage()
|
|
|
|
sys.exit()
|
|
|
|
elif opt in ("-i", "--ignore-from"):
|
|
|
|
data = open(arg).read()
|
|
|
|
if data[:1] == "\\":
|
|
|
|
ignore_from_idx(data, ignore_dict)
|
|
|
|
else:
|
1999-02-24 18:39:47 +00:00
|
|
|
ignore_from_modulelist(data, ignore_dict)
|
1999-02-23 23:07:48 +00:00
|
|
|
if args or (annotate and categorize):
|
|
|
|
usage()
|
|
|
|
sys.exit(2)
|
|
|
|
#
|
|
|
|
# Populate the database:
|
|
|
|
#
|
|
|
|
srcdir = os.path.normpath(os.path.join(
|
|
|
|
os.path.dirname(sys.argv[0]), os.pardir, os.pardir))
|
|
|
|
os.chdir(srcdir)
|
|
|
|
modules_by_name = {}
|
|
|
|
modules_by_dir = {}
|
|
|
|
if builtin:
|
|
|
|
l = []
|
|
|
|
modules_by_dir["<builtin>"] = l
|
|
|
|
for name in sys.builtin_module_names:
|
|
|
|
if not ignore(name):
|
|
|
|
modules_by_name[name] = "<built-in>"
|
|
|
|
l.append(name)
|
|
|
|
rx = re.compile("Lib/plat-[a-z0-9]*/", re.IGNORECASE)
|
1999-06-17 18:49:18 +00:00
|
|
|
fp = os.popen("find Lib -name \*.py -print", "r")
|
1999-02-23 23:07:48 +00:00
|
|
|
while 1:
|
|
|
|
line = fp.readline()
|
|
|
|
if not line:
|
|
|
|
break
|
|
|
|
m = rx.match(line)
|
|
|
|
if m:
|
|
|
|
line = "Lib/plat-*/" + line[m.end():]
|
|
|
|
line = line[4:-4] # strip off 'Lib/' and '.py\n'
|
|
|
|
dir, name = os.path.split(line)
|
|
|
|
dir = dir or "<standard>"
|
|
|
|
if ignore(name):
|
|
|
|
continue
|
|
|
|
if dir not in REMOVE_DIRS:
|
|
|
|
modules_by_name[name] = dir
|
|
|
|
l = modules_by_dir.get(dir, [])
|
|
|
|
modules_by_dir[dir] = l
|
|
|
|
if name not in l:
|
|
|
|
l.append(name)
|
1999-06-17 18:49:18 +00:00
|
|
|
# load up extension modules:
|
|
|
|
pwd = os.getcwd()
|
|
|
|
try:
|
|
|
|
os.chdir("Modules")
|
|
|
|
dir = "<extension>"
|
|
|
|
for line in glob.glob("*module.c"):
|
|
|
|
name = line[:-8]
|
|
|
|
if ignore(name) or modules_by_name.has_key(name) or name == "xx":
|
|
|
|
continue
|
|
|
|
modules_by_name[name] = dir
|
|
|
|
l = modules_by_dir.get(dir, [])
|
|
|
|
modules_by_dir[dir] = l
|
|
|
|
if name not in l:
|
|
|
|
l.append(name)
|
|
|
|
finally:
|
|
|
|
os.chdir(pwd)
|
1999-02-23 23:07:48 +00:00
|
|
|
#
|
|
|
|
# Dump the results:
|
|
|
|
#
|
|
|
|
if annotate:
|
|
|
|
modules = modules_by_name.items()
|
|
|
|
modules.sort()
|
|
|
|
width = max(map(len, modules_by_name.keys()))
|
|
|
|
format = "%%-%ds %%s" % width
|
|
|
|
for name, dir in modules:
|
|
|
|
if dir and dir[0] != "<":
|
|
|
|
print format % (name, dir)
|
|
|
|
else:
|
|
|
|
print name
|
|
|
|
elif categorize:
|
|
|
|
modules = modules_by_dir.items()
|
|
|
|
modules.sort()
|
|
|
|
width = max(map(len, modules_by_dir.keys()))
|
|
|
|
format = "%%-%ds %%s" % width
|
|
|
|
for dir, names in modules:
|
|
|
|
names.sort()
|
|
|
|
print format % (dir, names[0])
|
|
|
|
for name in names[1:]:
|
|
|
|
print format % ('', name)
|
|
|
|
print
|
|
|
|
else:
|
|
|
|
modules = modules_by_name.keys()
|
|
|
|
modules.sort()
|
|
|
|
print string.join(modules, "\n")
|
|
|
|
|
|
|
|
|
1999-02-24 18:39:47 +00:00
|
|
|
def ignore_from_modulelist(data, ignore_dict):
|
1999-02-23 23:07:48 +00:00
|
|
|
for name in string.split(data):
|
|
|
|
ignore_dict[name] = name
|
|
|
|
|
|
|
|
def ignore_from_idx(data, ignore_dict):
|
|
|
|
data = string.replace(data, r"\hackscore {}", "_")
|
1999-02-24 18:39:47 +00:00
|
|
|
rx = re.compile(r"\\indexentry\s*{([^@]*)@")
|
1999-02-23 23:07:48 +00:00
|
|
|
for line in string.split(data, "\n"):
|
|
|
|
m = rx.match(line)
|
|
|
|
if m:
|
|
|
|
name = m.group(1)
|
|
|
|
ignore_dict[name] = name
|
|
|
|
|
|
|
|
|
|
|
|
def usage():
|
|
|
|
vars = {}
|
|
|
|
vars["program"] = os.path.basename(sys.argv[0])
|
|
|
|
print __doc__ % vars
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|