diff --git a/backend/sitecustomize.py b/backend/sitecustomize.py new file mode 100644 index 0000000000..4b85819e18 --- /dev/null +++ b/backend/sitecustomize.py @@ -0,0 +1,26 @@ +"""Process-wide Python startup customizations for backend entrypoints. + +When ``backend/`` is on ``sys.path``, Python imports this module during +interpreter startup. Keep changes here suitable for all gateway, script, +migration, and test entrypoints that run in that environment. +""" + +from __future__ import annotations + +import asyncio +import sys + + +def _configure_windows_event_loop_policy() -> None: + if sys.platform != "win32": + return + + selector_policy = getattr(asyncio, "WindowsSelectorEventLoopPolicy", None) + if selector_policy is None: + return + + if not isinstance(asyncio.get_event_loop_policy(), selector_policy): + asyncio.set_event_loop_policy(selector_policy()) + + +_configure_windows_event_loop_policy() diff --git a/scripts/serve.sh b/scripts/serve.sh index 485c9b5fe7..1abf353ea2 100755 --- a/scripts/serve.sh +++ b/scripts/serve.sh @@ -37,6 +37,17 @@ if [ -f "$REPO_ROOT/.env" ]; then set +a fi +_pick_python() { + local candidate + for candidate in python3 python py; do + if command -v "$candidate" >/dev/null 2>&1 && "$candidate" -c 'import sys; raise SystemExit(0 if sys.version_info.major >= 3 else 1)' >/dev/null 2>&1; then + printf '%s\n' "$candidate" + return 0 + fi + done + return 1 +} + # ── Argument parsing ───────────────────────────────────────────────────────── DEV_MODE=true @@ -218,11 +229,7 @@ fi if $DEV_MODE; then FRONTEND_CMD="pnpm run dev" else - if command -v python3 >/dev/null 2>&1; then - PYTHON_BIN="python3" - elif command -v python >/dev/null 2>&1; then - PYTHON_BIN="python" - else + if ! PYTHON_BIN="$(_pick_python)"; then echo "Python is required to generate BETTER_AUTH_SECRET." exit 1 fi @@ -259,15 +266,10 @@ fi # ── Install dependencies ──────────────────────────────────────────────────── -# Pick a Python for the extras detector. Falls back to plain `python` for -# Windows/Git Bash where only `python` is on PATH. -if command -v python3 >/dev/null 2>&1; then - DETECT_PYTHON="python3" -elif command -v python >/dev/null 2>&1; then - DETECT_PYTHON="python" -else - DETECT_PYTHON="" -fi +# Pick a runnable Python for the extras detector. On Windows/Git Bash, +# `python3` can resolve to the Microsoft Store alias in WindowsApps, which is +# present on PATH but not executable from Bash. +DETECT_PYTHON="$(_pick_python || true)" # Resolve uv extras (postgres, etc.) from UV_EXTRAS or config.yaml so that # `uv sync` does not wipe out optional dependencies on every restart. See diff --git a/scripts/wait-for-port.sh b/scripts/wait-for-port.sh index dc0dffa1d3..ef2522e638 100755 --- a/scripts/wait-for-port.sh +++ b/scripts/wait-for-port.sh @@ -17,10 +17,28 @@ PORT="${1:?Usage: wait-for-port.sh [timeout] [service_name]}" TIMEOUT="${2:-60}" SERVICE="${3:-Service}" +case "$PORT" in + ''|*[!0-9]*) + echo "Port must be a numeric TCP port: $PORT" >&2 + exit 1 + ;; +esac + +if [ "$PORT" -lt 1 ] || [ "$PORT" -gt 65535 ]; then + echo "Port must be between 1 and 65535: $PORT" >&2 + exit 1 +fi + elapsed=0 interval=1 is_port_listening() { + if command -v powershell.exe >/dev/null 2>&1; then + if WAIT_FOR_PORT_PORT="$PORT" powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "\$ErrorActionPreference='SilentlyContinue'; \$Port = [int]\$env:WAIT_FOR_PORT_PORT; if (Get-NetTCPConnection -LocalPort \$Port -State Listen) { exit 0 } else { exit 1 }" >/dev/null 2>&1; then + return 0 + fi + fi + if command -v lsof >/dev/null 2>&1; then if lsof -nP -iTCP:"$PORT" -sTCP:LISTEN -t >/dev/null 2>&1; then return 0