Skip to content

Commit b21edec

Browse files
committed
Inject ppd_instantiate.py module
This allows for a one line command to duplicate the Python distro and installing packages with pip.
1 parent 5cf249f commit b21edec

3 files changed

Lines changed: 29 additions & 48 deletions

File tree

in_container/build.sh

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,3 @@ echo "Launcher Size: $(ls -lh "$INSTALL_DIR/bin/python$PYTHON_MAJOR_MINOR" | awk
214214
echo "libpython: $LIBPYTHON"
215215
echo "libpython SHA256: $LIBPYTHON_SHA256"
216216
echo "libpython Size: $(ls -lh "$LIBPYTHON" | awk '{print $5}')"
217-
echo ""
218-
echo "This Python installation supports:"
219-
echo " ✓ Dynamic C extension loading"
220-
echo " ✓ Portable execution (static launcher)"
221-
echo " ✓ Virtual environments (venv)"
222-
echo " ✓ Standard Python tooling (pip, setuptools, etc.)"
223-
echo "=========================================="

instantiate.py

Lines changed: 27 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
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

@@ -9,18 +10,16 @@
910

1011

1112
def 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'}\ninclude-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

7059
if __name__ == "__main__":

package.sh

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ if [ ! -d "$OUTPUT_DIR" ]; then
1818
error "Output directory not found: $OUTPUT_DIR. Run ./build-launcher.sh first."
1919
fi
2020

21-
echo "Copying instantiate.py..."
22-
cp "$SCRIPT_DIR/instantiate.py" "$OUTPUT_DIR/bin/"
23-
chmod +x "$OUTPUT_DIR/bin/instantiate.py"
21+
echo "Copying instantiate..."
22+
cp "$SCRIPT_DIR/instantiate.py" "$OUTPUT_DIR/lib/python3.12/ppd_instantiate.py"
2423

2524
echo "Optimizing package size..."
2625
STDLIB_DIR="$OUTPUT_DIR/lib/python${PYTHON_MAJOR_MINOR}"

0 commit comments

Comments
 (0)