1313
1414PREBUILDS_BASE_URL = "https://github.com/astral-sh/python-build-standalone/releases/download"
1515PLATFORM_TO_PREBUILDS = {
16- "3.13.2" : {
17- "linux-x86_64" : f"{ PREBUILDS_BASE_URL } /20250205/cpython-3.13.2+20250205-x86_64_v3-unknown-linux-gnu-pgo+lto-full.tar.zst" ,
18- "windows-x86" : f"{ PREBUILDS_BASE_URL } /20250205/cpython-3.13.2+20250205-i686-pc-windows-msvc-shared-pgo-full.tar.zst" ,
19- "windows-x86_64" : f"{ PREBUILDS_BASE_URL } /20250205/cpython-3.13.2+20250205-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst" ,
20- "macos-x86_64" : f"{ PREBUILDS_BASE_URL } /20250205/cpython-3.13.2+20250205-x86_64-apple-darwin-pgo+lto-full.tar.zst" ,
21- },
22- "3.12.9" : {
23- "linux-x86_64" : f"{ PREBUILDS_BASE_URL } /20250205/cpython-3.12.9+20250205-x86_64_v3-unknown-linux-gnu-pgo+lto-full.tar.zst" ,
24- "windows-x86" : f"{ PREBUILDS_BASE_URL } /20250205/cpython-3.12.9+20250205-i686-pc-windows-msvc-shared-pgo-full.tar.zst" ,
25- "windows-x86_64" : f"{ PREBUILDS_BASE_URL } /20250205/cpython-3.12.9+20250205-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst" ,
26- "macos-x86_64" : f"{ PREBUILDS_BASE_URL } /20250205/cpython-3.12.9+20250205-x86_64-apple-darwin-pgo+lto-full.tar.zst" ,
27- },
28- "3.12.4" : {
29- "linux-x86_64" : f"{ PREBUILDS_BASE_URL } /20240713/cpython-3.12.4+20240713-x86_64-unknown-linux-gnu-pgo+lto-full.tar.zst" ,
30- "windows-x86" : f"{ PREBUILDS_BASE_URL } /20240713/cpython-3.12.4+20240713-i686-pc-windows-msvc-shared-pgo-full.tar.zst" ,
31- "windows-x86_64" : f"{ PREBUILDS_BASE_URL } /20240713/cpython-3.12.4+20240713-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst" ,
32- "macos-x86_64" : f"{ PREBUILDS_BASE_URL } /20240713/cpython-3.12.4+20240713-x86_64-apple-darwin-pgo+lto-full.tar.zst" ,
33- },
34- "3.12.0" : {
35- "linux-x86_64" : f"{ PREBUILDS_BASE_URL } /20231002/cpython-3.12.0+20231002-x86_64-unknown-linux-gnu-pgo+lto-full.tar.zst" ,
36- "windows-x86" : f"{ PREBUILDS_BASE_URL } /20231002/cpython-3.12.0+20231002-i686-pc-windows-msvc-shared-pgo-full.tar.zst" ,
37- "windows-x86_64" : f"{ PREBUILDS_BASE_URL } /20231002/cpython-3.12.0+20231002-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst" ,
38- "macos-x86_64" : f"{ PREBUILDS_BASE_URL } /20231002/cpython-3.12.0+20231002-x86_64-apple-darwin-pgo+lto-full.tar.zst" ,
39- },
40- "3.11.6" : {
41- "linux-x86_64" : f"{ PREBUILDS_BASE_URL } /20231002/cpython-3.11.6+20231002-x86_64-unknown-linux-gnu-pgo+lto-full.tar.zst" ,
42- "windows-x86" : f"{ PREBUILDS_BASE_URL } /20231002/cpython-3.11.6+20231002-i686-pc-windows-msvc-shared-pgo-full.tar.zst" ,
43- "windows-x86_64" : f"{ PREBUILDS_BASE_URL } /20231002/cpython-3.11.6+20231002-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst" ,
44- "macos-x86_64" : f"{ PREBUILDS_BASE_URL } /20231002/cpython-3.11.6+20231002-x86_64-apple-darwin-pgo+lto-full.tar.zst" ,
45- },
46- "3.11.5" : {
47- "linux-x86_64" : f"{ PREBUILDS_BASE_URL } /20230826/cpython-3.11.5+20230826-x86_64-unknown-linux-gnu-pgo+lto-full.tar.zst" ,
48- "windows-x86" : f"{ PREBUILDS_BASE_URL } /20230826/cpython-3.11.5+20230826-i686-pc-windows-msvc-shared-pgo-full.tar.zst" ,
49- "windows-x86_64" : f"{ PREBUILDS_BASE_URL } /20230826/cpython-3.11.5+20230826-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst" ,
50- "macos-x86_64" : f"{ PREBUILDS_BASE_URL } /20230826/cpython-3.11.5+20230826-x86_64-apple-darwin-pgo+lto-full.tar.zst" ,
51- },
52- "3.11.3" : {
53- "linux-x86_64" : f"{ PREBUILDS_BASE_URL } /20230507/cpython-3.11.3+20230507-x86_64-unknown-linux-gnu-pgo+lto-full.tar.zst" ,
54- "windows-x86" : f"{ PREBUILDS_BASE_URL } /20230507/cpython-3.11.3+20230507-i686-pc-windows-msvc-shared-pgo-full.tar.zst" ,
55- "windows-x86_64" : f"{ PREBUILDS_BASE_URL } /20230507/cpython-3.11.3+20230507-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst" ,
56- "macos-x86_64" : f"{ PREBUILDS_BASE_URL } /20230507/cpython-3.11.3+20230507-x86_64-apple-darwin-pgo+lto-full.tar.zst" ,
57- },
58- "3.11.1" : {
59- "linux-x86_64" : f"{ PREBUILDS_BASE_URL } /20230116/cpython-3.11.1+20230116-x86_64-unknown-linux-gnu-pgo+lto-full.tar.zst" ,
60- "windows-x86" : f"{ PREBUILDS_BASE_URL } /20230116/cpython-3.11.1+20230116-i686-pc-windows-msvc-shared-pgo-full.tar.zst" ,
61- "windows-x86_64" : f"{ PREBUILDS_BASE_URL } /20230116/cpython-3.11.1+20230116-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst" ,
62- "macos-x86_64" : f"{ PREBUILDS_BASE_URL } /20230116/cpython-3.11.1+20230116-x86_64-apple-darwin-pgo+lto-full.tar.zst" ,
16+ "3.13.7" : {
17+ "linux-x86_64" : f"{ PREBUILDS_BASE_URL } /20250902/cpython-3.13.7+20250902-x86_64_v3-unknown-linux-gnu-pgo+lto-full.tar.zst" ,
18+ "windows-x86" : f"{ PREBUILDS_BASE_URL } /20250902/cpython-3.13.7+20250902-i686-pc-windows-msvc-install_only.tar.gz" ,
19+ "windows-x86_64" : f"{ PREBUILDS_BASE_URL } /20250902/cpython-3.13.7+20250902-x86_64-pc-windows-msvc-install_only.tar.gz" ,
20+ "macos-x86_64" : f"{ PREBUILDS_BASE_URL } /20250902/cpython-3.13.7+20250902-x86_64-apple-darwin-pgo+lto-full.tar.zst" ,
6321 },
6422}
6523
@@ -126,7 +84,15 @@ def load_config(prebuild_dir: Path) -> dict:
12684 return conf
12785
12886
129- def install_linux (conf : dict , build_dir : Path , prebuild_dir : Path , compressed_stdlib : bool ) -> None :
87+ def install_linux (
88+ conf : dict ,
89+ build_dir : Path ,
90+ prebuild_dir : Path ,
91+ compressed_stdlib : bool ,
92+ without_pyc : bool ,
93+ without_ensurepip : bool ,
94+ without_pip : bool ,
95+ ) -> None :
13096 print (f"Create clean distribution { build_dir } ..." )
13197
13298 # See https://gregoryszorc.com/docs/python-build-standalone/main/running.html#obtaining-distributions
@@ -153,32 +119,51 @@ def install_linux(conf: dict, build_dir: Path, prebuild_dir: Path, compressed_st
153119 shutil .rmtree (stdlib_path / "test" )
154120
155121 # Also remove __pycache__ & .pyc stuff
156- for pycache in stdlib_path .glob ("**/__pycache__" ):
157- shutil .rmtree (pycache )
122+ if without_pyc :
123+ for pycache in stdlib_path .glob ("**/__pycache__" ):
124+ shutil .rmtree (pycache )
125+
126+ site_packages_path = stdlib_path / "site-packages"
158127
159- # Make sure site-packages is empty to avoid including pip (ensurepip should be used instead)
160- shutil .rmtree (stdlib_path / "site-packages" )
128+ if without_ensurepip :
129+ shutil .rmtree (stdlib_path / "ensurepip" )
130+
131+ if without_pip :
132+ shutil .rmtree (site_packages_path / "pip" )
133+ shutil .rmtree (next (site_packages_path .glob ("pip-*.dist-info" )))
161134
162135 # Zip the stdlib to save plenty of space \o/
163136 if compressed_stdlib :
164137 tmp_stdlib_path = build_dir / f"lib/tmp_python{ major } .{ minor } "
165138 shutil .move (stdlib_path , tmp_stdlib_path )
139+
140+ # `site-packages` is not stdlib, so it must be excluded from the archive
166141 stdlib_path .mkdir ()
142+ shutil .move (tmp_stdlib_path / site_packages_path .name , site_packages_path )
143+
167144 shutil .move (tmp_stdlib_path / "lib-dynload" , stdlib_path / "lib-dynload" )
168145 shutil .make_archive (
169146 base_name = str (build_dir / f"lib/python{ major } { minor } " ),
170- format = "zip" ,
147+ format = "zip" , # TODO: use zstd in Python 3.14+
171148 root_dir = tmp_stdlib_path ,
172149 )
173150 shutil .rmtree (tmp_stdlib_path )
174151 # Oddly enough, os.py must be present (even if empty !) otherwise
175- # Python failed to find it home...
152+ # Python fails to find its home...
176153 (stdlib_path / "os.py" ).touch ()
177154
178- ( stdlib_path / "site-packages" ). mkdir ()
155+ assert site_packages_path . exists ()
179156
180157
181- def install_macos (conf : dict , build_dir : Path , prebuild_dir : Path , compressed_stdlib : bool ) -> None :
158+ def install_macos (
159+ conf : dict ,
160+ build_dir : Path ,
161+ prebuild_dir : Path ,
162+ compressed_stdlib : bool ,
163+ without_pyc : bool ,
164+ without_ensurepip : bool ,
165+ without_pip : bool ,
166+ ) -> None :
182167 print (f"Create clean distribution { build_dir } ..." )
183168
184169 if conf ["target_triple" ] not in ("x86_64-apple-darwin" ,):
@@ -204,33 +189,50 @@ def install_macos(conf: dict, build_dir: Path, prebuild_dir: Path, compressed_st
204189 shutil .rmtree (stdlib_path / "test" )
205190
206191 # Also remove __pycache__ & .pyc stuff
207- for pycache in stdlib_path .glob ("**/__pycache__" ):
208- shutil .rmtree (pycache )
192+ if without_pyc :
193+ for pycache in stdlib_path .glob ("**/__pycache__" ):
194+ shutil .rmtree (pycache )
209195
210- # Make sure site-packages is empty to avoid including pip (ensurepip should be used instead)
211- shutil .rmtree (stdlib_path / "site-packages" )
196+ site_packages_path = stdlib_path / "site-packages"
197+
198+ if without_ensurepip :
199+ shutil .rmtree (stdlib_path / "ensurepip" )
200+
201+ if without_pip :
202+ shutil .rmtree (site_packages_path / "pip" )
203+ shutil .rmtree (next (site_packages_path .glob ("pip-*.dist-info" )))
212204
213205 # Zip the stdlib to save plenty of space \o/
214206 if compressed_stdlib :
215207 tmp_stdlib_path = build_dir / f"lib/tmp_python{ major } .{ minor } "
216208 shutil .move (stdlib_path , tmp_stdlib_path )
209+
210+ # `site-packages` is not stdlib, so it must be excluded from the archive
217211 stdlib_path .mkdir ()
212+ shutil .move (tmp_stdlib_path / site_packages_path .name , site_packages_path )
213+
218214 shutil .move (tmp_stdlib_path / "lib-dynload" , stdlib_path / "lib-dynload" )
219215 shutil .make_archive (
220216 base_name = str (build_dir / f"lib/python{ major } { minor } " ),
221- format = "zip" ,
217+ format = "zip" , # TODO: use zstd in Python 3.14+
222218 root_dir = tmp_stdlib_path ,
223219 )
224220 shutil .rmtree (tmp_stdlib_path )
225221 # Oddly enough, os.py must be present (even if empty !) otherwise
226- # Python failed to find it home...
222+ # Python fails to find its home...
227223 (stdlib_path / "os.py" ).touch ()
228224
229- ( stdlib_path / "site-packages" ). mkdir ()
225+ assert site_packages_path . exists ()
230226
231227
232228def install_windows (
233- conf : dict , build_dir : Path , prebuild_dir : Path , compressed_stdlib : bool
229+ conf : dict ,
230+ build_dir : Path ,
231+ prebuild_dir : Path ,
232+ compressed_stdlib : bool ,
233+ without_pyc : bool ,
234+ without_ensurepip : bool ,
235+ without_pip : bool ,
234236) -> None :
235237 print (f"Create clean distribution { build_dir } ..." )
236238
@@ -251,30 +253,50 @@ def install_windows(
251253 pdbfile .unlink ()
252254
253255 # Also remove __pycache__ & .pyc stuff
254- for pycache in stdlib_path .glob ("**/__pycache__" ):
255- shutil .rmtree (pycache )
256+ if without_pyc :
257+ for pycache in stdlib_path .glob ("**/__pycache__" ):
258+ shutil .rmtree (pycache )
256259
257- # Make sure site-packages is empty to avoid including pip (ensurepip should be used instead)
258- shutil .rmtree (stdlib_path / "site-packages" )
260+ site_packages_path = stdlib_path / "site-packages"
261+
262+ if without_ensurepip :
263+ shutil .rmtree (stdlib_path / "ensurepip" )
264+
265+ if without_pip :
266+ shutil .rmtree (site_packages_path / "pip" )
267+ shutil .rmtree (next (site_packages_path .glob ("pip-*.dist-info" )))
259268
260269 # Zip the stdlib to save plenty of space \o/
261270 if compressed_stdlib :
271+ tmp_stdlib_path = build_dir / f"lib/tmp_python{ major } .{ minor } "
272+ shutil .move (stdlib_path , tmp_stdlib_path )
273+
274+ # `site-packages` is not stdlib, so it must be excluded from the archive
275+ stdlib_path .mkdir ()
276+ shutil .move (tmp_stdlib_path / site_packages_path .name , site_packages_path )
277+
278+ shutil .move (tmp_stdlib_path / "lib-dynload" , stdlib_path / "lib-dynload" )
262279 shutil .make_archive (
263280 base_name = str (build_dir / f"python{ major } { minor } " ),
264- format = "zip" ,
265- root_dir = stdlib_path ,
281+ format = "zip" , # TODO: use zstd in Python 3.14+
282+ root_dir = tmp_stdlib_path ,
266283 )
267- shutil .rmtree (stdlib_path )
268- stdlib_path .mkdir ()
284+ shutil .rmtree (tmp_stdlib_path )
269285 # Oddly enough, os.py must be present (even if empty !) otherwise
270- # Python failed to find it home...
286+ # Python fails to find its home...
271287 (stdlib_path / "os.py" ).touch ()
272288
273- ( stdlib_path / "site-packages" ). mkdir ()
289+ assert site_packages_path . exists ()
274290
275291
276292def build_distrib (
277- build_dir : Path , prebuild_dir : Path , compressed_stdlib : bool , force : bool
293+ build_dir : Path ,
294+ prebuild_dir : Path ,
295+ force : bool ,
296+ compressed_stdlib : bool ,
297+ without_pyc : bool ,
298+ without_ensurepip : bool ,
299+ without_pip : bool ,
278300) -> None :
279301 # Config may have change, so must clean previous prebuild
280302 if build_dir .exists ():
@@ -289,21 +311,30 @@ def build_distrib(
289311 conf = config ,
290312 build_dir = build_dir ,
291313 prebuild_dir = prebuild_dir ,
292- compressed_stdlib = args .compressed_stdlib ,
314+ compressed_stdlib = compressed_stdlib ,
315+ without_pyc = without_pyc ,
316+ without_ensurepip = without_ensurepip ,
317+ without_pip = without_pip ,
293318 )
294319 elif config ["python_platform_tag" ].startswith ("win" ):
295320 install_windows (
296321 conf = config ,
297322 build_dir = build_dir ,
298323 prebuild_dir = prebuild_dir ,
299- compressed_stdlib = args .compressed_stdlib ,
324+ compressed_stdlib = compressed_stdlib ,
325+ without_pyc = without_pyc ,
326+ without_ensurepip = without_ensurepip ,
327+ without_pip = without_pip ,
300328 )
301329 elif config ["python_platform_tag" ].startswith ("macosx" ):
302330 install_macos (
303331 conf = config ,
304332 build_dir = build_dir ,
305333 prebuild_dir = prebuild_dir ,
306- compressed_stdlib = args .compressed_stdlib ,
334+ compressed_stdlib = compressed_stdlib ,
335+ without_pyc = without_pyc ,
336+ without_ensurepip = without_ensurepip ,
337+ without_pip = without_pip ,
307338 )
308339 else :
309340 raise RuntimeError (f"Unsupported Python platform tag: `{ config ['python_platform_tag' ]} `" )
@@ -317,6 +348,9 @@ def build_distrib(
317348 parser .add_argument ("--cpython-version" , required = True )
318349 parser .add_argument ("--output-dir" , type = Path , required = True )
319350 parser .add_argument ("--compressed-stdlib" , action = "store_true" )
351+ parser .add_argument ("--without-pyc" , action = "store_true" )
352+ parser .add_argument ("--without-ensurepip" , action = "store_true" )
353+ parser .add_argument ("--without-pip" , action = "store_true" )
320354
321355 args = parser .parse_args ()
322356
@@ -337,6 +371,9 @@ def build_distrib(
337371 build_distrib (
338372 prebuild_dir = prebuild_dir ,
339373 build_dir = build_dir ,
340- compressed_stdlib = args .compressed_stdlib ,
341374 force = args .force ,
375+ compressed_stdlib = args .compressed_stdlib ,
376+ without_pyc = args .without_pyc ,
377+ without_ensurepip = args .without_ensurepip ,
378+ without_pip = args .without_pip ,
342379 )
0 commit comments