diff mbox series

[v3,1/6] configure: Look for auxiliary Python installations

Message ID 20230221012456.2607692-2-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. 21, 2023, 1:24 a.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.

As a courtesy, we can make a cursory attempt to locate a suitable Python
binary ourselves, looking for the remaining well-known binaries. This
also has the added benefit of making configure "just work" more often
on various BSD distributions that do not have the concept of a
"platform default python".

This configure loop will prefer, in order:

1. Whatever is specified in $PYTHON
2. python3
3. python (Which is usually 2.x, but might be 3.x on some platforms.)
4. python3.11 down through python3.6

Notes:

- Python virtual environments provide 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 | 34 ++++++++++++++++++++++++++--------
 1 file changed, 26 insertions(+), 8 deletions(-)

Comments

Paolo Bonzini Feb. 21, 2023, 11:03 a.m. UTC | #1
On 2/21/23 02:24, 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.
> 
> As a courtesy, we can make a cursory attempt to locate a suitable Python
> binary ourselves, looking for the remaining well-known binaries. This
> also has the added benefit of making configure "just work" more often
> on various BSD distributions that do not have the concept of a
> "platform default python".
> 
> This configure loop will prefer, in order:
> 
> 1. Whatever is specified in $PYTHON
> 2. python3
> 3. python (Which is usually 2.x, but might be 3.x on some platforms.)
> 4. python3.11 down through python3.6
> 
> Notes:
> 
> - Python virtual environments provide 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 | 34 ++++++++++++++++++++++++++--------
>   1 file changed, 26 insertions(+), 8 deletions(-)
> 
> diff --git a/configure b/configure
> index cf6db3d5518..6abf5a72078 100755
> --- a/configure
> +++ b/configure
> @@ -592,20 +592,40 @@ 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
> +# Check for $PYTHON, python3, python, then explicitly-versioned interpreters.
> +for binary in "${PYTHON-python3}" ${PYTHON:+python3} python \
> +                                  python3.11 python3.10 python3.9 \
> +                                  python3.8 python3.7 python3.6

I think if PYTHON is set we shouldn't look at anything else.

Paolo

>   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 +1057,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
John Snow Feb. 21, 2023, 5:37 p.m. UTC | #2
On Tue, Feb 21, 2023, 6:03 AM Paolo Bonzini <pbonzini@redhat.com> wrote:

> On 2/21/23 02:24, 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.
> >
> > As a courtesy, we can make a cursory attempt to locate a suitable Python
> > binary ourselves, looking for the remaining well-known binaries. This
> > also has the added benefit of making configure "just work" more often
> > on various BSD distributions that do not have the concept of a
> > "platform default python".
> >
> > This configure loop will prefer, in order:
> >
> > 1. Whatever is specified in $PYTHON
> > 2. python3
> > 3. python (Which is usually 2.x, but might be 3.x on some platforms.)
> > 4. python3.11 down through python3.6
> >
> > Notes:
> >
> > - Python virtual environments provide 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 | 34 ++++++++++++++++++++++++++--------
> >   1 file changed, 26 insertions(+), 8 deletions(-)
> >
> > diff --git a/configure b/configure
> > index cf6db3d5518..6abf5a72078 100755
> > --- a/configure
> > +++ b/configure
> > @@ -592,20 +592,40 @@ 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
> > +# Check for $PYTHON, python3, python, then explicitly-versioned
> interpreters.
> > +for binary in "${PYTHON-python3}" ${PYTHON:+python3} python \
> > +                                  python3.11 python3.10 python3.9 \
> > +                                  python3.8 python3.7 python3.6
>
> I think if PYTHON is set we shouldn't look at anything else.
>
> Paolo
>

PYTHON is one we made up, right?


> >   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 +1057,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
>
>
Daniel P. Berrangé Feb. 21, 2023, 5:54 p.m. UTC | #3
On Tue, Feb 21, 2023 at 12:37:43PM -0500, John Snow wrote:
> On Tue, Feb 21, 2023, 6:03 AM Paolo Bonzini <pbonzini@redhat.com> wrote:
> 
> > On 2/21/23 02:24, 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.
> > >
> > > As a courtesy, we can make a cursory attempt to locate a suitable Python
> > > binary ourselves, looking for the remaining well-known binaries. This
> > > also has the added benefit of making configure "just work" more often
> > > on various BSD distributions that do not have the concept of a
> > > "platform default python".
> > >
> > > This configure loop will prefer, in order:
> > >
> > > 1. Whatever is specified in $PYTHON
> > > 2. python3
> > > 3. python (Which is usually 2.x, but might be 3.x on some platforms.)
> > > 4. python3.11 down through python3.6
> > >
> > > Notes:
> > >
> > > - Python virtual environments provide 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 | 34 ++++++++++++++++++++++++++--------
> > >   1 file changed, 26 insertions(+), 8 deletions(-)
> > >
> > > diff --git a/configure b/configure
> > > index cf6db3d5518..6abf5a72078 100755
> > > --- a/configure
> > > +++ b/configure
> > > @@ -592,20 +592,40 @@ 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
> > > +# Check for $PYTHON, python3, python, then explicitly-versioned
> > interpreters.
> > > +for binary in "${PYTHON-python3}" ${PYTHON:+python3} python \
> > > +                                  python3.11 python3.10 python3.9 \
> > > +                                  python3.8 python3.7 python3.6
> >
> > I think if PYTHON is set we shouldn't look at anything else.
> >
> > Paolo
> >
> 
> PYTHON is one we made up, right?

$PYTHON is explicitly set in all our dockerfiles. We should
ensure we honour it and not fallback to anything else when
it is set. ie it would be a user error to set it to point
to a python that is missing/broken, so the user should
expect an error, not fallback to another version.


With regards,
Daniel
Eric Blake Feb. 24, 2023, 6:04 p.m. UTC | #4
On Tue, Feb 21, 2023 at 12:03:44PM +0100, Paolo Bonzini wrote:
> > 
> > This configure loop will prefer, in order:
> > 
> > 1. Whatever is specified in $PYTHON
> > 2. python3
> > 3. python (Which is usually 2.x, but might be 3.x on some platforms.)
> > 4. python3.11 down through python3.6
> > 
> > +
> >   python=
> > +first_python=
> >   explicit_python=no
> > -for binary in "${PYTHON-python3}" python
> > +# Check for $PYTHON, python3, python, then explicitly-versioned interpreters.
> > +for binary in "${PYTHON-python3}" ${PYTHON:+python3} python \
> > +                                  python3.11 python3.10 python3.9 \
> > +                                  python3.8 python3.7 python3.6
> 
> I think if PYTHON is set we shouldn't look at anything else.

Now that you mention that, it does sound more like what autoconf does
(if the user specified something, honor it; otherwise, find the best
match in a list of candidates).

> 
> Paolo
> 
> >   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

One easy way to do that is add this here:

             if test -n "$PYTHON"; then 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
diff mbox series

Patch

diff --git a/configure b/configure
index cf6db3d5518..6abf5a72078 100755
--- a/configure
+++ b/configure
@@ -592,20 +592,40 @@  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
+# Check for $PYTHON, python3, python, then explicitly-versioned interpreters.
+for binary in "${PYTHON-python3}" ${PYTHON:+python3} python \
+                                  python3.11 python3.10 python3.9 \
+                                  python3.8 python3.7 python3.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 +1057,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