https://github.com/python/cpython/commit/781eb1a688e0575a38c79575493f3ff83208a33e
commit: 781eb1a688e0575a38c79575493f3ff83208a33e
branch: main
author: Ned Deily <[email protected]>
committer: ned-deily <[email protected]>
date: 2025-08-06T07:21:30-04:00
summary:
gh-137450: macOS installer shell path management improvements (#137451)
Separate the installer `Shell profile updater` postinstall script from the
`Update Shell Profile.command` to enable more robust error handling.
files:
A Mac/BuildScript/resources/update_shell_profile.command
A Misc/NEWS.d/next/macOS/2025-08-06-06-29-12.gh-issue-137450.JZypb7.rst
M Mac/BuildScript/build-installer.py
M Mac/BuildScript/scripts/postflight.patch-profile
diff --git a/Mac/BuildScript/build-installer.py
b/Mac/BuildScript/build-installer.py
index 8ae2cff93d2082..4da6d924848889 100755
--- a/Mac/BuildScript/build-installer.py
+++ b/Mac/BuildScript/build-installer.py
@@ -1747,7 +1747,7 @@ def main():
fn = os.path.join(folder, "ReadMe.rtf")
patchFile("resources/ReadMe.rtf", fn)
fn = os.path.join(folder, "Update Shell Profile.command")
- patchScript("scripts/postflight.patch-profile", fn)
+ patchScript("resources/update_shell_profile.command", fn)
fn = os.path.join(folder, "Install Certificates.command")
patchScript("resources/install_certificates.command", fn)
os.chmod(folder, STAT_0o755)
diff --git a/Mac/BuildScript/resources/update_shell_profile.command
b/Mac/BuildScript/resources/update_shell_profile.command
new file mode 100755
index 00000000000000..3cf4d74de9f09a
--- /dev/null
+++ b/Mac/BuildScript/resources/update_shell_profile.command
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+echo "This script will update your shell profile when the 'bin' directory"
+echo "of python is not early enough of the PATH of your shell."
+echo "These changes will be effective only in shell windows that you open"
+echo "after running this script."
+
+PYVER=@PYVER@
+PYTHON_ROOT="/Library/Frameworks/Python.framework/Versions/@PYVER@"
+
+if [ `id -ur` = 0 ]; then
+ # Run from the installer, do some trickery to fetch the information
+ # we need.
+ theShell="`finger $USER | grep Shell: | head -1 | awk '{ print $NF }'`"
+
+else
+ theShell="${SHELL}"
+fi
+
+# Make sure the directory ${PYTHON_ROOT}/bin is on the users PATH.
+BSH="`basename "${theShell}"`"
+case "${BSH}" in
+bash|ksh|sh|*csh|zsh|fish)
+ if [ `id -ur` = 0 ]; then
+ P=`su - ${USER} -c 'echo A-X-4-X@@$PATH@@X-4-X-A' | grep
'A-X-4-X@@.*@@X-4-X-A' | sed -e 's/^A-X-4-X@@//g' -e 's/@@X-4-X-A$//g'`
+ else
+ P="`(exec -l ${theShell} -c 'echo $PATH')`"
+ fi
+ ;;
+*)
+ echo "Sorry, I don't know how to patch $BSH shells"
+ exit 0
+ ;;
+esac
+
+# Now ensure that our bin directory is on $P and before /usr/bin at that
+for elem in `echo $P | tr ':' ' '`
+do
+ if [ "${elem}" = "${PYTHON_ROOT}/bin" ]; then
+ echo "All right, you're a python lover already"
+ exit 0
+ elif [ "${elem}" = "/usr/bin" ]; then
+ break
+ fi
+done
+
+echo "${PYTHON_ROOT}/bin is not on your PATH or at least not early enough"
+case "${BSH}" in
+*csh)
+ if [ -f "${HOME}/.tcshrc" ]; then
+ RC="${HOME}/.tcshrc"
+ else
+ RC="${HOME}/.cshrc"
+ fi
+ # Create backup copy before patching
+ if [ -f "${RC}" ]; then
+ cp -fp "${RC}" "${RC}.pysave"
+ fi
+ echo "" >> "${RC}"
+ echo "# Setting PATH for Python ${PYVER}" >> "${RC}"
+ echo "# The original version is saved in .cshrc.pysave" >> "${RC}"
+ echo "set path=(${PYTHON_ROOT}/bin "'$path'")" >> "${RC}"
+ if [ `id -ur` = 0 ]; then
+ chown -h "${USER}" "${RC}"
+ fi
+ exit 0
+ ;;
+bash)
+ if [ -e "${HOME}/.bash_profile" ]; then
+ PR="${HOME}/.bash_profile"
+ elif [ -e "${HOME}/.bash_login" ]; then
+ PR="${HOME}/.bash_login"
+ elif [ -e "${HOME}/.profile" ]; then
+ PR="${HOME}/.profile"
+ else
+ PR="${HOME}/.bash_profile"
+ fi
+ ;;
+fish)
+ CONFIG_DIR="${HOME}/.config/fish/conf.d/"
+ RC="${CONFIG_DIR}/python-${PYVER}.fish"
+ mkdir -p "$CONFIG_DIR"
+ if [ -f "${RC}" ]; then
+ cp -fp "${RC}" "${RC}.pysave"
+ fi
+ echo "# Setting PATH for Python ${PYVER}" > "${RC}"
+ if [ -f "${RC}.pysave" ]; then
+ echo "# The original version is saved in ${RC}.pysave" >>
"${RC}"
+ fi
+ echo "fish_add_path -g \"${PYTHON_ROOT}/bin\"" >> "${RC}"
+ if [ `id -ur` = 0 ]; then
+ chown -h "${USER}" "${RC}"
+ fi
+ exit 0
+ ;;
+zsh)
+ PR="${HOME}/.zprofile"
+ ;;
+*sh)
+ PR="${HOME}/.profile"
+ ;;
+esac
+
+# Create backup copy before patching
+if [ -f "${PR}" ]; then
+ cp -fp "${PR}" "${PR}.pysave"
+fi
+echo "" >> "${PR}"
+echo "# Setting PATH for Python ${PYVER}" >> "${PR}"
+echo "# The original version is saved in `basename ${PR}`.pysave" >> "${PR}"
+echo 'PATH="'"${PYTHON_ROOT}/bin"':${PATH}"' >> "${PR}"
+echo 'export PATH' >> "${PR}"
+if [ `id -ur` = 0 ]; then
+ chown -h "${USER}" "${PR}"
+fi
+exit 0
diff --git a/Mac/BuildScript/scripts/postflight.patch-profile
b/Mac/BuildScript/scripts/postflight.patch-profile
index 9caf62211ddd16..ce8720f895d1b5 100755
--- a/Mac/BuildScript/scripts/postflight.patch-profile
+++ b/Mac/BuildScript/scripts/postflight.patch-profile
@@ -1,116 +1,104 @@
#!/bin/sh
-echo "This script will update your shell profile when the 'bin' directory"
-echo "of python is not early enough of the PATH of your shell."
-echo "These changes will be effective only in shell windows that you open"
-echo "after running this script."
-
PYVER=@PYVER@
PYTHON_ROOT="/Library/Frameworks/Python.framework/Versions/@PYVER@"
-if [ `id -ur` = 0 ]; then
- # Run from the installer, do some trickery to fetch the information
- # we need.
- theShell="`finger $USER | grep Shell: | head -1 | awk '{ print $NF }'`"
-else
- theShell="${SHELL}"
-fi
+# Run from the installer, do some trickery to fetch the information
+# we need.
+theShell="`finger $USER | grep Shell: | head -1 | awk '{ print $NF }'`"
# Make sure the directory ${PYTHON_ROOT}/bin is on the users PATH.
BSH="`basename "${theShell}"`"
case "${BSH}" in
bash|ksh|sh|*csh|zsh|fish)
- if [ `id -ur` = 0 ]; then
- P=`su - ${USER} -c 'echo A-X-4-X@@$PATH@@X-4-X-A' | grep
'A-X-4-X@@.*@@X-4-X-A' | sed -e 's/^A-X-4-X@@//g' -e 's/@@X-4-X-A$//g'`
- else
- P="`(exec -l ${theShell} -c 'echo $PATH')`"
- fi
- ;;
+ true
+ ;;
*)
- echo "Sorry, I don't know how to patch $BSH shells"
- exit 0
- ;;
+ exit 0
+ ;;
esac
-# Now ensure that our bin directory is on $P and before /usr/bin at that
-for elem in `echo $P | tr ':' ' '`
-do
- if [ "${elem}" = "${PYTHON_ROOT}/bin" ]; then
- echo "All right, you're a python lover already"
- exit 0
- elif [ "${elem}" = "/usr/bin" ]; then
- break
- fi
-done
-
-echo "${PYTHON_ROOT}/bin is not on your PATH or at least not early enough"
case "${BSH}" in
*csh)
- if [ -f "${HOME}/.tcshrc" ]; then
- RC="${HOME}/.tcshrc"
- else
- RC="${HOME}/.cshrc"
- fi
- # Create backup copy before patching
- if [ -f "${RC}" ]; then
- cp -fp "${RC}" "${RC}.pysave"
- fi
- echo "" >> "${RC}"
- echo "# Setting PATH for Python ${PYVER}" >> "${RC}"
- echo "# The original version is saved in .cshrc.pysave" >> "${RC}"
- echo "set path=(${PYTHON_ROOT}/bin "'$path'")" >> "${RC}"
- if [ `id -ur` = 0 ]; then
- chown "${USER}" "${RC}"
- fi
- exit 0
- ;;
+ if [ -f "${HOME}/.tcshrc" ]; then
+ RC="${HOME}/.tcshrc"
+ else
+ RC="${HOME}/.cshrc"
+ fi
+
+ # Drop privileges while writing files.
+ su -m ${USER} <<EOFC
+ # Create backup copy before patching
+ if [ -f "${RC}" ]; then
+ cp -fp "${RC}" "${RC}.pysave"
+ fi
+ echo "" >> "${RC}"
+ echo "# Setting PATH for Python ${PYVER}" >> "${RC}"
+ echo "# The original version is saved in .cshrc.pysave" >> "${RC}"
+ echo "set path=(${PYTHON_ROOT}/bin "'\$path'")" >> "${RC}"
+EOFC
+
+ if [ `id -ur` = 0 ]; then
+ chown -h "${USER}" "${RC}"
+ fi
+ exit 0
+ ;;
bash)
- if [ -e "${HOME}/.bash_profile" ]; then
- PR="${HOME}/.bash_profile"
- elif [ -e "${HOME}/.bash_login" ]; then
- PR="${HOME}/.bash_login"
- elif [ -e "${HOME}/.profile" ]; then
- PR="${HOME}/.profile"
- else
- PR="${HOME}/.bash_profile"
- fi
- ;;
+ if [ -e "${HOME}/.bash_profile" ]; then
+ PR="${HOME}/.bash_profile"
+ elif [ -e "${HOME}/.bash_login" ]; then
+ PR="${HOME}/.bash_login"
+ elif [ -e "${HOME}/.profile" ]; then
+ PR="${HOME}/.profile"
+ else
+ PR="${HOME}/.bash_profile"
+ fi
+ ;;
fish)
- CONFIG_DIR="${HOME}/.config/fish/conf.d/"
- RC="${CONFIG_DIR}/python-${PYVER}.fish"
- mkdir -p "$CONFIG_DIR"
- if [ -f "${RC}" ]; then
- cp -fp "${RC}" "${RC}.pysave"
- fi
- echo "# Setting PATH for Python ${PYVER}" > "${RC}"
- if [ -f "${RC}.pysave" ]; then
- echo "# The original version is saved in ${RC}.pysave" >>
"${RC}"
- fi
- echo "fish_add_path -g \"${PYTHON_ROOT}/bin\"" >> "${RC}"
- if [ `id -ur` = 0 ]; then
- chown "${USER}" "${RC}"
- fi
- exit 0
- ;;
+ CONFIG_DIR="${HOME}/.config/fish/conf.d/"
+ RC="${CONFIG_DIR}/python-${PYVER}.fish"
+
+ # Drop privileges while writing files.
+ su -m ${USER} <<EOFF
+ mkdir -p "$CONFIG_DIR"
+ if [ -f "${RC}" ]; then
+ cp -fp "${RC}" "${RC}.pysave"
+ fi
+ echo "# Setting PATH for Python ${PYVER}" > "${RC}"
+ if [ -f "${RC}.pysave" ]; then
+ echo "# The original version is saved in ${RC}.pysave" >> "${RC}"
+ fi
+ echo "fish_add_path -g \"${PYTHON_ROOT}/bin\"" >> "${RC}"
+EOFF
+
+ if [ `id -ur` = 0 ]; then
+ chown -h "${USER}" "${RC}"
+ fi
+ exit 0
+ ;;
zsh)
- PR="${HOME}/.zprofile"
- ;;
+ PR="${HOME}/.zprofile"
+ ;;
*sh)
- PR="${HOME}/.profile"
- ;;
+ PR="${HOME}/.profile"
+ ;;
esac
+# Drop privileges while writing files.
+su -m ${USER} <<EOFS
# Create backup copy before patching
if [ -f "${PR}" ]; then
- cp -fp "${PR}" "${PR}.pysave"
+ cp -fp "${PR}" "${PR}.pysave"
fi
echo "" >> "${PR}"
echo "# Setting PATH for Python ${PYVER}" >> "${PR}"
echo "# The original version is saved in `basename ${PR}`.pysave" >> "${PR}"
-echo 'PATH="'"${PYTHON_ROOT}/bin"':${PATH}"' >> "${PR}"
+echo 'PATH="'"${PYTHON_ROOT}/bin"':\${PATH}"' >> "${PR}"
echo 'export PATH' >> "${PR}"
+EOFS
+
if [ `id -ur` = 0 ]; then
- chown "${USER}" "${PR}"
+ chown -h "${USER}" "${PR}"
fi
exit 0
diff --git
a/Misc/NEWS.d/next/macOS/2025-08-06-06-29-12.gh-issue-137450.JZypb7.rst
b/Misc/NEWS.d/next/macOS/2025-08-06-06-29-12.gh-issue-137450.JZypb7.rst
new file mode 100644
index 00000000000000..5efd74660c95d2
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2025-08-06-06-29-12.gh-issue-137450.JZypb7.rst
@@ -0,0 +1,3 @@
+macOS installer shell path management improvements: separate the installer
+``Shell profile updater`` postinstall script from the
+``Update Shell Profile.command`` to enable more robust error handling.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]