public inbox for gentoo-dev@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-dev] [PATCH v2 00/20] python-r2 suite
@ 2020-03-05 15:10 Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 01/20] eclass: Copy python-r1 suite to python-r2 Michał Górny
                   ` (19 more replies)
  0 siblings, 20 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Hi,

Here's the second iteration of python-r2 proposal.  This time I've
decided to follow purely the approach of lint-safe changes.  Most
of the conversions would be doable via script, the remaining
incompatibilities would be detectable via script.

A wip version of the script is at [1].  Right now it just detects use
of deprecated EAPIs (including python.eclass leftovers), I will add API
update support later on.  FWICS it has two false positives right now
but I think that's good enough.  To do better, we'd have to employ
a proper bash parser.


Differences from patch v1:

- rebased on cleaned up python-r1 suite (so changes applicable to -r1
  were merged there)

- lowered DISTUTILS_USE_SETUPTOOLS warnings to non-fatal again, as this
  is something that can be detected only at runtime


Overall changes from python-r1 suite:

- the following deprecated API were removed:
  - EXAMPLES -- they were banned in EAPI 7 already yet people kept
                failing to remove them anyway
  - distutils-r2_python_{prepare,configure} -- no-op defaults
  - python_gen_usedep -- deprecated in favor of python_gen_cond_dep

- the following functions were made private:
  - python_wrapper_setup (part of python_setup)
  - python_is_installed (internal since inception)
  - python_export (in favor of python_get*)

- PYTHON_MULTI_USEDEP was renamed back to PYTHON_USEDEP for consistency
  between eclasses (but still needs python_gen_cond_dep in p-s-r1)

- python-r1 becomes python-multi-r2

- distutils-r2 now passes --skip-build to install target -- this is
  the only potentially breaking change but the potential is really
  minimal, so we should catch it via testing the eclasses


[1] https://github.com/mgorny/pymighelper


Michał Górny (20):
  eclass: Copy python-r1 suite to python-r2
  distutils-r2.eclass: Remove EXAMPLES
  distutils-r2.eclass: Remove no-op subphase defaults
  distutils-r2.eclass: Remove distutils.eclass checks
  python-r2.eclass: Remove python_gen_usedep
  python-utils-r2.eclass: Remove python.eclass checks
  python-utils-r2.eclass: Mark python_wrapper_setup private
  python-utils-r2.eclass: Mark python_is_installed private
  python-utils-r2.eclass: Fix obsolete docs on python_export_best
  python-utils-r2.eclass: Mark python_export private
  python-utils-r2.eclass: Remove PYTHON_SITEDIR export
  python-utils-r2.eclass: Remove PYTHON_INCLUDEDIR export
  python-utils-r2.eclass: Remove PYTHON_LIBPATH export
  python-utils-r2.eclass: Remove PYTHON_CFLAGS export
  python-utils-r2.eclass: Remove PYTHON_LIBS export
  python-utils-r2.eclass: Remove PYTHON_CONFIG export
  python-utils-r2.eclass: Remove PYTHON_SCRIPTDIR export
  python-single-r2.eclass: PYTHON_MULTI_USEDEP → PYTHON_USEDEP
  distutils-r2.eclass: Pass --skip-build to install
  eclass: python-r2.eclass → python-multi-r2.eclass

 eclass/distutils-r2.eclass      | 1109 +++++++++++++++++++++++++++++
 eclass/python-any-r2.eclass     |  363 ++++++++++
 eclass/python-multi-r2.eclass   |  786 ++++++++++++++++++++
 eclass/python-single-r2.eclass  |  512 ++++++++++++++
 eclass/python-utils-r2.eclass   | 1180 +++++++++++++++++++++++++++++++
 eclass/tests/distutils-r2.sh    |   98 +++
 eclass/tests/python-utils-r2.sh |  250 +++++++
 7 files changed, 4298 insertions(+)
 create mode 100644 eclass/distutils-r2.eclass
 create mode 100644 eclass/python-any-r2.eclass
 create mode 100644 eclass/python-multi-r2.eclass
 create mode 100644 eclass/python-single-r2.eclass
 create mode 100644 eclass/python-utils-r2.eclass
 create mode 100755 eclass/tests/distutils-r2.sh
 create mode 100755 eclass/tests/python-utils-r2.sh

-- 
2.25.1



^ permalink raw reply	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 01/20] eclass: Copy python-r1 suite to python-r2
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 02/20] distutils-r2.eclass: Remove EXAMPLES Michał Górny
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/distutils-r2.eclass      | 1188 ++++++++++++++++++++++++
 eclass/python-any-r2.eclass     |  364 ++++++++
 eclass/python-r2.eclass         |  829 +++++++++++++++++
 eclass/python-single-r2.eclass  |  512 +++++++++++
 eclass/python-utils-r2.eclass   | 1508 +++++++++++++++++++++++++++++++
 eclass/tests/distutils-r2.sh    |   98 ++
 eclass/tests/python-utils-r2.sh |  237 +++++
 7 files changed, 4736 insertions(+)
 create mode 100644 eclass/distutils-r2.eclass
 create mode 100644 eclass/python-any-r2.eclass
 create mode 100644 eclass/python-r2.eclass
 create mode 100644 eclass/python-single-r2.eclass
 create mode 100644 eclass/python-utils-r2.eclass
 create mode 100755 eclass/tests/distutils-r2.sh
 create mode 100755 eclass/tests/python-utils-r2.sh

diff --git a/eclass/distutils-r2.eclass b/eclass/distutils-r2.eclass
new file mode 100644
index 000000000000..559ca2b72c1c
--- /dev/null
+++ b/eclass/distutils-r2.eclass
@@ -0,0 +1,1188 @@
+# Copyright 1999-2020 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: distutils-r2.eclass
+# @MAINTAINER:
+# Python team <python@gentoo.org>
+# @AUTHOR:
+# Author: Michał Górny <mgorny@gentoo.org>
+# @SUPPORTED_EAPIS: 5 6 7
+# @BLURB: A simple eclass to build Python packages using distutils.
+# @DESCRIPTION:
+# A simple eclass providing functions to build Python packages using
+# the distutils build system. It exports phase functions for all
+# the src_* phases. Each of the phases runs two pseudo-phases:
+# python_..._all() (e.g. python_prepare_all()) once in ${S}, then
+# python_...() (e.g. python_prepare()) for each implementation
+# (see: python_foreach_impl() in python-r2).
+#
+# In distutils-r2_src_prepare(), the 'all' function is run before
+# per-implementation ones (because it creates the implementations),
+# per-implementation functions are run in a random order.
+#
+# In remaining phase functions, the per-implementation functions are run
+# before the 'all' one, and they are ordered from the least to the most
+# preferred implementation (so that 'better' files overwrite 'worse'
+# ones).
+#
+# If the ebuild doesn't specify a particular pseudo-phase function,
+# the default one will be used (distutils-r2_...). Defaults are provided
+# for all per-implementation pseudo-phases, python_prepare_all()
+# and python_install_all(); whenever writing your own pseudo-phase
+# functions, you should consider calling the defaults (and especially
+# distutils-r2_python_prepare_all).
+#
+# Please note that distutils-r2 sets RDEPEND and DEPEND unconditionally
+# for you.
+#
+# Also, please note that distutils-r2 will always inherit python-r2
+# as well. Thus, all the variables defined and documented there are
+# relevant to the packages using distutils-r2.
+#
+# For more information, please see the Python Guide:
+# https://dev.gentoo.org/~mgorny/python-guide/
+
+case "${EAPI:-0}" in
+	0|1|2|3|4)
+		die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
+		;;
+	5|6|7)
+		;;
+	*)
+		die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
+		;;
+esac
+
+# @ECLASS-VARIABLE: DISTUTILS_OPTIONAL
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# If set to a non-null value, distutils part in the ebuild will
+# be considered optional. No dependencies will be added and no phase
+# functions will be exported.
+#
+# If you enable DISTUTILS_OPTIONAL, you have to set proper dependencies
+# for your package (using ${PYTHON_DEPS}) and to either call
+# distutils-r2 default phase functions or call the build system
+# manually.
+
+# @ECLASS-VARIABLE: DISTUTILS_SINGLE_IMPL
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# If set to a non-null value, the ebuild will support setting a single
+# Python implementation only. It will effectively replace the python-r2
+# eclass inherit with python-single-r2.
+#
+# Note that inheriting python-single-r2 will cause pkg_setup()
+# to be exported. It must be run in order for the eclass functions
+# to function properly.
+
+# @ECLASS-VARIABLE: DISTUTILS_USE_SETUPTOOLS
+# @PRE_INHERIT
+# @DESCRIPTION:
+# Controls adding dev-python/setuptools dependency.  The allowed values
+# are:
+#
+# - no -- do not add the dependency (pure distutils package)
+# - bdepend -- add it to BDEPEND (the default)
+# - rdepend -- add it to BDEPEND+RDEPEND (when using entry_points)
+# - pyproject.toml -- use pyproject2setuptools to install a project
+#                     using pyproject.toml (flit, poetry...)
+# - manual -- do not add the depedency and suppress the checks
+#             (assumes you will take care of doing it correctly)
+#
+# This variable is effective only if DISTUTILS_OPTIONAL is disabled.
+# It needs to be set before the inherit line.
+: ${DISTUTILS_USE_SETUPTOOLS:=bdepend}
+
+if [[ ! ${_DISTUTILS_R2} ]]; then
+
+[[ ${EAPI} == [456] ]] && inherit eutils
+[[ ${EAPI} == [56] ]] && inherit xdg-utils
+inherit multiprocessing toolchain-funcs
+
+if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
+	inherit python-r2
+else
+	inherit python-single-r2
+fi
+
+fi
+
+if [[ ! ${DISTUTILS_OPTIONAL} ]]; then
+	EXPORT_FUNCTIONS src_prepare src_configure src_compile src_test src_install
+fi
+
+if [[ ! ${_DISTUTILS_R2} ]]; then
+
+_distutils_set_globals() {
+	local rdep=${PYTHON_DEPS}
+	local bdep=${rdep}
+
+	if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
+		local sdep="dev-python/setuptools[${PYTHON_USEDEP}]"
+	else
+		local sdep="$(python_gen_cond_dep '
+			dev-python/setuptools[${PYTHON_MULTI_USEDEP}]
+		')"
+	fi
+
+	case ${DISTUTILS_USE_SETUPTOOLS} in
+		no|manual)
+			;;
+		bdepend)
+			bdep+=" ${sdep}"
+			;;
+		rdepend)
+			bdep+=" ${sdep}"
+			rdep+=" ${sdep}"
+			;;
+		pyproject.toml)
+			bdep+=" dev-python/pyproject2setuppy[${PYTHON_USEDEP}]"
+			;;
+		*)
+			die "Invalid DISTUTILS_USE_SETUPTOOLS=${DISTUTILS_USE_SETUPTOOLS}"
+			;;
+	esac
+
+	RDEPEND=${rdep}
+	if [[ ${EAPI} != [56] ]]; then
+		BDEPEND=${bdep}
+	else
+		DEPEND=${bdep}
+	fi
+	REQUIRED_USE=${PYTHON_REQUIRED_USE}
+}
+[[ ! ${DISTUTILS_OPTIONAL} ]] && _distutils_set_globals
+unset -f _distutils_set_globals
+
+# @ECLASS-VARIABLE: PATCHES
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# An array containing patches to be applied to the sources before
+# copying them.
+#
+# If unset, no custom patches will be applied.
+#
+# Please note, however, that at some point the eclass may apply
+# additional distutils patches/quirks independently of this variable.
+#
+# Example:
+# @CODE
+# PATCHES=( "${FILESDIR}"/${P}-make-gentoo-happy.patch )
+# @CODE
+
+# @ECLASS-VARIABLE: DOCS
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# An array containing documents installed using dodoc. The files listed
+# there must exist in the directory from which
+# distutils-r2_python_install_all() is run (${S} by default).
+#
+# If unset, the function will instead look up files matching default
+# filename pattern list (from the Package Manager Specification),
+# and install those found.
+#
+# Example:
+# @CODE
+# DOCS=( NEWS README )
+# @CODE
+
+# @ECLASS-VARIABLE: HTML_DOCS
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# An array containing documents installed using dohtml. The files
+# and directories listed there must exist in the directory from which
+# distutils-r2_python_install_all() is run (${S} by default).
+#
+# If unset, no HTML docs will be installed.
+#
+# Example:
+# @CODE
+# HTML_DOCS=( doc/html/. )
+# @CODE
+
+# @ECLASS-VARIABLE: EXAMPLES
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# OBSOLETE: this variable is deprecated and banned in EAPI 6
+#
+# An array containing examples installed into 'examples' doc
+# subdirectory. The files and directories listed there must exist
+# in the directory from which distutils-r2_python_install_all() is run
+# (${S} by default).
+#
+# The 'examples' subdirectory will be marked not to be compressed
+# automatically.
+#
+# If unset, no examples will be installed.
+#
+# Example:
+# @CODE
+# EXAMPLES=( examples/. demos/. )
+# @CODE
+
+# @ECLASS-VARIABLE: DISTUTILS_IN_SOURCE_BUILD
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# If set to a non-null value, in-source builds will be enabled.
+# If unset, the default is to use in-source builds when python_prepare()
+# is declared, and out-of-source builds otherwise.
+#
+# If in-source builds are used, the eclass will create a copy of package
+# sources for each Python implementation in python_prepare_all(),
+# and work on that copy afterwards.
+#
+# If out-of-source builds are used, the eclass will instead work
+# on the sources directly, prepending setup.py arguments with
+# 'build --build-base ${BUILD_DIR}' to enforce keeping & using built
+# files in the specific root.
+
+# @ECLASS-VARIABLE: DISTUTILS_ALL_SUBPHASE_IMPLS
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# An array of patterns specifying which implementations can be used
+# for *_all() sub-phase functions. If undefined, defaults to '*'
+# (allowing any implementation). If multiple values are specified,
+# implementations matching any of the patterns will be accepted.
+#
+# The patterns can be either fnmatch-style patterns (matched via bash
+# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
+# appropriately all enabled Python 2/3 implementations (alike
+# python_is_python3). Remember to escape or quote the fnmatch patterns
+# to prevent accidental shell filename expansion.
+#
+# If the restriction needs to apply conditionally to a USE flag,
+# the variable should be set conditionally as well (e.g. in an early
+# phase function or other convenient location).
+#
+# Please remember to add a matching || block to REQUIRED_USE,
+# to ensure that at least one implementation matching the patterns will
+# be enabled.
+#
+# Example:
+# @CODE
+# REQUIRED_USE="doc? ( || ( $(python_gen_useflags 'python2*') ) )"
+#
+# pkg_setup() {
+#     use doc && DISTUTILS_ALL_SUBPHASE_IMPLS=( 'python2*' )
+# }
+# @CODE
+
+# @ECLASS-VARIABLE: mydistutilsargs
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# An array containing options to be passed to setup.py.
+#
+# Example:
+# @CODE
+# python_configure_all() {
+# 	mydistutilsargs=( --enable-my-hidden-option )
+# }
+# @CODE
+
+# @FUNCTION: distutils_enable_sphinx
+# @USAGE: <subdir> [--no-autodoc | <plugin-pkgs>...]
+# @DESCRIPTION:
+# Set up IUSE, BDEPEND, python_check_deps() and python_compile_all() for
+# building HTML docs via dev-python/sphinx.  python_compile_all() will
+# append to HTML_DOCS if docs are enabled.
+#
+# This helper is meant for the most common case, that is a single Sphinx
+# subdirectory with standard layout, building and installing HTML docs
+# behind USE=doc.  It assumes it's the only consumer of the three
+# aforementioned functions.  If you need to use a custom implemention,
+# you can't use it.
+#
+# If your package uses additional Sphinx plugins, they should be passed
+# (without PYTHON_USEDEP) as <plugin-pkgs>.  The function will take care
+# of setting appropriate any-of dep and python_check_deps().
+#
+# If no plugin packages are specified, the eclass will still utilize
+# any-r2 API to support autodoc (documenting source code).
+# If the package uses neither autodoc nor additional plugins, you should
+# pass --no-autodoc to disable this API and simplify the resulting code.
+#
+# This function must be called in global scope.  Take care not to
+# overwrite the variables set by it.  If you need to extend
+# python_compile_all(), you can call the original implementation
+# as sphinx_compile_all.
+distutils_enable_sphinx() {
+	debug-print-function ${FUNCNAME} "${@}"
+	[[ ${#} -ge 1 ]] || die "${FUNCNAME} takes at least one arg: <subdir>"
+
+	_DISTUTILS_SPHINX_SUBDIR=${1}
+	shift
+	_DISTUTILS_SPHINX_PLUGINS=( "${@}" )
+
+	local deps autodoc=1 d
+	for d; do
+		if [[ ${d} == --no-autodoc ]]; then
+			autodoc=
+		else
+			deps+="
+				${d}[\${PYTHON_USEDEP}]"
+		fi
+	done
+
+	if [[ ! ${autodoc} && -n ${deps} ]]; then
+		die "${FUNCNAME}: do not pass --no-autodoc if external plugins are used"
+	fi
+	if [[ ${autodoc} ]]; then
+		deps="$(python_gen_any_dep "
+			dev-python/sphinx[\${PYTHON_USEDEP}]
+			${deps}")"
+
+		python_check_deps() {
+			use doc || return 0
+			local p
+			for p in dev-python/sphinx "${_DISTUTILS_SPHINX_PLUGINS[@]}"; do
+				has_version "${p}[${PYTHON_USEDEP}]" || return 1
+			done
+		}
+	else
+		deps="dev-python/sphinx"
+	fi
+
+	sphinx_compile_all() {
+		use doc || return
+
+		local confpy=${_DISTUTILS_SPHINX_SUBDIR}/conf.py
+		[[ -f ${confpy} ]] ||
+			die "${confpy} not found, distutils_enable_sphinx call wrong"
+
+		if [[ ${_DISTUTILS_SPHINX_PLUGINS[0]} == --no-autodoc ]]; then
+			if grep -F -q 'sphinx.ext.autodoc' "${confpy}"; then
+				die "distutils_enable_sphinx: --no-autodoc passed but sphinx.ext.autodoc found in ${confpy}"
+			fi
+		else
+			if ! grep -F -q 'sphinx.ext.autodoc' "${confpy}"; then
+				die "distutils_enable_sphinx: sphinx.ext.autodoc not found in ${confpy}, pass --no-autodoc"
+			fi
+		fi
+
+		build_sphinx "${_DISTUTILS_SPHINX_SUBDIR}"
+	}
+	python_compile_all() { sphinx_compile_all; }
+
+	IUSE+=" doc"
+	if [[ ${EAPI} == [56] ]]; then
+		DEPEND+=" doc? ( ${deps} )"
+	else
+		BDEPEND+=" doc? ( ${deps} )"
+	fi
+
+	# we need to ensure successful return in case we're called last,
+	# otherwise Portage may wrongly assume sourcing failed
+	return 0
+}
+
+# @FUNCTION: distutils_enable_tests
+# @USAGE: <test-runner>
+# @DESCRIPTION:
+# Set up IUSE, RESTRICT, BDEPEND and python_test() for running tests
+# with the specified test runner.  Also copies the current value
+# of RDEPEND to test?-BDEPEND.  The test-runner argument must be one of:
+#
+# - nose: nosetests (dev-python/nose)
+# - pytest: dev-python/pytest
+# - setup.py: setup.py test (no deps included)
+# - unittest: for built-in Python unittest module
+#
+# This function is meant as a helper for common use cases, and it only
+# takes care of basic setup.  You still need to list additional test
+# dependencies manually.  If you have uncommon use case, you should
+# not use it and instead enable tests manually.
+#
+# This function must be called in global scope, after RDEPEND has been
+# declared.  Take care not to overwrite the variables set by it.
+distutils_enable_tests() {
+	debug-print-function ${FUNCNAME} "${@}"
+	[[ ${#} -eq 1 ]] || die "${FUNCNAME} takes exactly one argument: test-runner"
+
+	local test_pkg
+	case ${1} in
+		nose)
+			test_pkg="dev-python/nose"
+			python_test() {
+				nosetests -v || die "Tests fail with ${EPYTHON}"
+			}
+			;;
+		pytest)
+			test_pkg="dev-python/pytest"
+			python_test() {
+				pytest -vv || die "Tests fail with ${EPYTHON}"
+			}
+			;;
+		setup.py)
+			python_test() {
+				esetup.py test --verbose
+			}
+			;;
+		unittest)
+			python_test() {
+				"${EPYTHON}" -m unittest discover -v ||
+					die "Tests fail with ${EPYTHON}"
+			}
+			;;
+		*)
+			die "${FUNCNAME}: unsupported argument: ${1}"
+	esac
+
+	local test_deps=${RDEPEND}
+	if [[ -n ${test_pkg} ]]; then
+		if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
+			test_deps+=" ${test_pkg}[${PYTHON_USEDEP}]"
+		else
+			test_deps+=" $(python_gen_cond_dep "
+				${test_pkg}[\${PYTHON_MULTI_USEDEP}]
+			")"
+		fi
+	fi
+	if [[ -n ${test_deps} ]]; then
+		IUSE+=" test"
+		RESTRICT+=" !test? ( test )"
+		if [[ ${EAPI} == [56] ]]; then
+			DEPEND+=" test? ( ${test_deps} )"
+		else
+			BDEPEND+=" test? ( ${test_deps} )"
+		fi
+	fi
+
+	# we need to ensure successful return in case we're called last,
+	# otherwise Portage may wrongly assume sourcing failed
+	return 0
+}
+
+# @FUNCTION: _distutils-r2_verify_use_setuptools
+# @INTERNAL
+# @DESCRIPTION:
+# Check setup.py for signs that DISTUTILS_USE_SETUPTOOLS have been set
+# incorrectly.
+_distutils_verify_use_setuptools() {
+	[[ ${DISTUTILS_OPTIONAL} ]] && return
+	[[ ${DISTUTILS_USE_SETUPTOOLS} == manual ]] && return
+	[[ ${DISTUTILS_USE_SETUPTOOLS} == pyproject.toml ]] && return
+
+	# ok, those are cheap greps.  we can try toimprove them if we hit
+	# false positives.
+	local expected=no
+	if [[ ${CATEGORY}/${PN} == dev-python/setuptools ]]; then
+		# as a special case, setuptools provides itself ;-)
+		:
+	elif grep -E -q -s '(from|import)\s+setuptools' setup.py; then
+		if grep -E -q -s 'entry_points\s*=' setup.py; then
+			expected=rdepend
+		elif grep -F -q -s '[options.entry_points]' setup.cfg; then
+			expected=rdepend
+		else
+			expected=bdepend
+		fi
+	fi
+
+	if [[ ${DISTUTILS_USE_SETUPTOOLS} != ${expected} ]]; then
+		if [[ ! ${_DISTUTILS_SETUPTOOLS_WARNED} ]]; then
+			_DISTUTILS_SETUPTOOLS_WARNED=1
+			local def=
+			[[ ${DISTUTILS_USE_SETUPTOOLS} == bdepend ]] && def=' (default?)'
+
+			eqawarn "DISTUTILS_USE_SETUPTOOLS value is probably incorrect"
+			eqawarn "  value:    DISTUTILS_USE_SETUPTOOLS=${DISTUTILS_USE_SETUPTOOLS}${def}"
+			eqawarn "  expected: DISTUTILS_USE_SETUPTOOLS=${expected}"
+		fi
+	fi
+}
+
+# @FUNCTION: esetup.py
+# @USAGE: [<args>...]
+# @DESCRIPTION:
+# Run setup.py using currently selected Python interpreter
+# (if ${EPYTHON} is set; fallback 'python' otherwise).
+#
+# setup.py will be passed the following, in order:
+# 1. ${mydistutilsargs[@]}
+# 2. additional arguments passed to the esetup.py function.
+#
+# Please note that setup.py will respect defaults (unless overridden
+# via command-line options) from setup.cfg that is created
+# in distutils-r2_python_compile and in distutils-r2_python_install.
+#
+# This command dies on failure.
+esetup.py() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local die_args=()
+	[[ ${EAPI} != [45] ]] && die_args+=( -n )
+
+	[[ ${BUILD_DIR} ]] && _distutils-r2_create_setup_cfg
+	_distutils_verify_use_setuptools
+
+	set -- "${EPYTHON:-python}" setup.py "${mydistutilsargs[@]}" "${@}"
+
+	echo "${@}" >&2
+	"${@}" || die "${die_args[@]}"
+	local ret=${?}
+
+	if [[ ${BUILD_DIR} ]]; then
+		rm "${HOME}"/.pydistutils.cfg || die "${die_args[@]}"
+	fi
+
+	return ${ret}
+}
+
+# @FUNCTION: distutils_install_for_testing
+# @USAGE: [<args>...]
+# @DESCRIPTION:
+# Install the package into a temporary location for running tests.
+# Update PYTHONPATH appropriately and set TEST_DIR to the test
+# installation root. The Python packages will be installed in 'lib'
+# subdir, and scripts in 'scripts' subdir (like in BUILD_DIR).
+#
+# Please note that this function should be only used if package uses
+# namespaces (and therefore proper install needs to be done to enforce
+# PYTHONPATH) or tests rely on the results of install command.
+# For most of the packages, tests built in BUILD_DIR are good enough.
+distutils_install_for_testing() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	# A few notes:
+	# 1) because of namespaces, we can't use 'install --root',
+	# 2) 'install --home' is terribly broken on pypy, so we need
+	#    to override --install-lib and --install-scripts,
+	# 3) non-root 'install' complains about PYTHONPATH and missing dirs,
+	#    so we need to set it properly and mkdir them,
+	# 4) it runs a bunch of commands which write random files to cwd,
+	#    in order to avoid that, we add the necessary path overrides
+	#    in _distutils-r2_create_setup_cfg.
+
+	TEST_DIR=${BUILD_DIR}/test
+	local bindir=${TEST_DIR}/scripts
+	local libdir=${TEST_DIR}/lib
+	PYTHONPATH=${libdir}:${PYTHONPATH}
+
+	local add_args=(
+		install
+			--home="${TEST_DIR}"
+			--install-lib="${libdir}"
+			--install-scripts="${bindir}"
+	)
+
+	mkdir -p "${libdir}" || die
+	esetup.py "${add_args[@]}" "${@}"
+}
+
+# @FUNCTION: _distutils-r2_disable_ez_setup
+# @INTERNAL
+# @DESCRIPTION:
+# Stub out ez_setup.py and distribute_setup.py to prevent packages
+# from trying to download a local copy of setuptools.
+_distutils-r2_disable_ez_setup() {
+	local stub="def use_setuptools(*args, **kwargs): pass"
+	if [[ -f ez_setup.py ]]; then
+		echo "${stub}" > ez_setup.py || die
+	fi
+	if [[ -f distribute_setup.py ]]; then
+		echo "${stub}" > distribute_setup.py || die
+	fi
+}
+
+# @FUNCTION: _distutils-r2_handle_pyproject_toml
+# @INTERNAL
+# @DESCRIPTION:
+# Generate setup.py for pyproject.toml if requested.
+_distutils-r2_handle_pyproject_toml() {
+	if [[ ! -f setup.py && -f pyproject.toml ]]; then
+		if [[ ${DISTUTILS_USE_SETUPTOOLS} == pyproject.toml ]]; then
+			cat > setup.py <<-EOF || die
+				#!/usr/bin/env python
+				from pyproject2setuppy.main import main
+				main()
+			EOF
+			chmod +x setup.py || die
+		else
+			eerror "No setup.py found but pyproject.toml is present.  In order to enable"
+			eerror "pyproject.toml support in distutils-r2, set:"
+			eerror "  DISTUTILS_USE_SETUPTOOLS=pyproject.toml"
+			die "No setup.py found and DISTUTILS_USE_SETUPTOOLS!=pyproject.toml"
+		fi
+	fi
+}
+
+# @FUNCTION: distutils-r2_python_prepare_all
+# @DESCRIPTION:
+# The default python_prepare_all(). It applies the patches from PATCHES
+# array, then user patches and finally calls python_copy_sources to
+# create copies of resulting sources for each Python implementation.
+#
+# At some point in the future, it may also apply eclass-specific
+# distutils patches and/or quirks.
+distutils-r2_python_prepare_all() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	if [[ ! ${DISTUTILS_OPTIONAL} ]]; then
+		if [[ ${EAPI} != [45] ]]; then
+			default
+		else
+			[[ ${PATCHES} ]] && epatch "${PATCHES[@]}"
+			epatch_user
+		fi
+	fi
+
+	# by default, use in-source build if python_prepare() is used
+	if [[ ! ${DISTUTILS_IN_SOURCE_BUILD+1} ]]; then
+		if declare -f python_prepare >/dev/null; then
+			DISTUTILS_IN_SOURCE_BUILD=1
+		fi
+	fi
+
+	_distutils-r2_disable_ez_setup
+	_distutils-r2_handle_pyproject_toml
+
+	if [[ ${DISTUTILS_IN_SOURCE_BUILD} && ! ${DISTUTILS_SINGLE_IMPL} ]]
+	then
+		# create source copies for each implementation
+		python_copy_sources
+	fi
+
+	_DISTUTILS_DEFAULT_CALLED=1
+}
+
+# @FUNCTION: distutils-r2_python_prepare
+# @DESCRIPTION:
+# The default python_prepare(). A no-op.
+distutils-r2_python_prepare() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	[[ ${EAPI} == [45] ]] || die "${FUNCNAME} is banned in EAPI 6 (it was a no-op)"
+}
+
+# @FUNCTION: distutils-r2_python_configure
+# @DESCRIPTION:
+# The default python_configure(). A no-op.
+distutils-r2_python_configure() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	[[ ${EAPI} == [45] ]] || die "${FUNCNAME} is banned in EAPI 6 (it was a no-op)"
+}
+
+# @FUNCTION: _distutils-r2_create_setup_cfg
+# @INTERNAL
+# @DESCRIPTION:
+# Create implementation-specific configuration file for distutils,
+# setting proper build-dir (and install-dir) paths.
+_distutils-r2_create_setup_cfg() {
+	cat > "${HOME}"/.pydistutils.cfg <<-_EOF_ || die
+		[build]
+		build-base = ${BUILD_DIR}
+
+		# using a single directory for them helps us export
+		# ${PYTHONPATH} and ebuilds find the sources independently
+		# of whether the package installs extensions or not
+		#
+		# note: due to some packages (wxpython) relying on separate
+		# platlib & purelib dirs, we do not set --build-lib (which
+		# can not be overridden with --build-*lib)
+		build-platlib = %(build-base)s/lib
+		build-purelib = %(build-base)s/lib
+
+		# make the ebuild writer lives easier
+		build-scripts = %(build-base)s/scripts
+
+		# this is needed by distutils_install_for_testing since
+		# setuptools like to create .egg files for install --home.
+		[bdist_egg]
+		dist-dir = ${BUILD_DIR}/dist
+	_EOF_
+
+	# we can't refer to ${D} before src_install()
+	if [[ ${EBUILD_PHASE} == install ]]; then
+		cat >> "${HOME}"/.pydistutils.cfg <<-_EOF_ || die
+
+			# installation paths -- allow calling extra install targets
+			# without the default 'install'
+			[install]
+			compile = True
+			optimize = 2
+			root = ${D%/}
+		_EOF_
+
+		if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
+			cat >> "${HOME}"/.pydistutils.cfg <<-_EOF_ || die
+				install-scripts = $(python_get_scriptdir)
+			_EOF_
+		fi
+	fi
+}
+
+# @FUNCTION: _distutils-r2_copy_egg_info
+# @INTERNAL
+# @DESCRIPTION:
+# Copy egg-info files to the ${BUILD_DIR} (that's going to become
+# egg-base in esetup.py). This way, we respect whatever's in upstream
+# egg-info.
+_distutils-r2_copy_egg_info() {
+	mkdir -p "${BUILD_DIR}" || die
+	# stupid freebsd can't do 'cp -t ${BUILD_DIR} {} +'
+	find -name '*.egg-info' -type d -exec cp -R -p {} "${BUILD_DIR}"/ ';' || die
+}
+
+# @FUNCTION: distutils-r2_python_compile
+# @USAGE: [additional-args...]
+# @DESCRIPTION:
+# The default python_compile(). 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.
+#
+# This phase also sets up initial setup.cfg with build directories
+# and copies upstream egg-info files if supplied.
+distutils-r2_python_compile() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	_distutils-r2_copy_egg_info
+
+	local build_args=()
+	# distutils is parallel-capable since py3.5
+	# to avoid breaking stable ebuilds, enable it only if either:
+	# a. we're dealing with EAPI 7
+	# b. we're dealing with Python 3.7 or PyPy3
+	if python_is_python3 && [[ ${EPYTHON} != python3.4 ]]; then
+		if [[ ${EAPI} != [56] || ${EPYTHON} != python3.[56] ]]; then
+			local jobs=$(makeopts_jobs "${MAKEOPTS}" INF)
+			if [[ ${jobs} == INF ]]; then
+				local nproc=$(get_nproc)
+				jobs=$(( nproc + 1 ))
+			fi
+			build_args+=( -j "${jobs}" )
+		fi
+	fi
+
+	esetup.py build "${build_args[@]}" "${@}"
+}
+
+# @FUNCTION: _distutils-r2_wrap_scripts
+# @USAGE: <path> <bindir>
+# @INTERNAL
+# @DESCRIPTION:
+# Moves and wraps all installed scripts/executables as necessary.
+_distutils-r2_wrap_scripts() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	[[ ${#} -eq 2 ]] || die "usage: ${FUNCNAME} <path> <bindir>"
+	local path=${1}
+	local bindir=${2}
+
+	local PYTHON_SCRIPTDIR
+	python_export PYTHON_SCRIPTDIR
+
+	local f python_files=() non_python_files=()
+
+	if [[ -d ${path}${PYTHON_SCRIPTDIR} ]]; then
+		for f in "${path}${PYTHON_SCRIPTDIR}"/*; do
+			[[ -d ${f} ]] && die "Unexpected directory: ${f}"
+			debug-print "${FUNCNAME}: found executable at ${f#${path}/}"
+
+			local shebang
+			read -r shebang < "${f}"
+			if [[ ${shebang} == '#!'*${EPYTHON}* ]]; then
+				debug-print "${FUNCNAME}: matching shebang: ${shebang}"
+				python_files+=( "${f}" )
+			else
+				debug-print "${FUNCNAME}: non-matching shebang: ${shebang}"
+				non_python_files+=( "${f}" )
+			fi
+
+			mkdir -p "${path}${bindir}" || die
+		done
+
+		for f in "${python_files[@]}"; do
+			local basename=${f##*/}
+
+			debug-print "${FUNCNAME}: installing wrapper at ${bindir}/${basename}"
+			_python_ln_rel "${path}${EPREFIX}"/usr/lib/python-exec/python-exec2 \
+				"${path}${bindir}/${basename}" || die
+		done
+
+		for f in "${non_python_files[@]}"; do
+			local basename=${f##*/}
+
+			debug-print "${FUNCNAME}: moving ${f#${path}/} to ${bindir}/${basename}"
+			mv "${f}" "${path}${bindir}/${basename}" || die
+		done
+	fi
+}
+
+# @FUNCTION: distutils-r2_python_install
+# @USAGE: [additional-args...]
+# @DESCRIPTION:
+# The default python_install(). Runs 'esetup.py install', doing
+# intermediate root install and handling script wrapping afterwards.
+# Any parameters passed to this function will be appended
+# to the setup.py invocation (i.e. as options to the 'install' command).
+#
+# This phase updates the setup.cfg file with install directories.
+distutils-r2_python_install() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local args=( "${@}" )
+
+	# enable compilation for the install phase.
+	local -x PYTHONDONTWRITEBYTECODE=
+
+	# python likes to compile any module it sees, which triggers sandbox
+	# failures if some packages haven't compiled their modules yet.
+	addpredict "${EPREFIX}/usr/lib/${EPYTHON}"
+	addpredict "${EPREFIX}/usr/$(get_libdir)/${EPYTHON}"
+	addpredict /usr/lib/pypy2.7
+	addpredict /usr/lib/pypy3.6
+	addpredict /usr/lib/portage/pym
+	addpredict /usr/local # bug 498232
+
+	if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
+		# user may override --install-scripts
+		# note: this is poor but distutils argv parsing is dumb
+		local mydistutilsargs=( "${mydistutilsargs[@]}" )
+		local scriptdir=${EPREFIX}/usr/bin
+
+		# construct a list of mydistutilsargs[0] args[0] args[1]...
+		local arg arg_vars
+		[[ ${mydistutilsargs[@]} ]] && eval arg_vars+=(
+			'mydistutilsargs['{0..$(( ${#mydistutilsargs[@]} - 1 ))}']'
+		)
+		[[ ${args[@]} ]] && eval arg_vars+=(
+			'args['{0..$(( ${#args[@]} - 1 ))}']'
+		)
+
+		set -- "${arg_vars[@]}"
+		while [[ ${@} ]]; do
+			local arg_var=${1}
+			shift
+			local a=${!arg_var}
+
+			case "${a}" in
+				--install-scripts=*)
+					scriptdir=${a#--install-scripts=}
+					unset "${arg_var}"
+					;;
+				--install-scripts)
+					scriptdir=${!1}
+					unset "${arg_var}" "${1}"
+					shift
+					;;
+			esac
+		done
+	fi
+
+	local root=${D%/}/_${EPYTHON}
+	[[ ${DISTUTILS_SINGLE_IMPL} ]] && root=${D%/}
+
+	esetup.py install --root="${root}" "${args[@]}"
+
+	local forbidden_package_names=( examples test tests .pytest_cache )
+	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}/usr/$(get_libdir)"/pypy*/share
+		"${root}/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} ]]; then
+		_distutils-r2_wrap_scripts "${root}" "${scriptdir}"
+		multibuild_merge_root "${root}" "${D%/}"
+	fi
+}
+
+# @FUNCTION: distutils-r2_python_install_all
+# @DESCRIPTION:
+# The default python_install_all(). It installs the documentation.
+distutils-r2_python_install_all() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	einstalldocs
+
+	if declare -p EXAMPLES &>/dev/null; then
+		[[ ${EAPI} != [45] ]] && die "EXAMPLES are banned in EAPI ${EAPI}"
+
+		(
+			docinto examples
+			dodoc -r "${EXAMPLES[@]}"
+		)
+		docompress -x "/usr/share/doc/${PF}/examples"
+	fi
+}
+
+# @FUNCTION: distutils-r2_run_phase
+# @USAGE: [<argv>...]
+# @INTERNAL
+# @DESCRIPTION:
+# Run the given command.
+#
+# If out-of-source builds are used, the phase function is run in source
+# directory, with BUILD_DIR pointing at the build directory
+# and PYTHONPATH having an entry for the module build directory.
+#
+# If in-source builds are used, the command is executed in the directory
+# holding the per-implementation copy of sources. BUILD_DIR points
+# to the 'build' subdirectory.
+distutils-r2_run_phase() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	if [[ ${DISTUTILS_IN_SOURCE_BUILD} ]]; then
+		# only force BUILD_DIR if implementation is explicitly enabled
+		# for building; any-r2 API may select one that is not
+		# https://bugs.gentoo.org/701506
+		if [[ ! ${DISTUTILS_SINGLE_IMPL} ]] &&
+				has "${EPYTHON/./_}" ${PYTHON_TARGETS}; then
+			cd "${BUILD_DIR}" || die
+		fi
+		local BUILD_DIR=${BUILD_DIR}/build
+	fi
+	local -x PYTHONPATH="${BUILD_DIR}/lib:${PYTHONPATH}"
+
+	# Bug 559644
+	# using PYTHONPATH when the ${BUILD_DIR}/lib is not created yet might lead to
+	# problems in setup.py scripts that try to import modules/packages from that path
+	# during the build process (Python at startup evaluates PYTHONPATH, if the dir is
+	# not valid then associates a NullImporter object to ${BUILD_DIR}/lib storing it
+	# in the sys.path_importer_cache)
+	mkdir -p "${BUILD_DIR}/lib" || die
+
+	# Set up build environment, bug #513664.
+	local -x AR=${AR} CC=${CC} CPP=${CPP} CXX=${CXX}
+	tc-export AR CC CPP CXX
+
+	# How to build Python modules in different worlds...
+	local ldopts
+	case "${CHOST}" in
+		# provided by haubi, 2014-07-08
+		*-aix*) ldopts='-shared -Wl,-berok';; # good enough
+		# provided by grobian, 2014-06-22, bug #513664 c7
+		*-darwin*) ldopts='-bundle -undefined dynamic_lookup';;
+		*) ldopts='-shared';;
+	esac
+
+	local -x LDSHARED="${CC} ${ldopts}" LDCXXSHARED="${CXX} ${ldopts}"
+
+	"${@}"
+
+	cd "${_DISTUTILS_INITIAL_CWD}" || die
+}
+
+# @FUNCTION: _distutils-r2_run_common_phase
+# @USAGE: [<argv>...]
+# @INTERNAL
+# @DESCRIPTION:
+# Run the given command, restoring the state for a most preferred Python
+# implementation matching DISTUTILS_ALL_SUBPHASE_IMPLS.
+#
+# If in-source build is used, the command will be run in the copy
+# of sources made for the selected Python interpreter.
+_distutils-r2_run_common_phase() {
+	local DISTUTILS_ORIG_BUILD_DIR=${BUILD_DIR}
+
+	if [[ ${DISTUTILS_SINGLE_IMPL} ]]; then
+		# reuse the dedicated code branch
+		_distutils-r2_run_foreach_impl "${@}"
+	else
+		local -x EPYTHON PYTHON
+		local -x PATH=${PATH} PKG_CONFIG_PATH=${PKG_CONFIG_PATH}
+		python_setup "${DISTUTILS_ALL_SUBPHASE_IMPLS[@]}"
+
+		local MULTIBUILD_VARIANTS=( "${EPYTHON/./_}" )
+		# store for restoring after distutils-r2_run_phase.
+		local _DISTUTILS_INITIAL_CWD=${PWD}
+		multibuild_foreach_variant \
+			distutils-r2_run_phase "${@}"
+	fi
+}
+
+# @FUNCTION: _distutils-r2_run_foreach_impl
+# @INTERNAL
+# @DESCRIPTION:
+# Run the given phase for each implementation if multiple implementations
+# are enabled, once otherwise.
+_distutils-r2_run_foreach_impl() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	# store for restoring after distutils-r2_run_phase.
+	local _DISTUTILS_INITIAL_CWD=${PWD}
+	set -- distutils-r2_run_phase "${@}"
+
+	if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
+		python_foreach_impl "${@}"
+	else
+		if [[ ! ${EPYTHON} ]]; then
+			die "EPYTHON unset, python-single-r2_pkg_setup not called?!"
+		fi
+		local BUILD_DIR=${BUILD_DIR:-${S}}
+		BUILD_DIR=${BUILD_DIR%%/}_${EPYTHON}
+
+		"${@}"
+	fi
+}
+
+distutils-r2_src_prepare() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local _DISTUTILS_DEFAULT_CALLED
+
+	# common preparations
+	if declare -f python_prepare_all >/dev/null; then
+		python_prepare_all
+	else
+		distutils-r2_python_prepare_all
+	fi
+
+	if [[ ! ${_DISTUTILS_DEFAULT_CALLED} ]]; then
+		local cmd=die
+		[[ ${EAPI} == [45] ]] && cmd=eqawarn
+
+		"${cmd}" "QA: python_prepare_all() didn't call distutils-r2_python_prepare_all"
+	fi
+
+	if declare -f python_prepare >/dev/null; then
+		_distutils-r2_run_foreach_impl python_prepare
+	fi
+}
+
+distutils-r2_src_configure() {
+	python_export_utf8_locale
+	[[ ${EAPI} == [56] ]] && xdg_environment_reset # Bug 577704
+
+	if declare -f python_configure >/dev/null; then
+		_distutils-r2_run_foreach_impl python_configure
+	fi
+
+	if declare -f python_configure_all >/dev/null; then
+		_distutils-r2_run_common_phase python_configure_all
+	fi
+}
+
+distutils-r2_src_compile() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	if declare -f python_compile >/dev/null; then
+		_distutils-r2_run_foreach_impl python_compile
+	else
+		_distutils-r2_run_foreach_impl distutils-r2_python_compile
+	fi
+
+	if declare -f python_compile_all >/dev/null; then
+		_distutils-r2_run_common_phase python_compile_all
+	fi
+}
+
+# @FUNCTION: _distutils-r2_clean_egg_info
+# @INTERNAL
+# @DESCRIPTION:
+# Clean up potential stray egg-info files left by setuptools test phase.
+# Those files ended up being unversioned, and caused issues:
+# https://bugs.gentoo.org/534058
+_distutils-r2_clean_egg_info() {
+	rm -rf "${BUILD_DIR}"/lib/*.egg-info || die
+}
+
+distutils-r2_src_test() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	if declare -f python_test >/dev/null; then
+		_distutils-r2_run_foreach_impl python_test
+		_distutils-r2_run_foreach_impl _distutils-r2_clean_egg_info
+	fi
+
+	if declare -f python_test_all >/dev/null; then
+		_distutils-r2_run_common_phase python_test_all
+	fi
+}
+
+# @FUNCTION: _distutils-r2_check_namespace_pth
+# @INTERNAL
+# @DESCRIPTION:
+# Check if any *-nspkg.pth files were installed (by setuptools)
+# and warn about the policy non-conformance if they were.
+_distutils-r2_check_namespace_pth() {
+	local f pth=()
+
+	while IFS= read -r -d '' f; do
+		pth+=( "${f}" )
+	done < <(find "${ED%/}" -name '*-nspkg.pth' -print0)
+
+	if [[ ${pth[@]} ]]; then
+		ewarn "The following *-nspkg.pth files were found installed:"
+		ewarn
+		for f in "${pth[@]}"; do
+			ewarn "  ${f#${ED%/}}"
+		done
+		ewarn
+		ewarn "The presence of those files may break namespaces in Python 3.5+. Please"
+		ewarn "read our documentation on reliable handling of namespaces and update"
+		ewarn "the ebuild accordingly:"
+		ewarn
+		ewarn "  https://wiki.gentoo.org/wiki/Project:Python/Namespace_packages"
+	fi
+}
+
+distutils-r2_src_install() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	if declare -f python_install >/dev/null; then
+		_distutils-r2_run_foreach_impl python_install
+	else
+		_distutils-r2_run_foreach_impl distutils-r2_python_install
+	fi
+
+	if declare -f python_install_all >/dev/null; then
+		_distutils-r2_run_common_phase python_install_all
+	else
+		_distutils-r2_run_common_phase distutils-r2_python_install_all
+	fi
+
+	_distutils-r2_check_namespace_pth
+}
+
+# -- distutils.eclass functions --
+
+distutils_get_intermediate_installation_image() {
+	die "${FUNCNAME}() is invalid for distutils-r2"
+}
+
+distutils_src_unpack() {
+	die "${FUNCNAME}() is invalid for distutils-r2, and you don't want it in EAPI ${EAPI} anyway"
+}
+
+distutils_src_prepare() {
+	die "${FUNCNAME}() is invalid for distutils-r2, you probably want: ${FUNCNAME/_/-r2_}"
+}
+
+distutils_src_compile() {
+	die "${FUNCNAME}() is invalid for distutils-r2, you probably want: ${FUNCNAME/_/-r2_}"
+}
+
+distutils_src_test() {
+	die "${FUNCNAME}() is invalid for distutils-r2, you probably want: ${FUNCNAME/_/-r2_}"
+}
+
+distutils_src_install() {
+	die "${FUNCNAME}() is invalid for distutils-r2, you probably want: ${FUNCNAME/_/-r2_}"
+}
+
+distutils_pkg_postinst() {
+	die "${FUNCNAME}() is invalid for distutils-r2, and pkg_postinst is unnecessary"
+}
+
+distutils_pkg_postrm() {
+	die "${FUNCNAME}() is invalid for distutils-r2, and pkg_postrm is unnecessary"
+}
+
+_DISTUTILS_R2=1
+fi
diff --git a/eclass/python-any-r2.eclass b/eclass/python-any-r2.eclass
new file mode 100644
index 000000000000..08e424254983
--- /dev/null
+++ b/eclass/python-any-r2.eclass
@@ -0,0 +1,364 @@
+# Copyright 1999-2020 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: python-any-r2.eclass
+# @MAINTAINER:
+# Python team <python@gentoo.org>
+# @AUTHOR:
+# Author: Michał Górny <mgorny@gentoo.org>
+# @SUPPORTED_EAPIS: 5 6 7
+# @BLURB: An eclass for packages having build-time dependency on Python.
+# @DESCRIPTION:
+# A minimal eclass for packages which need any Python interpreter
+# installed without a need for explicit choice and invariability.
+# This usually involves packages requiring Python at build-time
+# but having no other relevance to it.
+#
+# This eclass provides a minimal PYTHON_DEPS variable with a dependency
+# string on any of the supported Python implementations. It also exports
+# pkg_setup() which finds the best supported implementation and sets it
+# as the active one.
+#
+# Optionally, you can define a python_check_deps() function. It will
+# be called by the eclass with EPYTHON set to each matching Python
+# implementation and it is expected to check whether the implementation
+# fulfills the package requirements. You can use the locally exported
+# PYTHON_USEDEP to check USE-dependencies of relevant packages. It
+# should return a true value (0) if the Python implementation fulfills
+# the requirements, a false value (non-zero) otherwise.
+#
+# Please note that python-any-r2 will always inherit python-utils-r2
+# as well. Thus, all the functions defined there can be used in the
+# packages using python-any-r2, and there is no need ever to inherit
+# both.
+#
+# For more information, please see the Python Guide:
+# https://dev.gentoo.org/~mgorny/python-guide/
+
+case "${EAPI:-0}" in
+	[0-4]) die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}" ;;
+	[5-7]) ;;
+	*)     die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" ;;
+esac
+
+if [[ ! ${_PYTHON_ANY_R2} ]]; then
+
+if [[ ${_PYTHON_R2} ]]; then
+	die 'python-any-r2.eclass can not be used with python-r2.eclass.'
+elif [[ ${_PYTHON_SINGLE_R2} ]]; then
+	die 'python-any-r2.eclass can not be used with python-single-r2.eclass.'
+fi
+
+inherit python-utils-r2
+
+fi
+
+EXPORT_FUNCTIONS pkg_setup
+
+# @ECLASS-VARIABLE: PYTHON_COMPAT
+# @REQUIRED
+# @DESCRIPTION:
+# This variable contains a list of Python implementations the package
+# supports. It must be set before the `inherit' call. It has to be
+# an array.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT=( python{2_5,2_6,2_7} )
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_COMPAT_OVERRIDE
+# @INTERNAL
+# @DESCRIPTION:
+# This variable can be used when working with ebuilds to override
+# the in-ebuild PYTHON_COMPAT. It is a string naming the implementation
+# which will be used to build the package. It needs to be specified
+# in the calling environment, and not in ebuilds.
+#
+# It should be noted that in order to preserve metadata immutability,
+# PYTHON_COMPAT_OVERRIDE does not affect dependencies. The value of
+# EPYTHON and eselect-python preferences are ignored. Dependencies need
+# to be satisfied manually.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT_OVERRIDE='pypy' emerge -1v dev-python/bar
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_REQ_USE
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The list of USEflags required to be enabled on the Python
+# implementations, formed as a USE-dependency string. It should be valid
+# for all implementations in PYTHON_COMPAT, so it may be necessary to
+# use USE defaults.
+#
+# Example:
+# @CODE
+# PYTHON_REQ_USE="gdbm,ncurses(-)?"
+# @CODE
+#
+# It will cause the Python dependencies to look like:
+# @CODE
+# || ( dev-lang/python:X.Y[gdbm,ncurses(-)?] ... )
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_DEPS
+# @DESCRIPTION:
+# This is an eclass-generated Python dependency string for all
+# implementations listed in PYTHON_COMPAT.
+#
+# Any of the supported interpreters will satisfy the dependency.
+#
+# Example use:
+# @CODE
+# DEPEND="${RDEPEND}
+#	${PYTHON_DEPS}"
+# @CODE
+#
+# Example value:
+# @CODE
+# || ( dev-lang/python:2.7[gdbm]
+# 	dev-lang/python:2.6[gdbm] )
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_USEDEP
+# @DESCRIPTION:
+# An eclass-generated USE-dependency string for the currently tested
+# implementation. It is set locally for python_check_deps() call.
+#
+# The generate USE-flag list is compatible with packages using python-r2,
+# python-single-r2 and python-distutils-ng eclasses. It must not be used
+# on packages using python.eclass.
+#
+# Example use:
+# @CODE
+# python_check_deps() {
+#	has_version "dev-python/foo[${PYTHON_USEDEP}]"
+# }
+# @CODE
+#
+# Example value:
+# @CODE
+# python_targets_python2_7(-)?,python_single_target_python2_7(+)?
+# @CODE
+
+_python_any_set_globals() {
+	local usestr deps i PYTHON_PKG_DEP
+	[[ ${PYTHON_REQ_USE} ]] && usestr="[${PYTHON_REQ_USE}]"
+
+	_python_set_impls
+
+	for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+		python_export "${i}" PYTHON_PKG_DEP
+
+		# note: need to strip '=' slot operator for || deps
+		deps="${PYTHON_PKG_DEP/:0=/:0} ${deps}"
+	done
+	deps="|| ( ${deps})"
+
+	if [[ ${PYTHON_DEPS+1} ]]; then
+		if [[ ${PYTHON_DEPS} != "${deps}" ]]; then
+			eerror "PYTHON_DEPS have changed between inherits (PYTHON_REQ_USE?)!"
+			eerror "Before: ${PYTHON_DEPS}"
+			eerror "Now   : ${deps}"
+			die "PYTHON_DEPS integrity check failed"
+		fi
+	else
+		PYTHON_DEPS=${deps}
+		readonly PYTHON_DEPS
+	fi
+
+	if [[ ! ${PYTHON_REQUIRED_USE+1} ]]; then
+		# fake var to catch mistaken usage
+		PYTHON_REQUIRED_USE='I-DO-NOT-EXIST-IN-PYTHON-ANY-R1'
+		readonly PYTHON_REQUIRED_USE
+	fi
+}
+_python_any_set_globals
+unset -f _python_any_set_globals
+
+if [[ ! ${_PYTHON_ANY_R2} ]]; then
+
+# @FUNCTION: python_gen_any_dep
+# @USAGE: <dependency-block>
+# @DESCRIPTION:
+# Generate an any-of dependency that enforces a version match between
+# the Python interpreter and Python packages. <dependency-block> needs
+# to list one or more dependencies with verbatim '${PYTHON_USEDEP}'
+# references (quoted!) that will get expanded inside the function.
+#
+# This should be used along with an appropriate python_check_deps()
+# that checks which of the any-of blocks were matched.
+#
+# Example use:
+# @CODE
+# DEPEND="$(python_gen_any_dep '
+#	dev-python/foo[${PYTHON_USEDEP}]
+#	|| ( dev-python/bar[${PYTHON_USEDEP}]
+#		dev-python/baz[${PYTHON_USEDEP}] )')"
+#
+# python_check_deps() {
+#	has_version "dev-python/foo[${PYTHON_USEDEP}]" \
+#		&& { has_version "dev-python/bar[${PYTHON_USEDEP}]" \
+#			|| has_version "dev-python/baz[${PYTHON_USEDEP}]"; }
+# }
+# @CODE
+#
+# Example value:
+# @CODE
+# || (
+#	(
+#		dev-lang/python:2.7
+#		dev-python/foo[python_targets_python2_7(-)?,python_single_target_python2_7(+)?]
+#		|| ( dev-python/bar[python_targets_python2_7(-)?,python_single_target_python2_7(+)?]
+#			dev-python/baz[python_targets_python2_7(-)?,python_single_target_python2_7(+)?] )
+#	)
+#	(
+#		dev-lang/python:3.3
+#		dev-python/foo[python_targets_python3_3(-)?,python_single_target_python3_3(+)?]
+#		|| ( dev-python/bar[python_targets_python3_3(-)?,python_single_target_python3_3(+)?]
+#			dev-python/baz[python_targets_python3_3(-)?,python_single_target_python3_3(+)?] )
+#	)
+# )
+# @CODE
+python_gen_any_dep() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local depstr=${1}
+	[[ ${depstr} ]] || die "No dependency string provided"
+
+	local i PYTHON_PKG_DEP out=
+	for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+		local PYTHON_USEDEP="python_targets_${i}(-),python_single_target_${i}(+)"
+		python_export "${i}" PYTHON_PKG_DEP
+
+		local i_depstr=${depstr//\$\{PYTHON_USEDEP\}/${PYTHON_USEDEP}}
+		# note: need to strip '=' slot operator for || deps
+		out="( ${PYTHON_PKG_DEP%=} ${i_depstr} ) ${out}"
+	done
+	echo "|| ( ${out})"
+}
+
+# @FUNCTION: _python_EPYTHON_supported
+# @USAGE: <epython>
+# @INTERNAL
+# @DESCRIPTION:
+# Check whether the specified implementation is supported by package
+# (specified in PYTHON_COMPAT). Calls python_check_deps() if declared.
+_python_EPYTHON_supported() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local EPYTHON=${1}
+	local i=${EPYTHON/./_}
+
+	case "${i}" in
+		python*|jython*|pypy*)
+			;;
+		*)
+			ewarn "Invalid EPYTHON: ${EPYTHON}"
+			return 1
+			;;
+	esac
+
+	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}(+)"
+				python_check_deps
+				return ${?}
+			fi
+
+			return 0
+		fi
+	elif ! has "${i}" "${_PYTHON_ALL_IMPLS[@]}"; then
+		ewarn "Invalid EPYTHON: ${EPYTHON}"
+	fi
+	return 1
+}
+
+# @FUNCTION: python_setup
+# @DESCRIPTION:
+# Determine what the best installed (and supported) Python
+# implementation is, and set the Python build environment up for it.
+#
+# This function will call python_check_deps() if defined.
+python_setup() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	# support developer override
+	if [[ ${PYTHON_COMPAT_OVERRIDE} ]]; then
+		local impls=( ${PYTHON_COMPAT_OVERRIDE} )
+		[[ ${#impls[@]} -eq 1 ]] || die "PYTHON_COMPAT_OVERRIDE must name exactly one implementation for python-any-r2"
+
+		ewarn "WARNING: PYTHON_COMPAT_OVERRIDE in effect. The following Python"
+		ewarn "implementation will be used:"
+		ewarn
+		ewarn "	${PYTHON_COMPAT_OVERRIDE}"
+		ewarn
+		ewarn "Dependencies won't be satisfied, and EPYTHON/eselect-python will be ignored."
+
+		python_export "${impls[0]}" EPYTHON PYTHON
+		python_wrapper_setup
+		einfo "Using ${EPYTHON} to build"
+		return
+	fi
+
+	# first, try ${EPYTHON}... maybe it's good enough for us.
+	if [[ ${EPYTHON} ]]; then
+		if _python_EPYTHON_supported "${EPYTHON}"; then
+			python_export EPYTHON PYTHON
+			python_wrapper_setup
+			einfo "Using ${EPYTHON} to build"
+			return
+		fi
+	fi
+
+	# then, try eselect-python
+	local variant i
+	for variant in '' '--python2' '--python3'; do
+		i=$(eselect python --show ${variant} 2>/dev/null)
+
+		if [[ ! ${i} ]]; then
+			# no eselect-python?
+			break
+		elif _python_EPYTHON_supported "${i}"; then
+			python_export "${i}" EPYTHON PYTHON
+			python_wrapper_setup
+			einfo "Using ${EPYTHON} to build"
+			return
+		fi
+	done
+
+	# fallback to best installed impl.
+	# (reverse iteration over _PYTHON_SUPPORTED_IMPLS)
+	for (( i = ${#_PYTHON_SUPPORTED_IMPLS[@]} - 1; i >= 0; i-- )); do
+		python_export "${_PYTHON_SUPPORTED_IMPLS[i]}" EPYTHON PYTHON
+		if _python_EPYTHON_supported "${EPYTHON}"; then
+			python_wrapper_setup
+			einfo "Using ${EPYTHON} to build"
+			return
+		fi
+	done
+
+	eerror "No Python implementation found for the build. This is usually"
+	eerror "a bug in the ebuild. Please report it to bugs.gentoo.org"
+	eerror "along with the build log."
+	echo
+	die "No supported Python implementation installed."
+}
+
+# @FUNCTION: python-any-r2_pkg_setup
+# @DESCRIPTION:
+# Runs python_setup during from-source installs.
+#
+# In a binary package installs is a no-op. If you need Python in pkg_*
+# phases of a binary package, call python_setup directly.
+python-any-r2_pkg_setup() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	[[ ${MERGE_TYPE} != binary ]] && python_setup
+}
+
+_PYTHON_ANY_R2=1
+fi
diff --git a/eclass/python-r2.eclass b/eclass/python-r2.eclass
new file mode 100644
index 000000000000..a71ebeba7c54
--- /dev/null
+++ b/eclass/python-r2.eclass
@@ -0,0 +1,829 @@
+# Copyright 1999-2020 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: python-r2.eclass
+# @MAINTAINER:
+# Python team <python@gentoo.org>
+# @AUTHOR:
+# Author: Michał Górny <mgorny@gentoo.org>
+# @SUPPORTED_EAPIS: 5 6 7
+# @BLURB: A common, simple eclass for Python packages.
+# @DESCRIPTION:
+# A common eclass providing helper functions to build and install
+# packages supporting being installed for multiple Python
+# implementations.
+#
+# This eclass sets correct IUSE. Modification of REQUIRED_USE has to
+# be done by the author of the ebuild (but PYTHON_REQUIRED_USE is
+# provided for convenience, see below). python-r2 exports PYTHON_DEPS
+# and PYTHON_USEDEP so you can create correct dependencies for your
+# package easily. It also provides methods to easily run a command for
+# each enabled Python implementation and duplicate the sources for them.
+#
+# Please note that python-r2 will always inherit python-utils-r2 as
+# well. Thus, all the functions defined there can be used
+# in the packages using python-r2, and there is no need ever to inherit
+# both.
+#
+# For more information, please see the Python Guide:
+# https://dev.gentoo.org/~mgorny/python-guide/
+
+case "${EAPI:-0}" in
+	0|1|2|3|4)
+		die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
+		;;
+	5|6|7)
+		# EAPI=5 is required for sane USE_EXPAND dependencies
+		;;
+	*)
+		die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
+		;;
+esac
+
+if [[ ! ${_PYTHON_R2} ]]; then
+
+if [[ ${_PYTHON_SINGLE_R2} ]]; then
+	die 'python-r2.eclass can not be used with python-single-r2.eclass.'
+elif [[ ${_PYTHON_ANY_R2} ]]; then
+	die 'python-r2.eclass can not be used with python-any-r2.eclass.'
+fi
+
+[[ ${EAPI} == [45] ]] && inherit eutils
+inherit multibuild python-utils-r2
+
+fi
+
+# @ECLASS-VARIABLE: PYTHON_COMPAT
+# @REQUIRED
+# @DESCRIPTION:
+# This variable contains a list of Python implementations the package
+# supports. It must be set before the `inherit' call. It has to be
+# an array.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT=( python2_7 python3_3 python3_4 )
+# @CODE
+#
+# Please note that you can also use bash brace expansion if you like:
+# @CODE
+# PYTHON_COMPAT=( python2_7 python3_{3,4} )
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_COMPAT_OVERRIDE
+# @INTERNAL
+# @DESCRIPTION:
+# This variable can be used when working with ebuilds to override
+# the in-ebuild PYTHON_COMPAT. It is a string listing all
+# the implementations which package will be built for. It need be
+# specified in the calling environment, and not in ebuilds.
+#
+# It should be noted that in order to preserve metadata immutability,
+# PYTHON_COMPAT_OVERRIDE does not affect IUSE nor dependencies.
+# The state of PYTHON_TARGETS is ignored, and all the implementations
+# in PYTHON_COMPAT_OVERRIDE are built. Dependencies need to be satisfied
+# manually.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT_OVERRIDE='pypy python3_3' emerge -1v dev-python/foo
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_REQ_USE
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The list of USEflags required to be enabled on the chosen Python
+# implementations, formed as a USE-dependency string. It should be valid
+# for all implementations in PYTHON_COMPAT, so it may be necessary to
+# use USE defaults.
+#
+# This should be set before calling `inherit'.
+#
+# Example:
+# @CODE
+# PYTHON_REQ_USE="gdbm,ncurses(-)?"
+# @CODE
+#
+# It will cause the Python dependencies to look like:
+# @CODE
+# python_targets_pythonX_Y? ( dev-lang/python:X.Y[gdbm,ncurses(-)?] )
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_DEPS
+# @DESCRIPTION:
+# This is an eclass-generated Python dependency string for all
+# implementations listed in PYTHON_COMPAT.
+#
+# Example use:
+# @CODE
+# RDEPEND="${PYTHON_DEPS}
+#	dev-foo/mydep"
+# DEPEND="${RDEPEND}"
+# @CODE
+#
+# Example value:
+# @CODE
+# dev-lang/python-exec:=
+# python_targets_python2_7? ( dev-lang/python:2.7[gdbm] )
+# python_targets_pypy? ( dev-python/pypy[gdbm] )
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_USEDEP
+# @DESCRIPTION:
+# This is an eclass-generated USE-dependency string which can be used to
+# depend on another Python package being built for the same Python
+# implementations.
+#
+# The generate USE-flag list is compatible with packages using python-r2
+# and python-distutils-ng eclasses. It must not be used on packages
+# using python.eclass.
+#
+# Example use:
+# @CODE
+# RDEPEND="dev-python/foo[${PYTHON_USEDEP}]"
+# @CODE
+#
+# Example value:
+# @CODE
+# python_targets_python2_7(-)?,python_targets_python3_4(-)?
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_REQUIRED_USE
+# @DESCRIPTION:
+# This is an eclass-generated required-use expression which ensures at
+# least one Python implementation has been enabled.
+#
+# This expression should be utilized in an ebuild by including it in
+# REQUIRED_USE, optionally behind a use flag.
+#
+# Example use:
+# @CODE
+# REQUIRED_USE="python? ( ${PYTHON_REQUIRED_USE} )"
+# @CODE
+#
+# Example value:
+# @CODE
+# || ( python_targets_python2_7 python_targets_python3_4 )
+# @CODE
+
+_python_set_globals() {
+	local deps i PYTHON_PKG_DEP
+
+	_python_set_impls
+
+	for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+		python_export "${i}" PYTHON_PKG_DEP
+		deps+="python_targets_${i}? ( ${PYTHON_PKG_DEP} ) "
+	done
+
+	local flags=( "${_PYTHON_SUPPORTED_IMPLS[@]/#/python_targets_}" )
+	local optflags=${flags[@]/%/(-)?}
+
+	# A nice QA trick here. Since a python-single-r2 package has to have
+	# at least one PYTHON_SINGLE_TARGET enabled (REQUIRED_USE),
+	# the following check will always fail on those packages. Therefore,
+	# it should prevent developers from mistakenly depending on packages
+	# not supporting multiple Python implementations.
+
+	local flags_st=( "${_PYTHON_SUPPORTED_IMPLS[@]/#/-python_single_target_}" )
+	optflags+=,${flags_st[@]/%/(-)}
+	local requse="|| ( ${flags[*]} )"
+	local usedep=${optflags// /,}
+
+	# 1) well, python-exec would suffice as an RDEP
+	# but no point in making this overcomplex, BDEP doesn't hurt anyone
+	# 2) python-exec should be built with all targets forced anyway
+	# but if new targets were added, we may need to force a rebuild
+	deps+=">=dev-lang/python-exec-2:=[${usedep}]"
+
+	if [[ ${PYTHON_DEPS+1} ]]; then
+		# IUSE is magical, so we can't really check it
+		# (but we verify PYTHON_COMPAT already)
+
+		if [[ ${PYTHON_DEPS} != "${deps}" ]]; then
+			eerror "PYTHON_DEPS have changed between inherits (PYTHON_REQ_USE?)!"
+			eerror "Before: ${PYTHON_DEPS}"
+			eerror "Now   : ${deps}"
+			die "PYTHON_DEPS integrity check failed"
+		fi
+
+		# these two are formality -- they depend on PYTHON_COMPAT only
+		if [[ ${PYTHON_REQUIRED_USE} != ${requse} ]]; then
+			eerror "PYTHON_REQUIRED_USE have changed between inherits!"
+			eerror "Before: ${PYTHON_REQUIRED_USE}"
+			eerror "Now   : ${requse}"
+			die "PYTHON_REQUIRED_USE integrity check failed"
+		fi
+
+		if [[ ${PYTHON_USEDEP} != "${usedep}" ]]; then
+			eerror "PYTHON_USEDEP have changed between inherits!"
+			eerror "Before: ${PYTHON_USEDEP}"
+			eerror "Now   : ${usedep}"
+			die "PYTHON_USEDEP integrity check failed"
+		fi
+	else
+		IUSE=${flags[*]}
+
+		PYTHON_DEPS=${deps}
+		PYTHON_REQUIRED_USE=${requse}
+		PYTHON_USEDEP=${usedep}
+		readonly PYTHON_DEPS PYTHON_REQUIRED_USE
+	fi
+}
+_python_set_globals
+unset -f _python_set_globals
+
+if [[ ! ${_PYTHON_R2} ]]; then
+
+# @FUNCTION: _python_validate_useflags
+# @INTERNAL
+# @DESCRIPTION:
+# Enforce the proper setting of PYTHON_TARGETS, if PYTHON_COMPAT_OVERRIDE
+# is not in effect. If it is, just warn that the flags will be ignored.
+_python_validate_useflags() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	if [[ ${PYTHON_COMPAT_OVERRIDE} ]]; then
+		if [[ ! ${_PYTHON_COMPAT_OVERRIDE_WARNED} ]]; then
+			ewarn "WARNING: PYTHON_COMPAT_OVERRIDE in effect. The following Python"
+			ewarn "implementations will be enabled:"
+			ewarn
+			ewarn "	${PYTHON_COMPAT_OVERRIDE}"
+			ewarn
+			ewarn "Dependencies won't be satisfied, and PYTHON_TARGETS will be ignored."
+			_PYTHON_COMPAT_OVERRIDE_WARNED=1
+		fi
+		# we do not use flags with PCO
+		return
+	fi
+
+	local i
+
+	for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+		use "python_targets_${i}" && return 0
+	done
+
+	eerror "No Python implementation selected for the build. Please add one"
+	eerror "of the following values to your PYTHON_TARGETS (in make.conf):"
+	eerror
+	eerror "${PYTHON_COMPAT[@]}"
+	echo
+	die "No supported Python implementation in PYTHON_TARGETS."
+}
+
+# @FUNCTION: _python_gen_usedep
+# @INTERNAL
+# @USAGE: [<pattern>...]
+# @DESCRIPTION:
+# Output a USE dependency string for Python implementations which
+# are both in PYTHON_COMPAT and match any of the patterns passed
+# as parameters to the function.
+#
+# The patterns can be either fnmatch-style patterns (matched via bash
+# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
+# appropriately all enabled Python 2/3 implementations (alike
+# python_is_python3). Remember to escape or quote the fnmatch patterns
+# to prevent accidental shell filename expansion.
+#
+# This is an internal function used to implement python_gen_cond_dep
+# and deprecated python_gen_usedep.
+_python_gen_usedep() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local impl matches=()
+
+	for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+		if _python_impl_matches "${impl}" "${@}"; then
+			matches+=(
+				"python_targets_${impl}(-)?"
+				"-python_single_target_${impl}(-)"
+			)
+		fi
+	done
+
+	[[ ${matches[@]} ]] || die "No supported implementations match python_gen_usedep patterns: ${@}"
+
+	local out=${matches[@]}
+	echo "${out// /,}"
+}
+
+# @FUNCTION: python_gen_usedep
+# @USAGE: <pattern> [...]
+# @DESCRIPTION:
+# DEPRECATED.  Please use python_gen_cond_dep instead.
+#
+# Output a USE dependency string for Python implementations which
+# are both in PYTHON_COMPAT and match any of the patterns passed
+# as parameters to the function.
+#
+# The patterns can be either fnmatch-style patterns (matched via bash
+# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
+# appropriately all enabled Python 2/3 implementations (alike
+# python_is_python3). Remember to escape or quote the fnmatch patterns
+# to prevent accidental shell filename expansion.
+#
+# When all implementations are requested, please use ${PYTHON_USEDEP}
+# instead. Please also remember to set an appropriate REQUIRED_USE
+# to avoid ineffective USE flags.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT=( python{2_7,3_4} )
+# DEPEND="doc? ( dev-python/epydoc[$(python_gen_usedep 'python2*')] )"
+# @CODE
+#
+# It will cause the dependency to look like:
+# @CODE
+# DEPEND="doc? ( dev-python/epydoc[python_targets_python2_7?] )"
+# @CODE
+python_gen_usedep() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	# output only once, during some reasonable phase
+	# (avoid spamming cache regen runs)
+	if [[ ${EBUILD_PHASE} == setup ]]; then
+		eqawarn "python_gen_usedep() is deprecated. Please use python_gen_cond_dep instead."
+	fi
+	_python_gen_usedep "${@}"
+}
+
+# @FUNCTION: python_gen_useflags
+# @USAGE: [<pattern>...]
+# @DESCRIPTION:
+# Output a list of USE flags for Python implementations which
+# are both in PYTHON_COMPAT and match any of the patterns passed
+# as parameters to the function.
+#
+# The patterns can be either fnmatch-style patterns (matched via bash
+# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
+# appropriately all enabled Python 2/3 implementations (alike
+# python_is_python3). Remember to escape or quote the fnmatch patterns
+# to prevent accidental shell filename expansion.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT=( python{2_7,3_4} )
+# REQUIRED_USE="doc? ( || ( $(python_gen_useflags python2*) ) )"
+# @CODE
+#
+# It will cause the variable to look like:
+# @CODE
+# REQUIRED_USE="doc? ( || ( python_targets_python2_7 ) )"
+# @CODE
+python_gen_useflags() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local impl matches=()
+
+	for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+		if _python_impl_matches "${impl}" "${@}"; then
+			matches+=( "python_targets_${impl}" )
+		fi
+	done
+
+	echo "${matches[@]}"
+}
+
+# @FUNCTION: python_gen_cond_dep
+# @USAGE: <dependency> [<pattern>...]
+# @DESCRIPTION:
+# Output a list of <dependency>-ies made conditional to USE flags
+# of Python implementations which are both in PYTHON_COMPAT and match
+# any of the patterns passed as the remaining parameters.
+#
+# The patterns can be either fnmatch-style patterns (matched via bash
+# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
+# appropriately all enabled Python 2/3 implementations (alike
+# python_is_python3). Remember to escape or quote the fnmatch patterns
+# to prevent accidental shell filename expansion.
+#
+# In order to enforce USE constraints on the packages, verbatim
+# '${PYTHON_USEDEP}' (quoted!) may be placed in the dependency
+# specification. It will get expanded within the function into a proper
+# USE dependency string.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT=( python{2_7,3_{3,4}} pypy )
+# RDEPEND="$(python_gen_cond_dep \
+#   'dev-python/unittest2[${PYTHON_USEDEP}]' python2_7 pypy )"
+# @CODE
+#
+# It will cause the variable to look like:
+# @CODE
+# RDEPEND="python_targets_python2_7? (
+#     dev-python/unittest2[python_targets_python2_7?] )
+#	python_targets_pypy? (
+#     dev-python/unittest2[python_targets_pypy?] )"
+# @CODE
+python_gen_cond_dep() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local impl matches=()
+	local dep=${1}
+	shift
+
+	for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+		if _python_impl_matches "${impl}" "${@}"; then
+			# substitute ${PYTHON_USEDEP} if used
+			# (since python_gen_usedep() will not return ${PYTHON_USEDEP}
+			#  the code is run at most once)
+			if [[ ${dep} == *'${PYTHON_USEDEP}'* ]]; then
+				local usedep=$(_python_gen_usedep "${@}")
+				dep=${dep//\$\{PYTHON_USEDEP\}/${usedep}}
+			fi
+
+			matches+=( "python_targets_${impl}? ( ${dep} )" )
+		fi
+	done
+
+	echo "${matches[@]}"
+}
+
+# @FUNCTION: python_gen_impl_dep
+# @USAGE: [<requested-use-flags> [<impl-pattern>...]]
+# @DESCRIPTION:
+# Output a dependency on Python implementations with the specified USE
+# dependency string appended, or no USE dependency string if called
+# without the argument (or with empty argument). If any implementation
+# patterns are passed, the output dependencies will be generated only
+# for the implementations matching them.
+#
+# The patterns can be either fnmatch-style patterns (matched via bash
+# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
+# appropriately all enabled Python 2/3 implementations (alike
+# python_is_python3). Remember to escape or quote the fnmatch patterns
+# to prevent accidental shell filename expansion.
+#
+# Use this function when you need to request different USE flags
+# on the Python interpreter depending on package's USE flags. If you
+# only need a single set of interpreter USE flags, just set
+# PYTHON_REQ_USE and use ${PYTHON_DEPS} globally.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT=( python{2_7,3_{3,4}} pypy )
+# RDEPEND="foo? ( $(python_gen_impl_dep 'xml(+)') )"
+# @CODE
+#
+# It will cause the variable to look like:
+# @CODE
+# RDEPEND="foo? (
+#   python_targets_python2_7? (
+#     dev-lang/python:2.7[xml(+)] )
+#	python_targets_pypy? (
+#     dev-python/pypy[xml(+)] ) )"
+# @CODE
+python_gen_impl_dep() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local impl matches=()
+	local PYTHON_REQ_USE=${1}
+	shift
+
+	for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+		if _python_impl_matches "${impl}" "${@}"; then
+			local PYTHON_PKG_DEP
+			python_export "${impl}" PYTHON_PKG_DEP
+			matches+=( "python_targets_${impl}? ( ${PYTHON_PKG_DEP} )" )
+		fi
+	done
+
+	echo "${matches[@]}"
+}
+
+# @FUNCTION: python_gen_any_dep
+# @USAGE: <dependency-block> [<impl-pattern>...]
+# @DESCRIPTION:
+# Generate an any-of dependency that enforces a version match between
+# the Python interpreter and Python packages. <dependency-block> needs
+# to list one or more dependencies with verbatim '${PYTHON_USEDEP}'
+# references (quoted!) that will get expanded inside the function.
+# Optionally, patterns may be specified to restrict the dependency
+# to a subset of Python implementations supported by the ebuild.
+#
+# The patterns can be either fnmatch-style patterns (matched via bash
+# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
+# appropriately all enabled Python 2/3 implementations (alike
+# python_is_python3). Remember to escape or quote the fnmatch patterns
+# to prevent accidental shell filename expansion.
+#
+# This should be used along with an appropriate python_check_deps()
+# that checks which of the any-of blocks were matched, and python_setup
+# call that enables use of the matched implementation.
+#
+# Example use:
+# @CODE
+# DEPEND="$(python_gen_any_dep '
+#	dev-python/foo[${PYTHON_USEDEP}]
+#	|| ( dev-python/bar[${PYTHON_USEDEP}]
+#		dev-python/baz[${PYTHON_USEDEP}] )' -2)"
+#
+# python_check_deps() {
+#	has_version "dev-python/foo[${PYTHON_USEDEP}]" \
+#		&& { has_version "dev-python/bar[${PYTHON_USEDEP}]" \
+#			|| has_version "dev-python/baz[${PYTHON_USEDEP}]"; }
+# }
+#
+# src_compile() {
+#	python_foreach_impl usual_code
+#
+#	# some common post-build task that requires Python 2
+#	python_setup -2
+#	emake frobnicate
+# }
+# @CODE
+#
+# Example value:
+# @CODE
+# || (
+#	(
+#		dev-lang/python:2.7
+#		dev-python/foo[python_targets_python2_7(-)?,python_single_target_python2_7(+)?]
+#		|| ( dev-python/bar[python_targets_python2_7(-)?,python_single_target_python2_7(+)?]
+#			dev-python/baz[python_targets_python2_7(-)?,python_single_target_python2_7(+)?] )
+#	)
+#	(
+#		dev-lang/python:3.3
+#		dev-python/foo[python_targets_python3_3(-)?,python_single_target_python3_3(+)?]
+#		|| ( dev-python/bar[python_targets_python3_3(-)?,python_single_target_python3_3(+)?]
+#			dev-python/baz[python_targets_python3_3(-)?,python_single_target_python3_3(+)?] )
+#	)
+# )
+# @CODE
+python_gen_any_dep() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local depstr=${1}
+	[[ ${depstr} ]] || die "No dependency string provided"
+	shift
+
+	local i PYTHON_PKG_DEP out=
+	for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+		if _python_impl_matches "${i}" "${@}"; then
+			local PYTHON_USEDEP="python_targets_${i}(-),python_single_target_${i}(+)"
+			python_export "${i}" PYTHON_PKG_DEP
+
+			local i_depstr=${depstr//\$\{PYTHON_USEDEP\}/${PYTHON_USEDEP}}
+			# note: need to strip '=' slot operator for || deps
+			out="( ${PYTHON_PKG_DEP/:0=/:0} ${i_depstr} ) ${out}"
+		fi
+	done
+	echo "|| ( ${out})"
+}
+
+# @ECLASS-VARIABLE: BUILD_DIR
+# @DESCRIPTION:
+# The current build directory. In global scope, it is supposed to
+# contain an initial build directory; if unset, it defaults to ${S}.
+#
+# In functions run by python_foreach_impl(), the BUILD_DIR is locally
+# set to an implementation-specific build directory. That path is
+# created through appending a hyphen and the implementation name
+# to the final component of the initial BUILD_DIR.
+#
+# Example value:
+# @CODE
+# ${WORKDIR}/foo-1.3-python2_7
+# @CODE
+
+# @FUNCTION: python_copy_sources
+# @DESCRIPTION:
+# Create a single copy of the package sources for each enabled Python
+# implementation.
+#
+# The sources are always copied from initial BUILD_DIR (or S if unset)
+# to implementation-specific build directory matching BUILD_DIR used by
+# python_foreach_abi().
+python_copy_sources() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local MULTIBUILD_VARIANTS
+	_python_obtain_impls
+
+	multibuild_copy_sources
+}
+
+# @FUNCTION: _python_obtain_impls
+# @INTERNAL
+# @DESCRIPTION:
+# Set up the enabled implementation list.
+_python_obtain_impls() {
+	_python_validate_useflags
+
+	if [[ ${PYTHON_COMPAT_OVERRIDE} ]]; then
+		MULTIBUILD_VARIANTS=( ${PYTHON_COMPAT_OVERRIDE} )
+		return
+	fi
+
+	MULTIBUILD_VARIANTS=()
+
+	local impl
+	for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+		has "${impl}" "${PYTHON_COMPAT[@]}" && \
+		use "python_targets_${impl}" && MULTIBUILD_VARIANTS+=( "${impl}" )
+	done
+}
+
+# @FUNCTION: _python_multibuild_wrapper
+# @USAGE: <command> [<args>...]
+# @INTERNAL
+# @DESCRIPTION:
+# Initialize the environment for Python implementation selected
+# for multibuild.
+_python_multibuild_wrapper() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local -x EPYTHON PYTHON
+	local -x PATH=${PATH} PKG_CONFIG_PATH=${PKG_CONFIG_PATH}
+	python_export "${MULTIBUILD_VARIANT}" EPYTHON PYTHON
+	python_wrapper_setup
+
+	"${@}"
+}
+
+# @FUNCTION: python_foreach_impl
+# @USAGE: <command> [<args>...]
+# @DESCRIPTION:
+# Run the given command for each of the enabled Python implementations.
+# If additional parameters are passed, they will be passed through
+# to the command.
+#
+# The function will return 0 status if all invocations succeed.
+# Otherwise, the return code from first failing invocation will
+# be returned.
+#
+# For each command being run, EPYTHON, PYTHON and BUILD_DIR are set
+# locally, and the former two are exported to the command environment.
+python_foreach_impl() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local MULTIBUILD_VARIANTS
+	_python_obtain_impls
+
+	multibuild_foreach_variant _python_multibuild_wrapper "${@}"
+}
+
+# @FUNCTION: python_setup
+# @USAGE: [<impl-pattern>...]
+# @DESCRIPTION:
+# Find the best (most preferred) Python implementation that is suitable
+# for running common Python code. Set the Python build environment up
+# for that implementation. This function has two modes of operation:
+# pure and any-of dep.
+#
+# The pure mode is used if python_check_deps() function is not declared.
+# In this case, an implementation is considered suitable if it is
+# supported (in PYTHON_COMPAT), enabled (via USE flags) and matches
+# at least one of the patterns passed (or '*' if no patterns passed).
+#
+# Implementation restrictions in the pure mode need to be accompanied
+# by appropriate REQUIRED_USE constraints. Otherwise, the eclass may
+# fail at build time due to unsatisfied dependencies.
+#
+# The any-of dep mode is used if python_check_deps() is declared.
+# In this mode, an implementation is considered suitable if it is
+# supported, matches at least one of the patterns and python_check_deps()
+# has successful return code. USE flags are not considered.
+#
+# The python_check_deps() function in the any-of mode needs to be
+# accompanied by appropriate any-of dependencies.
+#
+# The patterns can be either fnmatch-style patterns (matched via bash
+# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
+# appropriately all enabled Python 2/3 implementations (alike
+# python_is_python3). Remember to escape or quote the fnmatch patterns
+# to prevent accidental shell filename expansion.
+#
+# This function needs to be used when Python is being called outside
+# of python_foreach_impl calls (e.g. for shared processes like doc
+# building). python_foreach_impl sets up the build environment itself.
+#
+# Pure mode example:
+# @CODE
+# DEPEND="doc? ( dev-python/epydoc[$(python_gen_usedep 'python2*')] )"
+# REQUIRED_USE="doc? ( $(python_gen_useflags 'python2*') )"
+#
+# src_compile() {
+#   #...
+#   if use doc; then
+#     python_setup 'python2*'
+#     make doc
+#   fi
+# }
+# @CODE
+#
+# Any-of mode example:
+# @CODE
+# DEPEND="doc? (
+#	$(python_gen_any_dep 'dev-python/epydoc[${PYTHON_USEDEP}]' 'python2*') )"
+#
+# python_check_deps() {
+#	has_version "dev-python/epydoc[${PYTHON_USEDEP}]"
+# }
+#
+# src_compile() {
+#   #...
+#   if use doc; then
+#     python_setup 'python2*'
+#     make doc
+#   fi
+# }
+# @CODE
+python_setup() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	_python_validate_useflags
+	local pycompat=( "${PYTHON_COMPAT[@]}" )
+	if [[ ${PYTHON_COMPAT_OVERRIDE} ]]; then
+		pycompat=( ${PYTHON_COMPAT_OVERRIDE} )
+	fi
+
+	local has_check_deps
+	declare -f python_check_deps >/dev/null && has_check_deps=1
+
+	# (reverse iteration -- newest impl first)
+	local found
+	for (( i = ${#_PYTHON_SUPPORTED_IMPLS[@]} - 1; i >= 0; i-- )); do
+		local impl=${_PYTHON_SUPPORTED_IMPLS[i]}
+
+		# check PYTHON_COMPAT[_OVERRIDE]
+		has "${impl}" "${pycompat[@]}" || continue
+
+		# match USE flags only if override is not in effect
+		# and python_check_deps() is not defined
+		if [[ ! ${PYTHON_COMPAT_OVERRIDE} && ! ${has_check_deps} ]]; then
+			use "python_targets_${impl}" || continue
+		fi
+
+		# check patterns
+		_python_impl_matches "${impl}" "${@}" || continue
+
+		python_export "${impl}" EPYTHON PYTHON
+
+		# if python_check_deps() is declared, switch into any-of mode
+		if [[ ${has_check_deps} ]]; then
+			# first check if the interpreter is installed
+			python_is_installed "${impl}" || continue
+			# then run python_check_deps
+			local PYTHON_USEDEP="python_targets_${impl}(-),python_single_target_${impl}(+)"
+			python_check_deps || continue
+		fi
+
+		found=1
+		break
+	done
+
+	if [[ ! ${found} ]]; then
+		eerror "${FUNCNAME}: none of the enabled implementation matched the patterns."
+		eerror "  patterns: ${@-'(*)'}"
+		eerror "Likely a REQUIRED_USE constraint (possibly USE-conditional) is missing."
+		eerror "  suggested: || ( \$(python_gen_useflags ${@}) )"
+		eerror "(remember to quote all the patterns with '')"
+		die "${FUNCNAME}: no enabled implementation satisfy requirements"
+	fi
+
+	python_wrapper_setup
+	einfo "Using ${EPYTHON} in global scope"
+}
+
+# @FUNCTION: python_replicate_script
+# @USAGE: <path>...
+# @DESCRIPTION:
+# Copy the given script to variants for all enabled Python
+# implementations, then replace it with a symlink to the wrapper.
+#
+# All specified files must start with a 'python' shebang. A file not
+# having a matching shebang will be refused.
+python_replicate_script() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	_python_replicate_script() {
+		local _PYTHON_FIX_SHEBANG_QUIET=1
+
+		local PYTHON_SCRIPTDIR
+		python_export PYTHON_SCRIPTDIR
+
+		(
+			exeopts -m 0755
+			exeinto "${PYTHON_SCRIPTDIR#${EPREFIX}}"
+			doexe "${files[@]}"
+		)
+
+		python_fix_shebang -q \
+			"${files[@]/*\//${D%/}/${PYTHON_SCRIPTDIR}/}"
+	}
+
+	local files=( "${@}" )
+	python_foreach_impl _python_replicate_script
+	unset -f _python_replicate_script
+
+	# install the wrappers
+	local f
+	for f; do
+		_python_ln_rel "${ED%/}/usr/lib/python-exec/python-exec2" "${f}" || die
+	done
+}
+
+_PYTHON_R2=1
+fi
diff --git a/eclass/python-single-r2.eclass b/eclass/python-single-r2.eclass
new file mode 100644
index 000000000000..d9d535711252
--- /dev/null
+++ b/eclass/python-single-r2.eclass
@@ -0,0 +1,512 @@
+# Copyright 1999-2020 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: python-single-r2.eclass
+# @MAINTAINER:
+# Python team <python@gentoo.org>
+# @AUTHOR:
+# Author: Michał Górny <mgorny@gentoo.org>
+# @SUPPORTED_EAPIS: 5 6 7
+# @BLURB: An eclass for Python packages not installed for multiple implementations.
+# @DESCRIPTION:
+# An extension of the python-r2 eclass suite for packages which
+# don't support being installed for multiple Python implementations.
+# This mostly includes tools embedding Python and packages using foreign
+# build systems.
+#
+# This eclass sets correct IUSE.  It also provides PYTHON_DEPS
+# and PYTHON_REQUIRED_USE that need to be added to appropriate ebuild
+# metadata variables.
+#
+# The eclass exports PYTHON_SINGLE_USEDEP that is suitable for depending
+# on other packages using the eclass.  Dependencies on packages using
+# python-r2 should be created via python_gen_cond_dep() function,
+# using PYTHON_MULTI_USEDEP placeholder.
+#
+# Please note that packages support multiple Python implementations
+# (using python-r2 eclass) can not depend on packages not supporting
+# them (using this eclass).
+#
+# Please note that python-single-r2 will always inherit python-utils-r2
+# as well. Thus, all the functions defined there can be used
+# in the packages using python-single-r2, and there is no need ever
+# to inherit both.
+#
+# For more information, please see the Python Guide:
+# https://dev.gentoo.org/~mgorny/python-guide/
+
+case "${EAPI:-0}" in
+	0|1|2|3|4)
+		die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
+		;;
+	5|6|7)
+		# EAPI=5 is required for sane USE_EXPAND dependencies
+		;;
+	*)
+		die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
+		;;
+esac
+
+if [[ ! ${_PYTHON_SINGLE_R2} ]]; then
+
+if [[ ${_PYTHON_R2} ]]; then
+	die 'python-single-r2.eclass can not be used with python-r2.eclass.'
+elif [[ ${_PYTHON_ANY_R2} ]]; then
+	die 'python-single-r2.eclass can not be used with python-any-r2.eclass.'
+fi
+
+inherit python-utils-r2
+
+fi
+
+EXPORT_FUNCTIONS pkg_setup
+
+# @ECLASS-VARIABLE: PYTHON_COMPAT
+# @REQUIRED
+# @DESCRIPTION:
+# This variable contains a list of Python implementations the package
+# supports. It must be set before the `inherit' call. It has to be
+# an array.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT=( python2_7 python3_3 python3_4 )
+# @CODE
+#
+# Please note that you can also use bash brace expansion if you like:
+# @CODE
+# PYTHON_COMPAT=( python2_7 python3_{3,4} )
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_COMPAT_OVERRIDE
+# @INTERNAL
+# @DESCRIPTION:
+# This variable can be used when working with ebuilds to override
+# the in-ebuild PYTHON_COMPAT. It is a string naming the implementation
+# which package will be built for. It needs to be specified
+# in the calling environment, and not in ebuilds.
+#
+# It should be noted that in order to preserve metadata immutability,
+# PYTHON_COMPAT_OVERRIDE does not affect IUSE nor dependencies.
+# The state of PYTHON_SINGLE_TARGET is ignored, and the implementation
+# in PYTHON_COMPAT_OVERRIDE is built instead.  Dependencies need to be
+# satisfied manually.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT_OVERRIDE='pypy' emerge -1v dev-python/bar
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_REQ_USE
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The list of USEflags required to be enabled on the chosen Python
+# implementations, formed as a USE-dependency string. It should be valid
+# for all implementations in PYTHON_COMPAT, so it may be necessary to
+# use USE defaults.
+#
+# This should be set before calling `inherit'.
+#
+# Example:
+# @CODE
+# PYTHON_REQ_USE="gdbm,ncurses(-)?"
+# @CODE
+#
+# It will cause the Python dependencies to look like:
+# @CODE
+# python_single_target_pythonX_Y? ( dev-lang/python:X.Y[gdbm,ncurses(-)?] )
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_DEPS
+# @DESCRIPTION:
+# This is an eclass-generated Python dependency string for all
+# implementations listed in PYTHON_COMPAT.
+#
+# The dependency string is conditional on PYTHON_SINGLE_TARGET.
+#
+# Example use:
+# @CODE
+# RDEPEND="${PYTHON_DEPS}
+#	dev-foo/mydep"
+# DEPEND="${RDEPEND}"
+# @CODE
+#
+# Example value:
+# @CODE
+# dev-lang/python-exec:=
+# python_single_target_python2_7? ( dev-lang/python:2.7[gdbm] )
+# python_single_target_pypy? ( dev-python/pypy[gdbm] )
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_SINGLE_USEDEP
+# @DESCRIPTION:
+# This is an eclass-generated USE-dependency string which can be used to
+# depend on another python-single-r2 package being built for the same
+# Python implementations.
+#
+# If you need to depend on a multi-impl (python-r2) package, use
+# python_gen_cond_dep with PYTHON_MULTI_USEDEP placeholder instead.
+#
+# Example use:
+# @CODE
+# RDEPEND="dev-python/foo[${PYTHON_SINGLE_USEDEP}]"
+# @CODE
+#
+# Example value:
+# @CODE
+# python_single_target_python3_4(-)?
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_MULTI_USEDEP
+# @DESCRIPTION:
+# This is a placeholder variable supported by python_gen_cond_dep,
+# in order to depend on python-r2 packages built for the same Python
+# implementations.
+#
+# Example use:
+# @CODE
+# RDEPEND="$(python_gen_cond_dep '
+#     dev-python/foo[${PYTHON_MULTI_USEDEP}]
+#   ')"
+# @CODE
+#
+# Example value:
+# @CODE
+# python_targets_python3_4(-)
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_REQUIRED_USE
+# @DESCRIPTION:
+# This is an eclass-generated required-use expression which ensures
+# that exactly one PYTHON_SINGLE_TARGET value has been enabled.
+#
+# This expression should be utilized in an ebuild by including it in
+# REQUIRED_USE, optionally behind a use flag.
+#
+# Example use:
+# @CODE
+# REQUIRED_USE="python? ( ${PYTHON_REQUIRED_USE} )"
+# @CODE
+#
+# Example value:
+# @CODE
+# ^^ ( python_single_target_python2_7 python_single_target_python3_3 )
+# @CODE
+
+_python_single_set_globals() {
+	_python_set_impls
+
+	local flags=( "${_PYTHON_SUPPORTED_IMPLS[@]/#/python_single_target_}" )
+
+	if [[ ${#_PYTHON_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
+		# if only one implementation is supported, use IUSE defaults
+		# to avoid requesting the user to enable it
+		IUSE="+${flags[0]}"
+	else
+		IUSE="${flags[*]}"
+	fi
+
+	local requse="^^ ( ${flags[*]} )"
+	local single_flags="${flags[@]/%/(-)?}"
+	local single_usedep=${single_flags// /,}
+
+	local deps= i PYTHON_PKG_DEP
+	for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+		python_export "${i}" PYTHON_PKG_DEP
+		# 1) well, python-exec would suffice as an RDEP
+		# but no point in making this overcomplex, BDEP doesn't hurt anyone
+		# 2) python-exec should be built with all targets forced anyway
+		# but if new targets were added, we may need to force a rebuild
+		deps+="python_single_target_${i}? (
+			${PYTHON_PKG_DEP}
+			>=dev-lang/python-exec-2:=[python_targets_${i}]
+		) "
+	done
+
+	if [[ ${PYTHON_DEPS+1} ]]; then
+		if [[ ${PYTHON_DEPS} != "${deps}" ]]; then
+			eerror "PYTHON_DEPS have changed between inherits (PYTHON_REQ_USE?)!"
+			eerror "Before: ${PYTHON_DEPS}"
+			eerror "Now   : ${deps}"
+			die "PYTHON_DEPS integrity check failed"
+		fi
+
+		# these two are formality -- they depend on PYTHON_COMPAT only
+		if [[ ${PYTHON_REQUIRED_USE} != ${requse} ]]; then
+			eerror "PYTHON_REQUIRED_USE have changed between inherits!"
+			eerror "Before: ${PYTHON_REQUIRED_USE}"
+			eerror "Now   : ${requse}"
+			die "PYTHON_REQUIRED_USE integrity check failed"
+		fi
+
+		if [[ ${PYTHON_SINGLE_USEDEP} != "${single_usedep}" ]]; then
+			eerror "PYTHON_SINGLE_USEDEP have changed between inherits!"
+			eerror "Before: ${PYTHON_SINGLE_USEDEP}"
+			eerror "Now   : ${single_usedep}"
+			die "PYTHON_SINGLE_USEDEP integrity check failed"
+		fi
+	else
+		PYTHON_DEPS=${deps}
+		PYTHON_REQUIRED_USE=${requse}
+		PYTHON_USEDEP='%PYTHON_USEDEP-HAS-BEEN-REMOVED%'
+		PYTHON_SINGLE_USEDEP=${single_usedep}
+		readonly PYTHON_DEPS PYTHON_REQUIRED_USE PYTHON_SINGLE_USEDEP \
+			PYTHON_USEDEP
+	fi
+}
+_python_single_set_globals
+unset -f _python_single_set_globals
+
+if [[ ! ${_PYTHON_SINGLE_R2} ]]; then
+
+# @FUNCTION: _python_gen_usedep
+# @INTERNAL
+# @USAGE: [<pattern>...]
+# @DESCRIPTION:
+# Output a USE dependency string for Python implementations which
+# are both in PYTHON_COMPAT and match any of the patterns passed
+# as parameters to the function.
+#
+# The patterns can be either fnmatch-style patterns (matched via bash
+# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
+# appropriately all enabled Python 2/3 implementations (alike
+# python_is_python3). Remember to escape or quote the fnmatch patterns
+# to prevent accidental shell filename expansion.
+#
+# This is an internal function used to implement python_gen_cond_dep.
+_python_gen_usedep() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local impl matches=()
+
+	for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+		if _python_impl_matches "${impl}" "${@}"; then
+			matches+=(
+				"python_single_target_${impl}(-)?"
+			)
+		fi
+	done
+
+	[[ ${matches[@]} ]] || die "No supported implementations match python_gen_usedep patterns: ${@}"
+
+	local out=${matches[@]}
+	echo "${out// /,}"
+}
+
+# @FUNCTION: python_gen_useflags
+# @USAGE: [<pattern>...]
+# @DESCRIPTION:
+# Output a list of USE flags for Python implementations which
+# are both in PYTHON_COMPAT and match any of the patterns passed
+# as parameters to the function.
+#
+# The patterns can be either fnmatch-style patterns (matched via bash
+# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
+# appropriately all enabled Python 2/3 implementations (alike
+# python_is_python3). Remember to escape or quote the fnmatch patterns
+# to prevent accidental shell filename expansion.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT=( python{2_7,3_4} )
+# REQUIRED_USE="doc? ( ^^ ( $(python_gen_useflags 'python2*') ) )"
+# @CODE
+#
+# It will cause the variable to look like:
+# @CODE
+# REQUIRED_USE="doc? ( ^^ ( python_single_target_python2_7 ) )"
+# @CODE
+python_gen_useflags() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local impl matches=()
+
+	for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+		if _python_impl_matches "${impl}" "${@}"; then
+			matches+=( "python_single_target_${impl}" )
+		fi
+	done
+
+	echo "${matches[@]}"
+}
+
+# @FUNCTION: python_gen_cond_dep
+# @USAGE: <dependency> [<pattern>...]
+# @DESCRIPTION:
+# Output a list of <dependency>-ies made conditional to USE flags
+# of Python implementations which are both in PYTHON_COMPAT and match
+# any of the patterns passed as the remaining parameters.
+#
+# The patterns can be either fnmatch-style patterns (matched via bash
+# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
+# appropriately all enabled Python 2/3 implementations (alike
+# python_is_python3). Remember to escape or quote the fnmatch patterns
+# to prevent accidental shell filename expansion.
+#
+# In order to enforce USE constraints on the packages, verbatim
+# '${PYTHON_SINGLE_USEDEP}' and '${PYTHON_MULTI_USEDEP}' (quoted!) may
+# be placed in the dependency specification. It will get expanded within
+# the function into a proper USE dependency string.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT=( python{2_7,3_{3,4}} pypy )
+# RDEPEND="$(python_gen_cond_dep \
+#   'dev-python/unittest2[${PYTHON_MULTI_USEDEP}]' python2_7 pypy )"
+# @CODE
+#
+# It will cause the variable to look like:
+# @CODE
+# RDEPEND="python_single_target_python2_7? (
+#     dev-python/unittest2[python_targets_python2_7(-)?,...] )
+#	python_single_target_pypy? (
+#     dev-python/unittest2[python_targets_pypy(-)?,...] )"
+# @CODE
+python_gen_cond_dep() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local impl matches=()
+
+	local dep=${1}
+	shift
+
+	for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+		if _python_impl_matches "${impl}" "${@}"; then
+			# substitute ${PYTHON_SINGLE_USEDEP} if used
+			# (since python_gen_usedep() will not return
+			#  ${PYTHON_SINGLE_USEDEP}, the code is run at most once)
+			if [[ ${dep} == *'${PYTHON_SINGLE_USEDEP}'* ]]; then
+				local usedep=$(_python_gen_usedep "${@}")
+				dep=${dep//\$\{PYTHON_SINGLE_USEDEP\}/${usedep}}
+			fi
+			local multi_usedep="python_targets_${impl}(-)"
+
+			matches+=( "python_single_target_${impl}? (
+				${dep//\$\{PYTHON_MULTI_USEDEP\}/${multi_usedep}} )" )
+		fi
+	done
+
+	echo "${matches[@]}"
+}
+
+# @FUNCTION: python_gen_impl_dep
+# @USAGE: [<requested-use-flags> [<impl-pattern>...]]
+# @DESCRIPTION:
+# Output a dependency on Python implementations with the specified USE
+# dependency string appended, or no USE dependency string if called
+# without the argument (or with empty argument). If any implementation
+# patterns are passed, the output dependencies will be generated only
+# for the implementations matching them.
+#
+# The patterns can be either fnmatch-style patterns (matched via bash
+# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
+# appropriately all enabled Python 2/3 implementations (alike
+# python_is_python3). Remember to escape or quote the fnmatch patterns
+# to prevent accidental shell filename expansion.
+#
+# Use this function when you need to request different USE flags
+# on the Python interpreter depending on package's USE flags. If you
+# only need a single set of interpreter USE flags, just set
+# PYTHON_REQ_USE and use ${PYTHON_DEPS} globally.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT=( python{2_7,3_{3,4}} pypy )
+# RDEPEND="foo? ( $(python_gen_impl_dep 'xml(+)') )"
+# @CODE
+#
+# It will cause the variable to look like:
+# @CODE
+# RDEPEND="foo? (
+#   python_single_target_python2_7? (
+#     dev-lang/python:2.7[xml(+)] )
+#	python_single_target_pypy? (
+#     dev-python/pypy[xml(+)] ) )"
+# @CODE
+python_gen_impl_dep() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local impl
+	local matches=()
+
+	local PYTHON_REQ_USE=${1}
+	shift
+
+	for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
+		if _python_impl_matches "${impl}" "${@}"; then
+			local PYTHON_PKG_DEP
+			python_export "${impl}" PYTHON_PKG_DEP
+			matches+=( "python_single_target_${impl}? ( ${PYTHON_PKG_DEP} )" )
+		fi
+	done
+
+	echo "${matches[@]}"
+}
+
+# @FUNCTION: python_setup
+# @DESCRIPTION:
+# Determine what the selected Python implementation is and set
+# the Python build environment up for it.
+python_setup() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	unset EPYTHON
+
+	# support developer override
+	if [[ ${PYTHON_COMPAT_OVERRIDE} ]]; then
+		local impls=( ${PYTHON_COMPAT_OVERRIDE} )
+		[[ ${#impls[@]} -eq 1 ]] || die "PYTHON_COMPAT_OVERRIDE must name exactly one implementation for python-single-r2"
+
+		ewarn "WARNING: PYTHON_COMPAT_OVERRIDE in effect. The following Python"
+		ewarn "implementation will be used:"
+		ewarn
+		ewarn "	${PYTHON_COMPAT_OVERRIDE}"
+		ewarn
+		ewarn "Dependencies won't be satisfied, and PYTHON_SINGLE_TARGET flags will be ignored."
+
+		python_export "${impls[0]}" EPYTHON PYTHON
+		python_wrapper_setup
+		einfo "Using ${EPYTHON} to build"
+		return
+	fi
+
+	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"
+				eerror "implementation. Please set it to just one value. If you need"
+				eerror "to override the value for a single package, please use package.env"
+				eerror "or an equivalent solution (man 5 portage)."
+				echo
+				die "More than one implementation in PYTHON_SINGLE_TARGET."
+			fi
+
+			python_export "${impl}" EPYTHON PYTHON
+			python_wrapper_setup
+			einfo "Using ${EPYTHON} to build"
+		fi
+	done
+
+	if [[ ! ${EPYTHON} ]]; then
+		eerror "No Python implementation selected for the build. Please set"
+		eerror "the PYTHON_SINGLE_TARGET variable in your make.conf to one"
+		eerror "of the following values:"
+		eerror
+		eerror "${_PYTHON_SUPPORTED_IMPLS[@]}"
+		echo
+		die "No supported Python implementation in PYTHON_SINGLE_TARGET."
+	fi
+}
+
+# @FUNCTION: python-single-r2_pkg_setup
+# @DESCRIPTION:
+# Runs python_setup.
+python-single-r2_pkg_setup() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	[[ ${MERGE_TYPE} != binary ]] && python_setup
+}
+
+_PYTHON_SINGLE_R2=1
+fi
diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
new file mode 100644
index 000000000000..c28c42493173
--- /dev/null
+++ b/eclass/python-utils-r2.eclass
@@ -0,0 +1,1508 @@
+# Copyright 1999-2020 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: python-utils-r2.eclass
+# @MAINTAINER:
+# Python team <python@gentoo.org>
+# @AUTHOR:
+# Author: Michał Górny <mgorny@gentoo.org>
+# @SUPPORTED_EAPIS: 5 6 7
+# @BLURB: Utility functions for packages with Python parts.
+# @DESCRIPTION:
+# A utility eclass providing functions to query Python implementations,
+# install Python modules and scripts.
+#
+# This eclass does not set any metadata variables nor export any phase
+# functions. It can be inherited safely.
+#
+# For more information, please see the Python Guide:
+# https://dev.gentoo.org/~mgorny/python-guide/
+
+case "${EAPI:-0}" in
+	[0-4]) die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}" ;;
+	[5-7]) ;;
+	*)     die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" ;;
+esac
+
+if [[ ${_PYTHON_UTILS_R1} ]]; then
+	die 'python-r2 suite eclasses can not be combined with python-r1 suite.'
+fi
+
+if [[ ! ${_PYTHON_UTILS_R2} ]]; then
+
+[[ ${EAPI} == 5 ]] && inherit eutils multilib
+inherit toolchain-funcs
+
+# @ECLASS-VARIABLE: _PYTHON_ALL_IMPLS
+# @INTERNAL
+# @DESCRIPTION:
+# All supported Python implementations, most preferred last.
+_PYTHON_ALL_IMPLS=(
+	pypy3
+	python2_7
+	python3_6 python3_7 python3_8
+)
+readonly _PYTHON_ALL_IMPLS
+
+# @ECLASS-VARIABLE: PYTHON_COMPAT_NO_STRICT
+# @INTERNAL
+# @DESCRIPTION:
+# Set to a non-empty value in order to make eclass tolerate (ignore)
+# unknown implementations in PYTHON_COMPAT.
+#
+# This is intended to be set by the user when using ebuilds that may
+# have unknown (newer) implementations in PYTHON_COMPAT. The assumption
+# is that the ebuilds are intended to be used within multiple contexts
+# which can involve revisions of this eclass that support a different
+# set of Python implementations.
+
+# @FUNCTION: _python_impl_supported
+# @USAGE: <impl>
+# @INTERNAL
+# @DESCRIPTION:
+# Check whether the implementation <impl> (PYTHON_COMPAT-form)
+# is still supported.
+#
+# Returns 0 if the implementation is valid and supported. If it is
+# unsupported, returns 1 -- and the caller should ignore the entry.
+# If it is invalid, dies with an appopriate error messages.
+_python_impl_supported() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	[[ ${#} -eq 1 ]] || die "${FUNCNAME}: takes exactly 1 argument (impl)."
+
+	local impl=${1}
+
+	# keep in sync with _PYTHON_ALL_IMPLS!
+	# (not using that list because inline patterns shall be faster)
+	case "${impl}" in
+		python2_7|python3_[678]|pypy3)
+			return 0
+			;;
+		jython2_7|pypy|pypy1_[89]|pypy2_0|python2_[56]|python3_[12345])
+			return 1
+			;;
+		*)
+			[[ ${PYTHON_COMPAT_NO_STRICT} ]] && return 1
+			die "Invalid implementation in PYTHON_COMPAT: ${impl}"
+	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
+
+	local supp=() unsupp=()
+
+	for i in "${_PYTHON_ALL_IMPLS[@]}"; do
+		if has "${i}" "${PYTHON_COMPAT[@]}"; then
+			supp+=( "${i}" )
+		else
+			unsupp+=( "${i}" )
+		fi
+	done
+
+	if [[ ! ${supp[@]} ]]; then
+		die "No supported implementation in PYTHON_COMPAT."
+	fi
+
+	if [[ ${_PYTHON_SUPPORTED_IMPLS[@]} ]]; then
+		# set once already, verify integrity
+		if [[ ${_PYTHON_SUPPORTED_IMPLS[@]} != ${supp[@]} ]]; then
+			eerror "Supported impls (PYTHON_COMPAT) changed between inherits!"
+			eerror "Before: ${_PYTHON_SUPPORTED_IMPLS[*]}"
+			eerror "Now   : ${supp[*]}"
+			die "_PYTHON_SUPPORTED_IMPLS integrity check failed"
+		fi
+		if [[ ${_PYTHON_UNSUPPORTED_IMPLS[@]} != ${unsupp[@]} ]]; then
+			eerror "Unsupported impls changed between inherits!"
+			eerror "Before: ${_PYTHON_UNSUPPORTED_IMPLS[*]}"
+			eerror "Now   : ${unsupp[*]}"
+			die "_PYTHON_UNSUPPORTED_IMPLS integrity check failed"
+		fi
+	else
+		_PYTHON_SUPPORTED_IMPLS=( "${supp[@]}" )
+		_PYTHON_UNSUPPORTED_IMPLS=( "${unsupp[@]}" )
+		readonly _PYTHON_SUPPORTED_IMPLS _PYTHON_UNSUPPORTED_IMPLS
+	fi
+}
+
+# @FUNCTION: _python_impl_matches
+# @USAGE: <impl> [<pattern>...]
+# @INTERNAL
+# @DESCRIPTION:
+# Check whether the specified <impl> matches at least one
+# of the patterns following it. Return 0 if it does, 1 otherwise.
+# Matches if no patterns are provided.
+#
+# <impl> can be in PYTHON_COMPAT or EPYTHON form. The patterns can be
+# either:
+# a) fnmatch-style patterns, e.g. 'python2*', 'pypy'...
+# b) '-2' to indicate all Python 2 variants (= !python_is_python3)
+# c) '-3' to indicate all Python 3 variants (= python_is_python3)
+_python_impl_matches() {
+	[[ ${#} -ge 1 ]] || die "${FUNCNAME}: takes at least 1 parameter"
+	[[ ${#} -eq 1 ]] && return 0
+
+	local impl=${1} pattern
+	shift
+
+	for pattern; do
+		if [[ ${pattern} == -2 ]]; then
+			python_is_python3 "${impl}" || return 0
+		elif [[ ${pattern} == -3 ]]; then
+			python_is_python3 "${impl}" && return 0
+			return
+		# unify value style to allow lax matching
+		elif [[ ${impl/./_} == ${pattern/./_} ]]; then
+			return 0
+		fi
+	done
+
+	return 1
+}
+
+# @ECLASS-VARIABLE: PYTHON
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The absolute path to the current Python interpreter.
+#
+# This variable is set automatically in the following contexts:
+#
+# python-r2: Set in functions called by python_foreach_impl() or after
+# calling python_export_best().
+#
+# python-single-r2: Set after calling python-single-r2_pkg_setup().
+#
+# distutils-r2: Set within any of the python sub-phase functions.
+#
+# Example value:
+# @CODE
+# /usr/bin/python2.7
+# @CODE
+
+# @ECLASS-VARIABLE: EPYTHON
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The executable name of the current Python interpreter.
+#
+# This variable is set automatically in the following contexts:
+#
+# python-r2: Set in functions called by python_foreach_impl() or after
+# calling python_export_best().
+#
+# python-single-r2: Set after calling python-single-r2_pkg_setup().
+#
+# distutils-r2: Set within any of the python sub-phase functions.
+#
+# Example value:
+# @CODE
+# python2.7
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_SITEDIR
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The path to Python site-packages directory.
+#
+# Set and exported on request using python_export().
+# Requires a proper build-time dependency on the Python implementation.
+#
+# Example value:
+# @CODE
+# /usr/lib64/python2.7/site-packages
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_INCLUDEDIR
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The path to Python include directory.
+#
+# Set and exported on request using python_export().
+# Requires a proper build-time dependency on the Python implementation.
+#
+# Example value:
+# @CODE
+# /usr/include/python2.7
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_LIBPATH
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The path to Python library.
+#
+# Set and exported on request using python_export().
+# Valid only for CPython. Requires a proper build-time dependency
+# on the Python implementation.
+#
+# Example value:
+# @CODE
+# /usr/lib64/libpython2.7.so
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_CFLAGS
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# Proper C compiler flags for building against Python. Obtained from
+# pkg-config or python-config.
+#
+# Set and exported on request using python_export().
+# Valid only for CPython. Requires a proper build-time dependency
+# on the Python implementation and on pkg-config.
+#
+# Example value:
+# @CODE
+# -I/usr/include/python2.7
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_LIBS
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# Proper C compiler flags for linking against Python. Obtained from
+# pkg-config or python-config.
+#
+# Set and exported on request using python_export().
+# Valid only for CPython. Requires a proper build-time dependency
+# on the Python implementation and on pkg-config.
+#
+# Example value:
+# @CODE
+# -lpython2.7
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_CONFIG
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# Path to the python-config executable.
+#
+# Set and exported on request using python_export().
+# Valid only for CPython. Requires a proper build-time dependency
+# on the Python implementation and on pkg-config.
+#
+# Example value:
+# @CODE
+# /usr/bin/python2.7-config
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_PKG_DEP
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The complete dependency on a particular Python package as a string.
+#
+# Set and exported on request using python_export().
+#
+# Example value:
+# @CODE
+# dev-lang/python:2.7[xml]
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_SCRIPTDIR
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The location where Python scripts must be installed for current impl.
+#
+# Set and exported on request using python_export().
+#
+# Example value:
+# @CODE
+# /usr/lib/python-exec/python2.7
+# @CODE
+
+# @FUNCTION: python_export
+# @USAGE: [<impl>] <variables>...
+# @DESCRIPTION:
+# Set and export the Python implementation-relevant variables passed
+# as parameters.
+#
+# The optional first parameter may specify the requested Python
+# implementation (either as PYTHON_TARGETS value, e.g. python2_7,
+# or an EPYTHON one, e.g. python2.7). If no implementation passed,
+# the current one will be obtained from ${EPYTHON}.
+#
+# The variables which can be exported are: PYTHON, EPYTHON,
+# PYTHON_SITEDIR. They are described more completely in the eclass
+# variable documentation.
+python_export() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local impl var
+
+	case "${1}" in
+		python*|jython*)
+			impl=${1/_/.}
+			shift
+			;;
+		pypy|pypy3)
+			impl=${1}
+			shift
+			;;
+		*)
+			impl=${EPYTHON}
+			if [[ -z ${impl} ]]; then
+				die "python_export called without a python implementation and EPYTHON is unset"
+			fi
+			;;
+	esac
+	debug-print "${FUNCNAME}: implementation: ${impl}"
+
+	for var; do
+		case "${var}" in
+			EPYTHON)
+				export EPYTHON=${impl}
+				debug-print "${FUNCNAME}: EPYTHON = ${EPYTHON}"
+				;;
+			PYTHON)
+				export PYTHON=${EPREFIX}/usr/bin/${impl}
+				debug-print "${FUNCNAME}: PYTHON = ${PYTHON}"
+				;;
+			PYTHON_SITEDIR)
+				[[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
+				# sysconfig can't be used because:
+				# 1) pypy doesn't give site-packages but stdlib
+				# 2) jython gives paths with wrong case
+				PYTHON_SITEDIR=$("${PYTHON}" -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_lib())') || die
+				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 distutils.sysconfig; print(distutils.sysconfig.get_python_inc())') || die
+				export PYTHON_INCLUDEDIR
+				debug-print "${FUNCNAME}: PYTHON_INCLUDEDIR = ${PYTHON_INCLUDEDIR}"
+
+				# Jython gives a non-existing directory
+				if [[ ! -d ${PYTHON_INCLUDEDIR} ]]; then
+					die "${impl} does not install any header files!"
+				fi
+				;;
+			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
+				export PYTHON_LIBPATH
+				debug-print "${FUNCNAME}: PYTHON_LIBPATH = ${PYTHON_LIBPATH}"
+
+				if [[ ! ${PYTHON_LIBPATH} ]]; then
+					die "${impl} lacks a (usable) dynamic library"
+				fi
+				;;
+			PYTHON_CFLAGS)
+				local val
+
+				case "${impl}" in
+					python*)
+						# python-2.7, python-3.2, etc.
+						val=$($(tc-getPKG_CONFIG) --cflags ${impl/n/n-}) || die
+						;;
+					*)
+						die "${impl}: obtaining ${var} not supported"
+						;;
+				esac
+
+				export PYTHON_CFLAGS=${val}
+				debug-print "${FUNCNAME}: PYTHON_CFLAGS = ${PYTHON_CFLAGS}"
+				;;
+			PYTHON_LIBS)
+				local val
+
+				case "${impl}" in
+					python*)
+						# python-2.7, python-3.2, etc.
+						val=$($(tc-getPKG_CONFIG) --libs ${impl/n/n-}) || die
+						;;
+					*)
+						die "${impl}: obtaining ${var} not supported"
+						;;
+				esac
+
+				export PYTHON_LIBS=${val}
+				debug-print "${FUNCNAME}: PYTHON_LIBS = ${PYTHON_LIBS}"
+				;;
+			PYTHON_CONFIG)
+				local flags val
+
+				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
+						val=${PYTHON}${flags}-config
+						;;
+					*)
+						die "${impl}: obtaining ${var} not supported"
+						;;
+				esac
+
+				export PYTHON_CONFIG=${val}
+				debug-print "${FUNCNAME}: PYTHON_CONFIG = ${PYTHON_CONFIG}"
+				;;
+			PYTHON_PKG_DEP)
+				local d
+				case ${impl} in
+					python2.7)
+						PYTHON_PKG_DEP='>=dev-lang/python-2.7.5-r2:2.7';;
+					python3.3)
+						PYTHON_PKG_DEP='>=dev-lang/python-3.3.2-r2:3.3';;
+					python*)
+						PYTHON_PKG_DEP="dev-lang/python:${impl#python}";;
+					pypy)
+						PYTHON_PKG_DEP='>=dev-python/pypy-5:0=';;
+					pypy3)
+						PYTHON_PKG_DEP='>=dev-python/pypy3-5:0=';;
+					jython2.7)
+						PYTHON_PKG_DEP='dev-java/jython:2.7';;
+					*)
+						die "Invalid implementation: ${impl}"
+				esac
+
+				# use-dep
+				if [[ ${PYTHON_REQ_USE} ]]; then
+					PYTHON_PKG_DEP+=[${PYTHON_REQ_USE}]
+				fi
+
+				export PYTHON_PKG_DEP
+				debug-print "${FUNCNAME}: PYTHON_PKG_DEP = ${PYTHON_PKG_DEP}"
+				;;
+			PYTHON_SCRIPTDIR)
+				local dir
+				export PYTHON_SCRIPTDIR=${EPREFIX}/usr/lib/python-exec/${impl}
+				debug-print "${FUNCNAME}: PYTHON_SCRIPTDIR = ${PYTHON_SCRIPTDIR}"
+				;;
+			*)
+				die "python_export: unknown variable ${var}"
+		esac
+	done
+}
+
+# @FUNCTION: python_get_sitedir
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Obtain and print the 'site-packages' path for the given
+# implementation. If no implementation is provided, ${EPYTHON} will
+# be used.
+#
+# If you just need to have PYTHON_SITEDIR set (and exported), then it is
+# better to use python_export() directly instead.
+python_get_sitedir() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	python_export "${@}" PYTHON_SITEDIR
+	echo "${PYTHON_SITEDIR}"
+}
+
+# @FUNCTION: python_get_includedir
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Obtain and print the include path for the given implementation. If no
+# implementation is provided, ${EPYTHON} will be used.
+#
+# If you just need to have PYTHON_INCLUDEDIR set (and exported), then it
+# is better to use python_export() directly instead.
+python_get_includedir() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	python_export "${@}" PYTHON_INCLUDEDIR
+	echo "${PYTHON_INCLUDEDIR}"
+}
+
+# @FUNCTION: python_get_library_path
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Obtain and print the Python library path for the given implementation.
+# If no implementation is provided, ${EPYTHON} will be used.
+#
+# Please note that this function can be used with CPython only. Use
+# in another implementation will result in a fatal failure.
+python_get_library_path() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	python_export "${@}" PYTHON_LIBPATH
+	echo "${PYTHON_LIBPATH}"
+}
+
+# @FUNCTION: python_get_CFLAGS
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Obtain and print the compiler flags for building against Python,
+# for the given implementation. If no implementation is provided,
+# ${EPYTHON} will be used.
+#
+# Please note that this function can be used with CPython only.
+# It requires Python and pkg-config installed, and therefore proper
+# build-time dependencies need be added to the ebuild.
+python_get_CFLAGS() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	python_export "${@}" PYTHON_CFLAGS
+	echo "${PYTHON_CFLAGS}"
+}
+
+# @FUNCTION: python_get_LIBS
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Obtain and print the compiler flags for linking against Python,
+# for the given implementation. If no implementation is provided,
+# ${EPYTHON} will be used.
+#
+# Please note that this function can be used with CPython only.
+# It requires Python and pkg-config installed, and therefore proper
+# build-time dependencies need be added to the ebuild.
+python_get_LIBS() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	python_export "${@}" PYTHON_LIBS
+	echo "${PYTHON_LIBS}"
+}
+
+# @FUNCTION: python_get_PYTHON_CONFIG
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Obtain and print the PYTHON_CONFIG location for the given
+# implementation. If no implementation is provided, ${EPYTHON} will be
+# used.
+#
+# Please note that this function can be used with CPython only.
+# It requires Python installed, and therefore proper build-time
+# dependencies need be added to the ebuild.
+python_get_PYTHON_CONFIG() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	python_export "${@}" PYTHON_CONFIG
+	echo "${PYTHON_CONFIG}"
+}
+
+# @FUNCTION: python_get_scriptdir
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Obtain and print the script install path for the given
+# implementation. If no implementation is provided, ${EPYTHON} will
+# be used.
+python_get_scriptdir() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	python_export "${@}" PYTHON_SCRIPTDIR
+	echo "${PYTHON_SCRIPTDIR}"
+}
+
+# @FUNCTION: _python_ln_rel
+# @USAGE: <from> <to>
+# @INTERNAL
+# @DESCRIPTION:
+# Create a relative symlink.
+_python_ln_rel() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local target=${1}
+	local symname=${2}
+
+	local tgpath=${target%/*}/
+	local sympath=${symname%/*}/
+	local rel_target=
+
+	while [[ ${sympath} ]]; do
+		local tgseg= symseg=
+
+		while [[ ! ${tgseg} && ${tgpath} ]]; do
+			tgseg=${tgpath%%/*}
+			tgpath=${tgpath#${tgseg}/}
+		done
+
+		while [[ ! ${symseg} && ${sympath} ]]; do
+			symseg=${sympath%%/*}
+			sympath=${sympath#${symseg}/}
+		done
+
+		if [[ ${tgseg} != ${symseg} ]]; then
+			rel_target=../${rel_target}${tgseg:+${tgseg}/}
+		fi
+	done
+	rel_target+=${tgpath}${target##*/}
+
+	debug-print "${FUNCNAME}: ${symname} -> ${target}"
+	debug-print "${FUNCNAME}: rel_target = ${rel_target}"
+
+	ln -fs "${rel_target}" "${symname}"
+}
+
+# @FUNCTION: python_optimize
+# @USAGE: [<directory>...]
+# @DESCRIPTION:
+# Compile and optimize Python modules in specified directories (absolute
+# paths). If no directories are provided, the default system paths
+# are used (prepended with ${D}).
+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}
+	[[ ${PYTHON} ]] || python_export PYTHON
+
+	# default to sys.path
+	if [[ ${#} -eq 0 ]]; then
+		local f
+		while IFS= read -r -d '' f; do
+			# 1) accept only absolute paths
+			#    (i.e. skip '', '.' or anything like that)
+			# 2) skip paths which do not exist
+			#    (python2.6 complains about them verbosely)
+
+			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)
+
+		debug-print "${FUNCNAME}: using sys.path: ${*/%/;}"
+	fi
+
+	local d
+	for d; do
+		# make sure to get a nice path without //
+		local instpath=${d#${D%/}}
+		instpath=/${instpath##/}
+
+		case "${EPYTHON}" in
+			python2.7|python3.[34])
+				"${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
+				"${PYTHON}" -OO -m compileall -q -f -d "${instpath}" "${d}"
+				;;
+			python*|pypy3)
+				# both levels of optimization are separate since 3.5
+				"${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
+				"${PYTHON}" -O -m compileall -q -f -d "${instpath}" "${d}"
+				"${PYTHON}" -OO -m compileall -q -f -d "${instpath}" "${d}"
+				;;
+			*)
+				"${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
+				;;
+		esac
+	done
+}
+
+# @FUNCTION: python_scriptinto
+# @USAGE: <new-path>
+# @DESCRIPTION:
+# Set the directory to which files passed to python_doexe(),
+# python_doscript(), python_newexe() and python_newscript()
+# are going to be installed. The new value needs to be relative
+# to the installation root (${ED}).
+#
+# If not set explicitly, the directory defaults to /usr/bin.
+#
+# Example:
+# @CODE
+# src_install() {
+#   python_scriptinto /usr/sbin
+#   python_foreach_impl python_doscript foo
+# }
+# @CODE
+python_scriptinto() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	python_scriptroot=${1}
+}
+
+# @FUNCTION: python_doexe
+# @USAGE: <files>...
+# @DESCRIPTION:
+# Install the given executables into the executable install directory,
+# for the current Python implementation (${EPYTHON}).
+#
+# The executable will be wrapped properly for the Python implementation,
+# though no shebang mangling will be performed.
+python_doexe() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local f
+	for f; do
+		python_newexe "${f}" "${f##*/}"
+	done
+}
+
+# @FUNCTION: python_newexe
+# @USAGE: <path> <new-name>
+# @DESCRIPTION:
+# Install the given executable into the executable install directory,
+# for the current Python implementation (${EPYTHON}).
+#
+# The executable will be wrapped properly for the Python implementation,
+# though no shebang mangling will be performed. It will be renamed
+# to <new-name>.
+python_newexe() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	[[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
+	[[ ${#} -eq 2 ]] || die "Usage: ${FUNCNAME} <path> <new-name>"
+
+	local wrapd=${python_scriptroot:-/usr/bin}
+
+	local f=${1}
+	local newfn=${2}
+
+	local PYTHON_SCRIPTDIR d
+	python_export PYTHON_SCRIPTDIR
+	d=${PYTHON_SCRIPTDIR#${EPREFIX}}
+
+	(
+		dodir "${wrapd}"
+		exeopts -m 0755
+		exeinto "${d}"
+		newexe "${f}" "${newfn}" || return ${?}
+	)
+
+	# install the wrapper
+	_python_ln_rel "${ED%/}"/usr/lib/python-exec/python-exec2 \
+		"${ED%/}/${wrapd}/${newfn}" || die
+
+	# don't use this at home, just call python_doscript() instead
+	if [[ ${_PYTHON_REWRITE_SHEBANG} ]]; then
+		python_fix_shebang -q "${ED%/}/${d}/${newfn}"
+	fi
+}
+
+# @FUNCTION: python_doscript
+# @USAGE: <files>...
+# @DESCRIPTION:
+# Install the given scripts into the executable install directory,
+# for the current Python implementation (${EPYTHON}).
+#
+# All specified files must start with a 'python' shebang. The shebang
+# will be converted, and the files will be wrapped properly
+# for the Python implementation.
+#
+# Example:
+# @CODE
+# src_install() {
+#   python_foreach_impl python_doscript ${PN}
+# }
+# @CODE
+python_doscript() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local _PYTHON_REWRITE_SHEBANG=1
+	python_doexe "${@}"
+}
+
+# @FUNCTION: python_newscript
+# @USAGE: <path> <new-name>
+# @DESCRIPTION:
+# Install the given script into the executable install directory
+# for the current Python implementation (${EPYTHON}), and name it
+# <new-name>.
+#
+# The file must start with a 'python' shebang. The shebang will be
+# converted, and the file will be wrapped properly for the Python
+# implementation. It will be renamed to <new-name>.
+#
+# Example:
+# @CODE
+# src_install() {
+#   python_foreach_impl python_newscript foo.py foo
+# }
+# @CODE
+python_newscript() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local _PYTHON_REWRITE_SHEBANG=1
+	python_newexe "${@}"
+}
+
+# @FUNCTION: python_moduleinto
+# @USAGE: <new-path>
+# @DESCRIPTION:
+# Set the Python module install directory for python_domodule().
+# The <new-path> can either be an absolute target system path (in which
+# case it needs to start with a slash, and ${ED} will be prepended to
+# it) or relative to the implementation's site-packages directory
+# (then it must not start with a slash). The relative path can be
+# specified either using the Python package notation (separated by dots)
+# or the directory notation (using slashes).
+#
+# When not set explicitly, the modules are installed to the top
+# site-packages directory.
+#
+# In the relative case, the exact path is determined directly
+# by each python_doscript/python_newscript function. Therefore,
+# python_moduleinto can be safely called before establishing the Python
+# interpreter and/or a single call can be used to set the path correctly
+# for multiple implementations, as can be seen in the following example.
+#
+# Example:
+# @CODE
+# src_install() {
+#   python_moduleinto bar
+#   # installs ${PYTHON_SITEDIR}/bar/baz.py
+#   python_foreach_impl python_domodule baz.py
+# }
+# @CODE
+python_moduleinto() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	python_moduleroot=${1}
+}
+
+# @FUNCTION: python_domodule
+# @USAGE: <files>...
+# @DESCRIPTION:
+# Install the given modules (or packages) into the current Python module
+# installation directory. The list can mention both modules (files)
+# and packages (directories). All listed files will be installed
+# for all enabled implementations, and compiled afterwards.
+#
+# Example:
+# @CODE
+# src_install() {
+#   # (${PN} being a directory)
+#   python_foreach_impl python_domodule ${PN}
+# }
+# @CODE
+python_domodule() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	[[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
+
+	local d
+	if [[ ${python_moduleroot} == /* ]]; then
+		# absolute path
+		d=${python_moduleroot}
+	else
+		# relative to site-packages
+		local PYTHON_SITEDIR=${PYTHON_SITEDIR}
+		[[ ${PYTHON_SITEDIR} ]] || python_export PYTHON_SITEDIR
+
+		d=${PYTHON_SITEDIR#${EPREFIX}}/${python_moduleroot//.//}
+	fi
+
+	(
+		insopts -m 0644
+		insinto "${d}"
+		doins -r "${@}" || return ${?}
+	)
+
+	python_optimize "${ED%/}/${d}"
+}
+
+# @FUNCTION: python_doheader
+# @USAGE: <files>...
+# @DESCRIPTION:
+# Install the given headers into the implementation-specific include
+# directory. This function is unconditionally recursive, i.e. you can
+# pass directories instead of files.
+#
+# Example:
+# @CODE
+# src_install() {
+#   python_foreach_impl python_doheader foo.h bar.h
+# }
+# @CODE
+python_doheader() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	[[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
+
+	local d PYTHON_INCLUDEDIR=${PYTHON_INCLUDEDIR}
+	[[ ${PYTHON_INCLUDEDIR} ]] || python_export PYTHON_INCLUDEDIR
+
+	d=${PYTHON_INCLUDEDIR#${EPREFIX}}
+
+	(
+		insopts -m 0644
+		insinto "${d}"
+		doins -r "${@}" || return ${?}
+	)
+}
+
+# @FUNCTION: python_wrapper_setup
+# @USAGE: [<path> [<impl>]]
+# @DESCRIPTION:
+# Create proper 'python' executable and pkg-config wrappers
+# (if available) in the directory named by <path>. Set up PATH
+# and PKG_CONFIG_PATH appropriately. <path> defaults to ${T}/${EPYTHON}.
+#
+# The wrappers will be created for implementation named by <impl>,
+# or for one named by ${EPYTHON} if no <impl> passed.
+#
+# If the named directory contains a python symlink already, it will
+# be assumed to contain proper wrappers already and only environment
+# setup will be done. If wrapper update is requested, the directory
+# shall be removed first.
+python_wrapper_setup() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local workdir=${1:-${T}/${EPYTHON}}
+	local impl=${2:-${EPYTHON}}
+
+	[[ ${workdir} ]] || die "${FUNCNAME}: no workdir specified."
+	[[ ${impl} ]] || die "${FUNCNAME}: no impl nor EPYTHON specified."
+
+	if [[ ! -x ${workdir}/bin/python ]]; then
+		_python_check_dead_variables
+
+		mkdir -p "${workdir}"/{bin,pkgconfig} || die
+
+		# Clean up, in case we were supposed to do a cheap update.
+		rm -f "${workdir}"/bin/python{,2,3}{,-config} || die
+		rm -f "${workdir}"/bin/2to3 || die
+		rm -f "${workdir}"/pkgconfig/python{,2,3}.pc || die
+
+		local EPYTHON PYTHON
+		python_export "${impl}" EPYTHON PYTHON
+
+		local pyver pyother
+		if python_is_python3; then
+			pyver=3
+			pyother=2
+		else
+			pyver=2
+			pyother=3
+		fi
+
+		# Python interpreter
+		# note: we don't use symlinks because python likes to do some
+		# symlink reading magic that breaks stuff
+		# https://bugs.gentoo.org/show_bug.cgi?id=555752
+		cat > "${workdir}/bin/python" <<-_EOF_ || die
+			#!/bin/sh
+			exec "${PYTHON}" "\${@}"
+		_EOF_
+		cp "${workdir}/bin/python" "${workdir}/bin/python${pyver}" || die
+		chmod +x "${workdir}/bin/python" "${workdir}/bin/python${pyver}" || die
+
+		local nonsupp=( "python${pyother}" "python${pyother}-config" )
+
+		# CPython-specific
+		if [[ ${EPYTHON} == python* ]]; then
+			cat > "${workdir}/bin/python-config" <<-_EOF_ || die
+				#!/bin/sh
+				exec "${PYTHON}-config" "\${@}"
+			_EOF_
+			cp "${workdir}/bin/python-config" \
+				"${workdir}/bin/python${pyver}-config" || die
+			chmod +x "${workdir}/bin/python-config" \
+				"${workdir}/bin/python${pyver}-config" || die
+
+			# Python 2.6+.
+			ln -s "${PYTHON/python/2to3-}" "${workdir}"/bin/2to3 || die
+
+			# Python 2.7+.
+			ln -s "${EPREFIX}"/usr/$(get_libdir)/pkgconfig/${EPYTHON/n/n-}.pc \
+				"${workdir}"/pkgconfig/python.pc || die
+			ln -s python.pc "${workdir}"/pkgconfig/python${pyver}.pc || die
+		else
+			nonsupp+=( 2to3 python-config "python${pyver}-config" )
+		fi
+
+		local x
+		for x in "${nonsupp[@]}"; do
+			cat >"${workdir}"/bin/${x} <<-_EOF_ || die
+				#!/bin/sh
+				echo "${ECLASS}: ${FUNCNAME}: ${x} is not supported by ${EPYTHON} (PYTHON_COMPAT)" >&2
+				exit 127
+			_EOF_
+			chmod +x "${workdir}"/bin/${x} || die
+		done
+	fi
+
+	# Now, set the environment.
+	# But note that ${workdir} may be shared with something else,
+	# and thus already on top of PATH.
+	if [[ ${PATH##:*} != ${workdir}/bin ]]; then
+		PATH=${workdir}/bin${PATH:+:${PATH}}
+	fi
+	if [[ ${PKG_CONFIG_PATH##:*} != ${workdir}/pkgconfig ]]; then
+		PKG_CONFIG_PATH=${workdir}/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}
+	fi
+	export PATH PKG_CONFIG_PATH
+}
+
+# @FUNCTION: python_is_python3
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Check whether <impl> (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() {
+	local impl=${1:-${EPYTHON}}
+	[[ ${impl} ]] || die "python_is_python3: no impl nor EPYTHON"
+
+	[[ ${impl} == python3* || ${impl} == pypy3 ]]
+}
+
+# @FUNCTION: python_is_installed
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Check whether the interpreter for <impl> (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=()
+
+	case ${EAPI} in
+		5|6)
+			hasv_args+=( --host-root )
+			;;
+		*)
+			hasv_args+=( -b )
+			;;
+	esac
+
+	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] <path>...
+# @DESCRIPTION:
+# Replace the shebang in Python scripts with the current Python
+# implementation (EPYTHON). If a directory is passed, works recursively
+# on all Python scripts.
+#
+# Only files having a 'python*' shebang will be modified. Files with
+# other shebang will either be skipped when working recursively
+# on a directory or treated as error when specified explicitly.
+#
+# Shebangs matching explicitly current Python version will be left
+# unmodified. Shebangs requesting another Python version will be treated
+# as fatal error, unless --force is given.
+#
+# --force causes the function to replace even shebangs that require
+# incompatible Python version. --quiet causes the function not to list
+# modified files verbosely.
+python_fix_shebang() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	[[ ${EPYTHON} ]] || die "${FUNCNAME}: EPYTHON unset (pkg_setup not called?)"
+
+	local force quiet
+	while [[ ${@} ]]; do
+		case "${1}" in
+			-f|--force) force=1; shift;;
+			-q|--quiet) quiet=1; shift;;
+			--) shift; break;;
+			*) break;;
+		esac
+	done
+
+	[[ ${1} ]] || die "${FUNCNAME}: no paths given"
+
+	local path f
+	for path; do
+		local any_correct any_fixed is_recursive
+
+		[[ -d ${path} ]] && is_recursive=1
+
+		while IFS= read -r -d '' f; do
+			local shebang i
+			local error= from=
+
+			# note: we can't ||die here since read will fail if file
+			# has no newline characters
+			IFS= read -r shebang <"${f}"
+
+			# First, check if it's shebang at all...
+			if [[ ${shebang} == '#!'* ]]; then
+				local split_shebang=()
+				read -r -a split_shebang <<<${shebang} || die
+
+				# Match left-to-right in a loop, to avoid matching random
+				# repetitions like 'python2.7 python2'.
+				for i in "${split_shebang[@]}"; do
+					case "${i}" in
+						*"${EPYTHON}")
+							debug-print "${FUNCNAME}: in file ${f#${D%/}}"
+							debug-print "${FUNCNAME}: shebang matches EPYTHON: ${shebang}"
+
+							# Nothing to do, move along.
+							any_correct=1
+							from=${EPYTHON}
+							break
+							;;
+						*python|*python[23])
+							debug-print "${FUNCNAME}: in file ${f#${D%/}}"
+							debug-print "${FUNCNAME}: rewriting shebang: ${shebang}"
+
+							if [[ ${i} == *python2 ]]; then
+								from=python2
+								if [[ ! ${force} ]]; then
+									python_is_python3 "${EPYTHON}" && error=1
+								fi
+							elif [[ ${i} == *python3 ]]; then
+								from=python3
+								if [[ ! ${force} ]]; then
+									python_is_python3 "${EPYTHON}" || error=1
+								fi
+							else
+								from=python
+							fi
+							break
+							;;
+						*python[23].[0123456789]|*pypy|*pypy3|*jython[23].[0123456789])
+							# Explicit mismatch.
+							if [[ ! ${force} ]]; then
+								error=1
+							else
+								case "${i}" in
+									*python[23].[0123456789])
+										from="python[23].[0123456789]";;
+									*pypy)
+										from="pypy";;
+									*pypy3)
+										from="pypy3";;
+									*jython[23].[0123456789])
+										from="jython[23].[0123456789]";;
+									*)
+										die "${FUNCNAME}: internal error in 2nd pattern match";;
+								esac
+							fi
+							break
+							;;
+					esac
+				done
+			fi
+
+			if [[ ! ${error} && ! ${from} ]]; then
+				# Non-Python shebang. Allowed in recursive mode,
+				# disallowed when specifying file explicitly.
+				[[ ${is_recursive} ]] && continue
+				error=1
+			fi
+
+			if [[ ! ${quiet} ]]; then
+				einfo "Fixing shebang in ${f#${D%/}}."
+			fi
+
+			if [[ ! ${error} ]]; then
+				# We either want to match ${from} followed by space
+				# or at end-of-string.
+				if [[ ${shebang} == *${from}" "* ]]; then
+					sed -i -e "1s:${from} :${EPYTHON} :" "${f}" || die
+				else
+					sed -i -e "1s:${from}$:${EPYTHON}:" "${f}" || die
+				fi
+				any_fixed=1
+			else
+				eerror "The file has incompatible shebang:"
+				eerror "  file: ${f#${D%/}}"
+				eerror "  current shebang: ${shebang}"
+				eerror "  requested impl: ${EPYTHON}"
+				die "${FUNCNAME}: conversion of incompatible shebang requested"
+			fi
+		done < <(find -H "${path}" -type f -print0 || die)
+
+		if [[ ! ${any_fixed} ]]; then
+			local cmd=eerror
+			[[ ${EAPI} == 5 ]] && cmd=eqawarn
+
+			"${cmd}" "QA warning: ${FUNCNAME}, ${path#${D%/}} did not match any fixable files."
+			if [[ ${any_correct} ]]; then
+				"${cmd}" "All files have ${EPYTHON} shebang already."
+			else
+				"${cmd}" "There are no Python files in specified directory."
+			fi
+
+			[[ ${cmd} == eerror ]] && die "${FUNCNAME} did not match any fixable files (QA warning fatal in EAPI ${EAPI})"
+		fi
+	done
+}
+
+# @FUNCTION: _python_check_locale_sanity
+# @USAGE: <locale>
+# @INTERNAL
+# @RETURN: 0 if sane, 1 otherwise
+# @DESCRIPTION:
+# Check whether the specified locale sanely maps between lowercase
+# and uppercase ASCII characters.
+_python_check_locale_sanity() {
+	local -x LC_ALL=${1}
+	local IFS=
+
+	local lc=( {a..z} )
+	local uc=( {A..Z} )
+	local input="${lc[*]}${uc[*]}"
+
+	local output=$(tr '[:lower:][:upper:]' '[:upper:][:lower:]' <<<"${input}")
+	[[ ${output} == "${uc[*]}${lc[*]}" ]]
+}
+
+# @FUNCTION: python_export_utf8_locale
+# @RETURN: 0 on success, 1 on failure.
+# @DESCRIPTION:
+# Attempts to export a usable UTF-8 locale in the LC_CTYPE variable. Does
+# nothing if LC_ALL is defined, or if the current locale uses a UTF-8 charmap.
+# This may be used to work around the quirky open() behavior of python3.
+python_export_utf8_locale() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	# If the locale program isn't available, just return.
+	type locale >/dev/null || return 0
+
+	if [[ $(locale charmap) != UTF-8 ]]; then
+		# Try English first, then everything else.
+		local lang locales="C.UTF-8 en_US.UTF-8 en_GB.UTF-8 $(locale -a)"
+
+		for lang in ${locales}; do
+			if [[ $(LC_ALL=${lang} locale charmap 2>/dev/null) == UTF-8 ]]; then
+				if _python_check_locale_sanity "${lang}"; then
+					export LC_CTYPE=${lang}
+					if [[ -n ${LC_ALL} ]]; then
+						export LC_NUMERIC=${LC_ALL}
+						export LC_TIME=${LC_ALL}
+						export LC_COLLATE=${LC_ALL}
+						export LC_MONETARY=${LC_ALL}
+						export LC_MESSAGES=${LC_ALL}
+						export LC_PAPER=${LC_ALL}
+						export LC_NAME=${LC_ALL}
+						export LC_ADDRESS=${LC_ALL}
+						export LC_TELEPHONE=${LC_ALL}
+						export LC_MEASUREMENT=${LC_ALL}
+						export LC_IDENTIFICATION=${LC_ALL}
+						export LC_ALL=
+					fi
+					return 0
+				fi
+			fi
+		done
+
+		ewarn "Could not find a UTF-8 locale. This may trigger build failures in"
+		ewarn "some python packages. Please ensure that a UTF-8 locale is listed in"
+		ewarn "/etc/locale.gen and run locale-gen."
+		return 1
+	fi
+
+	return 0
+}
+
+# @FUNCTION: build_sphinx
+# @USAGE: <directory>
+# @DESCRIPTION:
+# Build HTML documentation using dev-python/sphinx in the specified
+# <directory>.  Takes care of disabling Intersphinx and appending
+# to HTML_DOCS.
+#
+# If <directory> is relative to the current directory, care needs
+# to be taken to run einstalldocs from the same directory
+# (usually ${S}).
+build_sphinx() {
+	debug-print-function ${FUNCNAME} "${@}"
+	[[ ${#} -eq 1 ]] || die "${FUNCNAME} takes 1 arg: <directory>"
+
+	local dir=${1}
+
+	sed -i -e 's:^intersphinx_mapping:disabled_&:' \
+		"${dir}"/conf.py || die
+	# not all packages include the Makefile in pypi tarball
+	sphinx-build -b html -d "${dir}"/_build/doctrees "${dir}" \
+		"${dir}"/_build/html || die
+
+	HTML_DOCS+=( "${dir}/_build/html/." )
+}
+
+# -- python.eclass functions --
+
+_python_check_dead_variables() {
+	local v
+
+	for v in PYTHON_DEPEND PYTHON_USE_WITH{,_OR,_OPT} {RESTRICT,SUPPORT}_PYTHON_ABIS
+	do
+		if [[ ${!v} ]]; then
+			die "${v} is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Ebuild_head"
+		fi
+	done
+
+	for v in PYTHON_{CPPFLAGS,CFLAGS,CXXFLAGS,LDFLAGS}
+	do
+		if [[ ${!v} ]]; then
+			die "${v} is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#PYTHON_CFLAGS"
+		fi
+	done
+
+	for v in PYTHON_TESTS_RESTRICTED_ABIS PYTHON_EXPORT_PHASE_FUNCTIONS \
+		PYTHON_VERSIONED_{SCRIPTS,EXECUTABLES} PYTHON_NONVERSIONED_EXECUTABLES
+	do
+		if [[ ${!v} ]]; then
+			die "${v} is invalid for python-r2 suite"
+		fi
+	done
+
+	for v in DISTUTILS_USE_SEPARATE_SOURCE_DIRECTORIES DISTUTILS_SETUP_FILES \
+		DISTUTILS_GLOBAL_OPTIONS DISTUTILS_SRC_TEST PYTHON_MODNAME
+	do
+		if [[ ${!v} ]]; then
+			die "${v} is invalid for distutils-r2, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#${v}"
+		fi
+	done
+
+	if [[ ${DISTUTILS_DISABLE_TEST_DEPENDENCY} ]]; then
+		die "${v} is invalid for distutils-r2, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#DISTUTILS_SRC_TEST"
+	fi
+
+	# python.eclass::progress
+	for v in PYTHON_BDEPEND PYTHON_MULTIPLE_ABIS PYTHON_ABI_TYPE \
+		PYTHON_RESTRICTED_ABIS PYTHON_TESTS_FAILURES_TOLERANT_ABIS \
+		PYTHON_CFFI_MODULES_GENERATION_COMMANDS
+	do
+		if [[ ${!v} ]]; then
+			die "${v} is invalid for python-r2 suite"
+		fi
+	done
+}
+
+python_pkg_setup() {
+	die "${FUNCNAME}() is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#pkg_setup"
+}
+
+python_convert_shebangs() {
+	die "${FUNCNAME}() is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#python_convert_shebangs"
+}
+
+python_clean_py-compile_files() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_clean_installation_image() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_execute_function() {
+	die "${FUNCNAME}() is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#python_execute_function"
+}
+
+python_generate_wrapper_scripts() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_merge_intermediate_installation_images() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_set_active_version() {
+	die "${FUNCNAME}() is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#pkg_setup"
+}
+
+python_need_rebuild() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+PYTHON() {
+	die "${FUNCNAME}() is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#.24.28PYTHON.29.2C_.24.7BEPYTHON.7D"
+}
+
+python_get_implementation() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_get_implementational_package() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_get_libdir() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_get_library() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_get_version() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_get_implementation_and_version() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_execute_nosetests() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_execute_py.test() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_execute_trial() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_enable_pyc() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_disable_pyc() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_mod_optimize() {
+	die "${FUNCNAME}() is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Python_byte-code_compilation"
+}
+
+python_mod_cleanup() {
+	die "${FUNCNAME}() is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Python_byte-code_compilation"
+}
+
+# python.eclass::progress
+
+python_abi_depend() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_install_executables() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_get_extension_module_suffix() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_byte-compile_modules() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_clean_byte-compiled_modules() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+python_generate_cffi_modules() {
+	die "${FUNCNAME}() is invalid for python-r2 suite"
+}
+
+_PYTHON_UTILS_R2=1
+fi
diff --git a/eclass/tests/distutils-r2.sh b/eclass/tests/distutils-r2.sh
new file mode 100755
index 000000000000..15f59bcd7d48
--- /dev/null
+++ b/eclass/tests/distutils-r2.sh
@@ -0,0 +1,98 @@
+#!/bin/bash
+# Copyright 1999-2015 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=5
+PYTHON_COMPAT=( python2_7 )
+source tests-common.sh
+
+test-phase_name_free() {
+	local ph=${1}
+
+	if declare -f "${ph}"; then
+		die "${ph} function declared while name reserved for phase!"
+	fi
+	if declare -f "${ph}_all"; then
+		die "${ph}_all function declared while name reserved for phase!"
+	fi
+}
+
+test-distutils_enable_tests() {
+	local runner=${1}
+	local exp_IUSE=${2}
+	local exp_RESTRICT=${3}
+	local exp_DEPEND=${4}
+
+	local IUSE=${IUSE}
+	local RESTRICT=${RESTRICT}
+	local DEPEND=${DEPEND}
+
+	tbegin "${runner}"
+
+	distutils_enable_tests "${runner}"
+
+	local ret var
+	for var in IUSE RESTRICT DEPEND; do
+		local exp_var=exp_${var}
+		if [[ ${!var} != "${!exp_var}" ]]; then
+			eindent
+			eerror "${var} expected: ${!exp_var}"
+			eerror "${var}   actual: ${!var}"
+			eoutdent
+			ret=1
+			tret=1
+		fi
+	done
+
+	tend ${ret}
+}
+
+DISTUTILS_USE_SETUPTOOLS=no
+inherit distutils-r2
+
+tbegin "sane function names"
+
+test-phase_name_free python_prepare
+test-phase_name_free python_configure
+test-phase_name_free python_compile
+test-phase_name_free python_test
+test-phase_name_free python_install
+
+tend
+
+einfo distutils_enable_tests
+eindent
+BASE_IUSE="python_targets_python2_7"
+BASE_DEPS="python_targets_python2_7? ( >=dev-lang/python-2.7.5-r2:2.7 ) >=dev-lang/python-exec-2:=[python_targets_python2_7(-)?,-python_single_target_python2_7(-)]"
+TEST_RESTRICT=" !test? ( test )"
+
+einfo "empty RDEPEND"
+eindent
+RDEPEND=""
+test-distutils_enable_tests pytest \
+	"${BASE_IUSE} test" "${TEST_RESTRICT}" "${BASE_DEPS} test? (  dev-python/pytest[${PYTHON_USEDEP}] )"
+test-distutils_enable_tests nose \
+	"${BASE_IUSE} test" "${TEST_RESTRICT}" "${BASE_DEPS} test? (  dev-python/nose[${PYTHON_USEDEP}] )"
+test-distutils_enable_tests unittest \
+	"${BASE_IUSE}" "" "${BASE_DEPS}"
+test-distutils_enable_tests setup.py \
+	"${BASE_IUSE}" "" "${BASE_DEPS}"
+eoutdent
+
+einfo "non-empty RDEPEND"
+eindent
+BASE_RDEPEND="dev-python/foo[${PYTHON_USEDEP}]"
+RDEPEND=${BASE_RDEPEND}
+test-distutils_enable_tests pytest \
+	"${BASE_IUSE} test" "${TEST_RESTRICT}" "${BASE_DEPS} test? ( ${BASE_RDEPEND} dev-python/pytest[${PYTHON_USEDEP}] )"
+test-distutils_enable_tests nose \
+	"${BASE_IUSE} test" "${TEST_RESTRICT}" "${BASE_DEPS} test? ( ${BASE_RDEPEND} dev-python/nose[${PYTHON_USEDEP}] )"
+test-distutils_enable_tests unittest \
+	"${BASE_IUSE} test" "${TEST_RESTRICT}" "${BASE_DEPS} test? ( ${BASE_RDEPEND} )"
+test-distutils_enable_tests setup.py \
+	"${BASE_IUSE} test" "${TEST_RESTRICT}" "${BASE_DEPS} test? ( ${BASE_RDEPEND} )"
+eoutdent
+
+eoutdent
+
+texit
diff --git a/eclass/tests/python-utils-r2.sh b/eclass/tests/python-utils-r2.sh
new file mode 100755
index 000000000000..64490cb0d24a
--- /dev/null
+++ b/eclass/tests/python-utils-r2.sh
@@ -0,0 +1,237 @@
+#!/bin/bash
+# Copyright 1999-2019 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=7
+source tests-common.sh
+
+test_var() {
+	local var=${1}
+	local impl=${2}
+	local expect=${3}
+
+	tbegin "${var} for ${impl}"
+
+	local ${var}
+	python_export ${impl} PYTHON ${var}
+	[[ ${!var} == ${expect} ]] || eerror "(${impl}: ${var}: ${!var} != ${expect}"
+
+	tend ${?}
+}
+
+test_is() {
+	local func=${1}
+	local expect=${2}
+
+	tbegin "${func} (expecting: ${expect})"
+
+	${func}
+	[[ ${?} == ${expect} ]]
+
+	tend ${?}
+}
+
+test_fix_shebang() {
+	local from=${1}
+	local to=${2}
+	local expect=${3}
+	local args=( "${@:4}" )
+
+	tbegin "python_fix_shebang${args[@]+ ${args[*]}} from ${from} to ${to} (exp: ${expect})"
+
+	echo "${from}" > "${tmpfile}"
+	output=$( EPYTHON=${to} python_fix_shebang "${args[@]}" -q "${tmpfile}" 2>&1 )
+
+	if [[ ${?} != 0 ]]; then
+		if [[ ${expect} != FAIL ]]; then
+			echo "${output}"
+			tend 1
+		else
+			tend 0
+		fi
+	else
+		[[ $(<"${tmpfile}") == ${expect} ]] \
+			|| eerror "${from} -> ${to}: $(<"${tmpfile}") != ${expect}"
+		tend ${?}
+	fi
+}
+
+tmpfile=$(mktemp)
+
+inherit python-utils-r2
+
+test_var EPYTHON python2_7 python2.7
+test_var PYTHON python2_7 /usr/bin/python2.7
+if [[ -x /usr/bin/python2.7 ]]; then
+	test_var PYTHON_SITEDIR python2_7 "/usr/lib*/python2.7/site-packages"
+	test_var PYTHON_INCLUDEDIR python2_7 /usr/include/python2.7
+	test_var PYTHON_LIBPATH python2_7 "/usr/lib*/libpython2.7$(get_libname)"
+	test_var PYTHON_CONFIG python2_7 /usr/bin/python2.7-config
+	test_var PYTHON_CFLAGS python2_7 "*-I/usr/include/python2.7*"
+	test_var PYTHON_LIBS python2_7 "*-lpython2.7*"
+fi
+test_var PYTHON_PKG_DEP python2_7 '*dev-lang/python*:2.7'
+test_var PYTHON_SCRIPTDIR python2_7 /usr/lib/python-exec/python2.7
+
+test_var EPYTHON python3_6 python3.6
+test_var PYTHON python3_6 /usr/bin/python3.6
+if [[ -x /usr/bin/python3.6 ]]; then
+	abiflags=$(/usr/bin/python3.6 -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS"))')
+	test_var PYTHON_SITEDIR python3_6 "/usr/lib*/python3.6/site-packages"
+	test_var PYTHON_INCLUDEDIR python3_6 "/usr/include/python3.6${abiflags}"
+	test_var PYTHON_LIBPATH python3_6 "/usr/lib*/libpython3.6${abiflags}$(get_libname)"
+	test_var PYTHON_CONFIG python3_6 "/usr/bin/python3.6${abiflags}-config"
+	test_var PYTHON_CFLAGS python3_6 "*-I/usr/include/python3.6*"
+	test_var PYTHON_LIBS python3_6 "*-lpython3.6*"
+fi
+test_var PYTHON_PKG_DEP python3_6 '*dev-lang/python*:3.6'
+test_var PYTHON_SCRIPTDIR python3_6 /usr/lib/python-exec/python3.6
+
+test_var EPYTHON python3_7 python3.7
+test_var PYTHON python3_7 /usr/bin/python3.7
+if [[ -x /usr/bin/python3.7 ]]; then
+	abiflags=$(/usr/bin/python3.7 -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS"))')
+	test_var PYTHON_SITEDIR python3_7 "/usr/lib/python3.7/site-packages"
+	test_var PYTHON_INCLUDEDIR python3_7 "/usr/include/python3.7${abiflags}"
+	test_var PYTHON_LIBPATH python3_7 "/usr/lib*/libpython3.7${abiflags}$(get_libname)"
+	test_var PYTHON_CONFIG python3_7 "/usr/bin/python3.7${abiflags}-config"
+	test_var PYTHON_CFLAGS python3_7 "*-I/usr/include/python3.7*"
+	test_var PYTHON_LIBS python3_7 "*-lpython3.7*"
+fi
+test_var PYTHON_PKG_DEP python3_7 '*dev-lang/python*:3.7'
+test_var PYTHON_SCRIPTDIR python3_7 /usr/lib/python-exec/python3.7
+
+test_var EPYTHON jython2_7 jython2.7
+test_var PYTHON jython2_7 /usr/bin/jython2.7
+if [[ -x /usr/bin/jython2.7 ]]; then
+	test_var PYTHON_SITEDIR jython2_7 /usr/share/jython-2.7/Lib/site-packages
+fi
+test_var PYTHON_PKG_DEP jython2_7 '*dev-java/jython*:2.7'
+test_var PYTHON_SCRIPTDIR jython2_7 /usr/lib/python-exec/jython2.7
+
+test_var EPYTHON pypy pypy
+test_var PYTHON pypy /usr/bin/pypy
+if [[ -x /usr/bin/pypy ]]; then
+	test_var PYTHON_SITEDIR pypy "/usr/lib*/pypy2.7/site-packages"
+	test_var PYTHON_INCLUDEDIR pypy "/usr/lib*/pypy2.7/include"
+fi
+test_var PYTHON_PKG_DEP pypy '*dev-python/pypy*:0='
+test_var PYTHON_SCRIPTDIR pypy /usr/lib/python-exec/pypy
+
+test_var EPYTHON pypy3 pypy3
+test_var PYTHON pypy3 /usr/bin/pypy3
+if [[ -x /usr/bin/pypy3 ]]; then
+	test_var PYTHON_SITEDIR pypy3 "/usr/lib*/pypy3.?/site-packages"
+	test_var PYTHON_INCLUDEDIR pypy3 "/usr/lib*/pypy3.?/include"
+fi
+test_var PYTHON_PKG_DEP pypy3 '*dev-python/pypy3*:0='
+test_var PYTHON_SCRIPTDIR pypy3 /usr/lib/python-exec/pypy3
+
+test_is "python_is_python3 python2.7" 1
+test_is "python_is_python3 python3.2" 0
+test_is "python_is_python3 jython2.7" 1
+test_is "python_is_python3 pypy" 1
+test_is "python_is_python3 pypy3" 0
+
+# generic shebangs
+test_fix_shebang '#!/usr/bin/python' python2.7 '#!/usr/bin/python2.7'
+test_fix_shebang '#!/usr/bin/python' python3.6 '#!/usr/bin/python3.6'
+test_fix_shebang '#!/usr/bin/python' pypy '#!/usr/bin/pypy'
+test_fix_shebang '#!/usr/bin/python' pypy3 '#!/usr/bin/pypy3'
+test_fix_shebang '#!/usr/bin/python' jython2.7 '#!/usr/bin/jython2.7'
+
+# python2/python3 matching
+test_fix_shebang '#!/usr/bin/python2' python2.7 '#!/usr/bin/python2.7'
+test_fix_shebang '#!/usr/bin/python3' python2.7 FAIL
+test_fix_shebang '#!/usr/bin/python3' python2.7 '#!/usr/bin/python2.7' --force
+test_fix_shebang '#!/usr/bin/python3' python3.6 '#!/usr/bin/python3.6'
+test_fix_shebang '#!/usr/bin/python2' python3.6 FAIL
+test_fix_shebang '#!/usr/bin/python2' python3.6 '#!/usr/bin/python3.6' --force
+
+# pythonX.Y matching (those mostly test the patterns)
+test_fix_shebang '#!/usr/bin/python2.7' python2.7 '#!/usr/bin/python2.7'
+test_fix_shebang '#!/usr/bin/python2.7' python3.2 FAIL
+test_fix_shebang '#!/usr/bin/python2.7' python3.2 '#!/usr/bin/python3.2' --force
+test_fix_shebang '#!/usr/bin/python3.2' python3.2 '#!/usr/bin/python3.2'
+test_fix_shebang '#!/usr/bin/python3.2' python2.7 FAIL
+test_fix_shebang '#!/usr/bin/python3.2' python2.7 '#!/usr/bin/python2.7' --force
+test_fix_shebang '#!/usr/bin/pypy' pypy '#!/usr/bin/pypy'
+test_fix_shebang '#!/usr/bin/pypy' python2.7 FAIL
+test_fix_shebang '#!/usr/bin/pypy' python2.7 '#!/usr/bin/python2.7' --force
+test_fix_shebang '#!/usr/bin/jython2.7' jython2.7 '#!/usr/bin/jython2.7'
+test_fix_shebang '#!/usr/bin/jython2.7' jython3.2 FAIL
+test_fix_shebang '#!/usr/bin/jython2.7' jython3.2 '#!/usr/bin/jython3.2' --force
+
+# fancy path handling
+test_fix_shebang '#!/mnt/python2/usr/bin/python' python3.6 \
+	'#!/mnt/python2/usr/bin/python3.6'
+test_fix_shebang '#!/mnt/python2/usr/bin/python2' python2.7 \
+	'#!/mnt/python2/usr/bin/python2.7'
+test_fix_shebang '#!/mnt/python2/usr/bin/env python' python2.7 \
+	'#!/mnt/python2/usr/bin/env python2.7'
+test_fix_shebang '#!/mnt/python2/usr/bin/python2 python2' python2.7 \
+	'#!/mnt/python2/usr/bin/python2.7 python2'
+test_fix_shebang '#!/mnt/python2/usr/bin/python3 python2' python2.7 FAIL
+test_fix_shebang '#!/mnt/python2/usr/bin/python3 python2' python2.7 \
+	'#!/mnt/python2/usr/bin/python2.7 python2' --force
+test_fix_shebang '#!/usr/bin/foo' python2.7 FAIL
+
+# regression test for bug #522080
+test_fix_shebang '#!/usr/bin/python ' python2.7 '#!/usr/bin/python2.7 '
+
+# make sure we don't break pattern matching
+test_is "_python_impl_supported python2_5" 1
+test_is "_python_impl_supported python2_6" 1
+test_is "_python_impl_supported python2_7" 0
+test_is "_python_impl_supported python3_1" 1
+test_is "_python_impl_supported python3_2" 1
+test_is "_python_impl_supported python3_3" 1
+test_is "_python_impl_supported python3_4" 1
+test_is "_python_impl_supported python3_5" 1
+test_is "_python_impl_supported python3_6" 0
+test_is "_python_impl_supported python3_7" 0
+test_is "_python_impl_supported python3_8" 0
+test_is "_python_impl_supported pypy1_8" 1
+test_is "_python_impl_supported pypy1_9" 1
+test_is "_python_impl_supported pypy2_0" 1
+test_is "_python_impl_supported pypy" 1
+test_is "_python_impl_supported pypy3" 0
+test_is "_python_impl_supported jython2_7" 1
+
+# check _python_impl_matches behavior
+test_is "_python_impl_matches python2_7 -2" 0
+test_is "_python_impl_matches python3_6 -2" 1
+test_is "_python_impl_matches python3_7 -2" 1
+test_is "_python_impl_matches pypy -2" 0
+test_is "_python_impl_matches pypy3 -2" 1
+test_is "_python_impl_matches python2_7 -3" 1
+test_is "_python_impl_matches python3_6 -3" 0
+test_is "_python_impl_matches python3_7 -3" 0
+test_is "_python_impl_matches pypy -3" 1
+test_is "_python_impl_matches pypy3 -3" 0
+test_is "_python_impl_matches python2_7 -2 python3_6" 0
+test_is "_python_impl_matches python3_6 -2 python3_6" 0
+test_is "_python_impl_matches python3_7 -2 python3_6" 1
+test_is "_python_impl_matches pypy -2 python3_6" 0
+test_is "_python_impl_matches pypy3 -2 python3_6" 1
+test_is "_python_impl_matches python2_7 pypy3 -2 python3_6" 0
+test_is "_python_impl_matches python3_6 pypy3 -2 python3_6" 0
+test_is "_python_impl_matches python3_7 pypy3 -2 python3_6" 1
+test_is "_python_impl_matches pypy pypy3 -2 python3_6" 0
+test_is "_python_impl_matches pypy3 pypy3 -2 python3_6" 0
+set -f
+test_is "_python_impl_matches python2_7 pypy*" 1
+test_is "_python_impl_matches python3_6 pypy*" 1
+test_is "_python_impl_matches python3_7 pypy*" 1
+test_is "_python_impl_matches pypy pypy*" 0
+test_is "_python_impl_matches pypy3 pypy*" 0
+test_is "_python_impl_matches python2_7 python*" 0
+test_is "_python_impl_matches python3_6 python*" 0
+test_is "_python_impl_matches python3_7 python*" 0
+test_is "_python_impl_matches pypy python*" 1
+test_is "_python_impl_matches pypy3 python*" 1
+set +f
+
+rm "${tmpfile}"
+
+texit
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 02/20] distutils-r2.eclass: Remove EXAMPLES
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 01/20] eclass: Copy python-r1 suite to python-r2 Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 03/20] distutils-r2.eclass: Remove no-op subphase defaults Michał Górny
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/distutils-r2.eclass | 28 +---------------------------
 1 file changed, 1 insertion(+), 27 deletions(-)

diff --git a/eclass/distutils-r2.eclass b/eclass/distutils-r2.eclass
index 559ca2b72c1c..4995c95ea604 100644
--- a/eclass/distutils-r2.eclass
+++ b/eclass/distutils-r2.eclass
@@ -201,26 +201,6 @@ unset -f _distutils_set_globals
 # HTML_DOCS=( doc/html/. )
 # @CODE
 
-# @ECLASS-VARIABLE: EXAMPLES
-# @DEFAULT_UNSET
-# @DESCRIPTION:
-# OBSOLETE: this variable is deprecated and banned in EAPI 6
-#
-# An array containing examples installed into 'examples' doc
-# subdirectory. The files and directories listed there must exist
-# in the directory from which distutils-r2_python_install_all() is run
-# (${S} by default).
-#
-# The 'examples' subdirectory will be marked not to be compressed
-# automatically.
-#
-# If unset, no examples will be installed.
-#
-# Example:
-# @CODE
-# EXAMPLES=( examples/. demos/. )
-# @CODE
-
 # @ECLASS-VARIABLE: DISTUTILS_IN_SOURCE_BUILD
 # @DEFAULT_UNSET
 # @DESCRIPTION:
@@ -911,13 +891,7 @@ distutils-r2_python_install_all() {
 	einstalldocs
 
 	if declare -p EXAMPLES &>/dev/null; then
-		[[ ${EAPI} != [45] ]] && die "EXAMPLES are banned in EAPI ${EAPI}"
-
-		(
-			docinto examples
-			dodoc -r "${EXAMPLES[@]}"
-		)
-		docompress -x "/usr/share/doc/${PF}/examples"
+		die "EXAMPLES are no longer supported in distutils-r2"
 	fi
 }
 
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 03/20] distutils-r2.eclass: Remove no-op subphase defaults
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 01/20] eclass: Copy python-r1 suite to python-r2 Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 02/20] distutils-r2.eclass: Remove EXAMPLES Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 04/20] distutils-r2.eclass: Remove distutils.eclass checks Michał Górny
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/distutils-r2.eclass | 18 ------------------
 1 file changed, 18 deletions(-)

diff --git a/eclass/distutils-r2.eclass b/eclass/distutils-r2.eclass
index 4995c95ea604..fc241a73965a 100644
--- a/eclass/distutils-r2.eclass
+++ b/eclass/distutils-r2.eclass
@@ -626,24 +626,6 @@ distutils-r2_python_prepare_all() {
 	_DISTUTILS_DEFAULT_CALLED=1
 }
 
-# @FUNCTION: distutils-r2_python_prepare
-# @DESCRIPTION:
-# The default python_prepare(). A no-op.
-distutils-r2_python_prepare() {
-	debug-print-function ${FUNCNAME} "${@}"
-
-	[[ ${EAPI} == [45] ]] || die "${FUNCNAME} is banned in EAPI 6 (it was a no-op)"
-}
-
-# @FUNCTION: distutils-r2_python_configure
-# @DESCRIPTION:
-# The default python_configure(). A no-op.
-distutils-r2_python_configure() {
-	debug-print-function ${FUNCNAME} "${@}"
-
-	[[ ${EAPI} == [45] ]] || die "${FUNCNAME} is banned in EAPI 6 (it was a no-op)"
-}
-
 # @FUNCTION: _distutils-r2_create_setup_cfg
 # @INTERNAL
 # @DESCRIPTION:
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 04/20] distutils-r2.eclass: Remove distutils.eclass checks
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (2 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 03/20] distutils-r2.eclass: Remove no-op subphase defaults Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 05/20] python-r2.eclass: Remove python_gen_usedep Michał Górny
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/distutils-r2.eclass | 34 ----------------------------------
 1 file changed, 34 deletions(-)

diff --git a/eclass/distutils-r2.eclass b/eclass/distutils-r2.eclass
index fc241a73965a..e17345b58221 100644
--- a/eclass/distutils-r2.eclass
+++ b/eclass/distutils-r2.eclass
@@ -1106,39 +1106,5 @@ distutils-r2_src_install() {
 	_distutils-r2_check_namespace_pth
 }
 
-# -- distutils.eclass functions --
-
-distutils_get_intermediate_installation_image() {
-	die "${FUNCNAME}() is invalid for distutils-r2"
-}
-
-distutils_src_unpack() {
-	die "${FUNCNAME}() is invalid for distutils-r2, and you don't want it in EAPI ${EAPI} anyway"
-}
-
-distutils_src_prepare() {
-	die "${FUNCNAME}() is invalid for distutils-r2, you probably want: ${FUNCNAME/_/-r2_}"
-}
-
-distutils_src_compile() {
-	die "${FUNCNAME}() is invalid for distutils-r2, you probably want: ${FUNCNAME/_/-r2_}"
-}
-
-distutils_src_test() {
-	die "${FUNCNAME}() is invalid for distutils-r2, you probably want: ${FUNCNAME/_/-r2_}"
-}
-
-distutils_src_install() {
-	die "${FUNCNAME}() is invalid for distutils-r2, you probably want: ${FUNCNAME/_/-r2_}"
-}
-
-distutils_pkg_postinst() {
-	die "${FUNCNAME}() is invalid for distutils-r2, and pkg_postinst is unnecessary"
-}
-
-distutils_pkg_postrm() {
-	die "${FUNCNAME}() is invalid for distutils-r2, and pkg_postrm is unnecessary"
-}
-
 _DISTUTILS_R2=1
 fi
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 05/20] python-r2.eclass: Remove python_gen_usedep
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (3 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 04/20] distutils-r2.eclass: Remove distutils.eclass checks Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 06/20] python-utils-r2.eclass: Remove python.eclass checks Michał Górny
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/python-r2.eclass | 43 +----------------------------------------
 1 file changed, 1 insertion(+), 42 deletions(-)

diff --git a/eclass/python-r2.eclass b/eclass/python-r2.eclass
index a71ebeba7c54..20d80940c31f 100644
--- a/eclass/python-r2.eclass
+++ b/eclass/python-r2.eclass
@@ -285,8 +285,7 @@ _python_validate_useflags() {
 # python_is_python3). Remember to escape or quote the fnmatch patterns
 # to prevent accidental shell filename expansion.
 #
-# This is an internal function used to implement python_gen_cond_dep
-# and deprecated python_gen_usedep.
+# This is an internal function used to implement python_gen_cond_dep.
 _python_gen_usedep() {
 	debug-print-function ${FUNCNAME} "${@}"
 
@@ -307,46 +306,6 @@ _python_gen_usedep() {
 	echo "${out// /,}"
 }
 
-# @FUNCTION: python_gen_usedep
-# @USAGE: <pattern> [...]
-# @DESCRIPTION:
-# DEPRECATED.  Please use python_gen_cond_dep instead.
-#
-# Output a USE dependency string for Python implementations which
-# are both in PYTHON_COMPAT and match any of the patterns passed
-# as parameters to the function.
-#
-# The patterns can be either fnmatch-style patterns (matched via bash
-# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
-# appropriately all enabled Python 2/3 implementations (alike
-# python_is_python3). Remember to escape or quote the fnmatch patterns
-# to prevent accidental shell filename expansion.
-#
-# When all implementations are requested, please use ${PYTHON_USEDEP}
-# instead. Please also remember to set an appropriate REQUIRED_USE
-# to avoid ineffective USE flags.
-#
-# Example:
-# @CODE
-# PYTHON_COMPAT=( python{2_7,3_4} )
-# DEPEND="doc? ( dev-python/epydoc[$(python_gen_usedep 'python2*')] )"
-# @CODE
-#
-# It will cause the dependency to look like:
-# @CODE
-# DEPEND="doc? ( dev-python/epydoc[python_targets_python2_7?] )"
-# @CODE
-python_gen_usedep() {
-	debug-print-function ${FUNCNAME} "${@}"
-
-	# output only once, during some reasonable phase
-	# (avoid spamming cache regen runs)
-	if [[ ${EBUILD_PHASE} == setup ]]; then
-		eqawarn "python_gen_usedep() is deprecated. Please use python_gen_cond_dep instead."
-	fi
-	_python_gen_usedep "${@}"
-}
-
 # @FUNCTION: python_gen_useflags
 # @USAGE: [<pattern>...]
 # @DESCRIPTION:
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 06/20] python-utils-r2.eclass: Remove python.eclass checks
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (4 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 05/20] python-r2.eclass: Remove python_gen_usedep Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 07/20] python-utils-r2.eclass: Mark python_wrapper_setup private Michał Górny
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/python-utils-r2.eclass | 170 ----------------------------------
 1 file changed, 170 deletions(-)

diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
index c28c42493173..fe129f48c9c9 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -970,8 +970,6 @@ python_wrapper_setup() {
 	[[ ${impl} ]] || die "${FUNCNAME}: no impl nor EPYTHON specified."
 
 	if [[ ! -x ${workdir}/bin/python ]]; then
-		_python_check_dead_variables
-
 		mkdir -p "${workdir}"/{bin,pkgconfig} || die
 
 		# Clean up, in case we were supposed to do a cheap update.
@@ -1336,173 +1334,5 @@ build_sphinx() {
 	HTML_DOCS+=( "${dir}/_build/html/." )
 }
 
-# -- python.eclass functions --
-
-_python_check_dead_variables() {
-	local v
-
-	for v in PYTHON_DEPEND PYTHON_USE_WITH{,_OR,_OPT} {RESTRICT,SUPPORT}_PYTHON_ABIS
-	do
-		if [[ ${!v} ]]; then
-			die "${v} is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Ebuild_head"
-		fi
-	done
-
-	for v in PYTHON_{CPPFLAGS,CFLAGS,CXXFLAGS,LDFLAGS}
-	do
-		if [[ ${!v} ]]; then
-			die "${v} is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#PYTHON_CFLAGS"
-		fi
-	done
-
-	for v in PYTHON_TESTS_RESTRICTED_ABIS PYTHON_EXPORT_PHASE_FUNCTIONS \
-		PYTHON_VERSIONED_{SCRIPTS,EXECUTABLES} PYTHON_NONVERSIONED_EXECUTABLES
-	do
-		if [[ ${!v} ]]; then
-			die "${v} is invalid for python-r2 suite"
-		fi
-	done
-
-	for v in DISTUTILS_USE_SEPARATE_SOURCE_DIRECTORIES DISTUTILS_SETUP_FILES \
-		DISTUTILS_GLOBAL_OPTIONS DISTUTILS_SRC_TEST PYTHON_MODNAME
-	do
-		if [[ ${!v} ]]; then
-			die "${v} is invalid for distutils-r2, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#${v}"
-		fi
-	done
-
-	if [[ ${DISTUTILS_DISABLE_TEST_DEPENDENCY} ]]; then
-		die "${v} is invalid for distutils-r2, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#DISTUTILS_SRC_TEST"
-	fi
-
-	# python.eclass::progress
-	for v in PYTHON_BDEPEND PYTHON_MULTIPLE_ABIS PYTHON_ABI_TYPE \
-		PYTHON_RESTRICTED_ABIS PYTHON_TESTS_FAILURES_TOLERANT_ABIS \
-		PYTHON_CFFI_MODULES_GENERATION_COMMANDS
-	do
-		if [[ ${!v} ]]; then
-			die "${v} is invalid for python-r2 suite"
-		fi
-	done
-}
-
-python_pkg_setup() {
-	die "${FUNCNAME}() is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#pkg_setup"
-}
-
-python_convert_shebangs() {
-	die "${FUNCNAME}() is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#python_convert_shebangs"
-}
-
-python_clean_py-compile_files() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_clean_installation_image() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_execute_function() {
-	die "${FUNCNAME}() is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#python_execute_function"
-}
-
-python_generate_wrapper_scripts() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_merge_intermediate_installation_images() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_set_active_version() {
-	die "${FUNCNAME}() is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#pkg_setup"
-}
-
-python_need_rebuild() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-PYTHON() {
-	die "${FUNCNAME}() is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#.24.28PYTHON.29.2C_.24.7BEPYTHON.7D"
-}
-
-python_get_implementation() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_get_implementational_package() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_get_libdir() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_get_library() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_get_version() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_get_implementation_and_version() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_execute_nosetests() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_execute_py.test() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_execute_trial() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_enable_pyc() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_disable_pyc() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_mod_optimize() {
-	die "${FUNCNAME}() is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Python_byte-code_compilation"
-}
-
-python_mod_cleanup() {
-	die "${FUNCNAME}() is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Python_byte-code_compilation"
-}
-
-# python.eclass::progress
-
-python_abi_depend() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_install_executables() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_get_extension_module_suffix() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_byte-compile_modules() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_clean_byte-compiled_modules() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
-python_generate_cffi_modules() {
-	die "${FUNCNAME}() is invalid for python-r2 suite"
-}
-
 _PYTHON_UTILS_R2=1
 fi
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 07/20] python-utils-r2.eclass: Mark python_wrapper_setup private
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (5 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 06/20] python-utils-r2.eclass: Remove python.eclass checks Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 08/20] python-utils-r2.eclass: Mark python_is_installed private Michał Górny
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/python-any-r2.eclass    | 8 ++++----
 eclass/python-r2.eclass        | 4 ++--
 eclass/python-single-r2.eclass | 4 ++--
 eclass/python-utils-r2.eclass  | 5 +++--
 4 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/eclass/python-any-r2.eclass b/eclass/python-any-r2.eclass
index 08e424254983..c680d383fef6 100644
--- a/eclass/python-any-r2.eclass
+++ b/eclass/python-any-r2.eclass
@@ -299,7 +299,7 @@ python_setup() {
 		ewarn "Dependencies won't be satisfied, and EPYTHON/eselect-python will be ignored."
 
 		python_export "${impls[0]}" EPYTHON PYTHON
-		python_wrapper_setup
+		_python_wrapper_setup
 		einfo "Using ${EPYTHON} to build"
 		return
 	fi
@@ -308,7 +308,7 @@ python_setup() {
 	if [[ ${EPYTHON} ]]; then
 		if _python_EPYTHON_supported "${EPYTHON}"; then
 			python_export EPYTHON PYTHON
-			python_wrapper_setup
+			_python_wrapper_setup
 			einfo "Using ${EPYTHON} to build"
 			return
 		fi
@@ -324,7 +324,7 @@ python_setup() {
 			break
 		elif _python_EPYTHON_supported "${i}"; then
 			python_export "${i}" EPYTHON PYTHON
-			python_wrapper_setup
+			_python_wrapper_setup
 			einfo "Using ${EPYTHON} to build"
 			return
 		fi
@@ -335,7 +335,7 @@ python_setup() {
 	for (( i = ${#_PYTHON_SUPPORTED_IMPLS[@]} - 1; i >= 0; i-- )); do
 		python_export "${_PYTHON_SUPPORTED_IMPLS[i]}" EPYTHON PYTHON
 		if _python_EPYTHON_supported "${EPYTHON}"; then
-			python_wrapper_setup
+			_python_wrapper_setup
 			einfo "Using ${EPYTHON} to build"
 			return
 		fi
diff --git a/eclass/python-r2.eclass b/eclass/python-r2.eclass
index 20d80940c31f..64b3742fc08f 100644
--- a/eclass/python-r2.eclass
+++ b/eclass/python-r2.eclass
@@ -596,7 +596,7 @@ _python_multibuild_wrapper() {
 	local -x EPYTHON PYTHON
 	local -x PATH=${PATH} PKG_CONFIG_PATH=${PKG_CONFIG_PATH}
 	python_export "${MULTIBUILD_VARIANT}" EPYTHON PYTHON
-	python_wrapper_setup
+	_python_wrapper_setup
 
 	"${@}"
 }
@@ -742,7 +742,7 @@ python_setup() {
 		die "${FUNCNAME}: no enabled implementation satisfy requirements"
 	fi
 
-	python_wrapper_setup
+	_python_wrapper_setup
 	einfo "Using ${EPYTHON} in global scope"
 }
 
diff --git a/eclass/python-single-r2.eclass b/eclass/python-single-r2.eclass
index d9d535711252..0bd4d84eaa52 100644
--- a/eclass/python-single-r2.eclass
+++ b/eclass/python-single-r2.eclass
@@ -465,7 +465,7 @@ python_setup() {
 		ewarn "Dependencies won't be satisfied, and PYTHON_SINGLE_TARGET flags will be ignored."
 
 		python_export "${impls[0]}" EPYTHON PYTHON
-		python_wrapper_setup
+		_python_wrapper_setup
 		einfo "Using ${EPYTHON} to build"
 		return
 	fi
@@ -483,7 +483,7 @@ python_setup() {
 			fi
 
 			python_export "${impl}" EPYTHON PYTHON
-			python_wrapper_setup
+			_python_wrapper_setup
 			einfo "Using ${EPYTHON} to build"
 		fi
 	done
diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
index fe129f48c9c9..b49cd7cc6341 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -946,8 +946,9 @@ python_doheader() {
 	)
 }
 
-# @FUNCTION: python_wrapper_setup
+# @FUNCTION: _python_wrapper_setup
 # @USAGE: [<path> [<impl>]]
+# @INTERNAL
 # @DESCRIPTION:
 # Create proper 'python' executable and pkg-config wrappers
 # (if available) in the directory named by <path>. Set up PATH
@@ -960,7 +961,7 @@ python_doheader() {
 # be assumed to contain proper wrappers already and only environment
 # setup will be done. If wrapper update is requested, the directory
 # shall be removed first.
-python_wrapper_setup() {
+_python_wrapper_setup() {
 	debug-print-function ${FUNCNAME} "${@}"
 
 	local workdir=${1:-${T}/${EPYTHON}}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 08/20] python-utils-r2.eclass: Mark python_is_installed private
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (6 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 07/20] python-utils-r2.eclass: Mark python_wrapper_setup private Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 09/20] python-utils-r2.eclass: Fix obsolete docs on python_export_best Michał Górny
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/python-any-r2.eclass   | 2 +-
 eclass/python-r2.eclass       | 2 +-
 eclass/python-utils-r2.eclass | 5 +++--
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/eclass/python-any-r2.eclass b/eclass/python-any-r2.eclass
index c680d383fef6..b85de5f7b32d 100644
--- a/eclass/python-any-r2.eclass
+++ b/eclass/python-any-r2.eclass
@@ -262,7 +262,7 @@ _python_EPYTHON_supported() {
 	esac
 
 	if has "${i}" "${_PYTHON_SUPPORTED_IMPLS[@]}"; then
-		if python_is_installed "${i}"; 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}(+)"
 				python_check_deps
diff --git a/eclass/python-r2.eclass b/eclass/python-r2.eclass
index 64b3742fc08f..a96098fe65cf 100644
--- a/eclass/python-r2.eclass
+++ b/eclass/python-r2.eclass
@@ -723,7 +723,7 @@ python_setup() {
 		# if python_check_deps() is declared, switch into any-of mode
 		if [[ ${has_check_deps} ]]; then
 			# first check if the interpreter is installed
-			python_is_installed "${impl}" || continue
+			_python_is_installed "${impl}" || continue
 			# then run python_check_deps
 			local PYTHON_USEDEP="python_targets_${impl}(-),python_single_target_${impl}(+)"
 			python_check_deps || continue
diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
index b49cd7cc6341..7d1ef1da2b04 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -1062,14 +1062,15 @@ python_is_python3() {
 	[[ ${impl} == python3* || ${impl} == pypy3 ]]
 }
 
-# @FUNCTION: python_is_installed
+# @FUNCTION: _python_is_installed
 # @USAGE: [<impl>]
+# @INTERNAL
 # @DESCRIPTION:
 # Check whether the interpreter for <impl> (or ${EPYTHON}) is installed.
 # Uses has_version with a proper dependency string.
 #
 # Returns 0 (true) if it is, 1 (false) otherwise.
-python_is_installed() {
+_python_is_installed() {
 	local impl=${1:-${EPYTHON}}
 	[[ ${impl} ]] || die "${FUNCNAME}: no impl nor EPYTHON"
 	local hasv_args=()
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 09/20] python-utils-r2.eclass: Fix obsolete docs on python_export_best
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (7 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 08/20] python-utils-r2.eclass: Mark python_is_installed private Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 10/20] python-utils-r2.eclass: Mark python_export private Michał Górny
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/python-utils-r2.eclass | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
index 7d1ef1da2b04..ccac5677a323 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -197,7 +197,7 @@ _python_impl_matches() {
 # This variable is set automatically in the following contexts:
 #
 # python-r2: Set in functions called by python_foreach_impl() or after
-# calling python_export_best().
+# calling python_setup().
 #
 # python-single-r2: Set after calling python-single-r2_pkg_setup().
 #
@@ -216,7 +216,7 @@ _python_impl_matches() {
 # This variable is set automatically in the following contexts:
 #
 # python-r2: Set in functions called by python_foreach_impl() or after
-# calling python_export_best().
+# calling python_setup().
 #
 # python-single-r2: Set after calling python-single-r2_pkg_setup().
 #
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 10/20] python-utils-r2.eclass: Mark python_export private
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (8 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 09/20] python-utils-r2.eclass: Fix obsolete docs on python_export_best Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 11/20] python-utils-r2.eclass: Remove PYTHON_SITEDIR export Michał Górny
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/distutils-r2.eclass      |   2 +-
 eclass/python-any-r2.eclass     |  12 +--
 eclass/python-r2.eclass         |  12 +--
 eclass/python-single-r2.eclass  |   8 +-
 eclass/python-utils-r2.eclass   | 149 ++++----------------------------
 eclass/tests/python-utils-r2.sh |   2 +-
 6 files changed, 36 insertions(+), 149 deletions(-)

diff --git a/eclass/distutils-r2.eclass b/eclass/distutils-r2.eclass
index e17345b58221..99d93a2e830f 100644
--- a/eclass/distutils-r2.eclass
+++ b/eclass/distutils-r2.eclass
@@ -733,7 +733,7 @@ _distutils-r2_wrap_scripts() {
 	local bindir=${2}
 
 	local PYTHON_SCRIPTDIR
-	python_export PYTHON_SCRIPTDIR
+	_python_export PYTHON_SCRIPTDIR
 
 	local f python_files=() non_python_files=()
 
diff --git a/eclass/python-any-r2.eclass b/eclass/python-any-r2.eclass
index b85de5f7b32d..053bf4b5a0e3 100644
--- a/eclass/python-any-r2.eclass
+++ b/eclass/python-any-r2.eclass
@@ -150,7 +150,7 @@ _python_any_set_globals() {
 	_python_set_impls
 
 	for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
-		python_export "${i}" PYTHON_PKG_DEP
+		_python_export "${i}" PYTHON_PKG_DEP
 
 		# note: need to strip '=' slot operator for || deps
 		deps="${PYTHON_PKG_DEP/:0=/:0} ${deps}"
@@ -231,7 +231,7 @@ python_gen_any_dep() {
 	local i PYTHON_PKG_DEP out=
 	for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
 		local PYTHON_USEDEP="python_targets_${i}(-),python_single_target_${i}(+)"
-		python_export "${i}" PYTHON_PKG_DEP
+		_python_export "${i}" PYTHON_PKG_DEP
 
 		local i_depstr=${depstr//\$\{PYTHON_USEDEP\}/${PYTHON_USEDEP}}
 		# note: need to strip '=' slot operator for || deps
@@ -298,7 +298,7 @@ python_setup() {
 		ewarn
 		ewarn "Dependencies won't be satisfied, and EPYTHON/eselect-python will be ignored."
 
-		python_export "${impls[0]}" EPYTHON PYTHON
+		_python_export "${impls[0]}" EPYTHON PYTHON
 		_python_wrapper_setup
 		einfo "Using ${EPYTHON} to build"
 		return
@@ -307,7 +307,7 @@ python_setup() {
 	# first, try ${EPYTHON}... maybe it's good enough for us.
 	if [[ ${EPYTHON} ]]; then
 		if _python_EPYTHON_supported "${EPYTHON}"; then
-			python_export EPYTHON PYTHON
+			_python_export EPYTHON PYTHON
 			_python_wrapper_setup
 			einfo "Using ${EPYTHON} to build"
 			return
@@ -323,7 +323,7 @@ python_setup() {
 			# no eselect-python?
 			break
 		elif _python_EPYTHON_supported "${i}"; then
-			python_export "${i}" EPYTHON PYTHON
+			_python_export "${i}" EPYTHON PYTHON
 			_python_wrapper_setup
 			einfo "Using ${EPYTHON} to build"
 			return
@@ -333,7 +333,7 @@ python_setup() {
 	# fallback to best installed impl.
 	# (reverse iteration over _PYTHON_SUPPORTED_IMPLS)
 	for (( i = ${#_PYTHON_SUPPORTED_IMPLS[@]} - 1; i >= 0; i-- )); do
-		python_export "${_PYTHON_SUPPORTED_IMPLS[i]}" EPYTHON PYTHON
+		_python_export "${_PYTHON_SUPPORTED_IMPLS[i]}" EPYTHON PYTHON
 		if _python_EPYTHON_supported "${EPYTHON}"; then
 			_python_wrapper_setup
 			einfo "Using ${EPYTHON} to build"
diff --git a/eclass/python-r2.eclass b/eclass/python-r2.eclass
index a96098fe65cf..02b60d4e4de9 100644
--- a/eclass/python-r2.eclass
+++ b/eclass/python-r2.eclass
@@ -172,7 +172,7 @@ _python_set_globals() {
 	_python_set_impls
 
 	for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
-		python_export "${i}" PYTHON_PKG_DEP
+		_python_export "${i}" PYTHON_PKG_DEP
 		deps+="python_targets_${i}? ( ${PYTHON_PKG_DEP} ) "
 	done
 
@@ -443,7 +443,7 @@ python_gen_impl_dep() {
 	for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
 		if _python_impl_matches "${impl}" "${@}"; then
 			local PYTHON_PKG_DEP
-			python_export "${impl}" PYTHON_PKG_DEP
+			_python_export "${impl}" PYTHON_PKG_DEP
 			matches+=( "python_targets_${impl}? ( ${PYTHON_PKG_DEP} )" )
 		fi
 	done
@@ -521,7 +521,7 @@ python_gen_any_dep() {
 	for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
 		if _python_impl_matches "${i}" "${@}"; then
 			local PYTHON_USEDEP="python_targets_${i}(-),python_single_target_${i}(+)"
-			python_export "${i}" PYTHON_PKG_DEP
+			_python_export "${i}" PYTHON_PKG_DEP
 
 			local i_depstr=${depstr//\$\{PYTHON_USEDEP\}/${PYTHON_USEDEP}}
 			# note: need to strip '=' slot operator for || deps
@@ -595,7 +595,7 @@ _python_multibuild_wrapper() {
 
 	local -x EPYTHON PYTHON
 	local -x PATH=${PATH} PKG_CONFIG_PATH=${PKG_CONFIG_PATH}
-	python_export "${MULTIBUILD_VARIANT}" EPYTHON PYTHON
+	_python_export "${MULTIBUILD_VARIANT}" EPYTHON PYTHON
 	_python_wrapper_setup
 
 	"${@}"
@@ -718,7 +718,7 @@ python_setup() {
 		# check patterns
 		_python_impl_matches "${impl}" "${@}" || continue
 
-		python_export "${impl}" EPYTHON PYTHON
+		_python_export "${impl}" EPYTHON PYTHON
 
 		# if python_check_deps() is declared, switch into any-of mode
 		if [[ ${has_check_deps} ]]; then
@@ -761,7 +761,7 @@ python_replicate_script() {
 		local _PYTHON_FIX_SHEBANG_QUIET=1
 
 		local PYTHON_SCRIPTDIR
-		python_export PYTHON_SCRIPTDIR
+		_python_export PYTHON_SCRIPTDIR
 
 		(
 			exeopts -m 0755
diff --git a/eclass/python-single-r2.eclass b/eclass/python-single-r2.eclass
index 0bd4d84eaa52..ce170c1d13c9 100644
--- a/eclass/python-single-r2.eclass
+++ b/eclass/python-single-r2.eclass
@@ -212,7 +212,7 @@ _python_single_set_globals() {
 
 	local deps= i PYTHON_PKG_DEP
 	for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
-		python_export "${i}" PYTHON_PKG_DEP
+		_python_export "${i}" PYTHON_PKG_DEP
 		# 1) well, python-exec would suffice as an RDEP
 		# but no point in making this overcomplex, BDEP doesn't hurt anyone
 		# 2) python-exec should be built with all targets forced anyway
@@ -435,7 +435,7 @@ python_gen_impl_dep() {
 	for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
 		if _python_impl_matches "${impl}" "${@}"; then
 			local PYTHON_PKG_DEP
-			python_export "${impl}" PYTHON_PKG_DEP
+			_python_export "${impl}" PYTHON_PKG_DEP
 			matches+=( "python_single_target_${impl}? ( ${PYTHON_PKG_DEP} )" )
 		fi
 	done
@@ -464,7 +464,7 @@ python_setup() {
 		ewarn
 		ewarn "Dependencies won't be satisfied, and PYTHON_SINGLE_TARGET flags will be ignored."
 
-		python_export "${impls[0]}" EPYTHON PYTHON
+		_python_export "${impls[0]}" EPYTHON PYTHON
 		_python_wrapper_setup
 		einfo "Using ${EPYTHON} to build"
 		return
@@ -482,7 +482,7 @@ python_setup() {
 				die "More than one implementation in PYTHON_SINGLE_TARGET."
 			fi
 
-			python_export "${impl}" EPYTHON PYTHON
+			_python_export "${impl}" EPYTHON PYTHON
 			_python_wrapper_setup
 			einfo "Using ${EPYTHON} to build"
 		fi
diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
index ccac5677a323..dab4a5b5c87e 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -227,116 +227,9 @@ _python_impl_matches() {
 # python2.7
 # @CODE
 
-# @ECLASS-VARIABLE: PYTHON_SITEDIR
-# @DEFAULT_UNSET
-# @DESCRIPTION:
-# The path to Python site-packages directory.
-#
-# Set and exported on request using python_export().
-# Requires a proper build-time dependency on the Python implementation.
-#
-# Example value:
-# @CODE
-# /usr/lib64/python2.7/site-packages
-# @CODE
-
-# @ECLASS-VARIABLE: PYTHON_INCLUDEDIR
-# @DEFAULT_UNSET
-# @DESCRIPTION:
-# The path to Python include directory.
-#
-# Set and exported on request using python_export().
-# Requires a proper build-time dependency on the Python implementation.
-#
-# Example value:
-# @CODE
-# /usr/include/python2.7
-# @CODE
-
-# @ECLASS-VARIABLE: PYTHON_LIBPATH
-# @DEFAULT_UNSET
-# @DESCRIPTION:
-# The path to Python library.
-#
-# Set and exported on request using python_export().
-# Valid only for CPython. Requires a proper build-time dependency
-# on the Python implementation.
-#
-# Example value:
-# @CODE
-# /usr/lib64/libpython2.7.so
-# @CODE
-
-# @ECLASS-VARIABLE: PYTHON_CFLAGS
-# @DEFAULT_UNSET
-# @DESCRIPTION:
-# Proper C compiler flags for building against Python. Obtained from
-# pkg-config or python-config.
-#
-# Set and exported on request using python_export().
-# Valid only for CPython. Requires a proper build-time dependency
-# on the Python implementation and on pkg-config.
-#
-# Example value:
-# @CODE
-# -I/usr/include/python2.7
-# @CODE
-
-# @ECLASS-VARIABLE: PYTHON_LIBS
-# @DEFAULT_UNSET
-# @DESCRIPTION:
-# Proper C compiler flags for linking against Python. Obtained from
-# pkg-config or python-config.
-#
-# Set and exported on request using python_export().
-# Valid only for CPython. Requires a proper build-time dependency
-# on the Python implementation and on pkg-config.
-#
-# Example value:
-# @CODE
-# -lpython2.7
-# @CODE
-
-# @ECLASS-VARIABLE: PYTHON_CONFIG
-# @DEFAULT_UNSET
-# @DESCRIPTION:
-# Path to the python-config executable.
-#
-# Set and exported on request using python_export().
-# Valid only for CPython. Requires a proper build-time dependency
-# on the Python implementation and on pkg-config.
-#
-# Example value:
-# @CODE
-# /usr/bin/python2.7-config
-# @CODE
-
-# @ECLASS-VARIABLE: PYTHON_PKG_DEP
-# @DEFAULT_UNSET
-# @DESCRIPTION:
-# The complete dependency on a particular Python package as a string.
-#
-# Set and exported on request using python_export().
-#
-# Example value:
-# @CODE
-# dev-lang/python:2.7[xml]
-# @CODE
-
-# @ECLASS-VARIABLE: PYTHON_SCRIPTDIR
-# @DEFAULT_UNSET
-# @DESCRIPTION:
-# The location where Python scripts must be installed for current impl.
-#
-# Set and exported on request using python_export().
-#
-# Example value:
-# @CODE
-# /usr/lib/python-exec/python2.7
-# @CODE
-
-# @FUNCTION: python_export
+# @FUNCTION: _python_export
 # @USAGE: [<impl>] <variables>...
+# @INTERNAL
 # @DESCRIPTION:
 # Set and export the Python implementation-relevant variables passed
 # as parameters.
@@ -349,7 +242,7 @@ _python_impl_matches() {
 # The variables which can be exported are: PYTHON, EPYTHON,
 # PYTHON_SITEDIR. They are described more completely in the eclass
 # variable documentation.
-python_export() {
+_python_export() {
 	debug-print-function ${FUNCNAME} "${@}"
 
 	local impl var
@@ -366,7 +259,7 @@ python_export() {
 		*)
 			impl=${EPYTHON}
 			if [[ -z ${impl} ]]; then
-				die "python_export called without a python implementation and EPYTHON is unset"
+				die "_python_export called without a python implementation and EPYTHON is unset"
 			fi
 			;;
 	esac
@@ -494,7 +387,7 @@ python_export() {
 				debug-print "${FUNCNAME}: PYTHON_SCRIPTDIR = ${PYTHON_SCRIPTDIR}"
 				;;
 			*)
-				die "python_export: unknown variable ${var}"
+				die "_python_export: unknown variable ${var}"
 		esac
 	done
 }
@@ -505,13 +398,10 @@ python_export() {
 # Obtain and print the 'site-packages' path for the given
 # implementation. If no implementation is provided, ${EPYTHON} will
 # be used.
-#
-# If you just need to have PYTHON_SITEDIR set (and exported), then it is
-# better to use python_export() directly instead.
 python_get_sitedir() {
 	debug-print-function ${FUNCNAME} "${@}"
 
-	python_export "${@}" PYTHON_SITEDIR
+	_python_export "${@}" PYTHON_SITEDIR
 	echo "${PYTHON_SITEDIR}"
 }
 
@@ -520,13 +410,10 @@ python_get_sitedir() {
 # @DESCRIPTION:
 # Obtain and print the include path for the given implementation. If no
 # implementation is provided, ${EPYTHON} will be used.
-#
-# If you just need to have PYTHON_INCLUDEDIR set (and exported), then it
-# is better to use python_export() directly instead.
 python_get_includedir() {
 	debug-print-function ${FUNCNAME} "${@}"
 
-	python_export "${@}" PYTHON_INCLUDEDIR
+	_python_export "${@}" PYTHON_INCLUDEDIR
 	echo "${PYTHON_INCLUDEDIR}"
 }
 
@@ -541,7 +428,7 @@ python_get_includedir() {
 python_get_library_path() {
 	debug-print-function ${FUNCNAME} "${@}"
 
-	python_export "${@}" PYTHON_LIBPATH
+	_python_export "${@}" PYTHON_LIBPATH
 	echo "${PYTHON_LIBPATH}"
 }
 
@@ -558,7 +445,7 @@ python_get_library_path() {
 python_get_CFLAGS() {
 	debug-print-function ${FUNCNAME} "${@}"
 
-	python_export "${@}" PYTHON_CFLAGS
+	_python_export "${@}" PYTHON_CFLAGS
 	echo "${PYTHON_CFLAGS}"
 }
 
@@ -575,7 +462,7 @@ python_get_CFLAGS() {
 python_get_LIBS() {
 	debug-print-function ${FUNCNAME} "${@}"
 
-	python_export "${@}" PYTHON_LIBS
+	_python_export "${@}" PYTHON_LIBS
 	echo "${PYTHON_LIBS}"
 }
 
@@ -592,7 +479,7 @@ python_get_LIBS() {
 python_get_PYTHON_CONFIG() {
 	debug-print-function ${FUNCNAME} "${@}"
 
-	python_export "${@}" PYTHON_CONFIG
+	_python_export "${@}" PYTHON_CONFIG
 	echo "${PYTHON_CONFIG}"
 }
 
@@ -605,7 +492,7 @@ python_get_PYTHON_CONFIG() {
 python_get_scriptdir() {
 	debug-print-function ${FUNCNAME} "${@}"
 
-	python_export "${@}" PYTHON_SCRIPTDIR
+	_python_export "${@}" PYTHON_SCRIPTDIR
 	echo "${PYTHON_SCRIPTDIR}"
 }
 
@@ -670,7 +557,7 @@ python_optimize() {
 	[[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
 
 	local PYTHON=${PYTHON}
-	[[ ${PYTHON} ]] || python_export PYTHON
+	[[ ${PYTHON} ]] || _python_export PYTHON
 
 	# default to sys.path
 	if [[ ${#} -eq 0 ]]; then
@@ -774,7 +661,7 @@ python_newexe() {
 	local newfn=${2}
 
 	local PYTHON_SCRIPTDIR d
-	python_export PYTHON_SCRIPTDIR
+	_python_export PYTHON_SCRIPTDIR
 	d=${PYTHON_SCRIPTDIR#${EPREFIX}}
 
 	(
@@ -902,7 +789,7 @@ python_domodule() {
 	else
 		# relative to site-packages
 		local PYTHON_SITEDIR=${PYTHON_SITEDIR}
-		[[ ${PYTHON_SITEDIR} ]] || python_export PYTHON_SITEDIR
+		[[ ${PYTHON_SITEDIR} ]] || _python_export PYTHON_SITEDIR
 
 		d=${PYTHON_SITEDIR#${EPREFIX}}/${python_moduleroot//.//}
 	fi
@@ -935,7 +822,7 @@ python_doheader() {
 	[[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
 
 	local d PYTHON_INCLUDEDIR=${PYTHON_INCLUDEDIR}
-	[[ ${PYTHON_INCLUDEDIR} ]] || python_export PYTHON_INCLUDEDIR
+	[[ ${PYTHON_INCLUDEDIR} ]] || _python_export PYTHON_INCLUDEDIR
 
 	d=${PYTHON_INCLUDEDIR#${EPREFIX}}
 
@@ -979,7 +866,7 @@ _python_wrapper_setup() {
 		rm -f "${workdir}"/pkgconfig/python{,2,3}.pc || die
 
 		local EPYTHON PYTHON
-		python_export "${impl}" EPYTHON PYTHON
+		_python_export "${impl}" EPYTHON PYTHON
 
 		local pyver pyother
 		if python_is_python3; then
@@ -1085,7 +972,7 @@ _python_is_installed() {
 	esac
 
 	local PYTHON_PKG_DEP
-	python_export "${impl}" PYTHON_PKG_DEP
+	_python_export "${impl}" PYTHON_PKG_DEP
 	has_version "${hasv_args[@]}" "${PYTHON_PKG_DEP}"
 }
 
diff --git a/eclass/tests/python-utils-r2.sh b/eclass/tests/python-utils-r2.sh
index 64490cb0d24a..c5e618256519 100755
--- a/eclass/tests/python-utils-r2.sh
+++ b/eclass/tests/python-utils-r2.sh
@@ -13,7 +13,7 @@ test_var() {
 	tbegin "${var} for ${impl}"
 
 	local ${var}
-	python_export ${impl} PYTHON ${var}
+	_python_export ${impl} PYTHON ${var}
 	[[ ${!var} == ${expect} ]] || eerror "(${impl}: ${var}: ${!var} != ${expect}"
 
 	tend ${?}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 11/20] python-utils-r2.eclass: Remove PYTHON_SITEDIR export
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (9 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 10/20] python-utils-r2.eclass: Mark python_export private Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 12/20] python-utils-r2.eclass: Remove PYTHON_INCLUDEDIR export Michał Górny
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/python-utils-r2.eclass   | 34 +++++++++++----------------------
 eclass/tests/python-utils-r2.sh | 25 ++++++++++++++++++------
 2 files changed, 30 insertions(+), 29 deletions(-)

diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
index dab4a5b5c87e..4f9df6000e16 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -238,10 +238,6 @@ _python_impl_matches() {
 # implementation (either as PYTHON_TARGETS value, e.g. python2_7,
 # or an EPYTHON one, e.g. python2.7). If no implementation passed,
 # the current one will be obtained from ${EPYTHON}.
-#
-# The variables which can be exported are: PYTHON, EPYTHON,
-# PYTHON_SITEDIR. They are described more completely in the eclass
-# variable documentation.
 _python_export() {
 	debug-print-function ${FUNCNAME} "${@}"
 
@@ -275,15 +271,6 @@ _python_export() {
 				export PYTHON=${EPREFIX}/usr/bin/${impl}
 				debug-print "${FUNCNAME}: PYTHON = ${PYTHON}"
 				;;
-			PYTHON_SITEDIR)
-				[[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
-				# sysconfig can't be used because:
-				# 1) pypy doesn't give site-packages but stdlib
-				# 2) jython gives paths with wrong case
-				PYTHON_SITEDIR=$("${PYTHON}" -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_lib())') || die
-				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 distutils.sysconfig; print(distutils.sysconfig.get_python_inc())') || die
@@ -393,16 +380,18 @@ _python_export() {
 }
 
 # @FUNCTION: python_get_sitedir
-# @USAGE: [<impl>]
 # @DESCRIPTION:
-# Obtain and print the 'site-packages' path for the given
-# implementation. If no implementation is provided, ${EPYTHON} will
-# be used.
+# Obtain and print the 'site-packages' path for ${EPYTHON}.
 python_get_sitedir() {
 	debug-print-function ${FUNCNAME} "${@}"
-
-	_python_export "${@}" PYTHON_SITEDIR
-	echo "${PYTHON_SITEDIR}"
+	[[ ${EPYTHON} ]] || die "EPYTHON must be set before calling ${FUNCNAME}"
+
+	# sysconfig can't be used because:
+	# 1) pypy doesn't give site-packages but stdlib
+	# 2) jython gives paths with wrong case
+	local out=$("${EPYTHON}" -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_lib())') || die
+	debug-print "${FUNCNAME} -> ${out}"
+	echo "${out}"
 }
 
 # @FUNCTION: python_get_includedir
@@ -752,7 +741,7 @@ python_newscript() {
 # @CODE
 # src_install() {
 #   python_moduleinto bar
-#   # installs ${PYTHON_SITEDIR}/bar/baz.py
+#   # installs $(python_get_sitedir)/bar/baz.py
 #   python_foreach_impl python_domodule baz.py
 # }
 # @CODE
@@ -788,8 +777,7 @@ python_domodule() {
 		d=${python_moduleroot}
 	else
 		# relative to site-packages
-		local PYTHON_SITEDIR=${PYTHON_SITEDIR}
-		[[ ${PYTHON_SITEDIR} ]] || _python_export PYTHON_SITEDIR
+		local PYTHON_SITEDIR=$(python_get_sitedir)
 
 		d=${PYTHON_SITEDIR#${EPREFIX}}/${python_moduleroot//.//}
 	fi
diff --git a/eclass/tests/python-utils-r2.sh b/eclass/tests/python-utils-r2.sh
index c5e618256519..423a0465d39a 100755
--- a/eclass/tests/python-utils-r2.sh
+++ b/eclass/tests/python-utils-r2.sh
@@ -19,6 +19,19 @@ test_var() {
 	tend ${?}
 }
 
+test_get() {
+	local getter=python_get_${1}
+	local impl=${2}
+	local expect=${3}
+
+	tbegin "${getter} for ${impl}"
+
+	local val=$(EPYTHON=${impl} ${getter})
+	[[ ${val} == ${expect} ]] || eerror "(${impl}: ${getter}: ${val} != ${expect}"
+
+	tend ${?}
+}
+
 test_is() {
 	local func=${1}
 	local expect=${2}
@@ -63,7 +76,7 @@ inherit python-utils-r2
 test_var EPYTHON python2_7 python2.7
 test_var PYTHON python2_7 /usr/bin/python2.7
 if [[ -x /usr/bin/python2.7 ]]; then
-	test_var PYTHON_SITEDIR python2_7 "/usr/lib*/python2.7/site-packages"
+	test_get sitedir python2.7 "/usr/lib*/python2.7/site-packages"
 	test_var PYTHON_INCLUDEDIR python2_7 /usr/include/python2.7
 	test_var PYTHON_LIBPATH python2_7 "/usr/lib*/libpython2.7$(get_libname)"
 	test_var PYTHON_CONFIG python2_7 /usr/bin/python2.7-config
@@ -77,7 +90,7 @@ test_var EPYTHON python3_6 python3.6
 test_var PYTHON python3_6 /usr/bin/python3.6
 if [[ -x /usr/bin/python3.6 ]]; then
 	abiflags=$(/usr/bin/python3.6 -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS"))')
-	test_var PYTHON_SITEDIR python3_6 "/usr/lib*/python3.6/site-packages"
+	test_get sitedir python3.6 "/usr/lib*/python3.6/site-packages"
 	test_var PYTHON_INCLUDEDIR python3_6 "/usr/include/python3.6${abiflags}"
 	test_var PYTHON_LIBPATH python3_6 "/usr/lib*/libpython3.6${abiflags}$(get_libname)"
 	test_var PYTHON_CONFIG python3_6 "/usr/bin/python3.6${abiflags}-config"
@@ -91,7 +104,7 @@ test_var EPYTHON python3_7 python3.7
 test_var PYTHON python3_7 /usr/bin/python3.7
 if [[ -x /usr/bin/python3.7 ]]; then
 	abiflags=$(/usr/bin/python3.7 -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS"))')
-	test_var PYTHON_SITEDIR python3_7 "/usr/lib/python3.7/site-packages"
+	test_get sitedir python3.7 "/usr/lib/python3.7/site-packages"
 	test_var PYTHON_INCLUDEDIR python3_7 "/usr/include/python3.7${abiflags}"
 	test_var PYTHON_LIBPATH python3_7 "/usr/lib*/libpython3.7${abiflags}$(get_libname)"
 	test_var PYTHON_CONFIG python3_7 "/usr/bin/python3.7${abiflags}-config"
@@ -104,7 +117,7 @@ test_var PYTHON_SCRIPTDIR python3_7 /usr/lib/python-exec/python3.7
 test_var EPYTHON jython2_7 jython2.7
 test_var PYTHON jython2_7 /usr/bin/jython2.7
 if [[ -x /usr/bin/jython2.7 ]]; then
-	test_var PYTHON_SITEDIR jython2_7 /usr/share/jython-2.7/Lib/site-packages
+	test_get sitedir jython2.7 /usr/share/jython-2.7/Lib/site-packages
 fi
 test_var PYTHON_PKG_DEP jython2_7 '*dev-java/jython*:2.7'
 test_var PYTHON_SCRIPTDIR jython2_7 /usr/lib/python-exec/jython2.7
@@ -112,7 +125,7 @@ test_var PYTHON_SCRIPTDIR jython2_7 /usr/lib/python-exec/jython2.7
 test_var EPYTHON pypy pypy
 test_var PYTHON pypy /usr/bin/pypy
 if [[ -x /usr/bin/pypy ]]; then
-	test_var PYTHON_SITEDIR pypy "/usr/lib*/pypy2.7/site-packages"
+	test_get sitedir pypy "/usr/lib*/pypy2.7/site-packages"
 	test_var PYTHON_INCLUDEDIR pypy "/usr/lib*/pypy2.7/include"
 fi
 test_var PYTHON_PKG_DEP pypy '*dev-python/pypy*:0='
@@ -121,7 +134,7 @@ test_var PYTHON_SCRIPTDIR pypy /usr/lib/python-exec/pypy
 test_var EPYTHON pypy3 pypy3
 test_var PYTHON pypy3 /usr/bin/pypy3
 if [[ -x /usr/bin/pypy3 ]]; then
-	test_var PYTHON_SITEDIR pypy3 "/usr/lib*/pypy3.?/site-packages"
+	test_get sitedir pypy3 "/usr/lib*/pypy3.?/site-packages"
 	test_var PYTHON_INCLUDEDIR pypy3 "/usr/lib*/pypy3.?/include"
 fi
 test_var PYTHON_PKG_DEP pypy3 '*dev-python/pypy3*:0='
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 12/20] python-utils-r2.eclass: Remove PYTHON_INCLUDEDIR export
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (10 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 11/20] python-utils-r2.eclass: Remove PYTHON_SITEDIR export Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 13/20] python-utils-r2.eclass: Remove PYTHON_LIBPATH export Michał Górny
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/python-utils-r2.eclass   | 30 ++++++++++++------------------
 eclass/tests/python-utils-r2.sh | 10 +++++-----
 2 files changed, 17 insertions(+), 23 deletions(-)

diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
index 4f9df6000e16..1a91beea70bb 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -271,17 +271,6 @@ _python_export() {
 				export PYTHON=${EPREFIX}/usr/bin/${impl}
 				debug-print "${FUNCNAME}: PYTHON = ${PYTHON}"
 				;;
-			PYTHON_INCLUDEDIR)
-				[[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
-				PYTHON_INCLUDEDIR=$("${PYTHON}" -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_inc())') || die
-				export PYTHON_INCLUDEDIR
-				debug-print "${FUNCNAME}: PYTHON_INCLUDEDIR = ${PYTHON_INCLUDEDIR}"
-
-				# Jython gives a non-existing directory
-				if [[ ! -d ${PYTHON_INCLUDEDIR} ]]; then
-					die "${impl} does not install any header files!"
-				fi
-				;;
 			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
@@ -395,15 +384,21 @@ python_get_sitedir() {
 }
 
 # @FUNCTION: python_get_includedir
-# @USAGE: [<impl>]
 # @DESCRIPTION:
-# Obtain and print the include path for the given implementation. If no
-# implementation is provided, ${EPYTHON} will be used.
+# Obtain and print the include path for ${EPYTHON}.
 python_get_includedir() {
 	debug-print-function ${FUNCNAME} "${@}"
+	[[ ${EPYTHON} ]] || die "EPYTHON must be set before calling ${FUNCNAME}"
 
-	_python_export "${@}" PYTHON_INCLUDEDIR
-	echo "${PYTHON_INCLUDEDIR}"
+	local out=$("${EPYTHON}" -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_inc())') || die
+	debug-print "${FUNCNAME} -> ${out}"
+
+	# Jython gives a non-existing directory
+	if [[ ! -d ${out} ]]; then
+		die "${EPYTHON} does not install any header files!"
+	fi
+
+	echo "${out}"
 }
 
 # @FUNCTION: python_get_library_path
@@ -809,8 +804,7 @@ python_doheader() {
 
 	[[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
 
-	local d PYTHON_INCLUDEDIR=${PYTHON_INCLUDEDIR}
-	[[ ${PYTHON_INCLUDEDIR} ]] || _python_export PYTHON_INCLUDEDIR
+	local d PYTHON_INCLUDEDIR=$(python_get_includedir)
 
 	d=${PYTHON_INCLUDEDIR#${EPREFIX}}
 
diff --git a/eclass/tests/python-utils-r2.sh b/eclass/tests/python-utils-r2.sh
index 423a0465d39a..a6221a625c50 100755
--- a/eclass/tests/python-utils-r2.sh
+++ b/eclass/tests/python-utils-r2.sh
@@ -77,7 +77,7 @@ test_var EPYTHON python2_7 python2.7
 test_var PYTHON python2_7 /usr/bin/python2.7
 if [[ -x /usr/bin/python2.7 ]]; then
 	test_get sitedir python2.7 "/usr/lib*/python2.7/site-packages"
-	test_var PYTHON_INCLUDEDIR python2_7 /usr/include/python2.7
+	test_get includedir python2.7 /usr/include/python2.7
 	test_var PYTHON_LIBPATH python2_7 "/usr/lib*/libpython2.7$(get_libname)"
 	test_var PYTHON_CONFIG python2_7 /usr/bin/python2.7-config
 	test_var PYTHON_CFLAGS python2_7 "*-I/usr/include/python2.7*"
@@ -91,7 +91,7 @@ test_var PYTHON python3_6 /usr/bin/python3.6
 if [[ -x /usr/bin/python3.6 ]]; then
 	abiflags=$(/usr/bin/python3.6 -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS"))')
 	test_get sitedir python3.6 "/usr/lib*/python3.6/site-packages"
-	test_var PYTHON_INCLUDEDIR python3_6 "/usr/include/python3.6${abiflags}"
+	test_get includedir python3.6 "/usr/include/python3.6${abiflags}"
 	test_var PYTHON_LIBPATH python3_6 "/usr/lib*/libpython3.6${abiflags}$(get_libname)"
 	test_var PYTHON_CONFIG python3_6 "/usr/bin/python3.6${abiflags}-config"
 	test_var PYTHON_CFLAGS python3_6 "*-I/usr/include/python3.6*"
@@ -105,7 +105,7 @@ test_var PYTHON python3_7 /usr/bin/python3.7
 if [[ -x /usr/bin/python3.7 ]]; then
 	abiflags=$(/usr/bin/python3.7 -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS"))')
 	test_get sitedir python3.7 "/usr/lib/python3.7/site-packages"
-	test_var PYTHON_INCLUDEDIR python3_7 "/usr/include/python3.7${abiflags}"
+	test_get includedir python3.7 "/usr/include/python3.7${abiflags}"
 	test_var PYTHON_LIBPATH python3_7 "/usr/lib*/libpython3.7${abiflags}$(get_libname)"
 	test_var PYTHON_CONFIG python3_7 "/usr/bin/python3.7${abiflags}-config"
 	test_var PYTHON_CFLAGS python3_7 "*-I/usr/include/python3.7*"
@@ -126,7 +126,7 @@ test_var EPYTHON pypy pypy
 test_var PYTHON pypy /usr/bin/pypy
 if [[ -x /usr/bin/pypy ]]; then
 	test_get sitedir pypy "/usr/lib*/pypy2.7/site-packages"
-	test_var PYTHON_INCLUDEDIR pypy "/usr/lib*/pypy2.7/include"
+	test_get includedir pypy "/usr/lib*/pypy2.7/include"
 fi
 test_var PYTHON_PKG_DEP pypy '*dev-python/pypy*:0='
 test_var PYTHON_SCRIPTDIR pypy /usr/lib/python-exec/pypy
@@ -135,7 +135,7 @@ test_var EPYTHON pypy3 pypy3
 test_var PYTHON pypy3 /usr/bin/pypy3
 if [[ -x /usr/bin/pypy3 ]]; then
 	test_get sitedir pypy3 "/usr/lib*/pypy3.?/site-packages"
-	test_var PYTHON_INCLUDEDIR pypy3 "/usr/lib*/pypy3.?/include"
+	test_get includedir pypy3 "/usr/lib*/pypy3.?/include"
 fi
 test_var PYTHON_PKG_DEP pypy3 '*dev-python/pypy3*:0='
 test_var PYTHON_SCRIPTDIR pypy3 /usr/lib/python-exec/pypy3
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 13/20] python-utils-r2.eclass: Remove PYTHON_LIBPATH export
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (11 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 12/20] python-utils-r2.eclass: Remove PYTHON_INCLUDEDIR export Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 14/20] python-utils-r2.eclass: Remove PYTHON_CFLAGS export Michał Górny
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/python-utils-r2.eclass   | 25 ++++++++++---------------
 eclass/tests/python-utils-r2.sh |  6 +++---
 2 files changed, 13 insertions(+), 18 deletions(-)

diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
index 1a91beea70bb..eb3f2c7e5b14 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -271,16 +271,6 @@ _python_export() {
 				export PYTHON=${EPREFIX}/usr/bin/${impl}
 				debug-print "${FUNCNAME}: PYTHON = ${PYTHON}"
 				;;
-			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
-				export PYTHON_LIBPATH
-				debug-print "${FUNCNAME}: PYTHON_LIBPATH = ${PYTHON_LIBPATH}"
-
-				if [[ ! ${PYTHON_LIBPATH} ]]; then
-					die "${impl} lacks a (usable) dynamic library"
-				fi
-				;;
 			PYTHON_CFLAGS)
 				local val
 
@@ -402,18 +392,23 @@ python_get_includedir() {
 }
 
 # @FUNCTION: python_get_library_path
-# @USAGE: [<impl>]
 # @DESCRIPTION:
-# Obtain and print the Python library path for the given implementation.
-# If no implementation is provided, ${EPYTHON} will be used.
+# Obtain and print the Python library path for ${EPYTHON}.
 #
 # Please note that this function can be used with CPython only. Use
 # in another implementation will result in a fatal failure.
 python_get_library_path() {
 	debug-print-function ${FUNCNAME} "${@}"
+	[[ ${EPYTHON} ]] || die "EPYTHON must be set before calling ${FUNCNAME}"
 
-	_python_export "${@}" PYTHON_LIBPATH
-	echo "${PYTHON_LIBPATH}"
+	local out=$("${EPYTHON}" -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
+	debug-print "${FUNCNAME} -> ${out}"
+
+	if [[ ! ${out} ]]; then
+		die "${EPYTHON} lacks a (usable) dynamic library"
+	fi
+
+	echo "${out}"
 }
 
 # @FUNCTION: python_get_CFLAGS
diff --git a/eclass/tests/python-utils-r2.sh b/eclass/tests/python-utils-r2.sh
index a6221a625c50..cba74b84c70a 100755
--- a/eclass/tests/python-utils-r2.sh
+++ b/eclass/tests/python-utils-r2.sh
@@ -78,7 +78,7 @@ test_var PYTHON python2_7 /usr/bin/python2.7
 if [[ -x /usr/bin/python2.7 ]]; then
 	test_get sitedir python2.7 "/usr/lib*/python2.7/site-packages"
 	test_get includedir python2.7 /usr/include/python2.7
-	test_var PYTHON_LIBPATH python2_7 "/usr/lib*/libpython2.7$(get_libname)"
+	test_get library_path python2.7 "/usr/lib*/libpython2.7$(get_libname)"
 	test_var PYTHON_CONFIG python2_7 /usr/bin/python2.7-config
 	test_var PYTHON_CFLAGS python2_7 "*-I/usr/include/python2.7*"
 	test_var PYTHON_LIBS python2_7 "*-lpython2.7*"
@@ -92,7 +92,7 @@ if [[ -x /usr/bin/python3.6 ]]; then
 	abiflags=$(/usr/bin/python3.6 -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS"))')
 	test_get sitedir python3.6 "/usr/lib*/python3.6/site-packages"
 	test_get includedir python3.6 "/usr/include/python3.6${abiflags}"
-	test_var PYTHON_LIBPATH python3_6 "/usr/lib*/libpython3.6${abiflags}$(get_libname)"
+	test_get library_path python3.6 "/usr/lib*/libpython3.6${abiflags}$(get_libname)"
 	test_var PYTHON_CONFIG python3_6 "/usr/bin/python3.6${abiflags}-config"
 	test_var PYTHON_CFLAGS python3_6 "*-I/usr/include/python3.6*"
 	test_var PYTHON_LIBS python3_6 "*-lpython3.6*"
@@ -106,7 +106,7 @@ if [[ -x /usr/bin/python3.7 ]]; then
 	abiflags=$(/usr/bin/python3.7 -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS"))')
 	test_get sitedir python3.7 "/usr/lib/python3.7/site-packages"
 	test_get includedir python3.7 "/usr/include/python3.7${abiflags}"
-	test_var PYTHON_LIBPATH python3_7 "/usr/lib*/libpython3.7${abiflags}$(get_libname)"
+	test_get library_path python3.7 "/usr/lib*/libpython3.7${abiflags}$(get_libname)"
 	test_var PYTHON_CONFIG python3_7 "/usr/bin/python3.7${abiflags}-config"
 	test_var PYTHON_CFLAGS python3_7 "*-I/usr/include/python3.7*"
 	test_var PYTHON_LIBS python3_7 "*-lpython3.7*"
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 14/20] python-utils-r2.eclass: Remove PYTHON_CFLAGS export
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (12 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 13/20] python-utils-r2.eclass: Remove PYTHON_LIBPATH export Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 15/20] python-utils-r2.eclass: Remove PYTHON_LIBS export Michał Górny
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/python-utils-r2.eclass   | 36 ++++++++++++++-------------------
 eclass/tests/python-utils-r2.sh |  6 +++---
 2 files changed, 18 insertions(+), 24 deletions(-)

diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
index eb3f2c7e5b14..2aa063152e3e 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -271,22 +271,6 @@ _python_export() {
 				export PYTHON=${EPREFIX}/usr/bin/${impl}
 				debug-print "${FUNCNAME}: PYTHON = ${PYTHON}"
 				;;
-			PYTHON_CFLAGS)
-				local val
-
-				case "${impl}" in
-					python*)
-						# python-2.7, python-3.2, etc.
-						val=$($(tc-getPKG_CONFIG) --cflags ${impl/n/n-}) || die
-						;;
-					*)
-						die "${impl}: obtaining ${var} not supported"
-						;;
-				esac
-
-				export PYTHON_CFLAGS=${val}
-				debug-print "${FUNCNAME}: PYTHON_CFLAGS = ${PYTHON_CFLAGS}"
-				;;
 			PYTHON_LIBS)
 				local val
 
@@ -412,20 +396,30 @@ python_get_library_path() {
 }
 
 # @FUNCTION: python_get_CFLAGS
-# @USAGE: [<impl>]
 # @DESCRIPTION:
 # Obtain and print the compiler flags for building against Python,
-# for the given implementation. If no implementation is provided,
-# ${EPYTHON} will be used.
+# for ${EPYTHON}.
 #
 # Please note that this function can be used with CPython only.
 # It requires Python and pkg-config installed, and therefore proper
 # build-time dependencies need be added to the ebuild.
 python_get_CFLAGS() {
 	debug-print-function ${FUNCNAME} "${@}"
+	[[ ${EPYTHON} ]] || die "EPYTHON must be set before calling ${FUNCNAME}"
 
-	_python_export "${@}" PYTHON_CFLAGS
-	echo "${PYTHON_CFLAGS}"
+	local out
+	case ${EPYTHON} in
+		python*)
+			# python-2.7, python-3.2, etc.
+			out=$($(tc-getPKG_CONFIG) --cflags ${EPYTHON/n/n-}) || die
+			;;
+		*)
+			die "${impl}: obtaining CFLAGS not supported"
+			;;
+	esac
+
+	debug-print "${FUNCNAME} -> ${out}"
+	echo "${out}"
 }
 
 # @FUNCTION: python_get_LIBS
diff --git a/eclass/tests/python-utils-r2.sh b/eclass/tests/python-utils-r2.sh
index cba74b84c70a..fd0883376ab7 100755
--- a/eclass/tests/python-utils-r2.sh
+++ b/eclass/tests/python-utils-r2.sh
@@ -80,7 +80,7 @@ if [[ -x /usr/bin/python2.7 ]]; then
 	test_get includedir python2.7 /usr/include/python2.7
 	test_get library_path python2.7 "/usr/lib*/libpython2.7$(get_libname)"
 	test_var PYTHON_CONFIG python2_7 /usr/bin/python2.7-config
-	test_var PYTHON_CFLAGS python2_7 "*-I/usr/include/python2.7*"
+	test_get CFLAGS python2.7 "*-I/usr/include/python2.7*"
 	test_var PYTHON_LIBS python2_7 "*-lpython2.7*"
 fi
 test_var PYTHON_PKG_DEP python2_7 '*dev-lang/python*:2.7'
@@ -94,7 +94,7 @@ if [[ -x /usr/bin/python3.6 ]]; then
 	test_get includedir python3.6 "/usr/include/python3.6${abiflags}"
 	test_get library_path python3.6 "/usr/lib*/libpython3.6${abiflags}$(get_libname)"
 	test_var PYTHON_CONFIG python3_6 "/usr/bin/python3.6${abiflags}-config"
-	test_var PYTHON_CFLAGS python3_6 "*-I/usr/include/python3.6*"
+	test_get CFLAGS python3.6 "*-I/usr/include/python3.6*"
 	test_var PYTHON_LIBS python3_6 "*-lpython3.6*"
 fi
 test_var PYTHON_PKG_DEP python3_6 '*dev-lang/python*:3.6'
@@ -108,7 +108,7 @@ if [[ -x /usr/bin/python3.7 ]]; then
 	test_get includedir python3.7 "/usr/include/python3.7${abiflags}"
 	test_get library_path python3.7 "/usr/lib*/libpython3.7${abiflags}$(get_libname)"
 	test_var PYTHON_CONFIG python3_7 "/usr/bin/python3.7${abiflags}-config"
-	test_var PYTHON_CFLAGS python3_7 "*-I/usr/include/python3.7*"
+	test_get CFLAGS python3.7 "*-I/usr/include/python3.7*"
 	test_var PYTHON_LIBS python3_7 "*-lpython3.7*"
 fi
 test_var PYTHON_PKG_DEP python3_7 '*dev-lang/python*:3.7'
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 15/20] python-utils-r2.eclass: Remove PYTHON_LIBS export
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (13 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 14/20] python-utils-r2.eclass: Remove PYTHON_CFLAGS export Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 16/20] python-utils-r2.eclass: Remove PYTHON_CONFIG export Michał Górny
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/python-utils-r2.eclass   | 36 ++++++++++++++-------------------
 eclass/tests/python-utils-r2.sh |  6 +++---
 2 files changed, 18 insertions(+), 24 deletions(-)

diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
index 2aa063152e3e..7f4178da09d6 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -271,22 +271,6 @@ _python_export() {
 				export PYTHON=${EPREFIX}/usr/bin/${impl}
 				debug-print "${FUNCNAME}: PYTHON = ${PYTHON}"
 				;;
-			PYTHON_LIBS)
-				local val
-
-				case "${impl}" in
-					python*)
-						# python-2.7, python-3.2, etc.
-						val=$($(tc-getPKG_CONFIG) --libs ${impl/n/n-}) || die
-						;;
-					*)
-						die "${impl}: obtaining ${var} not supported"
-						;;
-				esac
-
-				export PYTHON_LIBS=${val}
-				debug-print "${FUNCNAME}: PYTHON_LIBS = ${PYTHON_LIBS}"
-				;;
 			PYTHON_CONFIG)
 				local flags val
 
@@ -423,20 +407,30 @@ python_get_CFLAGS() {
 }
 
 # @FUNCTION: python_get_LIBS
-# @USAGE: [<impl>]
 # @DESCRIPTION:
 # Obtain and print the compiler flags for linking against Python,
-# for the given implementation. If no implementation is provided,
-# ${EPYTHON} will be used.
+# for ${EPYTHON}.
 #
 # Please note that this function can be used with CPython only.
 # It requires Python and pkg-config installed, and therefore proper
 # build-time dependencies need be added to the ebuild.
 python_get_LIBS() {
 	debug-print-function ${FUNCNAME} "${@}"
+	[[ ${EPYTHON} ]] || die "EPYTHON must be set before calling ${FUNCNAME}"
+
+	local out
+	case ${EPYTHON} in
+		python*)
+			# python-2.7, python-3.2, etc.
+			out=$($(tc-getPKG_CONFIG) --libs ${EPYTHON/n/n-}) || die
+			;;
+		*)
+			die "${EPYTHON}: obtaining LIBS not supported"
+			;;
+	esac
 
-	_python_export "${@}" PYTHON_LIBS
-	echo "${PYTHON_LIBS}"
+	debug-print "${FUNCNAME} -> ${out}"
+	echo "${out}"
 }
 
 # @FUNCTION: python_get_PYTHON_CONFIG
diff --git a/eclass/tests/python-utils-r2.sh b/eclass/tests/python-utils-r2.sh
index fd0883376ab7..8758f6d20464 100755
--- a/eclass/tests/python-utils-r2.sh
+++ b/eclass/tests/python-utils-r2.sh
@@ -81,7 +81,7 @@ if [[ -x /usr/bin/python2.7 ]]; then
 	test_get library_path python2.7 "/usr/lib*/libpython2.7$(get_libname)"
 	test_var PYTHON_CONFIG python2_7 /usr/bin/python2.7-config
 	test_get CFLAGS python2.7 "*-I/usr/include/python2.7*"
-	test_var PYTHON_LIBS python2_7 "*-lpython2.7*"
+	test_get LIBS python2.7 "*-lpython2.7*"
 fi
 test_var PYTHON_PKG_DEP python2_7 '*dev-lang/python*:2.7'
 test_var PYTHON_SCRIPTDIR python2_7 /usr/lib/python-exec/python2.7
@@ -95,7 +95,7 @@ if [[ -x /usr/bin/python3.6 ]]; then
 	test_get library_path python3.6 "/usr/lib*/libpython3.6${abiflags}$(get_libname)"
 	test_var PYTHON_CONFIG python3_6 "/usr/bin/python3.6${abiflags}-config"
 	test_get CFLAGS python3.6 "*-I/usr/include/python3.6*"
-	test_var PYTHON_LIBS python3_6 "*-lpython3.6*"
+	test_get LIBS python3.6 "*-lpython3.6*"
 fi
 test_var PYTHON_PKG_DEP python3_6 '*dev-lang/python*:3.6'
 test_var PYTHON_SCRIPTDIR python3_6 /usr/lib/python-exec/python3.6
@@ -109,7 +109,7 @@ if [[ -x /usr/bin/python3.7 ]]; then
 	test_get library_path python3.7 "/usr/lib*/libpython3.7${abiflags}$(get_libname)"
 	test_var PYTHON_CONFIG python3_7 "/usr/bin/python3.7${abiflags}-config"
 	test_get CFLAGS python3.7 "*-I/usr/include/python3.7*"
-	test_var PYTHON_LIBS python3_7 "*-lpython3.7*"
+	test_get LIBS python3.7 "*-lpython3.7*"
 fi
 test_var PYTHON_PKG_DEP python3_7 '*dev-lang/python*:3.7'
 test_var PYTHON_SCRIPTDIR python3_7 /usr/lib/python-exec/python3.7
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 16/20] python-utils-r2.eclass: Remove PYTHON_CONFIG export
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (14 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 15/20] python-utils-r2.eclass: Remove PYTHON_LIBS export Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 17/20] python-utils-r2.eclass: Remove PYTHON_SCRIPTDIR export Michał Górny
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/python-utils-r2.eclass   | 41 +++++++++++++++------------------
 eclass/tests/python-utils-r2.sh |  6 ++---
 2 files changed, 21 insertions(+), 26 deletions(-)

diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
index 7f4178da09d6..026ef907a880 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -271,23 +271,6 @@ _python_export() {
 				export PYTHON=${EPREFIX}/usr/bin/${impl}
 				debug-print "${FUNCNAME}: PYTHON = ${PYTHON}"
 				;;
-			PYTHON_CONFIG)
-				local flags val
-
-				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
-						val=${PYTHON}${flags}-config
-						;;
-					*)
-						die "${impl}: obtaining ${var} not supported"
-						;;
-				esac
-
-				export PYTHON_CONFIG=${val}
-				debug-print "${FUNCNAME}: PYTHON_CONFIG = ${PYTHON_CONFIG}"
-				;;
 			PYTHON_PKG_DEP)
 				local d
 				case ${impl} in
@@ -434,20 +417,32 @@ python_get_LIBS() {
 }
 
 # @FUNCTION: python_get_PYTHON_CONFIG
-# @USAGE: [<impl>]
 # @DESCRIPTION:
-# Obtain and print the PYTHON_CONFIG location for the given
-# implementation. If no implementation is provided, ${EPYTHON} will be
-# used.
+# Obtain and print the PYTHON_CONFIG location for ${EPYTHON}.
 #
 # Please note that this function can be used with CPython only.
 # It requires Python installed, and therefore proper build-time
 # dependencies need be added to the ebuild.
 python_get_PYTHON_CONFIG() {
 	debug-print-function ${FUNCNAME} "${@}"
+	[[ ${EPYTHON} ]] || die "EPYTHON must be set before calling ${FUNCNAME}"
+
+	local flags out
+	local PYTHON
+	_python_export PYTHON
 
-	_python_export "${@}" PYTHON_CONFIG
-	echo "${PYTHON_CONFIG}"
+	case ${EPYTHON} in
+		python*)
+			flags=$("${EPYTHON}" -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS") or "")') || die
+			out=${PYTHON}${flags}-config
+			;;
+		*)
+			die "${EPYTHON}: obtaining PYTHON_CONFIG not supported"
+			;;
+	esac
+
+	debug-print "${FUNCNAME} -> ${out}"
+	echo "${out}"
 }
 
 # @FUNCTION: python_get_scriptdir
diff --git a/eclass/tests/python-utils-r2.sh b/eclass/tests/python-utils-r2.sh
index 8758f6d20464..0b41a7bcdb53 100755
--- a/eclass/tests/python-utils-r2.sh
+++ b/eclass/tests/python-utils-r2.sh
@@ -79,7 +79,7 @@ if [[ -x /usr/bin/python2.7 ]]; then
 	test_get sitedir python2.7 "/usr/lib*/python2.7/site-packages"
 	test_get includedir python2.7 /usr/include/python2.7
 	test_get library_path python2.7 "/usr/lib*/libpython2.7$(get_libname)"
-	test_var PYTHON_CONFIG python2_7 /usr/bin/python2.7-config
+	test_get PYTHON_CONFIG python2.7 /usr/bin/python2.7-config
 	test_get CFLAGS python2.7 "*-I/usr/include/python2.7*"
 	test_get LIBS python2.7 "*-lpython2.7*"
 fi
@@ -93,7 +93,7 @@ if [[ -x /usr/bin/python3.6 ]]; then
 	test_get sitedir python3.6 "/usr/lib*/python3.6/site-packages"
 	test_get includedir python3.6 "/usr/include/python3.6${abiflags}"
 	test_get library_path python3.6 "/usr/lib*/libpython3.6${abiflags}$(get_libname)"
-	test_var PYTHON_CONFIG python3_6 "/usr/bin/python3.6${abiflags}-config"
+	test_get PYTHON_CONFIG python3.6 "/usr/bin/python3.6${abiflags}-config"
 	test_get CFLAGS python3.6 "*-I/usr/include/python3.6*"
 	test_get LIBS python3.6 "*-lpython3.6*"
 fi
@@ -107,7 +107,7 @@ if [[ -x /usr/bin/python3.7 ]]; then
 	test_get sitedir python3.7 "/usr/lib/python3.7/site-packages"
 	test_get includedir python3.7 "/usr/include/python3.7${abiflags}"
 	test_get library_path python3.7 "/usr/lib*/libpython3.7${abiflags}$(get_libname)"
-	test_var PYTHON_CONFIG python3_7 "/usr/bin/python3.7${abiflags}-config"
+	test_get PYTHON_CONFIG python3.7 "/usr/bin/python3.7${abiflags}-config"
 	test_get CFLAGS python3.7 "*-I/usr/include/python3.7*"
 	test_get LIBS python3.7 "*-lpython3.7*"
 fi
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 17/20] python-utils-r2.eclass: Remove PYTHON_SCRIPTDIR export
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (15 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 16/20] python-utils-r2.eclass: Remove PYTHON_CONFIG export Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 18/20] python-single-r2.eclass: PYTHON_MULTI_USEDEP → PYTHON_USEDEP Michał Górny
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/distutils-r2.eclass      |  3 +--
 eclass/python-r2.eclass         |  3 +--
 eclass/python-utils-r2.eclass   | 21 +++++++--------------
 eclass/tests/python-utils-r2.sh | 12 ++++++------
 4 files changed, 15 insertions(+), 24 deletions(-)

diff --git a/eclass/distutils-r2.eclass b/eclass/distutils-r2.eclass
index 99d93a2e830f..678dc670c3ef 100644
--- a/eclass/distutils-r2.eclass
+++ b/eclass/distutils-r2.eclass
@@ -732,8 +732,7 @@ _distutils-r2_wrap_scripts() {
 	local path=${1}
 	local bindir=${2}
 
-	local PYTHON_SCRIPTDIR
-	_python_export PYTHON_SCRIPTDIR
+	local PYTHON_SCRIPTDIR=$(python_get_scriptdir)
 
 	local f python_files=() non_python_files=()
 
diff --git a/eclass/python-r2.eclass b/eclass/python-r2.eclass
index 02b60d4e4de9..93369b83e00a 100644
--- a/eclass/python-r2.eclass
+++ b/eclass/python-r2.eclass
@@ -760,8 +760,7 @@ python_replicate_script() {
 	_python_replicate_script() {
 		local _PYTHON_FIX_SHEBANG_QUIET=1
 
-		local PYTHON_SCRIPTDIR
-		_python_export PYTHON_SCRIPTDIR
+		local PYTHON_SCRIPTDIR=$(python_get_scriptdir)
 
 		(
 			exeopts -m 0755
diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
index 026ef907a880..a18da95b2be5 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -298,11 +298,6 @@ _python_export() {
 				export PYTHON_PKG_DEP
 				debug-print "${FUNCNAME}: PYTHON_PKG_DEP = ${PYTHON_PKG_DEP}"
 				;;
-			PYTHON_SCRIPTDIR)
-				local dir
-				export PYTHON_SCRIPTDIR=${EPREFIX}/usr/lib/python-exec/${impl}
-				debug-print "${FUNCNAME}: PYTHON_SCRIPTDIR = ${PYTHON_SCRIPTDIR}"
-				;;
 			*)
 				die "_python_export: unknown variable ${var}"
 		esac
@@ -446,16 +441,15 @@ python_get_PYTHON_CONFIG() {
 }
 
 # @FUNCTION: python_get_scriptdir
-# @USAGE: [<impl>]
 # @DESCRIPTION:
-# Obtain and print the script install path for the given
-# implementation. If no implementation is provided, ${EPYTHON} will
-# be used.
+# Obtain and print the script install path for ${EPYTHON}.
 python_get_scriptdir() {
 	debug-print-function ${FUNCNAME} "${@}"
+	[[ ${EPYTHON} ]] || die "EPYTHON must be set before calling ${FUNCNAME}"
 
-	_python_export "${@}" PYTHON_SCRIPTDIR
-	echo "${PYTHON_SCRIPTDIR}"
+	local out=${EPREFIX}/usr/lib/python-exec/${impl}
+	debug-print "${FUNCNAME} -> ${out}"
+	echo "${out}"
 }
 
 # @FUNCTION: _python_ln_rel
@@ -622,9 +616,8 @@ python_newexe() {
 	local f=${1}
 	local newfn=${2}
 
-	local PYTHON_SCRIPTDIR d
-	_python_export PYTHON_SCRIPTDIR
-	d=${PYTHON_SCRIPTDIR#${EPREFIX}}
+	local PYTHON_SCRIPTDIR=$(python_get_scriptdir)
+	local d=${PYTHON_SCRIPTDIR#${EPREFIX}}
 
 	(
 		dodir "${wrapd}"
diff --git a/eclass/tests/python-utils-r2.sh b/eclass/tests/python-utils-r2.sh
index 0b41a7bcdb53..b4b37efe179b 100755
--- a/eclass/tests/python-utils-r2.sh
+++ b/eclass/tests/python-utils-r2.sh
@@ -84,7 +84,7 @@ if [[ -x /usr/bin/python2.7 ]]; then
 	test_get LIBS python2.7 "*-lpython2.7*"
 fi
 test_var PYTHON_PKG_DEP python2_7 '*dev-lang/python*:2.7'
-test_var PYTHON_SCRIPTDIR python2_7 /usr/lib/python-exec/python2.7
+test_get scriptdir python2.7 /usr/lib/python-exec/python2.7
 
 test_var EPYTHON python3_6 python3.6
 test_var PYTHON python3_6 /usr/bin/python3.6
@@ -98,7 +98,7 @@ if [[ -x /usr/bin/python3.6 ]]; then
 	test_get LIBS python3.6 "*-lpython3.6*"
 fi
 test_var PYTHON_PKG_DEP python3_6 '*dev-lang/python*:3.6'
-test_var PYTHON_SCRIPTDIR python3_6 /usr/lib/python-exec/python3.6
+test_get scriptdir python3.6 /usr/lib/python-exec/python3.6
 
 test_var EPYTHON python3_7 python3.7
 test_var PYTHON python3_7 /usr/bin/python3.7
@@ -112,7 +112,7 @@ if [[ -x /usr/bin/python3.7 ]]; then
 	test_get LIBS python3.7 "*-lpython3.7*"
 fi
 test_var PYTHON_PKG_DEP python3_7 '*dev-lang/python*:3.7'
-test_var PYTHON_SCRIPTDIR python3_7 /usr/lib/python-exec/python3.7
+test_get scriptdir python3.7 /usr/lib/python-exec/python3.7
 
 test_var EPYTHON jython2_7 jython2.7
 test_var PYTHON jython2_7 /usr/bin/jython2.7
@@ -120,7 +120,7 @@ if [[ -x /usr/bin/jython2.7 ]]; then
 	test_get sitedir jython2.7 /usr/share/jython-2.7/Lib/site-packages
 fi
 test_var PYTHON_PKG_DEP jython2_7 '*dev-java/jython*:2.7'
-test_var PYTHON_SCRIPTDIR jython2_7 /usr/lib/python-exec/jython2.7
+test_get scriptdir jython2.7 /usr/lib/python-exec/jython2.7
 
 test_var EPYTHON pypy pypy
 test_var PYTHON pypy /usr/bin/pypy
@@ -129,7 +129,7 @@ if [[ -x /usr/bin/pypy ]]; then
 	test_get includedir pypy "/usr/lib*/pypy2.7/include"
 fi
 test_var PYTHON_PKG_DEP pypy '*dev-python/pypy*:0='
-test_var PYTHON_SCRIPTDIR pypy /usr/lib/python-exec/pypy
+test_get scriptdir pypy /usr/lib/python-exec/pypy
 
 test_var EPYTHON pypy3 pypy3
 test_var PYTHON pypy3 /usr/bin/pypy3
@@ -138,7 +138,7 @@ if [[ -x /usr/bin/pypy3 ]]; then
 	test_get includedir pypy3 "/usr/lib*/pypy3.?/include"
 fi
 test_var PYTHON_PKG_DEP pypy3 '*dev-python/pypy3*:0='
-test_var PYTHON_SCRIPTDIR pypy3 /usr/lib/python-exec/pypy3
+test_get scriptdir pypy3 /usr/lib/python-exec/pypy3
 
 test_is "python_is_python3 python2.7" 1
 test_is "python_is_python3 python3.2" 0
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 18/20] python-single-r2.eclass: PYTHON_MULTI_USEDEP → PYTHON_USEDEP
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (16 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 17/20] python-utils-r2.eclass: Remove PYTHON_SCRIPTDIR export Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 19/20] distutils-r2.eclass: Pass --skip-build to install Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 20/20] eclass: python-r2.eclass → python-multi-r2.eclass Michał Górny
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Rename PYTHON_MULTI_USEDEP to PYTHON_USEDEP for consistency with other
eclasses.  Since the old PYTHON_USEDEP API is no longer supported,
the name is free again.

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/python-single-r2.eclass | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/eclass/python-single-r2.eclass b/eclass/python-single-r2.eclass
index ce170c1d13c9..09fc47cbc064 100644
--- a/eclass/python-single-r2.eclass
+++ b/eclass/python-single-r2.eclass
@@ -21,7 +21,7 @@
 # The eclass exports PYTHON_SINGLE_USEDEP that is suitable for depending
 # on other packages using the eclass.  Dependencies on packages using
 # python-r2 should be created via python_gen_cond_dep() function,
-# using PYTHON_MULTI_USEDEP placeholder.
+# using PYTHON_USEDEP placeholder.
 #
 # Please note that packages support multiple Python implementations
 # (using python-r2 eclass) can not depend on packages not supporting
@@ -145,7 +145,7 @@ EXPORT_FUNCTIONS pkg_setup
 # Python implementations.
 #
 # If you need to depend on a multi-impl (python-r2) package, use
-# python_gen_cond_dep with PYTHON_MULTI_USEDEP placeholder instead.
+# python_gen_cond_dep with PYTHON_USEDEP placeholder instead.
 #
 # Example use:
 # @CODE
@@ -157,7 +157,7 @@ EXPORT_FUNCTIONS pkg_setup
 # python_single_target_python3_4(-)?
 # @CODE
 
-# @ECLASS-VARIABLE: PYTHON_MULTI_USEDEP
+# @ECLASS-VARIABLE: PYTHON_USEDEP
 # @DESCRIPTION:
 # This is a placeholder variable supported by python_gen_cond_dep,
 # in order to depend on python-r2 packages built for the same Python
@@ -166,7 +166,7 @@ EXPORT_FUNCTIONS pkg_setup
 # Example use:
 # @CODE
 # RDEPEND="$(python_gen_cond_dep '
-#     dev-python/foo[${PYTHON_MULTI_USEDEP}]
+#     dev-python/foo[${PYTHON_USEDEP}]
 #   ')"
 # @CODE
 #
@@ -248,7 +248,7 @@ _python_single_set_globals() {
 	else
 		PYTHON_DEPS=${deps}
 		PYTHON_REQUIRED_USE=${requse}
-		PYTHON_USEDEP='%PYTHON_USEDEP-HAS-BEEN-REMOVED%'
+		PYTHON_USEDEP='%PYTHON_USEDEP-MUST-BE-IN-python_gen_cond_dep%'
 		PYTHON_SINGLE_USEDEP=${single_usedep}
 		readonly PYTHON_DEPS PYTHON_REQUIRED_USE PYTHON_SINGLE_USEDEP \
 			PYTHON_USEDEP
@@ -344,7 +344,7 @@ python_gen_useflags() {
 # to prevent accidental shell filename expansion.
 #
 # In order to enforce USE constraints on the packages, verbatim
-# '${PYTHON_SINGLE_USEDEP}' and '${PYTHON_MULTI_USEDEP}' (quoted!) may
+# '${PYTHON_SINGLE_USEDEP}' and '${PYTHON_USEDEP}' (quoted!) may
 # be placed in the dependency specification. It will get expanded within
 # the function into a proper USE dependency string.
 #
@@ -352,7 +352,7 @@ python_gen_useflags() {
 # @CODE
 # PYTHON_COMPAT=( python{2_7,3_{3,4}} pypy )
 # RDEPEND="$(python_gen_cond_dep \
-#   'dev-python/unittest2[${PYTHON_MULTI_USEDEP}]' python2_7 pypy )"
+#   'dev-python/unittest2[${PYTHON_USEDEP}]' python2_7 pypy )"
 # @CODE
 #
 # It will cause the variable to look like:
@@ -382,7 +382,7 @@ python_gen_cond_dep() {
 			local multi_usedep="python_targets_${impl}(-)"
 
 			matches+=( "python_single_target_${impl}? (
-				${dep//\$\{PYTHON_MULTI_USEDEP\}/${multi_usedep}} )" )
+				${dep//\$\{PYTHON_USEDEP\}/${multi_usedep}} )" )
 		fi
 	done
 
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 19/20] distutils-r2.eclass: Pass --skip-build to install
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (17 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 18/20] python-single-r2.eclass: PYTHON_MULTI_USEDEP → PYTHON_USEDEP Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 20/20] eclass: python-r2.eclass → python-multi-r2.eclass Michał Górny
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/distutils-r2.eclass | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/eclass/distutils-r2.eclass b/eclass/distutils-r2.eclass
index 678dc670c3ef..8f16bddb83fd 100644
--- a/eclass/distutils-r2.eclass
+++ b/eclass/distutils-r2.eclass
@@ -835,7 +835,7 @@ distutils-r2_python_install() {
 	local root=${D%/}/_${EPYTHON}
 	[[ ${DISTUTILS_SINGLE_IMPL} ]] && root=${D%/}
 
-	esetup.py install --root="${root}" "${args[@]}"
+	esetup.py install --skip-build --root="${root}" "${args[@]}"
 
 	local forbidden_package_names=( examples test tests .pytest_cache )
 	local p
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [gentoo-dev] [PATCH v2 20/20] eclass: python-r2.eclass → python-multi-r2.eclass
  2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
                   ` (18 preceding siblings ...)
  2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 19/20] distutils-r2.eclass: Pass --skip-build to install Michał Górny
@ 2020-03-05 15:10 ` Michał Górny
  19 siblings, 0 replies; 21+ messages in thread
From: Michał Górny @ 2020-03-05 15:10 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/distutils-r2.eclass                    | 14 ++++----
 eclass/python-any-r2.eclass                   |  9 +++--
 ...ython-r2.eclass => python-multi-r2.eclass} | 33 +++++++++----------
 eclass/python-single-r2.eclass                | 16 ++++-----
 eclass/python-utils-r2.eclass                 |  8 ++---
 5 files changed, 39 insertions(+), 41 deletions(-)
 rename eclass/{python-r2.eclass => python-multi-r2.eclass} (96%)

diff --git a/eclass/distutils-r2.eclass b/eclass/distutils-r2.eclass
index 8f16bddb83fd..b9041f93145e 100644
--- a/eclass/distutils-r2.eclass
+++ b/eclass/distutils-r2.eclass
@@ -14,7 +14,7 @@
 # the src_* phases. Each of the phases runs two pseudo-phases:
 # python_..._all() (e.g. python_prepare_all()) once in ${S}, then
 # python_...() (e.g. python_prepare()) for each implementation
-# (see: python_foreach_impl() in python-r2).
+# (see: python_foreach_impl() in python-multi-r2).
 #
 # In distutils-r2_src_prepare(), the 'all' function is run before
 # per-implementation ones (because it creates the implementations),
@@ -35,9 +35,9 @@
 # Please note that distutils-r2 sets RDEPEND and DEPEND unconditionally
 # for you.
 #
-# Also, please note that distutils-r2 will always inherit python-r2
-# as well. Thus, all the variables defined and documented there are
-# relevant to the packages using distutils-r2.
+# Also, please note that distutils-r2 will always inherit
+# python-multi-r2 or python-single-r2.  Thus, all the variables defined
+# and documented there are relevant to the packages using distutils-r2.
 #
 # For more information, please see the Python Guide:
 # https://dev.gentoo.org/~mgorny/python-guide/
@@ -69,8 +69,8 @@ esac
 # @DEFAULT_UNSET
 # @DESCRIPTION:
 # If set to a non-null value, the ebuild will support setting a single
-# Python implementation only. It will effectively replace the python-r2
-# eclass inherit with python-single-r2.
+# Python implementation only. It will effectively replace
+# the python-multi-r2 eclass inherit with python-single-r2.
 #
 # Note that inheriting python-single-r2 will cause pkg_setup()
 # to be exported. It must be run in order for the eclass functions
@@ -101,7 +101,7 @@ if [[ ! ${_DISTUTILS_R2} ]]; then
 inherit multiprocessing toolchain-funcs
 
 if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
-	inherit python-r2
+	inherit python-multi-r2
 else
 	inherit python-single-r2
 fi
diff --git a/eclass/python-any-r2.eclass b/eclass/python-any-r2.eclass
index 053bf4b5a0e3..f674f01854da 100644
--- a/eclass/python-any-r2.eclass
+++ b/eclass/python-any-r2.eclass
@@ -43,8 +43,8 @@ esac
 
 if [[ ! ${_PYTHON_ANY_R2} ]]; then
 
-if [[ ${_PYTHON_R2} ]]; then
-	die 'python-any-r2.eclass can not be used with python-r2.eclass.'
+if [[ ${_PYTHON_MULTI_R2} ]]; then
+	die 'python-any-r2.eclass can not be used with python-multi-r2.eclass.'
 elif [[ ${_PYTHON_SINGLE_R2} ]]; then
 	die 'python-any-r2.eclass can not be used with python-single-r2.eclass.'
 fi
@@ -127,9 +127,8 @@ EXPORT_FUNCTIONS pkg_setup
 # An eclass-generated USE-dependency string for the currently tested
 # implementation. It is set locally for python_check_deps() call.
 #
-# The generate USE-flag list is compatible with packages using python-r2,
-# python-single-r2 and python-distutils-ng eclasses. It must not be used
-# on packages using python.eclass.
+# The generate USE-flag list is compatible with packages using
+# python-multi-r2 eclass.
 #
 # Example use:
 # @CODE
diff --git a/eclass/python-r2.eclass b/eclass/python-multi-r2.eclass
similarity index 96%
rename from eclass/python-r2.eclass
rename to eclass/python-multi-r2.eclass
index 93369b83e00a..7022533bd1b9 100644
--- a/eclass/python-r2.eclass
+++ b/eclass/python-multi-r2.eclass
@@ -1,7 +1,7 @@
 # Copyright 1999-2020 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
-# @ECLASS: python-r2.eclass
+# @ECLASS: python-multi-r2.eclass
 # @MAINTAINER:
 # Python team <python@gentoo.org>
 # @AUTHOR:
@@ -15,15 +15,15 @@
 #
 # This eclass sets correct IUSE. Modification of REQUIRED_USE has to
 # be done by the author of the ebuild (but PYTHON_REQUIRED_USE is
-# provided for convenience, see below). python-r2 exports PYTHON_DEPS
-# and PYTHON_USEDEP so you can create correct dependencies for your
-# package easily. It also provides methods to easily run a command for
-# each enabled Python implementation and duplicate the sources for them.
+# provided for convenience, see below). python-multi-r2 exports
+# PYTHON_DEPS and PYTHON_USEDEP so you can create correct dependencies
+# for your package easily. It also provides methods to easily run
+# a command for each enabled Python implementation and duplicate
+# the sources for them.
 #
-# Please note that python-r2 will always inherit python-utils-r2 as
-# well. Thus, all the functions defined there can be used
-# in the packages using python-r2, and there is no need ever to inherit
-# both.
+# Please note that python-multi-r2 will always inherit python-utils-r2.
+# Thus, all the functions defined there can be used in the packages
+# using python-multi-r2, and there is no need ever to inherit both.
 #
 # For more information, please see the Python Guide:
 # https://dev.gentoo.org/~mgorny/python-guide/
@@ -40,12 +40,12 @@ case "${EAPI:-0}" in
 		;;
 esac
 
-if [[ ! ${_PYTHON_R2} ]]; then
+if [[ ! ${_PYTHON_MULTI_R2} ]]; then
 
 if [[ ${_PYTHON_SINGLE_R2} ]]; then
-	die 'python-r2.eclass can not be used with python-single-r2.eclass.'
+	die 'python-multi-r2.eclass can not be used with python-single-r2.eclass.'
 elif [[ ${_PYTHON_ANY_R2} ]]; then
-	die 'python-r2.eclass can not be used with python-any-r2.eclass.'
+	die 'python-multi-r2.eclass can not be used with python-any-r2.eclass.'
 fi
 
 [[ ${EAPI} == [45] ]] && inherit eutils
@@ -134,9 +134,8 @@ fi
 # depend on another Python package being built for the same Python
 # implementations.
 #
-# The generate USE-flag list is compatible with packages using python-r2
-# and python-distutils-ng eclasses. It must not be used on packages
-# using python.eclass.
+# The generate USE-flag list is compatible with packages using
+# python-multi-r2.
 #
 # Example use:
 # @CODE
@@ -233,7 +232,7 @@ _python_set_globals() {
 _python_set_globals
 unset -f _python_set_globals
 
-if [[ ! ${_PYTHON_R2} ]]; then
+if [[ ! ${_PYTHON_MULTI_R2} ]]; then
 
 # @FUNCTION: _python_validate_useflags
 # @INTERNAL
@@ -783,5 +782,5 @@ python_replicate_script() {
 	done
 }
 
-_PYTHON_R2=1
+_PYTHON_MULTI_R2=1
 fi
diff --git a/eclass/python-single-r2.eclass b/eclass/python-single-r2.eclass
index 09fc47cbc064..f43faa4aad12 100644
--- a/eclass/python-single-r2.eclass
+++ b/eclass/python-single-r2.eclass
@@ -20,12 +20,12 @@
 #
 # The eclass exports PYTHON_SINGLE_USEDEP that is suitable for depending
 # on other packages using the eclass.  Dependencies on packages using
-# python-r2 should be created via python_gen_cond_dep() function,
+# python-multi-r2 should be created via python_gen_cond_dep() function,
 # using PYTHON_USEDEP placeholder.
 #
 # Please note that packages support multiple Python implementations
-# (using python-r2 eclass) can not depend on packages not supporting
-# them (using this eclass).
+# (using python-multi-r2 eclass) can not depend on packages
+# not supporting them (using this eclass).
 #
 # Please note that python-single-r2 will always inherit python-utils-r2
 # as well. Thus, all the functions defined there can be used
@@ -49,8 +49,8 @@ esac
 
 if [[ ! ${_PYTHON_SINGLE_R2} ]]; then
 
-if [[ ${_PYTHON_R2} ]]; then
-	die 'python-single-r2.eclass can not be used with python-r2.eclass.'
+if [[ ${_PYTHON_MULTI_R2} ]]; then
+	die 'python-single-r2.eclass can not be used with python-multi-r2.eclass.'
 elif [[ ${_PYTHON_ANY_R2} ]]; then
 	die 'python-single-r2.eclass can not be used with python-any-r2.eclass.'
 fi
@@ -144,7 +144,7 @@ EXPORT_FUNCTIONS pkg_setup
 # depend on another python-single-r2 package being built for the same
 # Python implementations.
 #
-# If you need to depend on a multi-impl (python-r2) package, use
+# If you need to depend on a multi-impl (python-multi-r2) package, use
 # python_gen_cond_dep with PYTHON_USEDEP placeholder instead.
 #
 # Example use:
@@ -160,8 +160,8 @@ EXPORT_FUNCTIONS pkg_setup
 # @ECLASS-VARIABLE: PYTHON_USEDEP
 # @DESCRIPTION:
 # This is a placeholder variable supported by python_gen_cond_dep,
-# in order to depend on python-r2 packages built for the same Python
-# implementations.
+# in order to depend on python-multi-r2 packages built for the same
+# Python implementations.
 #
 # Example use:
 # @CODE
diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
index a18da95b2be5..819ac7dd7195 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -196,8 +196,8 @@ _python_impl_matches() {
 #
 # This variable is set automatically in the following contexts:
 #
-# python-r2: Set in functions called by python_foreach_impl() or after
-# calling python_setup().
+# python-multi-r2: Set in functions called by python_foreach_impl()
+# or after calling python_setup().
 #
 # python-single-r2: Set after calling python-single-r2_pkg_setup().
 #
@@ -215,8 +215,8 @@ _python_impl_matches() {
 #
 # This variable is set automatically in the following contexts:
 #
-# python-r2: Set in functions called by python_foreach_impl() or after
-# calling python_setup().
+# python-multi-r2: Set in functions called by python_foreach_impl()
+# or after calling python_setup().
 #
 # python-single-r2: Set after calling python-single-r2_pkg_setup().
 #
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2020-03-05 15:18 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-03-05 15:10 [gentoo-dev] [PATCH v2 00/20] python-r2 suite Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 01/20] eclass: Copy python-r1 suite to python-r2 Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 02/20] distutils-r2.eclass: Remove EXAMPLES Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 03/20] distutils-r2.eclass: Remove no-op subphase defaults Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 04/20] distutils-r2.eclass: Remove distutils.eclass checks Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 05/20] python-r2.eclass: Remove python_gen_usedep Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 06/20] python-utils-r2.eclass: Remove python.eclass checks Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 07/20] python-utils-r2.eclass: Mark python_wrapper_setup private Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 08/20] python-utils-r2.eclass: Mark python_is_installed private Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 09/20] python-utils-r2.eclass: Fix obsolete docs on python_export_best Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 10/20] python-utils-r2.eclass: Mark python_export private Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 11/20] python-utils-r2.eclass: Remove PYTHON_SITEDIR export Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 12/20] python-utils-r2.eclass: Remove PYTHON_INCLUDEDIR export Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 13/20] python-utils-r2.eclass: Remove PYTHON_LIBPATH export Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 14/20] python-utils-r2.eclass: Remove PYTHON_CFLAGS export Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 15/20] python-utils-r2.eclass: Remove PYTHON_LIBS export Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 16/20] python-utils-r2.eclass: Remove PYTHON_CONFIG export Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 17/20] python-utils-r2.eclass: Remove PYTHON_SCRIPTDIR export Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 18/20] python-single-r2.eclass: PYTHON_MULTI_USEDEP → PYTHON_USEDEP Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 19/20] distutils-r2.eclass: Pass --skip-build to install Michał Górny
2020-03-05 15:10 ` [gentoo-dev] [PATCH v2 20/20] eclass: python-r2.eclass → python-multi-r2.eclass Michał Górny

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox