diff mbox series

[3/7] configure: Look for auxiliary Python installations

Message ID 20230209154034.983044-4-jsnow@redhat.com (mailing list archive)
State New, archived
Headers show
Series Python: Drop support for Python 3.6 | expand

Commit Message

John Snow Feb. 9, 2023, 3:40 p.m. UTC
At the moment, we look for just "python3" and "python", which is good
enough almost all of the time. But ... if you are on a platform that
uses an older Python by default and only offers a newer Python as an
option, you'll have to specify --python=/usr/bin/foo every time.

We can be kind and instead make a cursory attempt to locate a suitable
Python binary ourselves, looking for the remaining well-known binaries.

This configure loop will prefer, in order:

1. Whatever is specified in $PYTHON
2. python3
3. python
4. python3.11 down through python3.6

Notes:

- Python virtual environment provides binaries for "python3", "python",
  and whichever version you used to create the venv,
  e.g. "python3.8". If configure is invoked from inside of a venv, this
  configure loop will not "break out" of that venv unless that venv is
  created using an explicitly non-suitable version of Python that we
  cannot use.

- In the event that no suitable python is found, the first python found
  is the version used to generate the human-readable error message.

- The error message isn't printed right away to allow later
  configuration code to pick up an explicitly configured python.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 configure | 33 +++++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

Comments

Eric Blake Feb. 10, 2023, 7:45 p.m. UTC | #1
On Thu, Feb 09, 2023 at 10:40:30AM -0500, John Snow wrote:
> At the moment, we look for just "python3" and "python", which is good
> enough almost all of the time. But ... if you are on a platform that
> uses an older Python by default and only offers a newer Python as an
> option, you'll have to specify --python=/usr/bin/foo every time.
> 
> We can be kind and instead make a cursory attempt to locate a suitable
> Python binary ourselves, looking for the remaining well-known binaries.
> 
> This configure loop will prefer, in order:
> 
> 1. Whatever is specified in $PYTHON
> 2. python3
> 3. python
> 4. python3.11 down through python3.6

Makes sense.


>  python=
> +first_python=
>  explicit_python=no
> -for binary in "${PYTHON-python3}" python
> +# A bare 'python' is traditionally python 2.x, but some distros
> +# have it as python 3.x, so check in both places.
> +for binary in "${PYTHON-python3}" python python3.{11..6}

This does not match your commit message. If $PYTHON is set but fails,
you never check python3.  Pre-existing, but now that you're calling it
out as intended, it may be better to write the list prefix as:

for binary in $PYTHON python3 python ...

except that it mishandles $PYTHON containing space, so you want the
quotes, but you don't want to test an empty binary or waste time
testing python3 twice, so more precise could be:

for binary in "${PYTHON-python3}" ${PYTHON:+python3} python ...

Meanwhioe, your use of {11.6} is a bashism, but configure is /bin/sh.
It would be nice if you could use $(seq -f python3.%g 11 -1 6), but
that's probably too specific to GNU Coreutils and won't work on other
platforms; and open-coding it in a shell loop isn't going to be any
prettier.  So you'll be safest if you just manually spell it out:

python3.11 python3.10 ...
John Snow Feb. 15, 2023, 8:10 p.m. UTC | #2
On Fri, Feb 10, 2023 at 2:45 PM Eric Blake <eblake@redhat.com> wrote:
>
> On Thu, Feb 09, 2023 at 10:40:30AM -0500, John Snow wrote:
> > At the moment, we look for just "python3" and "python", which is good
> > enough almost all of the time. But ... if you are on a platform that
> > uses an older Python by default and only offers a newer Python as an
> > option, you'll have to specify --python=/usr/bin/foo every time.
> >
> > We can be kind and instead make a cursory attempt to locate a suitable
> > Python binary ourselves, looking for the remaining well-known binaries.
> >
> > This configure loop will prefer, in order:
> >
> > 1. Whatever is specified in $PYTHON
> > 2. python3
> > 3. python
> > 4. python3.11 down through python3.6
>
> Makes sense.
>
>
> >  python=
> > +first_python=
> >  explicit_python=no
> > -for binary in "${PYTHON-python3}" python
> > +# A bare 'python' is traditionally python 2.x, but some distros
> > +# have it as python 3.x, so check in both places.
> > +for binary in "${PYTHON-python3}" python python3.{11..6}
>
> This does not match your commit message. If $PYTHON is set but fails,
> you never check python3.  Pre-existing, but now that you're calling it
> out as intended, it may be better to write the list prefix as:
>
> for binary in $PYTHON python3 python ...
>
> except that it mishandles $PYTHON containing space, so you want the
> quotes, but you don't want to test an empty binary or waste time
> testing python3 twice, so more precise could be:
>
> for binary in "${PYTHON-python3}" ${PYTHON:+python3} python ...

Yep. I wonder if it's worth helping people work around broken
environment variables at all, but, eh, you already solved the more
difficult case, so I can include it.

(Well, pending other discussions, I s'pose.)

>
> Meanwhioe, your use of {11.6} is a bashism, but configure is /bin/sh.
> It would be nice if you could use $(seq -f python3.%g 11 -1 6), but
> that's probably too specific to GNU Coreutils and won't work on other
> platforms; and open-coding it in a shell loop isn't going to be any
> prettier.  So you'll be safest if you just manually spell it out:
>
> python3.11 python3.10 ...

Oh, icky.  Well, OK. Thanks for pointing it out before it became a
problem somewhere.

>
> --
> Eric Blake, Principal Software Engineer
> Red Hat, Inc.           +1-919-301-3266
> Virtualization:  qemu.org | libvirt.org
>
diff mbox series

Patch

diff --git a/configure b/configure
index 64960c6000f..ea8c973d13b 100755
--- a/configure
+++ b/configure
@@ -592,20 +592,39 @@  esac
 
 : ${make=${MAKE-make}}
 
-# We prefer python 3.x. A bare 'python' is traditionally
-# python 2.x, but some distros have it as python 3.x, so
-# we check that too
+
+check_py_version() {
+    # We require python >= 3.6.
+    # NB: a True python conditional creates a non-zero return code (Failure)
+    "$1" -c 'import sys; sys.exit(sys.version_info < (3,6))'
+}
+
 python=
+first_python=
 explicit_python=no
-for binary in "${PYTHON-python3}" python
+# A bare 'python' is traditionally python 2.x, but some distros
+# have it as python 3.x, so check in both places.
+for binary in "${PYTHON-python3}" python python3.{11..6}
 do
     if has "$binary"
     then
         python=$(command -v "$binary")
-        break
+        if test -z "$first_python"; then
+           first_python=$python
+        fi
+        if check_py_version "$python"; then
+            # This one is good.
+            first_python=
+            break
+        fi
     fi
 done
 
+# If first_python is set, we didn't find a suitable binary.
+# Use this one for possible future error messages.
+if test -n "$first_python"; then
+    python="$first_python"
+fi
 
 # Check for ancillary tools used in testing
 genisoimage=
@@ -1037,9 +1056,7 @@  then
     error_exit "GNU make ($make) not found"
 fi
 
-# Note that if the Python conditional here evaluates True we will exit
-# with status 1 which is a shell 'false' value.
-if ! $python -c 'import sys; sys.exit(sys.version_info < (3,6))'; then
+if ! check_py_version "$python"; then
   error_exit "Cannot use '$python', Python >= 3.6 is required." \
       "Use --python=/path/to/python to specify a supported Python."
 fi