commit:     33380ad5e121a47375442de08fd9239b9102b1fa
Author:     Michał Górny <mgorny <AT> gentoo <DOT> org>
AuthorDate: Sat Dec 12 22:06:33 2015 +0000
Commit:     Michał Górny <mgorny <AT> gentoo <DOT> org>
CommitDate: Tue Dec 22 22:12:23 2015 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=33380ad5

python*-r1.eclass: Commonize PYTHON_COMPAT processing, cache the result

Introduce a common _python_set_impls function in python-utils-r1.eclass
that validates and processes PYTHON_COMPAT, then stores the result in
_PYTHON_SUPPORTED_IMPLS and _PYTHON_UNSUPPORTED_IMPLS variables. Reuse
those variables in all python-r1 suite eclasses, effectively reducing
code duplication and providing cache for repeated implementation support
checks.

 eclass/python-any-r1.eclass    | 28 +++++--------------
 eclass/python-r1.eclass        | 47 ++++++++------------------------
 eclass/python-single-r1.eclass | 61 ++++++++++++------------------------------
 eclass/python-utils-r1.eclass  | 49 +++++++++++++++++++++++++++++++++
 4 files changed, 83 insertions(+), 102 deletions(-)

diff --git a/eclass/python-any-r1.eclass b/eclass/python-any-r1.eclass
index 721ba45..dbfeded 100644
--- a/eclass/python-any-r1.eclass
+++ b/eclass/python-any-r1.eclass
@@ -71,12 +71,6 @@ if [[ ! ${_PYTHON_ANY_R1} ]]; then
 # @CODE
 # PYTHON_COMPAT=( python{2_5,2_6,2_7} )
 # @CODE
-if ! declare -p PYTHON_COMPAT &>/dev/null; then
-       die 'PYTHON_COMPAT not declared.'
-fi
-if [[ $(declare -p PYTHON_COMPAT) != "declare -a"* ]]; then
-       die 'PYTHON_COMPAT must be an array.'
-fi
 
 # @ECLASS-VARIABLE: PYTHON_REQ_USE
 # @DEFAULT_UNSET
@@ -119,16 +113,10 @@ _python_any_set_globals() {
        local usestr i PYTHON_PKG_DEP
        [[ ${PYTHON_REQ_USE} ]] && usestr="[${PYTHON_REQ_USE}]"
 
-       # check for invalid PYTHON_COMPAT
-       for i in "${PYTHON_COMPAT[@]}"; do
-               # the function simply dies on invalid impl
-               _python_impl_supported "${i}"
-       done
+       _python_set_impls
 
        PYTHON_DEPS=
-       for i in "${_PYTHON_ALL_IMPLS[@]}"; do
-               has "${i}" "${PYTHON_COMPAT[@]}" || continue
-
+       for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
                python_export "${i}" PYTHON_PKG_DEP
 
                PYTHON_DEPS="${PYTHON_PKG_DEP} ${PYTHON_DEPS}"
@@ -209,9 +197,7 @@ python_gen_any_dep() {
        [[ ${depstr} ]] || die "No dependency string provided"
 
        local PYTHON_PKG_DEP out=
-       for i in "${_PYTHON_ALL_IMPLS[@]}"; do
-               has "${i}" "${PYTHON_COMPAT[@]}" || continue
-
+       for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
                local 
PYTHON_USEDEP="python_targets_${i}(-),python_single_target_${i}(+)"
                python_export "${i}" PYTHON_PKG_DEP
 
@@ -242,7 +228,7 @@ _python_EPYTHON_supported() {
                        ;;
        esac
 
-       if has "${i}" "${PYTHON_COMPAT[@]}"; then
+       if has "${i}" "${_PYTHON_SUPPORTED_IMPLS[@]}"; then
                if python_is_installed "${i}"; then
                        if declare -f python_check_deps >/dev/null; then
                                local 
PYTHON_USEDEP="python_targets_${i}(-),python_single_target_${i}(+)"
@@ -293,10 +279,8 @@ python_setup() {
 
        # fallback to best installed impl.
        local rev_impls=()
-       for i in "${_PYTHON_ALL_IMPLS[@]}"; do
-               if has "${i}" "${PYTHON_COMPAT[@]}"; then
-                       rev_impls=( "${i}" "${rev_impls[@]}" )
-               fi
+       for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+               rev_impls=( "${i}" "${rev_impls[@]}" )
        done
 
        for i in "${rev_impls[@]}"; do

diff --git a/eclass/python-r1.eclass b/eclass/python-r1.eclass
index fbc39dc..f7a8541 100644
--- a/eclass/python-r1.eclass
+++ b/eclass/python-r1.eclass
@@ -82,12 +82,6 @@ inherit multibuild python-utils-r1
 # @CODE
 # PYTHON_COMPAT=( python2_7 python3_{3,4} )
 # @CODE
-if ! declare -p PYTHON_COMPAT &>/dev/null; then
-       die 'PYTHON_COMPAT not declared.'
-fi
-if [[ $(declare -p PYTHON_COMPAT) != "declare -a"* ]]; then
-       die 'PYTHON_COMPAT must be an array.'
-fi
 
 # @ECLASS-VARIABLE: PYTHON_COMPAT_OVERRIDE
 # @INTERNAL
@@ -186,24 +180,17 @@ fi
 # @CODE
 
 _python_set_globals() {
-       local impls=()
-
        PYTHON_DEPS=
        local i PYTHON_PKG_DEP
-       for i in "${PYTHON_COMPAT[@]}"; do
-               _python_impl_supported "${i}" || continue
 
+       _python_set_impls
+
+       for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
                python_export "${i}" PYTHON_PKG_DEP
                PYTHON_DEPS+="python_targets_${i}? ( ${PYTHON_PKG_DEP} ) "
-
-               impls+=( "${i}" )
        done
 
-       if [[ ${#impls[@]} -eq 0 ]]; then
-               die "No supported implementation in PYTHON_COMPAT."
-       fi
-
-       local flags=( "${impls[@]/#/python_targets_}" )
+       local flags=( "${_PYTHON_SUPPORTED_IMPLS[@]/#/python_targets_}" )
        local optflags=${flags[@]/%/(-)?}
 
        # A nice QA trick here. Since a python-single-r1 package has to have
@@ -212,7 +199,7 @@ _python_set_globals() {
        # it should prevent developers from mistakenly depending on packages
        # not supporting multiple Python implementations.
 
-       local flags_st=( "${impls[@]/#/-python_single_target_}" )
+       local flags_st=( 
"${_PYTHON_SUPPORTED_IMPLS[@]/#/-python_single_target_}" )
        optflags+=,${flags_st[@]/%/(-)}
 
        IUSE=${flags[*]}
@@ -246,9 +233,7 @@ _python_validate_useflags() {
 
        local i
 
-       for i in "${PYTHON_COMPAT[@]}"; do
-               _python_impl_supported "${i}" || continue
-
+       for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
                use "python_targets_${i}" && return 0
        done
 
@@ -290,9 +275,7 @@ python_gen_usedep() {
        local impl pattern
        local matches=()
 
-       for impl in "${PYTHON_COMPAT[@]}"; do
-               _python_impl_supported "${impl}" || continue
-
+       for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
                for pattern; do
                        if [[ ${impl} == ${pattern} ]]; then
                                matches+=(
@@ -333,9 +316,7 @@ python_gen_useflags() {
        local impl pattern
        local matches=()
 
-       for impl in "${PYTHON_COMPAT[@]}"; do
-               _python_impl_supported "${impl}" || continue
-
+       for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
                for pattern; do
                        if [[ ${impl} == ${pattern} ]]; then
                                matches+=( "python_targets_${impl}" )
@@ -382,9 +363,7 @@ python_gen_cond_dep() {
        local dep=${1}
        shift
 
-       for impl in "${PYTHON_COMPAT[@]}"; do
-               _python_impl_supported "${impl}" || continue
-
+       for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
                for pattern; do
                        if [[ ${impl} == ${pattern} ]]; then
                                # substitute ${PYTHON_USEDEP} if used
@@ -460,12 +439,8 @@ _python_obtain_impls() {
 
        MULTIBUILD_VARIANTS=()
 
-       for impl in "${_PYTHON_ALL_IMPLS[@]}"; do
-               if has "${impl}" "${PYTHON_COMPAT[@]}" \
-                       && use "python_targets_${impl}"
-               then
-                       MULTIBUILD_VARIANTS+=( "${impl}" )
-               fi
+       for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+               use "python_targets_${impl}" && MULTIBUILD_VARIANTS+=( 
"${impl}" )
        done
 }
 

diff --git a/eclass/python-single-r1.eclass b/eclass/python-single-r1.eclass
index b8684f0..8ef3846 100644
--- a/eclass/python-single-r1.eclass
+++ b/eclass/python-single-r1.eclass
@@ -95,12 +95,6 @@ if [[ ! ${_PYTHON_SINGLE_R1} ]]; then
 # @CODE
 # PYTHON_COMPAT=( python2_7 python3_{3,4} )
 # @CODE
-if ! declare -p PYTHON_COMPAT &>/dev/null; then
-       die 'PYTHON_COMPAT not declared.'
-fi
-if [[ $(declare -p PYTHON_COMPAT) != "declare -a"* ]]; then
-       die 'PYTHON_COMPAT must be an array.'
-fi
 
 # @ECLASS-VARIABLE: PYTHON_REQ_USE
 # @DEFAULT_UNSET
@@ -186,34 +180,24 @@ fi
 # @CODE
 
 _python_single_set_globals() {
-       local impls=()
-       local unimpls=()
+       _python_set_impls
 
        PYTHON_DEPS=
        local i PYTHON_PKG_DEP
-       for i in "${_PYTHON_ALL_IMPLS[@]}"; do
-               has "${i}" "${PYTHON_COMPAT[@]}" \
-                       && impls+=( "${i}" ) \
-                       || unimpls+=( "${i}" )
-       done
-
-       if [[ ${#impls[@]} -eq 0 ]]; then
-               die "No supported implementation in PYTHON_COMPAT."
-       fi
 
-       local flags_mt=( "${impls[@]/#/python_targets_}" )
-       local flags=( "${impls[@]/#/python_single_target_}" )
-       local unflags=( "${unimpls[@]/#/-python_single_target_}" )
+       local flags_mt=( "${_PYTHON_SUPPORTED_IMPLS[@]/#/python_targets_}" )
+       local flags=( "${_PYTHON_SUPPORTED_IMPLS[@]/#/python_single_target_}" )
+       local unflags=( 
"${_PYTHON_UNSUPPORTED_IMPLS[@]/#/-python_single_target_}" )
 
        local optflags=${flags_mt[@]/%/(-)?},${unflags[@]/%/(-)}
 
        IUSE="${flags_mt[*]}"
 
-       if [[ ${#impls[@]} -eq 1 ]]; then
+       if [[ ${#_PYTHON_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
                # There is only one supported implementation; set IUSE and other
                # variables without PYTHON_SINGLE_TARGET.
                PYTHON_REQUIRED_USE="${flags_mt[*]}"
-               python_export "${impls[0]}" PYTHON_PKG_DEP
+               python_export "${_PYTHON_SUPPORTED_IMPLS[0]}" PYTHON_PKG_DEP
                PYTHON_DEPS="${PYTHON_PKG_DEP} "
                # Force on the python_single_target_* flag for this impl, so
                # that any dependencies that inherit python-single-r1 and
@@ -228,7 +212,7 @@ _python_single_set_globals() {
                # on this package.
                optflags+=,${flags[@]/%/(+)?}
 
-               for i in "${impls[@]}"; do
+               for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
                        # The chosen targets need to be in PYTHON_TARGETS as 
well.
                        # This is in order to enforce correct dependencies on 
packages
                        # supporting multiple implementations.
@@ -288,9 +272,7 @@ python_gen_usedep() {
        local impl pattern
        local matches=()
 
-       for impl in "${PYTHON_COMPAT[@]}"; do
-               _python_impl_supported "${impl}" || continue
-
+       for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
                for pattern; do
                        if [[ ${impl} == ${pattern} ]]; then
                                matches+=(
@@ -331,9 +313,7 @@ python_gen_useflags() {
        local impl pattern
        local matches=()
 
-       for impl in "${PYTHON_COMPAT[@]}"; do
-               _python_impl_supported "${impl}" || continue
-
+       for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
                for pattern; do
                        if [[ ${impl} == ${pattern} ]]; then
                                matches+=( "python_single_target_${impl}" )
@@ -380,9 +360,7 @@ python_gen_cond_dep() {
        local dep=${1}
        shift
 
-       for impl in "${PYTHON_COMPAT[@]}"; do
-               _python_impl_supported "${impl}" || continue
-
+       for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
                for pattern; do
                        if [[ ${impl} == ${pattern} ]]; then
                                # substitute ${PYTHON_USEDEP} if used
@@ -411,20 +389,15 @@ python_setup() {
 
        unset EPYTHON
 
-       local impl impls=()
-       for impl in "${PYTHON_COMPAT[@]}"; do
-               _python_impl_supported "${impl}" || continue
-               impls+=( "${impl}" )
-       done
-
-       if [[ ${#impls[@]} -eq 1 ]]; then
-               if use "python_targets_${impls[0]}"; then
+       if [[ ${#_PYTHON_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
+               if use "python_targets_${_PYTHON_SUPPORTED_IMPLS[0]}"; then
                        # Only one supported implementation, enable it 
explicitly
-                       python_export "${impls[0]}" EPYTHON PYTHON
+                       python_export "${_PYTHON_SUPPORTED_IMPLS[0]}" EPYTHON 
PYTHON
                        python_wrapper_setup
                fi
        else
-               for impl in "${impls[@]}"; do
+               local impl
+               for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
                        if use "python_single_target_${impl}"; then
                                if [[ ${EPYTHON} ]]; then
                                        eerror "Your PYTHON_SINGLE_TARGET 
setting lists more than a single Python"
@@ -452,14 +425,14 @@ python_setup() {
 
        if [[ ! ${EPYTHON} ]]; then
                eerror "No Python implementation selected for the build. Please 
set"
-               if [[ ${#impls[@]} -eq 1 ]]; then
+               if [[ ${#_PYTHON_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
                        eerror "the PYTHON_TARGETS variable in your make.conf 
to include one"
                else
                        eerror "the PYTHON_SINGLE_TARGET variable in your 
make.conf to one"
                fi
                eerror "of the following values:"
                eerror
-               eerror "${impls[@]}"
+               eerror "${_PYTHON_SUPPORTED_IMPLS[@]}"
                echo
                die "No supported Python implementation in 
PYTHON_SINGLE_TARGET/PYTHON_TARGETS."
        fi

diff --git a/eclass/python-utils-r1.eclass b/eclass/python-utils-r1.eclass
index 7830323..89a7cbf 100644
--- a/eclass/python-utils-r1.eclass
+++ b/eclass/python-utils-r1.eclass
@@ -84,6 +84,55 @@ _python_impl_supported() {
        esac
 }
 
+# @FUNCTION: _python_set_impls
+# @INTERNAL
+# @DESCRIPTION:
+# Check PYTHON_COMPAT for well-formedness and validity, then set
+# two global variables:
+#
+# - _PYTHON_SUPPORTED_IMPLS containing valid implementations supported
+#   by the ebuild (PYTHON_COMPAT - dead implementations),
+#
+# - and _PYTHON_UNSUPPORTED_IMPLS containing valid implementations that
+#   are not supported by the ebuild.
+#
+# Implementations in both variables are ordered using the pre-defined
+# eclass implementation ordering.
+#
+# This function must be called once in global scope by an eclass
+# utilizing PYTHON_COMPAT.
+_python_set_impls() {
+       local i
+
+       if ! declare -p PYTHON_COMPAT &>/dev/null; then
+               die 'PYTHON_COMPAT not declared.'
+       fi
+       if [[ $(declare -p PYTHON_COMPAT) != "declare -a"* ]]; then
+               die 'PYTHON_COMPAT must be an array.'
+       fi
+       for i in "${PYTHON_COMPAT[@]}"; do
+               # trigger validity checks
+               _python_impl_supported "${i}"
+       done
+
+       _PYTHON_SUPPORTED_IMPLS=()
+       _PYTHON_UNSUPPORTED_IMPLS=()
+
+       for i in "${_PYTHON_ALL_IMPLS[@]}"; do
+               if has "${i}" "${PYTHON_COMPAT[@]}"; then
+                       _PYTHON_SUPPORTED_IMPLS+=( "${i}" )
+               else
+                       _PYTHON_UNSUPPORTED_IMPLS+=( "${i}" )
+               fi
+       done
+
+       if [[ ${#_PYTHON_SUPPORTED_IMPLS[@]} -eq 0 ]]; then
+               die "No supported implementation in PYTHON_COMPAT."
+       fi
+
+       readonly _PYTHON_SUPPORTED_IMPLS _PYTHON_UNSUPPORTED_IMPLS
+}
+
 # @ECLASS-VARIABLE: PYTHON
 # @DEFAULT_UNSET
 # @DESCRIPTION:

Reply via email to