@@ -7,6 +7,7 @@ COMPILE_SCRIPT="$ROOT_DIR/bin/compile"
77TMP_DIR=" $( mktemp -d /tmp/compile-test.XXXXXX) "
88TEST_ROOT=" $TMP_DIR /test-root"
99FAKE_BIN_DIR=" $TMP_DIR /fake-bin"
10+ FAKE_MANAGED_PYTHON=" $FAKE_BIN_DIR /managed-python3"
1011
1112cleanup () {
1213 rm -rf " $TMP_DIR "
@@ -67,10 +68,9 @@ assert_path_exists() {
6768}
6869
6970setup_fake_commands () {
70- local pip_available=" ${1:- 1} "
7171 mkdir -p " $FAKE_BIN_DIR "
7272
73- cat > " $FAKE_BIN_DIR /python3 " << 'EOF '
73+ cat > " $FAKE_MANAGED_PYTHON " << 'EOF '
7474#!/usr/bin/env bash
7575set -euo pipefail
7676
@@ -79,28 +79,48 @@ if [ "$#" -ge 2 ] && [ "$1" = "-c" ] && [ "$2" = "import sys; print(f\"{sys.vers
7979 exit 0
8080fi
8181
82- if [ "$#" -ge 3 ] && [ "$1" = "-m" ] && [ "$2" = "pip" ] && [ "$3" = "--version" ]; then
83- if [ "${FAKE_PIP_AVAILABLE:-1}" = "1" ]; then
84- printf 'pip 24.0 from /fake/site-packages/pip (python 3.13)\n'
85- exit 0
86- fi
82+ echo "Unexpected python3 invocation: $*" >&2
83+ exit 1
84+ EOF
85+
86+ cat > " $FAKE_BIN_DIR /uv" << 'EOF '
87+ #!/usr/bin/env bash
88+ set -euo pipefail
8789
88- echo "No module named pip" >&2
89- exit 1
90+ log_file="${TEST_ROOT}/uv.log"
91+ mkdir -p "$(dirname "$log_file")"
92+ printf '%s\n' "$*" >> "$log_file"
93+
94+ if [ "$#" -ge 3 ] && [ "$1" = "python" ] && [ "$2" = "install" ]; then
95+ exit 0
9096fi
9197
92- if [ "$#" -ge 3 ] && [ "$1" = "-m" ] && [ "$2" = "ensurepip" ] && [ "$3" = "--upgrade" ]; then
93- log_file="${TEST_ROOT}/ensurepip.log"
94- mkdir -p "$(dirname "$log_file")"
95- printf '%s\n' "$*" >> "$log_file"
98+ if [ "$#" -ge 3 ] && [ "$1" = "python" ] && [ "$2" = "find" ]; then
99+ printf '%s\n' "${FAKE_MANAGED_PYTHON}"
96100 exit 0
97101fi
98102
99- if [ "$#" -ge 3 ] && [ "$1" = "-m" ] && [ "$2" = "pip" ]; then
100- log_file="${TEST_ROOT}/pip.log"
101- mkdir -p "$(dirname "$log_file")"
102- printf '%s\n' "$*" >> "$log_file"
103+ if [ "$1" = "export" ]; then
104+ output_file=""
105+
106+ while [ "$#" -gt 0 ]; do
107+ case "$1" in
108+ -o)
109+ shift
110+ output_file="$1"
111+ ;;
112+ esac
113+ shift || true
114+ done
115+
116+ cat > "$output_file" <<'REQ'
117+ fastapi==0.135.3
118+ uvicorn==0.44.0
119+ REQ
120+ exit 0
121+ fi
103122
123+ if [ "$1" = "pip" ] && [ "$2" = "install" ]; then
104124 target_dir=""
105125 requirements_file=""
106126
@@ -130,44 +150,11 @@ if [ "$#" -ge 3 ] && [ "$1" = "-m" ] && [ "$2" = "pip" ]; then
130150 exit 0
131151fi
132152
133- echo "Unexpected python3 invocation: $*" >&2
134- exit 1
135- EOF
136-
137- cat > " $FAKE_BIN_DIR /uv" << 'EOF '
138- #!/usr/bin/env bash
139- set -euo pipefail
140-
141- log_file="${TEST_ROOT}/uv.log"
142- mkdir -p "$(dirname "$log_file")"
143- printf '%s\n' "$*" >> "$log_file"
144-
145- if [ "$1" = "export" ]; then
146- output_file=""
147-
148- while [ "$#" -gt 0 ]; do
149- case "$1" in
150- -o)
151- shift
152- output_file="$1"
153- ;;
154- esac
155- shift || true
156- done
157-
158- cat > "$output_file" <<'REQ'
159- fastapi==0.135.3
160- uvicorn==0.44.0
161- REQ
162- exit 0
163- fi
164-
165153echo "Unexpected uv invocation: $*" >&2
166154exit 1
167155EOF
168156
169- chmod +x " $FAKE_BIN_DIR /python3" " $FAKE_BIN_DIR /uv"
170- FAKE_PIP_AVAILABLE=" $pip_available "
157+ chmod +x " $FAKE_MANAGED_PYTHON " " $FAKE_BIN_DIR /uv"
171158}
172159
173160run_compile () {
@@ -177,7 +164,7 @@ run_compile() {
177164 local output_file=" $TEST_ROOT /output.txt"
178165
179166 set +e
180- PATH=" $FAKE_BIN_DIR :/usr/bin:/bin" TEST_ROOT=" $TEST_ROOT " FAKE_PIP_AVAILABLE =" ${FAKE_PIP_AVAILABLE :- 1} " " $COMPILE_SCRIPT " " $build_dir " " $cache_dir " " $env_dir " > " $output_file " 2>&1
167+ PATH=" $FAKE_BIN_DIR :/usr/bin:/bin" TEST_ROOT=" $TEST_ROOT " FAKE_MANAGED_PYTHON =" $FAKE_MANAGED_PYTHON " " $COMPILE_SCRIPT " " $build_dir " " $cache_dir " " $env_dir " > " $output_file " 2>&1
181168 status=$?
182169 set -e
183170
@@ -192,9 +179,11 @@ test_compile_succeeds_for_locked_uv_project() {
192179 local site_packages_dir=" $build_dir /.python_packages/lib/python3.13/site-packages"
193180 local profile_file=" $build_dir /.profile.d/python.sh"
194181 local export_file=" $build_dir /.uv-export-requirements.txt"
182+ local shim_dir=" $build_dir /.python/bin"
195183
196184 mkdir -p " $build_dir " " $cache_dir " " $env_dir "
197185 touch " $build_dir /pyproject.toml" " $build_dir /uv.lock"
186+ printf ' 3.13\n' > " $build_dir /.python-version"
198187 setup_fake_commands
199188
200189 # Act
@@ -203,33 +192,18 @@ test_compile_succeeds_for_locked_uv_project() {
203192 # Assert
204193 assert_exit_code " $status " 0 " compile should succeed for a locked uv project"
205194 assert_contains " $output " " Detected uv project with lockfile. Installing dependencies with uv." " compile should announce supported uv projects"
195+ assert_contains " $output " " Installing Python 3.13 from .python-version." " compile should install the requested Python version"
206196 assert_path_exists " $site_packages_dir " " compile should create the staged site-packages directory"
207197 assert_path_exists " $profile_file " " compile should write a profile script for runtime imports"
208198 assert_path_exists " $export_file " " compile should write the exported requirements file"
199+ assert_path_exists " $shim_dir /python3" " compile should create a python3 shim for runtime commands"
200+ assert_path_exists " $shim_dir /python" " compile should create a python shim for runtime commands"
209201 assert_file_contains " $profile_file " " $site_packages_dir " " profile script should add staged dependencies to PYTHONPATH"
202+ assert_file_contains " $profile_file " " $shim_dir " " profile script should add the managed Python shims to PATH"
203+ assert_file_contains " $TEST_ROOT /uv.log" " python install 3.13" " compile should install the Python version pinned by .python-version"
204+ assert_file_contains " $TEST_ROOT /uv.log" " python find --managed-python 3.13" " compile should resolve the managed interpreter path after installation"
210205 assert_file_contains " $TEST_ROOT /uv.log" " export --locked --format requirements-txt --no-emit-local -o $export_file " " compile should export locked third-party dependencies"
211- assert_file_contains " $TEST_ROOT /pip.log" " -m pip install uv" " compile should install uv with pip"
212- assert_file_contains " $TEST_ROOT /pip.log" " --no-deps --target $site_packages_dir -r $export_file " " compile should install exported dependencies into the staged site-packages directory"
213- }
214-
215- test_compile_bootstraps_pip_when_missing () {
216- # Arrange
217- local build_dir=" $TEST_ROOT /missing-pip/build"
218- local cache_dir=" $TEST_ROOT /missing-pip/cache"
219- local env_dir=" $TEST_ROOT /missing-pip/env"
220-
221- mkdir -p " $build_dir " " $cache_dir " " $env_dir "
222- touch " $build_dir /pyproject.toml" " $build_dir /uv.lock"
223- setup_fake_commands 0
224-
225- # Act
226- run_compile " $build_dir " " $cache_dir " " $env_dir "
227-
228- # Assert
229- assert_exit_code " $status " 0 " compile should bootstrap pip when the interpreter does not ship it"
230- assert_contains " $output " " pip not found for python3. Bootstrapping with ensurepip." " compile should explain when it needs to bootstrap pip"
231- assert_file_contains " $TEST_ROOT /ensurepip.log" " -m ensurepip --upgrade" " compile should bootstrap pip before using it"
232- assert_file_contains " $TEST_ROOT /pip.log" " -m pip install uv" " compile should continue with pip installs after bootstrapping"
206+ assert_file_contains " $TEST_ROOT /uv.log" " pip install --python $FAKE_MANAGED_PYTHON --no-deps --target $site_packages_dir -r $export_file " " compile should install exported dependencies into the staged site-packages directory via uv pip"
233207}
234208
235209test_compile_adds_src_directory_to_pythonpath_when_present () {
@@ -241,6 +215,7 @@ test_compile_adds_src_directory_to_pythonpath_when_present() {
241215
242216 mkdir -p " $build_dir /src" " $cache_dir " " $env_dir "
243217 touch " $build_dir /pyproject.toml" " $build_dir /uv.lock"
218+ printf ' 3.13\n' > " $build_dir /.python-version"
244219 setup_fake_commands
245220
246221 # Act
@@ -259,6 +234,7 @@ test_compile_fails_when_lockfile_is_missing() {
259234
260235 mkdir -p " $build_dir " " $cache_dir " " $env_dir "
261236 touch " $build_dir /pyproject.toml"
237+ printf ' 3.13\n' > " $build_dir /.python-version"
262238 setup_fake_commands
263239
264240 # Act
@@ -270,7 +246,6 @@ test_compile_fails_when_lockfile_is_missing() {
270246}
271247
272248test_compile_succeeds_for_locked_uv_project
273- test_compile_bootstraps_pip_when_missing
274249test_compile_adds_src_directory_to_pythonpath_when_present
275250test_compile_fails_when_lockfile_is_missing
276251
0 commit comments