From a029d6f3369c7842217350fbac7e3622ac83b235 Mon Sep 17 00:00:00 2001 From: Slavi Pantaleev Date: Sun, 25 Oct 2026 09:40:02 +0200 Subject: [PATCH] Add a way to run Python scripts with the interpreter which runs Ansible bin/ansible-python.sh runs Python with the interpreter named in the first line of `ansible-playbook`. That interpreter has PyYAML, since Ansible depends on it, even when Ansible is installed in an environment of its own (e.g. with pipx), where the system's `python3` may lack it. If it is not a Python interpreter (e.g. `ansible-playbook` is a wrapper script), or Ansible is missing, `python3` is used. Role installation, which needs PyYAML, is the first to use it in the next commit, so that it works without installing PyYAML separately. The same script in mash-playbook (where its tests live): https://github.com/mother-of-all-self-hosting/mash-playbook/commit/1fe0f90f Co-Authored-By: Claude Opus 5.5 (1M context) --- bin/ansible-python.sh | 44 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100755 bin/ansible-python.sh diff --git a/bin/ansible-python.sh b/bin/ansible-python.sh new file mode 100755 index 000000000..ee55fd55f --- /dev/null +++ b/bin/ansible-python.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# SPDX-FileCopyrightText: 2026 MASH project contributors +# SPDX-FileCopyrightText: 2026 Slavi Pantaleev +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +# Runs Python (with the given arguments) using the interpreter which runs Ansible. +# +# The playbook's Python scripts need PyYAML, which Ansible depends on. The interpreter which runs Ansible +# therefore has it, even when Ansible is installed in an environment of its own (e.g. with pipx), +# where the system's `python3` may lack it. +# +# The interpreter is taken from the first line (shebang) of `ansible-playbook`. +# If that is not a Python interpreter (e.g. `ansible-playbook` is a wrapper script), or Ansible is not installed, +# `python3` is used. + +set -eu + +python=python3 + +ansible_playbook_path=$(command -v ansible-playbook 2>/dev/null || true) +if [ -n "$ansible_playbook_path" ] && [ -f "$ansible_playbook_path" ]; then + shebang=$(head -n 1 "$ansible_playbook_path") + case "$shebang" in + "#!"*) + read -r interpreter next_word _ </dev/null 2>&1; then + python=$interpreter + fi + ;; + esac + ;; + esac +fi + +exec "$python" "$@"