From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 14BE515808B for ; Thu, 10 Feb 2022 08:54:15 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 7C440E0863; Thu, 10 Feb 2022 08:54:13 +0000 (UTC) Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id C185DE0863 for ; Thu, 10 Feb 2022 08:54:11 +0000 (UTC) Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 26CAD343044 for ; Thu, 10 Feb 2022 08:54:10 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 9DFA2D0 for ; Thu, 10 Feb 2022 08:54:08 +0000 (UTC) From: "Fabian Groffen" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Fabian Groffen" Message-ID: <1644483244.7497d1d744af477e3c34862ad9e2c068d66c379d.grobian@gentoo> Subject: [gentoo-commits] repo/proj/prefix:master commit in: eclass/ X-VCS-Repository: repo/proj/prefix X-VCS-Files: eclass/python-utils-r1.eclass X-VCS-Directories: eclass/ X-VCS-Committer: grobian X-VCS-Committer-Name: Fabian Groffen X-VCS-Revision: 7497d1d744af477e3c34862ad9e2c068d66c379d X-VCS-Branch: master Date: Thu, 10 Feb 2022 08:54:08 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 189146da-eec1-4bc7-a19b-798c3c44e10e X-Archives-Hash: 09fce184bd05ee3dd7500fd9c468a43c commit: 7497d1d744af477e3c34862ad9e2c068d66c379d Author: Fabian Groffen gentoo org> AuthorDate: Thu Feb 10 08:54:04 2022 +0000 Commit: Fabian Groffen gentoo org> CommitDate: Thu Feb 10 08:54:04 2022 +0000 URL: https://gitweb.gentoo.org/repo/proj/prefix.git/commit/?id=7497d1d7 eclass/python-utils-r1: sync with gx86 Signed-off-by: Fabian Groffen gentoo.org> eclass/python-utils-r1.eclass | 224 ++++++++++++++++++++++++------------------ 1 file changed, 126 insertions(+), 98 deletions(-) diff --git a/eclass/python-utils-r1.eclass b/eclass/python-utils-r1.eclass index 53a305f40e..8c29a02090 100644 --- a/eclass/python-utils-r1.eclass +++ b/eclass/python-utils-r1.eclass @@ -82,7 +82,11 @@ _python_verify_patterns() { local impl pattern for pattern; do - [[ ${pattern} == -[23] ]] && continue + case ${pattern} in + -[23]|3.[89]|3.10) + continue + ;; + esac for impl in "${_PYTHON_ALL_IMPLS[@]}" "${_PYTHON_HISTORICAL_IMPLS[@]}" do @@ -119,6 +123,8 @@ _python_set_impls() { if [[ $(declare -p PYTHON_COMPAT) != "declare -a"* ]]; then die 'PYTHON_COMPAT must be an array.' fi + + local obsolete=() if [[ ! ${PYTHON_COMPAT_NO_STRICT} ]]; then for i in "${PYTHON_COMPAT[@]}"; do # check for incorrect implementations @@ -126,7 +132,10 @@ _python_set_impls() { # please keep them in sync with _PYTHON_ALL_IMPLS # and _PYTHON_HISTORICAL_IMPLS case ${i} in - jython2_7|pypy|pypy1_[89]|pypy2_0|pypy3|python2_[5-7]|python3_[1-9]|python3_10) + pypy3|python2_7|python3_[89]|python3_10) + ;; + jython2_7|pypy|pypy1_[89]|pypy2_0|python2_[5-6]|python3_[1-7]) + obsolete+=( "${i}" ) ;; *) if has "${i}" "${_PYTHON_ALL_IMPLS[@]}" \ @@ -140,6 +149,17 @@ _python_set_impls() { done fi + if [[ -n ${obsolete[@]} && ${EBUILD_PHASE} == setup ]]; then + # complain if people don't clean up old impls while touching + # the ebuilds recently. use the copyright year to infer last + # modification + # NB: this check doesn't have to work reliably + if [[ $(head -n 1 "${EBUILD}" 2>/dev/null) == *2022* ]]; then + eqawarn "Please clean PYTHON_COMPAT of obsolete implementations:" + eqawarn " ${obsolete[*]}" + fi + fi + local supp=() unsupp=() for i in "${_PYTHON_ALL_IMPLS[@]}"; do @@ -190,12 +210,14 @@ _python_set_impls() { # Matches if no patterns are provided. # # can be in PYTHON_COMPAT or EPYTHON form. The patterns -# are fnmatch-style. +# can either be fnmatch-style or stdlib versions, e.g. "3.8", "3.9". +# In the latter case, pypy3 will match if there is at least one pypy3 +# version matching the stdlib version. _python_impl_matches() { [[ ${#} -ge 1 ]] || die "${FUNCNAME}: takes at least 1 parameter" [[ ${#} -eq 1 ]] && return 0 - local impl=${1} pattern + local impl=${1/./_} pattern shift for pattern; do @@ -218,9 +240,17 @@ _python_impl_matches() { fi return 0 ;; + 3.8) + # the only unmasked pypy3 version is pypy3.8 atm + [[ ${impl} == python${pattern/./_} || ${impl} == pypy3 ]] && + return 0 + ;; + 3.9|3.10) + [[ ${impl} == python${pattern/./_} ]] && return 0 + ;; *) # unify value style to allow lax matching - [[ ${impl/./_} == ${pattern/./_} ]] && return 0 + [[ ${impl} == ${pattern/./_} ]] && return 0 ;; esac done @@ -266,23 +296,6 @@ _python_impl_matches() { # python2.7 # @CODE -# @FUNCTION: python_export -# @USAGE: [] ... -# @INTERNAL -# @DESCRIPTION: -# Backwards compatibility function. The relevant API is now considered -# private, please use python_get* instead. -python_export() { - debug-print-function ${FUNCNAME} "${@}" - - eqawarn "python_export() is part of private eclass API." - eqawarn "Please call python_get*() instead." - - [[ ${EAPI} == [67] ]] || die "${FUNCNAME} banned in EAPI ${EAPI}" - - _python_export "${@}" -} - # @FUNCTION: _python_export # @USAGE: [] ... # @INTERNAL @@ -353,13 +366,23 @@ _python_export() { ;; PYTHON_SITEDIR) [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it" - PYTHON_SITEDIR=$("${PYTHON}" -c 'import sysconfig; print(sysconfig.get_path("purelib"))') || die + PYTHON_SITEDIR=$( + "${PYTHON}" - <<-EOF || die + import sysconfig + print(sysconfig.get_path("purelib")) + EOF + ) export PYTHON_SITEDIR debug-print "${FUNCNAME}: PYTHON_SITEDIR = ${PYTHON_SITEDIR}" ;; PYTHON_INCLUDEDIR) [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it" - PYTHON_INCLUDEDIR=$("${PYTHON}" -c 'import sysconfig; print(sysconfig.get_path("platinclude"))') || die + PYTHON_INCLUDEDIR=$( + "${PYTHON}" - <<-EOF || die + import sysconfig + print(sysconfig.get_path("platinclude")) + EOF + ) export PYTHON_INCLUDEDIR debug-print "${FUNCNAME}: PYTHON_INCLUDEDIR = ${PYTHON_INCLUDEDIR}" @@ -370,7 +393,17 @@ _python_export() { ;; PYTHON_LIBPATH) [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it" - PYTHON_LIBPATH=$("${PYTHON}" -c 'import os.path, sysconfig; print(os.path.join(sysconfig.get_config_var("LIBDIR"), sysconfig.get_config_var("LDLIBRARY")) if sysconfig.get_config_var("LDLIBRARY") else "")') || die + PYTHON_LIBPATH=$( + "${PYTHON}" - <<-EOF || die + import os.path, sysconfig + print( + os.path.join( + sysconfig.get_config_var("LIBDIR"), + sysconfig.get_config_var("LDLIBRARY")) + if sysconfig.get_config_var("LDLIBRARY") + else "") + EOF + ) export PYTHON_LIBPATH debug-print "${FUNCNAME}: PYTHON_LIBPATH = ${PYTHON_LIBPATH}" @@ -420,7 +453,13 @@ _python_export() { case "${impl}" in python*) [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it" - flags=$("${PYTHON}" -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS") or "")') || die + flags=$( + "${PYTHON}" - <<-EOF || die + import sysconfig + print(sysconfig.get_config_var("ABIFLAGS") + or "") + EOF + ) val=${PYTHON}${flags}-config ;; *) @@ -437,9 +476,9 @@ _python_export() { python2.7) PYTHON_PKG_DEP='>=dev-lang/python-2.7.5-r2:2.7';; python3.8) - PYTHON_PKG_DEP=">=dev-lang/python-3.8.8_p1-r1:3.8";; + PYTHON_PKG_DEP=">=dev-lang/python-3.8.12_p1-r1:3.8";; python3.9) - PYTHON_PKG_DEP=">=dev-lang/python-3.9.6_p1-r1:3.9";; + PYTHON_PKG_DEP=">=dev-lang/python-3.9.9-r1:3.9";; python3.10) PYTHON_PKG_DEP=">=dev-lang/python-3.10.0_p1-r1:3.10";; python*) @@ -447,7 +486,7 @@ _python_export() { pypy) PYTHON_PKG_DEP='>=dev-python/pypy-7.3.0:0=';; pypy3) - PYTHON_PKG_DEP='>=dev-python/pypy3-7.3.0:0=';; + PYTHON_PKG_DEP='>=dev-python/pypy3-7.3.7-r1:0=';; *) die "Invalid implementation: ${impl}" esac @@ -592,15 +631,6 @@ python_get_scriptdir() { python_optimize() { debug-print-function ${FUNCNAME} "${@}" - if [[ ${EBUILD_PHASE} == pre* || ${EBUILD_PHASE} == post* ]]; then - eerror "The new Python eclasses expect the compiled Python files to" - eerror "be controlled by the Package Manager. For this reason," - eerror "the python_optimize function can be used only during src_* phases" - eerror "(src_install most commonly) and not during pkg_* phases." - echo - die "python_optimize is not to be used in pre/post* phases" - fi - [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).' local PYTHON=${PYTHON} @@ -619,7 +649,12 @@ python_optimize() { if [[ ${f} == /* && -d ${D%/}${f} ]]; then set -- "${D%/}${f}" "${@}" fi - done < <("${PYTHON}" -c 'import sys; print("".join(x + "\0" for x in sys.path))' || die) + done < <( + "${PYTHON}" - <<-EOF || die + import sys + print("".join(x + "\0" for x in sys.path)) + EOF + ) debug-print "${FUNCNAME}: using sys.path: ${*/%/;}" fi @@ -633,6 +668,7 @@ python_optimize() { local instpath=${d#${D%/}} instpath=/${instpath##/} + einfo "Optimize Python modules for ${instpath}" case "${EPYTHON}" in python2.7|python3.[34]) "${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}" @@ -714,9 +750,8 @@ python_newexe() { local f=${1} local newfn=${2} - local PYTHON_SCRIPTDIR d - _python_export PYTHON_SCRIPTDIR PYTHON_EPREFIX - d=${PYTHON_SCRIPTDIR#${PYTHON_EPREFIX}} + local scriptdir=$(python_get_scriptdir) + local d=${scriptdir#${EPREFIX}} ( dodir "${wrapd}" @@ -884,22 +919,6 @@ python_doheader() { ) } -# @FUNCTION: python_wrapper_setup -# @USAGE: [ []] -# @DESCRIPTION: -# Backwards compatibility function. The relevant API is now considered -# private, please use python_setup instead. -python_wrapper_setup() { - debug-print-function ${FUNCNAME} "${@}" - - eqawarn "python_wrapper_setup() is part of private eclass API." - eqawarn "Please call python_setup() instead." - - [[ ${EAPI} == [67] ]] || die "${FUNCNAME} banned in EAPI ${EAPI}" - - _python_wrapper_setup "${@}" -} - # @FUNCTION: _python_wrapper_setup # @USAGE: [ []] # @INTERNAL @@ -1007,41 +1026,6 @@ _python_wrapper_setup() { export PATH PKG_CONFIG_PATH } -# @FUNCTION: python_is_python3 -# @USAGE: [] -# @DESCRIPTION: -# Check whether (or ${EPYTHON}) is a Python3k variant -# (i.e. uses syntax and stdlib of Python 3.*). -# -# Returns 0 (true) if it is, 1 (false) otherwise. -python_is_python3() { - eqawarn "${FUNCNAME} is deprecated, as Python 2 is not supported anymore" - [[ ${EAPI} == [67] ]] || die "${FUNCNAME} banned in EAPI ${EAPI}" - - local impl=${1:-${EPYTHON}} - [[ ${impl} ]] || die "python_is_python3: no impl nor EPYTHON" - - [[ ${impl} == python3* || ${impl} == pypy3 ]] -} - -# @FUNCTION: python_is_installed -# @USAGE: [] -# @DESCRIPTION: -# Check whether the interpreter for (or ${EPYTHON}) is installed. -# Uses has_version with a proper dependency string. -# -# Returns 0 (true) if it is, 1 (false) otherwise. -python_is_installed() { - local impl=${1:-${EPYTHON}} - [[ ${impl} ]] || die "${FUNCNAME}: no impl nor EPYTHON" - local hasv_args=( -b ) - [[ ${EAPI} == 6 ]] && hasv_args=( --host-root ) - - local PYTHON_PKG_DEP - _python_export "${impl}" PYTHON_PKG_DEP - has_version "${hasv_args[@]}" "${PYTHON_PKG_DEP}" -} - # @FUNCTION: python_fix_shebang # @USAGE: [-f|--force] [-q|--quiet] ... # @DESCRIPTION: @@ -1222,7 +1206,7 @@ python_export_utf8_locale() { debug-print-function ${FUNCNAME} "${@}" # If the locale program isn't available, just return. - type locale >/dev/null || return 0 + type locale &>/dev/null || return 0 if [[ $(locale charmap) != UTF-8 ]]; then # Try English first, then everything else. @@ -1278,10 +1262,24 @@ build_sphinx() { sed -i -e 's:^intersphinx_mapping:disabled_&:' \ "${dir}"/conf.py || die - # not all packages include the Makefile in pypi tarball - "${EPYTHON}" -m sphinx.cmd.build \ - -b html -d "${dir}"/_build/doctrees "${dir}" \ - "${dir}"/_build/html || die + # 1. not all packages include the Makefile in pypi tarball, + # so we call sphinx-build directly + # 2. if autodoc is used, we need to call sphinx via EPYTHON, + # to ensure that PEP 517 venv is respected + # 3. if autodoc is not used, then sphinx might not be installed + # for the current impl, so we need a fallback to sphinx-build + local command=( "${EPYTHON}" -m sphinx.cmd.build ) + if ! "${EPYTHON}" -c "import sphinx.cmd.build" 2>/dev/null; then + command=( sphinx-build ) + fi + command+=( + -b html + -d "${dir}"/_build/doctrees + "${dir}" + "${dir}"/_build/html + ) + echo "${command[@]}" >&2 + "${command[@]}" || die HTML_DOCS+=( "${dir}/_build/html/." ) } @@ -1397,5 +1395,35 @@ eunittest() { return ${?} } +# @FUNCTION: _python_run_check_deps +# @INTERNAL +# @USAGE: +# @DESCRIPTION: +# Verify whether is an acceptable choice to run any-r1 style +# code. Checks whether the interpreter is installed, runs +# python_check_deps() if declared. +_python_run_check_deps() { + debug-print-function ${FUNCNAME} "${@}" + + local impl=${1} + local hasv_args=( -b ) + [[ ${EAPI} == 6 ]] && hasv_args=( --host-root ) + + einfo "Checking whether ${impl} is suitable ..." + + local PYTHON_PKG_DEP + _python_export "${impl}" PYTHON_PKG_DEP + ebegin " ${PYTHON_PKG_DEP}" + has_version "${hasv_args[@]}" "${PYTHON_PKG_DEP}" + eend ${?} || return 1 + declare -f python_check_deps >/dev/null || return 0 + + local PYTHON_USEDEP="python_targets_${impl}(-)" + local PYTHON_SINGLE_USEDEP="python_single_target_${impl}(-)" + ebegin " python_check_deps" + python_check_deps + eend ${?} +} + _PYTHON_UTILS_R1=1 fi