sg-python.sh 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. #!/usr/bin/env bash
  2. # Find a working Python 3 interpreter and exec the hook with it.
  3. #
  4. # On Windows + Git Bash, `python3` typically resolves to the Microsoft Store
  5. # stub at C:\Users\<user>\AppData\Local\Microsoft\WindowsApps\python3, which
  6. # exits 49 silently in non-TTY subprocess context (a known Microsoft Store
  7. # stub behavior). This shim
  8. # probes each candidate with `-c ""` and skips any that fails, so the Store
  9. # stub falls through to the real python.org install (`python` in Git Bash) or
  10. # the `py -3` launcher.
  11. #
  12. # Order:
  13. # 1. python3 — canonical on macOS/Linux; the Store stub fails the probe.
  14. # 2. python — python.org installs on Windows; some Linux distros (RHEL 7
  15. # EOL'd 2024-06) point this at Python 2, but `-c ""` succeeds
  16. # on Python 2 too — guard with a version check.
  17. # 3. py -3 — Windows Python launcher.
  18. #
  19. # Args after the shim path are passed straight through to the chosen
  20. # interpreter, so the hooks.json invocation is:
  21. # bash "${CLAUDE_PLUGIN_ROOT}/hooks/sg-python.sh" \
  22. # "${CLAUDE_PLUGIN_ROOT}/hooks/security_reminder_hook.py"
  23. set -e
  24. probe() {
  25. # $1..N: the interpreter command (may be multi-word like `py -3`)
  26. # Probe writes the major version to stdout and exits 0 iff it's >=3.
  27. "$@" -c 'import sys; print(sys.version_info[0])' 2>/dev/null
  28. }
  29. for cmd in "python3" "python" "py -3"; do
  30. # Word-split intentionally so `py -3` works
  31. # shellcheck disable=SC2086
  32. v=$(probe $cmd) || continue
  33. if [ "$v" = "3" ]; then
  34. # shellcheck disable=SC2086
  35. exec $cmd "$@"
  36. fi
  37. done
  38. echo "security-guidance: no working Python 3 interpreter found." >&2
  39. echo " tried: python3, python, py -3" >&2
  40. echo " on Windows, install Python from https://python.org (NOT the Microsoft Store)" >&2
  41. exit 1