@@ -11,6 +11,7 @@ API_KEY_ENV=""
1111AUTH_CHOICE=" "
1212AUTH_KEY_FLAG=" "
1313MODEL_ID=" "
14+ PYTHON_BIN=" ${PYTHON_BIN:- } "
1415PACKAGE_SPEC=" "
1516UPDATE_TARGET=" "
1617JSON_OUTPUT=0
@@ -62,6 +63,35 @@ cleanup() {
6263
6364trap cleanup EXIT
6465
66+ resolve_python_bin () {
67+ local candidate
68+
69+ python_bin_usable () {
70+ " $1 " - << 'PY ' >/dev/null 2>&1
71+ import sys
72+ if sys.version_info < (3, 10):
73+ raise SystemExit(1)
74+ _value: tuple[int, ...] | None = None
75+ PY
76+ }
77+
78+ if [[ -n " $PYTHON_BIN " ]]; then
79+ [[ -x " $PYTHON_BIN " ]] || die " PYTHON_BIN is not executable: $PYTHON_BIN "
80+ python_bin_usable " $PYTHON_BIN " || die " PYTHON_BIN must be Python 3.10+: $PYTHON_BIN "
81+ return
82+ fi
83+
84+ for candidate in " $( command -v python3 || true) " /opt/homebrew/bin/python3 /usr/local/bin/python3 /usr/bin/python3; do
85+ [[ -n " $candidate " && -x " $candidate " ]] || continue
86+ if python_bin_usable " $candidate " ; then
87+ PYTHON_BIN=" $candidate "
88+ return
89+ fi
90+ done
91+
92+ die " Python 3.10+ is required"
93+ }
94+
6595usage () {
6696 cat << 'EOF '
6797Usage: bash scripts/e2e/parallels-npm-update-smoke.sh [options]
@@ -142,12 +172,13 @@ esac
142172
143173API_KEY_VALUE=" ${! API_KEY_ENV:- } "
144174[[ -n " $API_KEY_VALUE " ]] || die " $API_KEY_ENV is required"
175+ resolve_python_bin
145176
146177resolve_linux_vm_name () {
147178 local json requested
148179 json=" $( prlctl list --all --json) "
149180 requested=" $LINUX_VM "
150- PRL_VM_JSON=" $json " REQUESTED_VM_NAME=" $requested " python3 - << 'PY '
181+ PRL_VM_JSON=" $json " REQUESTED_VM_NAME=" $requested " " $PYTHON_BIN " - << 'PY '
151182import difflib
152183import json
153184import os
@@ -220,7 +251,7 @@ resolve_host_ip() {
220251}
221252
222253allocate_host_port () {
223- python3 - << 'PY '
254+ " $PYTHON_BIN " - << 'PY '
224255import socket
225256
226257sock = socket.socket()
@@ -242,7 +273,7 @@ pack_main_tgz() {
242273 ensure_current_build
243274 pkg=" $(
244275 npm pack --ignore-scripts --json --pack-destination " $MAIN_TGZ_DIR " \
245- | python3 -c ' import json, sys; data = json.load(sys.stdin); print(data[-1]["filename"])'
276+ | " $PYTHON_BIN " -c ' import json, sys; data = json.load(sys.stdin); print(data[-1]["filename"])'
246277 ) "
247278 MAIN_TGZ_PATH=" $MAIN_TGZ_DIR /openclaw-main-$CURRENT_HEAD_SHORT .tgz"
248279 cp " $MAIN_TGZ_DIR /$pkg " " $MAIN_TGZ_PATH "
@@ -452,7 +483,7 @@ start_server() {
452483 say " Serve update helper artifacts on $HOST_IP :$HOST_PORT "
453484 (
454485 cd " $MAIN_TGZ_DIR "
455- exec python3 -m http.server " $HOST_PORT " --bind 0.0.0.0
486+ exec " $PYTHON_BIN " -m http.server " $HOST_PORT " --bind 0.0.0.0
456487 ) > /tmp/openclaw-parallels-npm-update-http.log 2>&1 &
457488 SERVER_PID=$!
458489 sleep 1
@@ -475,7 +506,7 @@ wait_job() {
475506
476507extract_log_progress () {
477508 local log_path=" $1 "
478- python3 - " $log_path " << 'PY '
509+ " $PYTHON_BIN " - " $log_path " << 'PY '
479510import pathlib
480511import sys
481512
@@ -557,7 +588,7 @@ monitor_jobs_progress() {
557588
558589extract_last_version () {
559590 local log_path=" $1 "
560- python3 - " $log_path " << 'PY '
591+ " $PYTHON_BIN " - " $log_path " << 'PY '
561592import pathlib
562593import re
563594import sys
@@ -573,7 +604,7 @@ guest_powershell() {
573604 local script=" $1 "
574605 local encoded
575606 encoded=" $(
576- SCRIPT_CONTENT=" $script " python3 - << 'PY '
607+ SCRIPT_CONTENT=" $script " " $PYTHON_BIN " - << 'PY '
577608import base64
578609import os
579610
588619host_timeout_exec () {
589620 local timeout_s=" $1 "
590621 shift
591- HOST_TIMEOUT_S=" $timeout_s " python3 - " $@ " << 'PY '
622+ HOST_TIMEOUT_S=" $timeout_s " " $PYTHON_BIN " - " $@ " << 'PY '
592623import os
593624import subprocess
594625import sys
@@ -670,7 +701,7 @@ guest_powershell_poll() {
670701 local script=" $2 "
671702 local encoded
672703 encoded=" $(
673- SCRIPT_CONTENT=" $script " python3 - << 'PY '
704+ SCRIPT_CONTENT=" $script " " $PYTHON_BIN " - << 'PY '
674705import base64
675706import os
676707
734765 if [[ $log_rc -ne 0 ]] || [[ -z " $guest_log " ]]; then
735766 return " $log_rc "
736767 fi
737- GUEST_LOG=" $guest_log " python3 - " $log_state_path " << 'PY '
768+ GUEST_LOG=" $guest_log " " $PYTHON_BIN " - " $log_state_path " << 'PY '
738769import os
739770import pathlib
740771import sys
893924
894925write_summary_json () {
895926 local summary_path=" $RUN_DIR /summary.json"
896- python3 - " $summary_path " << 'PY '
927+ " $PYTHON_BIN " - " $summary_path " << 'PY '
897928import json
898929import os
899930import sys
0 commit comments