eclass/distutils-r1: Sync with Gentoo

It's from Gentoo commit f162bdec61704b860c8c3be2c4ab44980165876d.
This commit is contained in:
Krzesimir Nowak 2023-01-24 10:40:49 +01:00
parent af7fce8f1f
commit c984495f87

View File

@ -1,4 +1,4 @@
# Copyright 1999-2022 Gentoo Authors # Copyright 1999-2023 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
# @ECLASS: distutils-r1.eclass # @ECLASS: distutils-r1.eclass
@ -7,7 +7,7 @@
# @AUTHOR: # @AUTHOR:
# Author: Michał Górny <mgorny@gentoo.org> # Author: Michał Górny <mgorny@gentoo.org>
# Based on the work of: Krzysztof Pawlik <nelchael@gentoo.org> # Based on the work of: Krzysztof Pawlik <nelchael@gentoo.org>
# @SUPPORTED_EAPIS: 6 7 8 # @SUPPORTED_EAPIS: 7 8
# @PROVIDES: python-r1 python-single-r1 # @PROVIDES: python-r1 python-single-r1
# @BLURB: A simple eclass to build Python packages using distutils. # @BLURB: A simple eclass to build Python packages using distutils.
# @DESCRIPTION: # @DESCRIPTION:
@ -44,15 +44,9 @@
# For more information, please see the Python Guide: # For more information, please see the Python Guide:
# https://projects.gentoo.org/python/guide/ # https://projects.gentoo.org/python/guide/
case "${EAPI:-0}" in case ${EAPI:-0} in
[0-5]) 7|8) ;;
die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}" *) die "EAPI=${EAPI:-0} not supported";;
;;
[6-8])
;;
*)
die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
;;
esac esac
# @ECLASS_VARIABLE: DISTUTILS_OPTIONAL # @ECLASS_VARIABLE: DISTUTILS_OPTIONAL
@ -106,6 +100,10 @@ esac
# #
# - maturin - maturin backend # - maturin - maturin backend
# #
# - meson-python - meson-python (mesonpy) backend
#
# - no - no PEP517 build system (see below)
#
# - pbr - pbr backend # - pbr - pbr backend
# #
# - pdm - pdm.pep517 backend # - pdm - pdm.pep517 backend
@ -121,6 +119,17 @@ esac
# #
# The variable needs to be set before the inherit line. The eclass # The variable needs to be set before the inherit line. The eclass
# adds appropriate build-time dependencies and verifies the value. # adds appropriate build-time dependencies and verifies the value.
#
# The special value "no" indicates that the package has no build system.
# This is not equivalent to unset DISTUTILS_USE_PEP517 (legacy mode).
# It causes the eclass not to include any build system dependencies
# and to disable default python_compile() and python_install()
# implementations. Baseline Python deps and phase functions will still
# be set (depending on the value of DISTUTILS_OPTIONAL). Most of
# the other eclass functions will work. Testing venv will be provided
# in ${BUILD_DIR}/install after python_compile(), and if any (other)
# files are found in ${BUILD_DIR}/install after python_install(), they
# will be merged into ${D}.
# @ECLASS_VARIABLE: DISTUTILS_USE_SETUPTOOLS # @ECLASS_VARIABLE: DISTUTILS_USE_SETUPTOOLS
# @DEFAULT_UNSET # @DEFAULT_UNSET
@ -135,9 +144,6 @@ esac
# #
# - rdepend -- add it to BDEPEND+RDEPEND (e.g. when using pkg_resources) # - rdepend -- add it to BDEPEND+RDEPEND (e.g. when using pkg_resources)
# #
# - pyproject.toml -- use pyproject2setuptools to install a project
# using pyproject.toml (flit, poetry...)
#
# - manual -- do not add the dependency and suppress the checks # - manual -- do not add the dependency and suppress the checks
# (assumes you will take care of doing it correctly) # (assumes you will take care of doing it correctly)
# #
@ -165,8 +171,7 @@ esac
if [[ ! ${_DISTUTILS_R1} ]]; then if [[ ! ${_DISTUTILS_R1} ]]; then
[[ ${EAPI} == 6 ]] && inherit eutils xdg-utils inherit multibuild multilib multiprocessing ninja-utils toolchain-funcs
inherit multibuild multiprocessing toolchain-funcs
if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
inherit python-r1 inherit python-r1
@ -190,48 +195,74 @@ _distutils_set_globals() {
fi fi
bdep=' bdep='
>=dev-python/gpep517-3[${PYTHON_USEDEP}]' >=dev-python/gpep517-13[${PYTHON_USEDEP}]
'
case ${DISTUTILS_USE_PEP517} in case ${DISTUTILS_USE_PEP517} in
flit) flit)
bdep+=' bdep+='
>=dev-python/flit_core-3.7.1[${PYTHON_USEDEP}]' >=dev-python/flit_core-3.8.0[${PYTHON_USEDEP}]
'
;; ;;
flit_scm) flit_scm)
bdep+=' bdep+='
dev-python/flit_scm[${PYTHON_USEDEP}]' >=dev-python/flit_scm-1.7.0[${PYTHON_USEDEP}]
'
;; ;;
hatchling) hatchling)
bdep+=' bdep+='
>=dev-python/hatchling-0.22.0[${PYTHON_USEDEP}]' >=dev-python/hatchling-1.12.2[${PYTHON_USEDEP}]
'
;; ;;
jupyter) jupyter)
bdep+=' bdep+='
>=dev-python/jupyter_packaging-0.11.1[${PYTHON_USEDEP}]' >=dev-python/jupyter_packaging-0.12.3[${PYTHON_USEDEP}]
'
;; ;;
maturin) maturin)
bdep+=' bdep+='
>=dev-util/maturin-0.12.7[${PYTHON_USEDEP}]' >=dev-util/maturin-0.14.10[${PYTHON_USEDEP}]
'
;;
no)
# undo the generic deps added above
bdep=
;;
meson-python)
bdep+='
>=dev-python/meson-python-0.12.0[${PYTHON_USEDEP}]
'
;; ;;
pbr) pbr)
bdep+=' bdep+='
>=dev-python/pbr-5.8.0-r1[${PYTHON_USEDEP}]' >=dev-python/pbr-5.11.1[${PYTHON_USEDEP}]
'
;; ;;
pdm) pdm)
bdep+=' bdep+='
>=dev-python/pdm-pep517-0.12.3[${PYTHON_USEDEP}]' >=dev-python/pdm-pep517-1.0.6[${PYTHON_USEDEP}]
'
;; ;;
poetry) poetry)
bdep+=' bdep+='
>=dev-python/poetry-core-1.0.8[${PYTHON_USEDEP}]' >=dev-python/poetry-core-1.4.0[${PYTHON_USEDEP}]
'
;; ;;
setuptools) setuptools)
# || ( ... ) dep is a workaround for bug #892525
# It can be removed once >=67.2.0 is stable and replaced with
# a simple >=67.2.0 dep.
bdep+=' bdep+='
>=dev-python/setuptools-60.5.0[${PYTHON_USEDEP}] || (
dev-python/wheel[${PYTHON_USEDEP}]' >=dev-python/setuptools-67.2.0[${PYTHON_USEDEP}]
<dev-python/setuptools-65.7.1[${PYTHON_USEDEP}]
)
>=dev-python/wheel-0.38.4[${PYTHON_USEDEP}]
'
;; ;;
sip) sip)
bdep+=' bdep+='
>=dev-python/sip-6.5.0-r1[${PYTHON_USEDEP}]' >=dev-python/sip-6.7.5-r1[${PYTHON_USEDEP}]
'
;; ;;
standalone) standalone)
;; ;;
@ -245,7 +276,7 @@ _distutils_set_globals() {
eqawarn "is enabled." eqawarn "is enabled."
fi fi
else else
local setuptools_dep='>=dev-python/setuptools-42.0.2[${PYTHON_USEDEP}]' local setuptools_dep='>=dev-python/setuptools-65.7.0[${PYTHON_USEDEP}]'
case ${DISTUTILS_USE_SETUPTOOLS:-bdepend} in case ${DISTUTILS_USE_SETUPTOOLS:-bdepend} in
no|manual) no|manual)
@ -258,7 +289,7 @@ _distutils_set_globals() {
rdep+=" ${setuptools_dep}" rdep+=" ${setuptools_dep}"
;; ;;
pyproject.toml) pyproject.toml)
bdep+=' >=dev-python/pyproject2setuppy-22[${PYTHON_USEDEP}]' die "DISTUTILS_USE_SETUPTOOLS=pyproject.toml is no longer supported, use DISTUTILS_USE_PEP517"
;; ;;
*) *)
die "Invalid DISTUTILS_USE_SETUPTOOLS=${DISTUTILS_USE_SETUPTOOLS}" die "Invalid DISTUTILS_USE_SETUPTOOLS=${DISTUTILS_USE_SETUPTOOLS}"
@ -290,11 +321,7 @@ _distutils_set_globals() {
if [[ ! ${DISTUTILS_OPTIONAL} ]]; then if [[ ! ${DISTUTILS_OPTIONAL} ]]; then
RDEPEND="${PYTHON_DEPS} ${rdep}" RDEPEND="${PYTHON_DEPS} ${rdep}"
if [[ ${EAPI} != 6 ]]; then
BDEPEND="${PYTHON_DEPS} ${bdep}" BDEPEND="${PYTHON_DEPS} ${bdep}"
else
DEPEND="${PYTHON_DEPS} ${bdep}"
fi
REQUIRED_USE=${PYTHON_REQUIRED_USE} REQUIRED_USE=${PYTHON_REQUIRED_USE}
fi fi
} }
@ -450,7 +477,7 @@ distutils_enable_sphinx() {
_DISTUTILS_SPHINX_PLUGINS=( "${@}" ) _DISTUTILS_SPHINX_PLUGINS=( "${@}" )
local deps autodoc=1 d local deps autodoc=1 d
deps=">=dev-python/sphinx-4.4.0[\${PYTHON_USEDEP}]" deps=">=dev-python/sphinx-5.3.0[\${PYTHON_USEDEP}]"
for d; do for d; do
if [[ ${d} == --no-autodoc ]]; then if [[ ${d} == --no-autodoc ]]; then
autodoc= autodoc=
@ -474,7 +501,7 @@ distutils_enable_sphinx() {
use doc || return 0 use doc || return 0
local p local p
for p in ">=dev-python/sphinx-4.4.0" \ for p in ">=dev-python/sphinx-5.3.0" \
"${_DISTUTILS_SPHINX_PLUGINS[@]}" "${_DISTUTILS_SPHINX_PLUGINS[@]}"
do do
python_has_version "${p}[${PYTHON_USEDEP}]" || python_has_version "${p}[${PYTHON_USEDEP}]" ||
@ -482,7 +509,7 @@ distutils_enable_sphinx() {
done done
} }
else else
deps=">=dev-python/sphinx-4.4.0" deps=">=dev-python/sphinx-5.3.0"
fi fi
sphinx_compile_all() { sphinx_compile_all() {
@ -507,11 +534,7 @@ distutils_enable_sphinx() {
python_compile_all() { sphinx_compile_all; } python_compile_all() { sphinx_compile_all; }
IUSE+=" doc" IUSE+=" doc"
if [[ ${EAPI} == 6 ]]; then
DEPEND+=" doc? ( ${deps} )"
else
BDEPEND+=" doc? ( ${deps} )" BDEPEND+=" doc? ( ${deps} )"
fi
# we need to ensure successful return in case we're called last, # we need to ensure successful return in case we're called last,
# otherwise Portage may wrongly assume sourcing failed # otherwise Portage may wrongly assume sourcing failed
@ -562,10 +585,10 @@ distutils_enable_tests() {
local test_pkg local test_pkg
case ${1} in case ${1} in
nose) nose)
test_pkg=">=dev-python/nose-1.3.7-r4" test_pkg=">=dev-python/nose-1.3.7_p20221026"
;; ;;
pytest) pytest)
test_pkg=">=dev-python/pytest-7.0.1" test_pkg=">=dev-python/pytest-7.2.1"
;; ;;
setup.py) setup.py)
;; ;;
@ -592,12 +615,8 @@ distutils_enable_tests() {
if [[ -n ${test_deps} ]]; then if [[ -n ${test_deps} ]]; then
IUSE+=" test" IUSE+=" test"
RESTRICT+=" !test? ( test )" RESTRICT+=" !test? ( test )"
if [[ ${EAPI} == 6 ]]; then
DEPEND+=" test? ( ${test_deps} )"
else
BDEPEND+=" test? ( ${test_deps} )" BDEPEND+=" test? ( ${test_deps} )"
fi fi
fi
# we need to ensure successful return in case we're called last, # we need to ensure successful return in case we're called last,
# otherwise Portage may wrongly assume sourcing failed # otherwise Portage may wrongly assume sourcing failed
@ -611,8 +630,11 @@ distutils_enable_tests() {
# (if ${EPYTHON} is set; fallback 'python' otherwise). # (if ${EPYTHON} is set; fallback 'python' otherwise).
# #
# setup.py will be passed the following, in order: # setup.py will be passed the following, in order:
#
# 1. ${DISTUTILS_ARGS[@]} # 1. ${DISTUTILS_ARGS[@]}
#
# 2. ${mydistutilsargs[@]} (deprecated) # 2. ${mydistutilsargs[@]} (deprecated)
#
# 3. additional arguments passed to the esetup.py function. # 3. additional arguments passed to the esetup.py function.
# #
# Please note that setup.py will respect defaults (unless overridden # Please note that setup.py will respect defaults (unless overridden
@ -630,16 +652,20 @@ esetup.py() {
fi fi
local setup_py=( setup.py ) local setup_py=( setup.py )
if [[ ${DISTUTILS_USE_SETUPTOOLS} == pyproject.toml ]]; then if [[ ! -f setup.py ]]; then
setup_py=( -m pyproject2setuppy ) # The following call can succeed even if the package does not
elif [[ ! -f setup.py ]]; then # feature any setuptools configuration. In non-PEP517 mode this
if [[ ! -f setup.cfg ]]; then # could lead to installing an "empty" package. In PEP517 mode,
# we verify the build system when invoking the backend,
# rendering this check redundant (and broken for projects using
# pyproject.toml configuration).
if [[ ! ${DISTUTILS_USE_PEP517} && ! -f setup.cfg ]]; then
die "${FUNCNAME}: setup.py nor setup.cfg not found" die "${FUNCNAME}: setup.py nor setup.cfg not found"
fi fi
setup_py=( -c "from setuptools import setup; setup()" ) setup_py=( -c "from setuptools import setup; setup()" )
fi fi
if [[ ${EAPI} != [67] && ${mydistutilsargs[@]} ]]; then if [[ ${EAPI} != 7 && ${mydistutilsargs[@]} ]]; then
die "mydistutilsargs is banned in EAPI ${EAPI} (use DISTUTILS_ARGS)" die "mydistutilsargs is banned in EAPI ${EAPI} (use DISTUTILS_ARGS)"
fi fi
@ -690,8 +716,8 @@ esetup.py() {
# to unmerge the package first. # to unmerge the package first.
# #
# This function is not available in PEP517 mode. The eclass provides # This function is not available in PEP517 mode. The eclass provides
# a venv-style install unconditionally therefore, and therefore it # a venv-style install unconditionally and therefore it should no longer
# should no longer be necessary. # be necessary.
distutils_install_for_testing() { distutils_install_for_testing() {
debug-print-function ${FUNCNAME} "${@}" debug-print-function ${FUNCNAME} "${@}"
@ -711,7 +737,7 @@ distutils_install_for_testing() {
local install_method=root local install_method=root
case ${1} in case ${1} in
--via-home) --via-home)
[[ ${EAPI} == [67] ]] || die "${*} is banned in EAPI ${EAPI}" [[ ${EAPI} == 7 ]] || die "${*} is banned in EAPI ${EAPI}"
install_method=home install_method=home
shift shift
;; ;;
@ -789,7 +815,7 @@ distutils_install_for_testing() {
distutils_write_namespace() { distutils_write_namespace() {
debug-print-function ${FUNCNAME} "${@}" debug-print-function ${FUNCNAME} "${@}"
if [[ ! ${DISTUTILS_USE_PEP517} ]]; then if [[ ! ${DISTUTILS_USE_PEP517:-no} != no ]]; then
die "${FUNCNAME} is available only in PEP517 mode" die "${FUNCNAME} is available only in PEP517 mode"
fi fi
if [[ ${EBUILD_PHASE} != test || ! ${BUILD_DIR} ]]; then if [[ ${EBUILD_PHASE} != test || ! ${BUILD_DIR} ]]; then
@ -835,7 +861,8 @@ _distutils-r1_disable_ez_setup() {
# @FUNCTION: _distutils-r1_handle_pyproject_toml # @FUNCTION: _distutils-r1_handle_pyproject_toml
# @INTERNAL # @INTERNAL
# @DESCRIPTION: # @DESCRIPTION:
# Generate setup.py for pyproject.toml if requested. # Verify whether DISTUTILS_USE_SETUPTOOLS is set correctly
# for pyproject.toml build systems (in non-PEP517 mode).
_distutils-r1_handle_pyproject_toml() { _distutils-r1_handle_pyproject_toml() {
if [[ ${DISTUTILS_USE_PEP517} ]]; then if [[ ${DISTUTILS_USE_PEP517} ]]; then
die "${FUNCNAME} is not implemented in PEP517 mode" die "${FUNCNAME} is not implemented in PEP517 mode"
@ -844,12 +871,10 @@ _distutils-r1_handle_pyproject_toml() {
[[ ${DISTUTILS_USE_SETUPTOOLS} == manual ]] && return [[ ${DISTUTILS_USE_SETUPTOOLS} == manual ]] && return
if [[ ! -f setup.py && -f pyproject.toml ]]; then if [[ ! -f setup.py && -f pyproject.toml ]]; then
if [[ ${DISTUTILS_USE_SETUPTOOLS} != pyproject.toml ]]; then eerror "No setup.py found but pyproject.toml is present. Please migrate"
eerror "No setup.py found but pyproject.toml is present. In order to enable" eerror "the package to use DISTUTILS_USE_PEP517. See:"
eerror "pyproject.toml support in distutils-r1, set:" eerror " https://projects.gentoo.org/python/guide/distutils.html"
eerror " DISTUTILS_USE_SETUPTOOLS=pyproject.toml" die "No setup.py found and PEP517 mode not enabled"
die "No setup.py found and DISTUTILS_USE_SETUPTOOLS!=pyproject.toml"
fi
fi fi
} }
@ -863,7 +888,7 @@ _distutils-r1_check_all_phase_mismatch() {
eqawarn "QA Notice: distutils-r1_python_${EBUILD_PHASE}_all called" eqawarn "QA Notice: distutils-r1_python_${EBUILD_PHASE}_all called"
eqawarn "from python_${EBUILD_PHASE}. Did you mean to use" eqawarn "from python_${EBUILD_PHASE}. Did you mean to use"
eqawarn "python_${EBUILD_PHASE}_all()?" eqawarn "python_${EBUILD_PHASE}_all()?"
[[ ${EAPI} != [67] ]] && [[ ${EAPI} != 7 ]] &&
die "distutils-r1_python_${EBUILD_PHASE}_all called from python_${EBUILD_PHASE}." die "distutils-r1_python_${EBUILD_PHASE}_all called from python_${EBUILD_PHASE}."
fi fi
} }
@ -897,6 +922,8 @@ _distutils-r1_print_package_versions() {
hatchling) hatchling)
packages+=( packages+=(
dev-python/hatchling dev-python/hatchling
dev-python/hatch-fancy-pypi-readme
dev-python/hatch-vcs
) )
;; ;;
jupyter) jupyter)
@ -912,6 +939,14 @@ _distutils-r1_print_package_versions() {
dev-util/maturin dev-util/maturin
) )
;; ;;
no)
return
;;
meson-python)
packages+=(
dev-python/meson-python
)
;;
pbr) pbr)
packages+=( packages+=(
dev-python/pbr dev-python/pbr
@ -959,7 +994,7 @@ _distutils-r1_print_package_versions() {
local pkg local pkg
einfo "Build system packages:" einfo "Build system packages:"
for pkg in "${packages[@]}"; do for pkg in "${packages[@]}"; do
local installed=$(best_version "${pkg}") local installed=$(best_version -b "${pkg}")
einfo " $(printf '%-30s' "${pkg}"): ${installed#${pkg}-}" einfo " $(printf '%-30s' "${pkg}"): ${installed#${pkg}-}"
done done
} }
@ -1008,7 +1043,6 @@ distutils-r1_python_prepare_all() {
fi fi
python_export_utf8_locale python_export_utf8_locale
[[ ${EAPI} == 6 ]] && xdg_environment_reset # Bug 577704
_distutils-r1_print_package_versions _distutils-r1_print_package_versions
_DISTUTILS_DEFAULT_CALLED=1 _DISTUTILS_DEFAULT_CALLED=1
@ -1114,6 +1148,9 @@ _distutils-r1_backend_to_key() {
maturin) maturin)
echo maturin echo maturin
;; ;;
mesonpy)
echo meson-python
;;
pbr.build) pbr.build)
echo pbr echo pbr
;; ;;
@ -1143,7 +1180,7 @@ _distutils-r1_backend_to_key() {
_distutils-r1_get_backend() { _distutils-r1_get_backend() {
debug-print-function ${FUNCNAME} "${@}" debug-print-function ${FUNCNAME} "${@}"
local build_backend local build_backend legacy_fallback
if [[ -f pyproject.toml ]]; then if [[ -f pyproject.toml ]]; then
# if pyproject.toml exists, try getting the backend from it # if pyproject.toml exists, try getting the backend from it
# NB: this could fail if pyproject.toml doesn't list one # NB: this could fail if pyproject.toml doesn't list one
@ -1154,6 +1191,7 @@ _distutils-r1_get_backend() {
then then
# use the legacy setuptools backend as a fallback # use the legacy setuptools backend as a fallback
build_backend=setuptools.build_meta:__legacy__ build_backend=setuptools.build_meta:__legacy__
legacy_fallback=1
fi fi
if [[ -z ${build_backend} ]]; then if [[ -z ${build_backend} ]]; then
die "Unable to obtain build-backend from pyproject.toml" die "Unable to obtain build-backend from pyproject.toml"
@ -1179,12 +1217,17 @@ _distutils-r1_get_backend() {
poetry.masonry.api) poetry.masonry.api)
new_backend=poetry.core.masonry.api new_backend=poetry.core.masonry.api
;; ;;
setuptools.build_meta:__legacy__)
# this backend should only be used as implicit fallback
[[ ! ${legacy_fallback} ]] &&
new_backend=setuptools.build_meta
;;
esac esac
if [[ -n ${new_backend} ]]; then if [[ -n ${new_backend} ]]; then
if [[ ! -f ${T}/.distutils_deprecated_backend_warned ]]; then if [[ ! -f ${T}/.distutils_deprecated_backend_warned ]]; then
eqawarn "${build_backend} backend is deprecated. Please see:" eqawarn "${build_backend} backend is deprecated. Please see:"
eqawarn "https://projects.gentoo.org/python/guide/distutils.html#deprecated-pep-517-backends" eqawarn "https://projects.gentoo.org/python/guide/qawarn.html#deprecated-pep-517-backends"
eqawarn "The eclass will be using ${new_backend} instead." eqawarn "The eclass will be using ${new_backend} instead."
> "${T}"/.distutils_deprecated_backend_warned || die > "${T}"/.distutils_deprecated_backend_warned || die
fi fi
@ -1195,6 +1238,47 @@ _distutils-r1_get_backend() {
echo "${build_backend}" echo "${build_backend}"
} }
# @FUNCTION: distutils_wheel_install
# @USAGE: <root> <wheel>
# @DESCRIPTION:
# Install the specified wheel into <root>.
#
# This function is intended for expert use only.
distutils_wheel_install() {
debug-print-function ${FUNCNAME} "${@}"
if [[ ${#} -ne 2 ]]; then
die "${FUNCNAME} takes exactly two arguments: <root> <wheel>"
fi
if [[ -z ${PYTHON} ]]; then
die "PYTHON unset, invalid call context"
fi
local root=${1}
local wheel=${2}
einfo " Installing ${wheel##*/} to ${root}"
local cmd=(
gpep517 install-wheel
--destdir="${root}"
--interpreter="${PYTHON}"
--prefix="${EPREFIX}/usr"
--optimize=all
"${wheel}"
)
printf '%s\n' "${cmd[*]}"
"${cmd[@]}" || die "Wheel install failed"
# remove installed licenses
find "${root}$(python_get_sitedir)" -depth \
\( -path '*.dist-info/COPYING*' \
-o -path '*.dist-info/LICENSE*' \
-o -path '*.dist-info/license_files/*' \
-o -path '*.dist-info/license_files' \
-o -path '*.dist-info/licenses/*' \
-o -path '*.dist-info/licenses' \
\) -delete || die
}
# @FUNCTION: distutils_pep517_install # @FUNCTION: distutils_pep517_install
# @USAGE: <root> # @USAGE: <root>
# @DESCRIPTION: # @DESCRIPTION:
@ -1207,6 +1291,10 @@ distutils_pep517_install() {
debug-print-function ${FUNCNAME} "${@}" debug-print-function ${FUNCNAME} "${@}"
[[ ${#} -eq 1 ]] || die "${FUNCNAME} takes exactly one argument: root" [[ ${#} -eq 1 ]] || die "${FUNCNAME} takes exactly one argument: root"
if [[ ! ${DISTUTILS_USE_PEP517:-no} != no ]]; then
die "${FUNCNAME} is available only in PEP517 mode"
fi
local root=${1} local root=${1}
local -x WHEEL_BUILD_DIR=${BUILD_DIR}/wheel local -x WHEEL_BUILD_DIR=${BUILD_DIR}/wheel
mkdir -p "${WHEEL_BUILD_DIR}" || die mkdir -p "${WHEEL_BUILD_DIR}" || die
@ -1216,9 +1304,29 @@ distutils_pep517_install() {
fi fi
local config_settings= local config_settings=
if [[ -n ${DISTUTILS_ARGS[@]} ]]; then
case ${DISTUTILS_USE_PEP517} in case ${DISTUTILS_USE_PEP517} in
meson-python)
local -x NINJAOPTS=$(get_NINJAOPTS)
config_settings=$(
"${EPYTHON}" - "${DISTUTILS_ARGS[@]}" <<-EOF || die
import json
import os
import shlex
import sys
ninjaopts = shlex.split(os.environ["NINJAOPTS"])
print(json.dumps({
"setup-args": sys.argv[1:],
"compile-args": [
"-v",
f"--ninja-args={ninjaopts!r}",
],
}))
EOF
)
;;
setuptools) setuptools)
if [[ -n ${DISTUTILS_ARGS[@]} ]]; then
config_settings=$( config_settings=$(
"${EPYTHON}" - "${DISTUTILS_ARGS[@]}" <<-EOF || die "${EPYTHON}" - "${DISTUTILS_ARGS[@]}" <<-EOF || die
import json import json
@ -1226,8 +1334,10 @@ distutils_pep517_install() {
print(json.dumps({"--global-option": sys.argv[1:]})) print(json.dumps({"--global-option": sys.argv[1:]}))
EOF EOF
) )
fi
;; ;;
sip) sip)
if [[ -n ${DISTUTILS_ARGS[@]} ]]; then
# NB: for practical reasons, we support only --foo=bar, # NB: for practical reasons, we support only --foo=bar,
# not --foo bar # not --foo bar
local arg local arg
@ -1250,39 +1360,35 @@ distutils_pep517_install() {
print(json.dumps(args)) print(json.dumps(args))
EOF EOF
) )
fi
;; ;;
*) *)
[[ -n ${DISTUTILS_ARGS[@]} ]] &&
die "DISTUTILS_ARGS are not supported by ${DISTUTILS_USE_PEP517}" die "DISTUTILS_ARGS are not supported by ${DISTUTILS_USE_PEP517}"
;; ;;
esac esac
fi
local build_backend=$(_distutils-r1_get_backend) local build_backend=$(_distutils-r1_get_backend)
einfo " Building the wheel for ${PWD#${WORKDIR}/} via ${build_backend}" einfo " Building the wheel for ${PWD#${WORKDIR}/} via ${build_backend}"
local config_args=() local cmd=(
[[ -n ${config_settings} ]] && gpep517 build-wheel
config_args+=( --config-json "${config_settings}" ) --backend "${build_backend}"
--output-fd 3
--wheel-dir "${WHEEL_BUILD_DIR}"
)
if [[ -n ${config_settings} ]]; then
cmd+=( --config-json "${config_settings}" )
fi
if [[ -n ${SYSROOT} ]]; then
cmd+=( --sysroot "${SYSROOT}" )
fi
printf '%s\n' "${cmd[*]}"
local wheel=$( local wheel=$(
gpep517 build-wheel --backend "${build_backend}" \ "${cmd[@]}" 3>&1 >&2 || die "Wheel build failed"
--output-fd 3 \
--wheel-dir "${WHEEL_BUILD_DIR}" \
"${config_args[@]}" 3>&1 >&2 ||
die "Wheel build failed"
) )
[[ -n ${wheel} ]] || die "No wheel name returned" [[ -n ${wheel} ]] || die "No wheel name returned"
einfo " Installing the wheel to ${root}" distutils_wheel_install "${root}" "${WHEEL_BUILD_DIR}/${wheel}"
gpep517 install-wheel --destdir="${root}" --interpreter="${PYTHON}" \
--prefix="${EPREFIX}/usr" "${WHEEL_BUILD_DIR}/${wheel}" ||
die "Wheel install failed"
# remove installed licenses
find "${root}$(python_get_sitedir)" -depth \
\( -path '*.dist-info/COPYING*' \
-o -path '*.dist-info/LICENSE*' \
-o -path '*.dist-info/license_files/*' \
-o -path '*.dist-info/license_files' \
\) -delete || die
# clean the build tree; otherwise we may end up with PyPy3 # clean the build tree; otherwise we may end up with PyPy3
# extensions duplicated into CPython dists # extensions duplicated into CPython dists
@ -1294,12 +1400,19 @@ distutils_pep517_install() {
# @FUNCTION: distutils-r1_python_compile # @FUNCTION: distutils-r1_python_compile
# @USAGE: [additional-args...] # @USAGE: [additional-args...]
# @DESCRIPTION: # @DESCRIPTION:
# The default python_compile(). Runs 'esetup.py build'. Any parameters # The default python_compile().
# passed to this function will be appended to setup.py invocation,
# i.e. passed as options to the 'build' command.
# #
# This phase also sets up initial setup.cfg with build directories # If DISTUTILS_USE_PEP517 is set to "no", a no-op.
# and copies upstream egg-info files if supplied. #
# If DISTUTILS_USE_PEP517 is set to any other value, builds a wheel
# using the PEP517 backend and installs it into ${BUILD_DIR}/install.
# May additionally call build_ext prior to that when using setuptools
# and the eclass detects a potential benefit from parallel extension
# builds.
#
# In legacy mode, runs 'esetup.py build'. Any parameters passed to this
# function will be appended to setup.py invocation, i.e. passed
# as options to the 'build' command.
distutils-r1_python_compile() { distutils-r1_python_compile() {
debug-print-function ${FUNCNAME} "${@}" debug-print-function ${FUNCNAME} "${@}"
@ -1331,7 +1444,9 @@ distutils-r1_python_compile() {
# #
# see extension.py for list of suffixes # see extension.py for list of suffixes
# .pyx is added for Cython # .pyx is added for Cython
if [[ 1 -ne ${jobs} && 2 -eq $( #
# esetup.py does not respect SYSROOT, so skip it there
if [[ -z ${SYSROOT} && 1 -ne ${jobs} && 2 -eq $(
find '(' -name '*.c' -o -name '*.cc' -o -name '*.cpp' \ find '(' -name '*.c' -o -name '*.cc' -o -name '*.cpp' \
-o -name '*.cxx' -o -name '*.c++' -o -name '*.m' \ -o -name '*.cxx' -o -name '*.c++' -o -name '*.m' \
-o -name '*.mm' -o -name '*.pyx' ')' -printf '\n' | -o -name '*.mm' -o -name '*.pyx' ')' -printf '\n' |
@ -1344,50 +1459,21 @@ distutils-r1_python_compile() {
fi fi
;; ;;
maturin) maturin)
# auditwheel may attempt to auto-bundle libraries, bug #831171 # auditwheel may auto-bundle libraries (bug #831171),
local -x MATURIN_PEP517_ARGS=--skip-auditwheel # also support cargo.eclass' IUSE=debug if available
local -x MATURIN_PEP517_ARGS="
# support cargo.eclass' IUSE=debug if available --jobs=$(makeopts_jobs)
in_iuse debug && use debug && --skip-auditwheel
MATURIN_PEP517_ARGS+=" --cargo-extra-args=--profile=dev" $(in_iuse debug && usex debug --profile=dev '')
"
;;
no)
return
;; ;;
esac esac
if [[ ${DISTUTILS_USE_PEP517} ]]; then if [[ ${DISTUTILS_USE_PEP517} ]]; then
# python likes to compile any module it sees, which triggers sandbox distutils_pep517_install "${BUILD_DIR}/install"
# failures if some packages haven't compiled their modules yet.
addpredict "${EPREFIX}/usr/lib/${EPYTHON}"
addpredict /usr/lib/pypy3.8
addpredict /usr/lib/portage/pym
addpredict /usr/local # bug 498232
local root=${BUILD_DIR}/install
distutils_pep517_install "${root}"
# copy executables to python-exec directory
# we do it early so that we can alter bindir recklessly
local bindir=${root}${EPREFIX}/usr/bin
local rscriptdir=${root}$(python_get_scriptdir)
[[ -d ${rscriptdir} ]] &&
die "${rscriptdir} should not exist!"
if [[ -d ${bindir} ]]; then
mkdir -p "${rscriptdir}" || die
cp -a --reflink=auto "${bindir}"/. "${rscriptdir}"/ || die
fi
# enable venv magic inside the install tree
mkdir -p "${bindir}" || die
ln -s "${PYTHON}" "${bindir}/${EPYTHON}" || die
ln -s "${EPYTHON}" "${bindir}/python3" || die
ln -s "${EPYTHON}" "${bindir}/python" || die
cat > "${bindir}"/pyvenv.cfg <<-EOF || die
include-system-site-packages = true
EOF
# we need to change shebangs to point to the venv-python
find "${bindir}" -type f -exec sed -i \
-e "1s@^#!\(${EPREFIX}/usr/bin/\(python\|pypy\)\)@#!${root}\1@" \
{} + || die
fi fi
} }
@ -1428,7 +1514,7 @@ _distutils-r1_wrap_scripts() {
debug-print "${FUNCNAME}: installing wrapper at ${bindir}/${basename}" debug-print "${FUNCNAME}: installing wrapper at ${bindir}/${basename}"
local dosym=dosym local dosym=dosym
[[ ${EAPI} == [67] ]] && dosym=dosym8 [[ ${EAPI} == 7 ]] && dosym=dosym8
"${dosym}" -r /usr/lib/python-exec/python-exec2 \ "${dosym}" -r /usr/lib/python-exec/python-exec2 \
"${bindir#${EPREFIX}}/${basename}" "${bindir#${EPREFIX}}/${basename}"
done done
@ -1482,36 +1568,72 @@ distutils-r1_python_test() {
esac esac
if [[ ${?} -ne 0 ]]; then if [[ ${?} -ne 0 ]]; then
die "Tests failed with ${EPYTHON}" die -n "Tests failed with ${EPYTHON}"
fi fi
} }
# @FUNCTION: distutils-r1_python_install # @FUNCTION: distutils-r1_python_install
# @USAGE: [additional-args...] # @USAGE: [additional-args...]
# @DESCRIPTION: # @DESCRIPTION:
# The default python_install(). Runs 'esetup.py install', doing # The default python_install().
# intermediate root install and handling script wrapping afterwards. #
# In PEP517 mode, merges the files from ${BUILD_DIR}/install
# (if present) to the image directory.
#
# In the legacy mode, calls `esetup.py install` to install the package.
# Any parameters passed to this function will be appended # Any parameters passed to this function will be appended
# to the setup.py invocation (i.e. as options to the 'install' command). # to the setup.py invocation (i.e. as options to the 'install' command).
#
# This phase updates the setup.cfg file with install directories.
distutils-r1_python_install() { distutils-r1_python_install() {
debug-print-function ${FUNCNAME} "${@}" debug-print-function ${FUNCNAME} "${@}"
_python_check_EPYTHON _python_check_EPYTHON
local scriptdir=${EPREFIX}/usr/bin local scriptdir=${EPREFIX}/usr/bin
local merge_root=
if [[ ${DISTUTILS_USE_PEP517} ]]; then if [[ ${DISTUTILS_USE_PEP517} ]]; then
local root=${BUILD_DIR}/install local root=${BUILD_DIR}/install
local reg_scriptdir=${root}/${scriptdir}
local wrapped_scriptdir=${root}$(python_get_scriptdir)
# we are assuming that _distutils-r1_post_python_compile
# has been called and ${root} has not been altered since
# let's explicitly verify these assumptions
# remove files that we've created explicitly
rm "${reg_scriptdir}"/{"${EPYTHON}",python3,python,pyvenv.cfg} || die
# Automagically do the QA check to avoid issues when bootstrapping
# prefix.
if type diff &>/dev/null ; then
# verify that scriptdir & wrapped_scriptdir both contain
# the same files
(
cd "${reg_scriptdir}" && find . -mindepth 1
) | sort > "${T}"/.distutils-files-bin
assert "listing ${reg_scriptdir} failed"
(
if [[ -d ${wrapped_scriptdir} ]]; then
cd "${wrapped_scriptdir}" && find . -mindepth 1
fi
) | sort > "${T}"/.distutils-files-wrapped
assert "listing ${wrapped_scriptdir} failed"
if ! diff -U 0 "${T}"/.distutils-files-{bin,wrapped}; then
die "File lists for ${reg_scriptdir} and ${wrapped_scriptdir} differ (see diff above)"
fi
fi
# remove the altered bindir, executables from the package # remove the altered bindir, executables from the package
# are already in scriptdir # are already in scriptdir
rm -r "${root}${scriptdir}" || die rm -r "${reg_scriptdir}" || die
if [[ ${DISTUTILS_SINGLE_IMPL} ]]; then if [[ ${DISTUTILS_SINGLE_IMPL} ]]; then
local wrapped_scriptdir=${root}$(python_get_scriptdir)
if [[ -d ${wrapped_scriptdir} ]]; then if [[ -d ${wrapped_scriptdir} ]]; then
mv "${wrapped_scriptdir}" "${root}${scriptdir}" || die mv "${wrapped_scriptdir}" "${reg_scriptdir}" || die
fi fi
fi fi
# prune empty directories to see if ${root} contains anything
# to merge
find "${BUILD_DIR}"/install -type d -empty -delete || die
[[ -d ${BUILD_DIR}/install ]] && merge_root=1
else else
local root=${D%/}/_${EPYTHON} local root=${D%/}/_${EPYTHON}
[[ ${DISTUTILS_SINGLE_IMPL} ]] && root=${D%/} [[ ${DISTUTILS_SINGLE_IMPL} ]] && root=${D%/}
@ -1533,11 +1655,12 @@ distutils-r1_python_install() {
# python likes to compile any module it sees, which triggers sandbox # python likes to compile any module it sees, which triggers sandbox
# failures if some packages haven't compiled their modules yet. # failures if some packages haven't compiled their modules yet.
addpredict "${EPREFIX}/usr/lib/${EPYTHON}" addpredict "${EPREFIX}/usr/lib/${EPYTHON}"
addpredict /usr/lib/pypy3.8 addpredict "${EPREFIX}/usr/lib/pypy3.9"
addpredict /usr/lib/portage/pym addpredict "${EPREFIX}/usr/local" # bug 498232
addpredict /usr/local # bug 498232
if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
merge_root=1
# user may override --install-scripts # user may override --install-scripts
# note: this is poor but distutils argv parsing is dumb # note: this is poor but distutils argv parsing is dumb
@ -1566,36 +1689,8 @@ distutils-r1_python_install() {
esetup.py "${args[@]}" esetup.py "${args[@]}"
fi fi
local forbidden_package_names=( if [[ ${merge_root} ]]; then
examples test tests
.pytest_cache .hypothesis
)
local p
for p in "${forbidden_package_names[@]}"; do
if [[ -d ${root}$(python_get_sitedir)/${p} ]]; then
die "Package installs '${p}' package which is forbidden and likely a bug in the build system."
fi
done
local shopt_save=$(shopt -p nullglob)
shopt -s nullglob
local pypy_dirs=(
"${root}${EPREFIX}/usr/$(get_libdir)"/pypy*/share
"${root}${EPREFIX}/usr/lib"/pypy*/share
)
${shopt_save}
if [[ -n ${pypy_dirs} ]]; then
die "Package installs 'share' in PyPy prefix, see bug #465546."
fi
if [[ ! ${DISTUTILS_SINGLE_IMPL} || ${DISTUTILS_USE_PEP517} ]]; then
multibuild_merge_root "${root}" "${D%/}" multibuild_merge_root "${root}" "${D%/}"
if [[ ${DISTUTILS_USE_PEP517} ]]; then
# we need to recompile everything here in order to embed
# the correct paths
python_optimize "${D%/}$(python_get_sitedir)"
fi
fi fi
if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
_distutils-r1_wrap_scripts "${scriptdir}" _distutils-r1_wrap_scripts "${scriptdir}"
@ -1629,6 +1724,8 @@ distutils-r1_run_phase() {
debug-print-function ${FUNCNAME} "${@}" debug-print-function ${FUNCNAME} "${@}"
if [[ ${DISTUTILS_IN_SOURCE_BUILD} ]]; then if [[ ${DISTUTILS_IN_SOURCE_BUILD} ]]; then
[[ ${DISTUTILS_USE_PEP517} ]] &&
die "DISTUTILS_IN_SOURCE_BUILD is not supported in PEP517 mode"
# only force BUILD_DIR if implementation is explicitly enabled # only force BUILD_DIR if implementation is explicitly enabled
# for building; any-r1 API may select one that is not # for building; any-r1 API may select one that is not
# https://bugs.gentoo.org/701506 # https://bugs.gentoo.org/701506
@ -1687,6 +1784,11 @@ distutils-r1_run_phase() {
fi fi
cd "${_DISTUTILS_INITIAL_CWD}" || die cd "${_DISTUTILS_INITIAL_CWD}" || die
if [[ ! ${_DISTUTILS_IN_COMMON_IMPL} ]] &&
declare -f "_distutils-r1_post_python_${EBUILD_PHASE}" >/dev/null
then
"_distutils-r1_post_python_${EBUILD_PHASE}"
fi
return "${ret}" return "${ret}"
} }
@ -1701,6 +1803,7 @@ distutils-r1_run_phase() {
# of sources made for the selected Python interpreter. # of sources made for the selected Python interpreter.
_distutils-r1_run_common_phase() { _distutils-r1_run_common_phase() {
local DISTUTILS_ORIG_BUILD_DIR=${BUILD_DIR} local DISTUTILS_ORIG_BUILD_DIR=${BUILD_DIR}
local _DISTUTILS_IN_COMMON_IMPL=1
if [[ ${DISTUTILS_SINGLE_IMPL} ]]; then if [[ ${DISTUTILS_SINGLE_IMPL} ]]; then
# reuse the dedicated code branch # reuse the dedicated code branch
@ -1731,6 +1834,7 @@ _distutils-r1_run_foreach_impl() {
set -- distutils-r1_run_phase "${@}" set -- distutils-r1_run_phase "${@}"
if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
local _DISTUTILS_CALLING_FOREACH_IMPL=1
python_foreach_impl "${@}" python_foreach_impl "${@}"
else else
if [[ ! ${EPYTHON} ]]; then if [[ ! ${EPYTHON} ]]; then
@ -1781,6 +1885,43 @@ distutils-r1_src_configure() {
return ${ret} return ${ret}
} }
# @FUNCTION: _distutils-r1_post_python_compile
# @INTERNAL
# @DESCRIPTION:
# Post-phase function called after python_compile. In PEP517 mode,
# it adjusts the install tree for venv-style usage.
_distutils-r1_post_python_compile() {
debug-print-function ${FUNCNAME} "${@}"
local root=${BUILD_DIR}/install
if [[ ${DISTUTILS_USE_PEP517} && -d ${root} ]]; then
# copy executables to python-exec directory
# we do it early so that we can alter bindir recklessly
local bindir=${root}${EPREFIX}/usr/bin
local rscriptdir=${root}$(python_get_scriptdir)
[[ -d ${rscriptdir} ]] &&
die "${rscriptdir} should not exist!"
if [[ -d ${bindir} ]]; then
mkdir -p "${rscriptdir}" || die
cp -a --reflink=auto "${bindir}"/. "${rscriptdir}"/ || die
fi
# enable venv magic inside the install tree
mkdir -p "${bindir}" || die
ln -s "${PYTHON}" "${bindir}/${EPYTHON}" || die
ln -s "${EPYTHON}" "${bindir}/python3" || die
ln -s "${EPYTHON}" "${bindir}/python" || die
cat > "${bindir}"/pyvenv.cfg <<-EOF || die
include-system-site-packages = true
EOF
# we need to change shebangs to point to the venv-python
find "${bindir}" -type f -exec sed -i \
-e "1s@^#!\(${EPREFIX}/usr/bin/\(python\|pypy\)\)@#!${root}\1@" \
{} + || die
fi
}
distutils-r1_src_compile() { distutils-r1_src_compile() {
debug-print-function ${FUNCNAME} "${@}" debug-print-function ${FUNCNAME} "${@}"
local ret=0 local ret=0
@ -1812,15 +1953,24 @@ _distutils-r1_clean_egg_info() {
rm -rf "${BUILD_DIR}"/lib/*.egg-info || die rm -rf "${BUILD_DIR}"/lib/*.egg-info || die
} }
# @FUNCTION: _distutils-r1_post_python_test
# @INTERNAL
# @DESCRIPTION:
# Post-phase function called after python_test.
_distutils-r1_post_python_test() {
debug-print-function ${FUNCNAME} "${@}"
if [[ ! ${DISTUTILS_USE_PEP517} ]]; then
_distutils-r1_clean_egg_info
fi
}
distutils-r1_src_test() { distutils-r1_src_test() {
debug-print-function ${FUNCNAME} "${@}" debug-print-function ${FUNCNAME} "${@}"
local ret=0 local ret=0
if declare -f python_test >/dev/null; then if declare -f python_test >/dev/null; then
_distutils-r1_run_foreach_impl python_test || ret=${?} _distutils-r1_run_foreach_impl python_test || ret=${?}
if [[ ! ${DISTUTILS_USE_PEP517} ]]; then
_distutils-r1_run_foreach_impl _distutils-r1_clean_egg_info
fi
fi fi
if declare -f python_test_all >/dev/null; then if declare -f python_test_all >/dev/null; then
@ -1830,6 +1980,51 @@ distutils-r1_src_test() {
return ${ret} return ${ret}
} }
# @FUNCTION: _distutils-r1_post_python_install
# @INTERNAL
# @DESCRIPTION:
# Post-phase function called after python_install. Performs QA checks.
# In PEP517 mode, additionally optimizes installed Python modules.
_distutils-r1_post_python_install() {
debug-print-function ${FUNCNAME} "${@}"
local sitedir=${D%/}$(python_get_sitedir)
if [[ -d ${sitedir} ]]; then
local forbidden_package_names=(
examples test tests
.pytest_cache .hypothesis _trial_temp
)
local strays=()
local p
mapfile -d $'\0' -t strays < <(
find "${sitedir}" -maxdepth 1 -type f '!' '(' \
-name '*.egg-info' -o \
-name '*.pth' -o \
-name '*.py' -o \
-name '*.pyi' -o \
-name "*$(get_modname)" \
')' -print0
)
for p in "${forbidden_package_names[@]}"; do
[[ -d ${sitedir}/${p} ]] && strays+=( "${sitedir}/${p}" )
done
if [[ -n ${strays[@]} ]]; then
eerror "The following unexpected files/directories were found top-level"
eerror "in the site-packages directory:"
eerror
for p in "${strays[@]}"; do
eerror " ${p#${ED}}"
done
eerror
eerror "This is most likely a bug in the build system. More information"
eerror "can be found in the Python Guide:"
eerror "https://projects.gentoo.org/python/guide/qawarn.html#stray-top-level-files-in-site-packages"
die "Failing install because of stray top-level files in site-packages"
fi
fi
}
# @FUNCTION: _distutils-r1_check_namespace_pth # @FUNCTION: _distutils-r1_check_namespace_pth
# @INTERNAL # @INTERNAL
# @DESCRIPTION: # @DESCRIPTION:
@ -1843,17 +2038,19 @@ _distutils-r1_check_namespace_pth() {
done < <(find "${ED%/}" -name '*-nspkg.pth' -print0) done < <(find "${ED%/}" -name '*-nspkg.pth' -print0)
if [[ ${pth[@]} ]]; then if [[ ${pth[@]} ]]; then
ewarn "The following *-nspkg.pth files were found installed:" eerror "The following *-nspkg.pth files were found installed:"
ewarn eerror
for f in "${pth[@]}"; do for f in "${pth[@]}"; do
ewarn " ${f#${ED%/}}" eerror " ${f#${ED%/}}"
done done
ewarn eerror
ewarn "The presence of those files may break namespaces in Python 3.5+. Please" eerror "The presence of those files may break namespaces in Python 3.5+. Please"
ewarn "read our documentation on reliable handling of namespaces and update" eerror "read our documentation on reliable handling of namespaces and update"
ewarn "the ebuild accordingly:" eerror "the ebuild accordingly:"
ewarn eerror
ewarn " https://projects.gentoo.org/python/guide/concept.html#namespace-packages" eerror " https://projects.gentoo.org/python/guide/concept.html#namespace-packages"
die "Installing *-nspkg.pth files is banned"
fi fi
} }