2626# Parameters:
2727# "$1": The name or path of the python binary to test.
2828#
29- # Return 0 (true) if the given argument "$1" is a Python 3 binary.
29+ # Return 0 (true) if the given argument "$1" is a viable Python 3 binary.
3030# Return a non-zero value (false) otherwise.
3131#
3232# Diagnostic messages may be printed to stderr (pipe 2). Redirect to /dev/null
@@ -35,41 +35,17 @@ is_python3() (
3535 set -o errexit
3636 set -o pipefail
3737
38+ HERE=" $( dirname " ${BASH_SOURCE[0]} " ) "
39+
3840 # Binary to use, e.g. "python".
3941 local -r bin=" ${1:? ' is_python3 requires a name or path of a python binary to test' } "
4042
4143 # Binary must be executable.
4244 command -V " $bin " & > /dev/null || return
4345
44- # Reject binaries that do not support argument "-V".
45- " $bin " -V & > /dev/null || return
46-
47- # Expect an output of the form: "Python x.y.z".
48- # Note: Python 2 binaries output to stderr rather than stdout.
49- local -r version_output=" $( " $bin " -V 2>&1 | tr -d ' \n' ) "
50-
51- # For diagnostic purposes.
52- echo " - $bin : $version_output "
53-
54- # shellcheck disable=SC2091
55- if ! $( " $bin " -c " import sys; exit('free-threading' in sys.version)" ) ; then
56- echo " Skipping free-threaded version of Python ${version} "
57- return 1
58- fi
59-
60- # The minimum version we support is Python 3.9. All other versions are EOL.
61- # shellcheck disable=SC2091
62- if ! $( " $bin " -c " import sys; exit(sys.version_info[0] == 3 and sys.version_info[1] < 9)" ) ; then
63- version=$( $bin --version)
64- echo " Detected EOL Python ${version} , skipping."
65- return 1
66- fi
46+ echo " - ${bin} "
6747
68- # Evaluate result of this function.
69- # Note: Python True (1) and False (0) is treated as fail (1) and success (0)
70- # by Bash; therefore `is_python3` returns "true" when `v < 3` is false.
71- # Skip prerelease versions of python.
72- " $bin " -c " import sys; exit(sys.version_info[0] < 3 or sys.version_info.releaselevel != 'final')"
48+ " $bin " " ${HERE:? } /is_python3.py" || return
7349) 1>&2
7450
7551# is_venv_capable
@@ -209,15 +185,26 @@ find_python3() (
209185 set -o errexit
210186 set -o pipefail
211187
212- local -a bins=()
213- local bin=" "
214-
215- # The list of Python binaries to test for venv or virtualenv support.
216- # The binaries are tested in the order of their position in the array.
217- {
218- echo " Finding python3 binaries to test..."
188+ # Prefer Python Toolchain Current version.
189+ declare python_binary=" "
190+ case " ${OSTYPE:? } " in
191+ cygwin)
192+ python_binary=" /cygdrive/c/Python/Current/python.exe"
193+ ;;
194+ darwin* )
195+ python_binary=" /Library/Frameworks/Python.Framework/Versions/Current/bin/python3"
196+ ;;
197+ * )
198+ python_binary=" /opt/python/Current/bin/python3"
199+ ;;
200+ esac
201+ if is_python3 " ${python_binary:? } " ; then
202+ echo " Using Python binary ${python_binary:? } " >&2
203+ echo " ${python_binary:? } "
204+ return
205+ fi
219206
220- append_bins () {
207+ test_bins () {
221208 local -r bin_path=" ${1:? ' missing path' } "
222209 shift
223210 local -r pattern=" ${1:? ' missing pattern' } "
@@ -227,78 +214,50 @@ find_python3() (
227214 for dir in $( find " $bin_path " -maxdepth 1 -name " $pattern " -type d 2> /dev/null | sort -rV) ; do
228215 for bin in " ${suffixes[@]} " ; do
229216 if is_python3 " $dir /$bin " ; then
230- bins+=(" $dir /$bin " )
217+ echo " $dir /$bin "
218+ return
231219 fi
232220 done
233221 done
234222 }
235223
236- # C:/python/Python3X/bin/python
237- append_bins " C:/python" " Python3[0-9]*" " python3.exe" " python.exe"
238-
239- # /opt/python/3.X/bin/python
240- append_bins " /opt/python" " 3.[0-9]*" " bin/python3" " bin/python"
241-
242- # /opt/mongodbtoolchain/vX/bin/python
243- append_bins " /opt/mongodbtoolchain" " v[0-9]*" " bin/python3" " bin/python"
244-
245- # /Library/Frameworks/Python.Framework/Versions/XXX/bin/python3 (used by AWS Mac Fleet)
246- append_bins " /Library/Frameworks/Python.Framework/Versions/" " [0-9]*" " bin/python3"
247-
248- bin=" python3"
249- if is_python3 " $bin " ; then bins+=(" $bin " ); fi
250-
251- bin=" python"
252- if is_python3 " $bin " ; then bins+=(" $bin " ); fi
253- } 1>&2
254-
255- {
256- # Some environments trigger an unbound variable error if "${bins[@]}" is empty when used below.
257- if (( "${# bins[@]} " == 0 )) ; then
258- echo " Could not find any python3 binaries!"
259- return 1
224+ # Look in other standard locations.
225+ case " ${OSTYPE:? } " in
226+ cygwin)
227+ # Python toolchain: C:/python/Python3X/bin/python
228+ python_binary=" $( test_bins " C:/python" " Python3[0-9]*" " python3.exe" " python.exe" ) "
229+ ;;
230+ darwin* )
231+ # Standard location: /Library/Frameworks/Python.Framework/Versions/XXX/bin/python3
232+ python_binary=" $( test_bins " /Library/Frameworks/Python.Framework/Versions/" " [0-9]*" " bin/python3" ) "
233+ ;;
234+ * )
235+ # MongoDB toolchain: /opt/mongodbtoolchain/vX/bin/python
236+ python_binary=" $( test_bins " /opt/mongodbtoolchain" " v[0-9]*" " bin/python3" " bin/python" ) "
237+ if [ -z " $python_binary " ]; then
238+ # Python toolchain: /opt/python/3.X/bin/python
239+ python_binary=$( test_bins " /opt/python" " 3.[0-9]*" " bin/python3" " bin/python" )
260240 fi
241+ ;;
242+ esac
261243
262- # For diagnostic purposes.
263- echo " List of python3 binaries to test:"
264- for bin in " ${bins[@]} " ; do
265- echo " - $bin "
266- done
267- } 1>&2
268-
269- # Find a binary that is capable of venv or virtualenv and set it as `res`.
270- local res=" "
271- {
272- echo " Testing python3 binaries..."
273- for bin in " ${bins[@]} " ; do
274- {
275- if ! is_venv_capable " $bin " ; then
276- echo " - $bin is not capable of venv"
277-
278- if ! is_virtualenv_capable " $bin " ; then
279- echo " - $bin is not capable of virtualenv"
280- continue
281- else
282- echo " - $bin is capable of virtualenv"
283- fi
284- else
285- echo " - $bin is capable of venv"
286- fi
287- } 1>&2
288-
289- res=" $bin "
290- break
291- done
292-
293- if [[ -z " $res " ]]; then
294- echo " Could not find a python3 binary capable of creating a virtual environment!"
295- return 1
244+ # Fall back to looking for a system python.
245+ if [ -z " ${python_binary} " ]; then
246+ if is_python3 " python3" ; then
247+ python_binary=" python3"
248+ elif is_python3 " python" ; then
249+ python_binary=" python"
296250 fi
297- } 1>&2
298-
299- echo " $res "
251+ fi
300252
301- return 0
253+ # Handle success.
254+ if [ -n " ${python_binary} " ]; then
255+ echo " Using Python binary ${python_binary:? } " >&2
256+ echo " ${python_binary:? } "
257+ return
258+ else
259+ echo " No valid pythons found!" >&2
260+ fi
302261)
303262
304263#
@@ -314,7 +273,6 @@ find_python3() (
314273# with `2>/dev/null` to silence these messages.
315274#
316275# If DRIVERS_TOOLS_PYTHON is set, it will return that value. Otherwise
317- # it will look for the "Current" python in the python toolchain. Finally,
318276# it will fall back to using find_python3 to return a suitable value.
319277#
320278ensure_python3 () {
@@ -325,30 +283,12 @@ ensure_python3() {
325283 return
326284 fi
327285
328- # Use Python Toolchain.
329- declare python_binary=" "
330- case " ${OSTYPE:? } " in
331- cygwin)
332- python_binary=" /cygdrive/c/Python/Current/python.exe"
333- ;;
334- darwin* )
335- python_binary=" /Library/Frameworks/Python.Framework/Versions/Current/bin/python3"
336- ;;
337- * )
338- python_binary=" /opt/python/Current/bin/python3"
339- ;;
340- esac
341- if command -v " ${python_binary:? } " > /dev/null; then
342- echo " Using Python binary ${python_binary:? } " >&2
343- echo " ${python_binary:? } "
344- return
345- fi
346-
347286 # Use find_python3.
287+ declare python_binary=" "
348288 {
349289 echo " Finding Python3 binary..."
350- python_binary=" $( find_python3 2> /dev/null) " || return
290+ python_binary=" $( find_python3 2> /dev/null) "
351291 echo " Finding Python3 binary... done."
352292 } 1>&2
353- echo " ${python_binary:? } "
293+ echo " ${python_binary} "
354294}
0 commit comments