11#!/usr/bin/env python3
2+ # This is "Portable Python Distro - the Instantiate script"
23# Copyright 2025 Andreas Zwinkau
34# SPDX-License-Identifier: Apache-2.0
45
910
1011
1112def main ():
12- if len (sys .argv ) != 2 :
13- sys .exit ("Usage: instantiate.py <target-directory>" )
13+ if len (sys .argv ) == 1 or len (sys .argv ) > 3 :
14+ sys .exit (
15+ "Usage: instantiate.py <target-directory> <optional: requirements.txt>"
16+ )
1417
18+ script_path = Path (sys .argv [0 ]) # lib/python3.12/x.py
19+ base_python = script_path .parent .parent .parent .resolve ()
1520 target_dir = Path (sys .argv [1 ]).resolve ()
16- base_python = Path (__file__ ).parent .parent .resolve ()
17-
18- if not base_python .is_dir ():
19- sys .exit ("Error: Run 'make' first to create base Python." )
20- if target_dir .exists ():
21- sys .exit (f"Error: Target directory already exists: { target_dir } " )
2221
23- print ( f"Creating Python environment at { target_dir } " )
22+ assert base_python . is_dir (), base_python
2423
2524 # Create structure and hardlink binaries
2625 (target_dir / "bin" ).mkdir (parents = True )
@@ -31,40 +30,30 @@ def main():
3130 # Hardlink base libraries
3231 _ = shutil .copytree (base_python / "lib" , target_dir / "lib" , copy_function = os .link )
3332
34- # Create independent site-packages
35- site_packages = target_dir / "lib/python3.12/site-packages"
36- shutil .rmtree (site_packages , ignore_errors = True )
37- site_packages .mkdir (parents = True )
38-
39- # Copy pip essentials
40- base_site = base_python / "lib/python3.12/site-packages"
41- for pkg in [
42- "pip" ,
43- "setuptools" ,
44- "packaging" ,
45- "_distutils_hack" ,
46- "distutils-precedence.pth" ,
47- ]:
48- if (src := base_site / pkg ).exists ():
49- (shutil .copytree if src .is_dir () else shutil .copy2 )(
50- src , site_packages / pkg
51- )
52-
53- # Create pip wrapper scripts
54- for name in ["pip" , "pip3" ]:
55- (target_dir / "bin" / name ).write_text (
56- "#!/bin/bash\n "
57- 'SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"\n '
58- 'exec "$SCRIPT_DIR/python3" -m pip "$@"\n '
59- )
60- (target_dir / "bin" / name ).chmod (0o755 )
61-
6233 # Create pyvenv.cfg
6334 (target_dir / "pyvenv.cfg" ).write_text (
6435 f"home = { base_python / 'bin' } \n include-system-site-packages = false\n "
6536 )
6637
67- print (f"Done! Use: { target_dir } /bin/python3 or { target_dir } /bin/pip" )
38+ if len (sys .argv ) == 3 :
39+ requirements_file = Path (sys .argv [2 ])
40+ assert requirements_file .is_file (), requirements_file
41+ import subprocess
42+
43+ cmd = [
44+ target_dir / "bin" / "python3" ,
45+ "-m" ,
46+ "pip" ,
47+ "install" ,
48+ "-r" ,
49+ requirements_file ,
50+ ]
51+ subprocess .run (cmd , check = True )
52+ # clean up __pycache__ folders at target
53+ for root , dirs , files in os .walk (target_dir ):
54+ for dir in dirs :
55+ if dir == "__pycache__" :
56+ shutil .rmtree (os .path .join (root , dir ))
6857
6958
7059if __name__ == "__main__" :
0 commit comments