Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Tools/build/generate_stdlib_module_names.py
12 views
1
# This script lists the names of standard library modules
2
# to update Python/stdlib_module_names.h
3
import _imp
4
import os.path
5
import sys
6
import sysconfig
7
8
from check_extension_modules import ModuleChecker
9
10
11
SCRIPT_NAME = 'Tools/build/generate_stdlib_module_names.py'
12
13
SRC_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
14
STDLIB_PATH = os.path.join(SRC_DIR, 'Lib')
15
16
IGNORE = {
17
'__init__',
18
'__pycache__',
19
'site-packages',
20
21
# Test modules and packages
22
'__hello__',
23
'__phello__',
24
'__hello_alias__',
25
'__phello_alias__',
26
'__hello_only__',
27
'_ctypes_test',
28
'_testbuffer',
29
'_testcapi',
30
'_testclinic',
31
'_testconsole',
32
'_testimportmultiple',
33
'_testinternalcapi',
34
'_testmultiphase',
35
'_testsinglephase',
36
'_xxsubinterpreters',
37
'_xxinterpchannels',
38
'_xxtestfuzz',
39
'idlelib.idle_test',
40
'test',
41
'xxlimited',
42
'xxlimited_35',
43
'xxsubtype',
44
}
45
46
ALLOW_TEST_MODULES = {
47
'doctest',
48
'unittest',
49
}
50
51
# Built-in modules
52
def list_builtin_modules(names):
53
names |= set(sys.builtin_module_names)
54
55
56
# Pure Python modules (Lib/*.py)
57
def list_python_modules(names):
58
for filename in os.listdir(STDLIB_PATH):
59
if not filename.endswith(".py"):
60
continue
61
name = filename.removesuffix(".py")
62
names.add(name)
63
64
65
# Packages in Lib/
66
def list_packages(names):
67
for name in os.listdir(STDLIB_PATH):
68
if name in IGNORE:
69
continue
70
package_path = os.path.join(STDLIB_PATH, name)
71
if not os.path.isdir(package_path):
72
continue
73
if any(package_file.endswith(".py")
74
for package_file in os.listdir(package_path)):
75
names.add(name)
76
77
78
# Built-in and extension modules built by Modules/Setup*
79
# includes Windows and macOS extensions.
80
def list_modules_setup_extensions(names):
81
checker = ModuleChecker()
82
names.update(checker.list_module_names(all=True))
83
84
85
# List frozen modules of the PyImport_FrozenModules list (Python/frozen.c).
86
# Use the "./Programs/_testembed list_frozen" command.
87
def list_frozen(names):
88
submodules = set()
89
for name in _imp._frozen_module_names():
90
# To skip __hello__, __hello_alias__ and etc.
91
if name.startswith('__'):
92
continue
93
if '.' in name:
94
submodules.add(name)
95
else:
96
names.add(name)
97
# Make sure all frozen submodules have a known parent.
98
for name in list(submodules):
99
if name.partition('.')[0] in names:
100
submodules.remove(name)
101
if submodules:
102
raise Exception(f'unexpected frozen submodules: {sorted(submodules)}')
103
104
105
def list_modules():
106
names = set()
107
108
list_builtin_modules(names)
109
list_modules_setup_extensions(names)
110
list_packages(names)
111
list_python_modules(names)
112
list_frozen(names)
113
114
# Remove ignored packages and modules
115
for name in list(names):
116
package_name = name.split('.')[0]
117
# package_name can be equal to name
118
if package_name in IGNORE:
119
names.discard(name)
120
121
# Sanity checks
122
for name in names:
123
if "." in name:
124
raise Exception(f"sub-modules must not be listed: {name}")
125
if ("test" in name or "xx" in name) and name not in ALLOW_TEST_MODULES:
126
raise Exception(f"test modules must not be listed: {name}")
127
128
return names
129
130
131
def write_modules(fp, names):
132
print(f"// Auto-generated by {SCRIPT_NAME}.",
133
file=fp)
134
print("// List used to create sys.stdlib_module_names.", file=fp)
135
print(file=fp)
136
print("static const char* _Py_stdlib_module_names[] = {", file=fp)
137
for name in sorted(names):
138
print(f'"{name}",', file=fp)
139
print("};", file=fp)
140
141
142
def main():
143
if not sysconfig.is_python_build():
144
print(f"ERROR: {sys.executable} is not a Python build",
145
file=sys.stderr)
146
sys.exit(1)
147
148
fp = sys.stdout
149
names = list_modules()
150
write_modules(fp, names)
151
152
153
if __name__ == "__main__":
154
main()
155
156