1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
#!/usr/bin/env bash
#
# Utility to find Python
#
function list_pythons() {
#
# List all python binaries/shims/links in a directory $1
#
ls -1 $1/python* 2>/dev/null | grep -E 'python[0-9.]+$'
}
function check_valid_python() {
#
# Return "$VERSION $1" for $1 if it returns a valid version string
# and has the required modules: ensurepip
#
# Note on versions: X.Y.Z... => XY, e.g.:
# 3.6.10 -> 36
# 3.10.1b1 -> 310
#
# This is required to sort versions correctly. The last version
# byte is ignored.
#
for MODULE in ensurepip sqlite3; do
$1 -c "import $MODULE" >/dev/null 2>&1 || return
done
VERSION=$( $1 -V 2>/dev/null |\
grep -E '^Python [0-9a-z.]+$' |\
sed 's/Python \([3-9]\.[0-9]\+\).*$/\1/;s/\.//' )
if [ ! -z "$VERSION" ]; then
echo $VERSION $1
fi
}
function list_valid_pythons() {
#
# Filter only valid Pythons in a directory $1, ignoring pyenv shims
# not pointing to an installed Python binary.
#
for PYTHON in $( list_pythons $1 ); do
PYTHON=$( check_valid_python $PYTHON )
if [ ! -z "$PYTHON" ]; then
echo $PYTHON
fi
done
}
function iterate_path() {
#
# Iterate dirs in the $PATH variable, sorting Python versions
# within each directory.
#
for DIR in $( echo $PATH | sed 's/:/ /g' ); do
list_valid_pythons $DIR | sort -r -n
done
}
#
# Take the first available Python with the highest version, respecting
# the $PATH variable.
#
# If operating in a venv, it will return the venv Python, despite the
# higher version may be available in the system directories.
#
iterate_path | head -1 | cut -d \ -f 2
|