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

Hello,

Here's a first proposed version of python-r2 suite.  This aims to switch
the eclasses into more proactive versioning model over deprecating
and removing API in place.  The main idea is that for the majority
of ebuilds (and especially those that do not trigger QA warnings right
now), the migration should be as simple as applying a few sed patterns.

Another implication of this model is that I'm going to provide a simple
conversion script once the eclasses are ready.  While it won't be able
to fix all possible issues, it should be able to fix the common renames,
and catch the removed bits.

The list of changes included so far:

- all deprecated things (read: those triggering deprecation warnings)
  have been removed or explicitly banned

- python.eclass / distutils.eclass failed migration checks have been
  removed

- some functions were explicitly made internal:

  a. python_wrapper_setup -- called by python_setup

  b. python_is_installed -- used by any-r1 python_setup

  c. python_export -- some bits are used only internally, others are now
                      available via python_get* only

- multi-impl eclass is now called python-multi-r2, to stop confusing
  people into using it

- distutils-r1 now passes --skip-build to install phase

- in python-single-r1, PYTHON_MULTI_USEDEP has been renamed back
  to PYTHON_USEDEP, for consistency between eclasses
  (PYTHON_SINGLE_USEDEP is still a thing)

I'm open to further suggestions.

-- 
Best regards,
Michał Górny

Michał Górny (25):
  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
  distutils-r2.eclass: Make all old QA warnings fatal
  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: Add missing @INTERNAL to private func
  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
  python-any-r2.eclass: Verbosely report used implementation
  python-single-r2.eclass: Report used impl verbosely
  python-multi-r2.eclass: Report python_setup impl verbosely

 eclass/distutils-r2.eclass      | 1112 +++++++++++++++++++++++++++++
 eclass/python-any-r2.eclass     |  360 ++++++++++
 eclass/python-multi-r2.eclass   |  783 ++++++++++++++++++++
 eclass/python-single-r2.eclass  |  509 +++++++++++++
 eclass/python-utils-r2.eclass   | 1191 +++++++++++++++++++++++++++++++
 eclass/tests/distutils-r2.sh    |   98 +++
 eclass/tests/python-utils-r2.sh |  250 +++++++
 7 files changed, 4303 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] 26+ messages in thread

* [gentoo-dev] [PATCH 01/25] eclass: Copy python-r1 suite to python-r2
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 02/25] distutils-r2.eclass: Remove EXAMPLES Michał Górny
                   ` (23 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

Signed-off-by: Michał Górny <mgorny@gentoo.org>
---
 eclass/distutils-r2.eclass      | 1198 ++++++++++++++++++++++++
 eclass/python-any-r2.eclass     |  357 ++++++++
 eclass/python-r2.eclass         |  825 +++++++++++++++++
 eclass/python-single-r2.eclass  |  507 +++++++++++
 eclass/python-utils-r2.eclass   | 1518 +++++++++++++++++++++++++++++++
 eclass/tests/distutils-r2.sh    |   98 ++
 eclass/tests/python-utils-r2.sh |  237 +++++
 7 files changed, 4740 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..662bad3b9bcd
--- /dev/null
+++ b/eclass/distutils-r2.eclass
@@ -0,0 +1,1198 @@
+# 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.
+
+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
+		local cmd=die
+		[[ ${EAPI} == [45] ]] && cmd=eqawarn
+		"${cmd}" "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
+
+	_DISTUTILS_DEFAULT_CALLED=1
+}
+
+# @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
+
+	local _DISTUTILS_DEFAULT_CALLED
+
+	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
+
+	if [[ ! ${_DISTUTILS_DEFAULT_CALLED} ]]; then
+		local cmd=die
+		[[ ${EAPI} == [45] ]] && cmd=eqawarn
+
+		"${cmd}" "QA: python_install_all() didn't call 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..cf70f23f69d5
--- /dev/null
+++ b/eclass/python-any-r2.eclass
@@ -0,0 +1,357 @@
+# 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.
+
+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
+		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
+			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
+			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
+			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..8bf0b1a1ac29
--- /dev/null
+++ b/eclass/python-r2.eclass
@@ -0,0 +1,825 @@
+# 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.
+
+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
+}
+
+# @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..5bf6ea7221bc
--- /dev/null
+++ b/eclass/python-single-r2.eclass
@@ -0,0 +1,507 @@
+# 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.
+
+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
+		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
+		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..9821c043021a
--- /dev/null
+++ b/eclass/python-utils-r2.eclass
@@ -0,0 +1,1518 @@
+# 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.
+
+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
+
+	case "${impl}" in
+		pypy|pypy3)
+			local append=
+			if [[ ${PYTHON_REQ_USE} ]]; then
+				append=[${PYTHON_REQ_USE}]
+			fi
+
+			# be happy with just the interpeter, no need for the virtual
+			has_version "${hasv_args[@]}" "dev-python/${impl}${append}" \
+				|| has_version "${hasv_args[@]}" "dev-python/${impl}-bin${append}"
+			;;
+		*)
+			local PYTHON_PKG_DEP
+			python_export "${impl}" PYTHON_PKG_DEP
+			has_version "${hasv_args[@]}" "${PYTHON_PKG_DEP}"
+			;;
+	esac
+}
+
+# @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>
+# @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] 26+ messages in thread

* [gentoo-dev] [PATCH 02/25] distutils-r2.eclass: Remove EXAMPLES
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 01/25] eclass: Copy python-r1 suite to python-r2 Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 03/25] distutils-r2.eclass: Remove no-op subphase defaults Michał Górny
                   ` (22 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 662bad3b9bcd..ec1eda6682ae 100644
--- a/eclass/distutils-r2.eclass
+++ b/eclass/distutils-r2.eclass
@@ -198,26 +198,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:
@@ -910,13 +890,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
 
 	_DISTUTILS_DEFAULT_CALLED=1
-- 
2.25.1



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

* [gentoo-dev] [PATCH 03/25] distutils-r2.eclass: Remove no-op subphase defaults
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 01/25] eclass: Copy python-r1 suite to python-r2 Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 02/25] distutils-r2.eclass: Remove EXAMPLES Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 04/25] distutils-r2.eclass: Remove distutils.eclass checks Michał Górny
                   ` (21 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 ec1eda6682ae..cc555771a46c 100644
--- a/eclass/distutils-r2.eclass
+++ b/eclass/distutils-r2.eclass
@@ -623,24 +623,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] 26+ messages in thread

* [gentoo-dev] [PATCH 04/25] distutils-r2.eclass: Remove distutils.eclass checks
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (2 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 03/25] distutils-r2.eclass: Remove no-op subphase defaults Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 05/25] distutils-r2.eclass: Make all old QA warnings fatal Michał Górny
                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 cc555771a46c..66df9e8f7272 100644
--- a/eclass/distutils-r2.eclass
+++ b/eclass/distutils-r2.eclass
@@ -1116,39 +1116,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] 26+ messages in thread

* [gentoo-dev] [PATCH 05/25] distutils-r2.eclass: Make all old QA warnings fatal
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (3 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 04/25] distutils-r2.eclass: Remove distutils.eclass checks Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 06/25] python-r2.eclass: Remove python_gen_usedep Michał Górny
                   ` (19 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

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

diff --git a/eclass/distutils-r2.eclass b/eclass/distutils-r2.eclass
index 66df9e8f7272..1b3f9e89fc49 100644
--- a/eclass/distutils-r2.eclass
+++ b/eclass/distutils-r2.eclass
@@ -93,7 +93,6 @@ esac
 
 if [[ ! ${_DISTUTILS_R2} ]]; then
 
-[[ ${EAPI} == [456] ]] && inherit eutils
 [[ ${EAPI} == [56] ]] && inherit xdg-utils
 inherit multiprocessing toolchain-funcs
 
@@ -462,9 +461,10 @@ _distutils_verify_use_setuptools() {
 			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}"
+			ewarn "DISTUTILS_USE_SETUPTOOLS value is probably incorrect"
+			ewarn "  value:    DISTUTILS_USE_SETUPTOOLS=${DISTUTILS_USE_SETUPTOOLS}${def}"
+			ewarn "  expected: DISTUTILS_USE_SETUPTOOLS=${expected}"
+			die "Incorrect DISTUTILS_USE_SETUPTOOLS"
 		fi
 	fi
 }
@@ -852,9 +852,7 @@ distutils-r2_python_install() {
 	${shopt_save}
 
 	if [[ -n ${pypy_dirs} ]]; then
-		local cmd=die
-		[[ ${EAPI} == [45] ]] && cmd=eqawarn
-		"${cmd}" "Package installs 'share' in PyPy prefix, see bug #465546."
+		die "Package installs 'share' in PyPy prefix, see bug #465546."
 	fi
 
 	if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
@@ -1001,10 +999,7 @@ distutils-r2_src_prepare() {
 	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"
+		die "QA: python_prepare_all() didn't call distutils-r2_python_prepare_all"
 	fi
 
 	if declare -f python_prepare >/dev/null; then
@@ -1086,6 +1081,7 @@ _distutils-r2_check_namespace_pth() {
 		ewarn "the ebuild accordingly:"
 		ewarn
 		ewarn "  https://wiki.gentoo.org/wiki/Project:Python/Namespace_packages"
+		die ".pth files installed"
 	fi
 }
 
@@ -1107,10 +1103,7 @@ distutils-r2_src_install() {
 	fi
 
 	if [[ ! ${_DISTUTILS_DEFAULT_CALLED} ]]; then
-		local cmd=die
-		[[ ${EAPI} == [45] ]] && cmd=eqawarn
-
-		"${cmd}" "QA: python_install_all() didn't call distutils-r2_python_install_all"
+		die "QA: python_install_all() didn't call distutils-r2_python_install_all"
 	fi
 
 	_distutils-r2_check_namespace_pth
-- 
2.25.1



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

* [gentoo-dev] [PATCH 06/25] python-r2.eclass: Remove python_gen_usedep
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (4 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 05/25] distutils-r2.eclass: Make all old QA warnings fatal Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 07/25] python-utils-r2.eclass: Remove python.eclass checks Michał Górny
                   ` (18 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 8bf0b1a1ac29..1ebc424bc9b3 100644
--- a/eclass/python-r2.eclass
+++ b/eclass/python-r2.eclass
@@ -282,8 +282,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} "${@}"
 
@@ -304,46 +303,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] 26+ messages in thread

* [gentoo-dev] [PATCH 07/25] python-utils-r2.eclass: Remove python.eclass checks
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (5 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 06/25] python-r2.eclass: Remove python_gen_usedep Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 08/25] python-utils-r2.eclass: Mark python_wrapper_setup private Michał Górny
                   ` (17 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 9821c043021a..1f904d035050 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -967,8 +967,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.
@@ -1346,173 +1344,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] 26+ messages in thread

* [gentoo-dev] [PATCH 08/25] python-utils-r2.eclass: Mark python_wrapper_setup private
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (6 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 07/25] python-utils-r2.eclass: Remove python.eclass checks Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 09/25] python-utils-r2.eclass: Mark python_is_installed private Michał Górny
                   ` (16 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 cf70f23f69d5..05e614ca4899 100644
--- a/eclass/python-any-r2.eclass
+++ b/eclass/python-any-r2.eclass
@@ -296,7 +296,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
 		return
 	fi
 
@@ -304,7 +304,7 @@ python_setup() {
 	if [[ ${EPYTHON} ]]; then
 		if _python_EPYTHON_supported "${EPYTHON}"; then
 			python_export EPYTHON PYTHON
-			python_wrapper_setup
+			_python_wrapper_setup
 			return
 		fi
 	fi
@@ -319,7 +319,7 @@ python_setup() {
 			break
 		elif _python_EPYTHON_supported "${i}"; then
 			python_export "${i}" EPYTHON PYTHON
-			python_wrapper_setup
+			_python_wrapper_setup
 			return
 		fi
 	done
@@ -329,7 +329,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
 			return
 		fi
 	done
diff --git a/eclass/python-r2.eclass b/eclass/python-r2.eclass
index 1ebc424bc9b3..feb8229eb2c5 100644
--- a/eclass/python-r2.eclass
+++ b/eclass/python-r2.eclass
@@ -593,7 +593,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
 
 	"${@}"
 }
@@ -739,7 +739,7 @@ python_setup() {
 		die "${FUNCNAME}: no enabled implementation satisfy requirements"
 	fi
 
-	python_wrapper_setup
+	_python_wrapper_setup
 }
 
 # @FUNCTION: python_replicate_script
diff --git a/eclass/python-single-r2.eclass b/eclass/python-single-r2.eclass
index 5bf6ea7221bc..fdb3438f0531 100644
--- a/eclass/python-single-r2.eclass
+++ b/eclass/python-single-r2.eclass
@@ -462,7 +462,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
 		return
 	fi
 
@@ -479,7 +479,7 @@ python_setup() {
 			fi
 
 			python_export "${impl}" EPYTHON PYTHON
-			python_wrapper_setup
+			_python_wrapper_setup
 		fi
 	done
 
diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
index 1f904d035050..f0d8f366c050 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -943,8 +943,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
@@ -957,7 +958,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] 26+ messages in thread

* [gentoo-dev] [PATCH 09/25] python-utils-r2.eclass: Mark python_is_installed private
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (7 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 08/25] python-utils-r2.eclass: Mark python_wrapper_setup private Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 10/25] python-utils-r2.eclass: Add missing @INTERNAL to private func Michał Górny
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 05e614ca4899..bedd4aa6cae1 100644
--- a/eclass/python-any-r2.eclass
+++ b/eclass/python-any-r2.eclass
@@ -259,7 +259,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 feb8229eb2c5..4dac2513c12b 100644
--- a/eclass/python-r2.eclass
+++ b/eclass/python-r2.eclass
@@ -720,7 +720,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 f0d8f366c050..bbd1802e3e7a 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -1059,14 +1059,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] 26+ messages in thread

* [gentoo-dev] [PATCH 10/25] python-utils-r2.eclass: Add missing @INTERNAL to private func
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (8 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 09/25] python-utils-r2.eclass: Mark python_is_installed private Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 11/25] python-utils-r2.eclass: Fix obsolete docs on python_export_best Michał Górny
                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

---
 eclass/python-utils-r2.eclass | 1 +
 1 file changed, 1 insertion(+)

diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
index bbd1802e3e7a..c0f3b7220a68 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -1257,6 +1257,7 @@ python_fix_shebang() {
 
 # @FUNCTION: _python_check_locale_sanity
 # @USAGE: <locale>
+# @INTERNAL
 # @RETURN: 0 if sane, 1 otherwise
 # @DESCRIPTION:
 # Check whether the specified locale sanely maps between lowercase
-- 
2.25.1



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

* [gentoo-dev] [PATCH 11/25] python-utils-r2.eclass: Fix obsolete docs on python_export_best
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (9 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 10/25] python-utils-r2.eclass: Add missing @INTERNAL to private func Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 12/25] python-utils-r2.eclass: Mark python_export private Michał Górny
                   ` (13 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 c0f3b7220a68..b9baf0267a47 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -194,7 +194,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().
 #
@@ -213,7 +213,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] 26+ messages in thread

* [gentoo-dev] [PATCH 12/25] python-utils-r2.eclass: Mark python_export private
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (10 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 11/25] python-utils-r2.eclass: Fix obsolete docs on python_export_best Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 13/25] python-utils-r2.eclass: Remove PYTHON_SITEDIR export Michał Górny
                   ` (12 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 1b3f9e89fc49..3863e0679e5b 100644
--- a/eclass/distutils-r2.eclass
+++ b/eclass/distutils-r2.eclass
@@ -730,7 +730,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 bedd4aa6cae1..11ff29167f56 100644
--- a/eclass/python-any-r2.eclass
+++ b/eclass/python-any-r2.eclass
@@ -147,7 +147,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}"
@@ -228,7 +228,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
@@ -295,7 +295,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
 		return
 	fi
@@ -303,7 +303,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
 			return
 		fi
@@ -318,7 +318,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
 			return
 		fi
@@ -327,7 +327,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
 			return
diff --git a/eclass/python-r2.eclass b/eclass/python-r2.eclass
index 4dac2513c12b..c5881a21d8cd 100644
--- a/eclass/python-r2.eclass
+++ b/eclass/python-r2.eclass
@@ -169,7 +169,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
 
@@ -440,7 +440,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
@@ -518,7 +518,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
@@ -592,7 +592,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
 
 	"${@}"
@@ -715,7 +715,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
@@ -757,7 +757,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 fdb3438f0531..2132141c82aa 100644
--- a/eclass/python-single-r2.eclass
+++ b/eclass/python-single-r2.eclass
@@ -209,7 +209,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
@@ -432,7 +432,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
@@ -461,7 +461,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
 		return
 	fi
@@ -478,7 +478,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
 		fi
 	done
diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
index b9baf0267a47..e7f2b4c68c59 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -224,116 +224,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.
@@ -346,7 +239,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
@@ -363,7 +256,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
@@ -491,7 +384,7 @@ python_export() {
 				debug-print "${FUNCNAME}: PYTHON_SCRIPTDIR = ${PYTHON_SCRIPTDIR}"
 				;;
 			*)
-				die "python_export: unknown variable ${var}"
+				die "_python_export: unknown variable ${var}"
 		esac
 	done
 }
@@ -502,13 +395,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}"
 }
 
@@ -517,13 +407,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}"
 }
 
@@ -538,7 +425,7 @@ python_get_includedir() {
 python_get_library_path() {
 	debug-print-function ${FUNCNAME} "${@}"
 
-	python_export "${@}" PYTHON_LIBPATH
+	_python_export "${@}" PYTHON_LIBPATH
 	echo "${PYTHON_LIBPATH}"
 }
 
@@ -555,7 +442,7 @@ python_get_library_path() {
 python_get_CFLAGS() {
 	debug-print-function ${FUNCNAME} "${@}"
 
-	python_export "${@}" PYTHON_CFLAGS
+	_python_export "${@}" PYTHON_CFLAGS
 	echo "${PYTHON_CFLAGS}"
 }
 
@@ -572,7 +459,7 @@ python_get_CFLAGS() {
 python_get_LIBS() {
 	debug-print-function ${FUNCNAME} "${@}"
 
-	python_export "${@}" PYTHON_LIBS
+	_python_export "${@}" PYTHON_LIBS
 	echo "${PYTHON_LIBS}"
 }
 
@@ -589,7 +476,7 @@ python_get_LIBS() {
 python_get_PYTHON_CONFIG() {
 	debug-print-function ${FUNCNAME} "${@}"
 
-	python_export "${@}" PYTHON_CONFIG
+	_python_export "${@}" PYTHON_CONFIG
 	echo "${PYTHON_CONFIG}"
 }
 
@@ -602,7 +489,7 @@ python_get_PYTHON_CONFIG() {
 python_get_scriptdir() {
 	debug-print-function ${FUNCNAME} "${@}"
 
-	python_export "${@}" PYTHON_SCRIPTDIR
+	_python_export "${@}" PYTHON_SCRIPTDIR
 	echo "${PYTHON_SCRIPTDIR}"
 }
 
@@ -667,7 +554,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
@@ -771,7 +658,7 @@ python_newexe() {
 	local newfn=${2}
 
 	local PYTHON_SCRIPTDIR d
-	python_export PYTHON_SCRIPTDIR
+	_python_export PYTHON_SCRIPTDIR
 	d=${PYTHON_SCRIPTDIR#${EPREFIX}}
 
 	(
@@ -899,7 +786,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
@@ -932,7 +819,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}}
 
@@ -976,7 +863,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
@@ -1094,7 +981,7 @@ _python_is_installed() {
 			;;
 		*)
 			local PYTHON_PKG_DEP
-			python_export "${impl}" PYTHON_PKG_DEP
+			_python_export "${impl}" PYTHON_PKG_DEP
 			has_version "${hasv_args[@]}" "${PYTHON_PKG_DEP}"
 			;;
 	esac
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] 26+ messages in thread

* [gentoo-dev] [PATCH 13/25] python-utils-r2.eclass: Remove PYTHON_SITEDIR export
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (11 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 12/25] python-utils-r2.eclass: Mark python_export private Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 14/25] python-utils-r2.eclass: Remove PYTHON_INCLUDEDIR export Michał Górny
                   ` (11 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 e7f2b4c68c59..971dd4393963 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -235,10 +235,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} "${@}"
 
@@ -272,15 +268,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
@@ -390,16 +377,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
@@ -749,7 +738,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
@@ -785,8 +774,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] 26+ messages in thread

* [gentoo-dev] [PATCH 14/25] python-utils-r2.eclass: Remove PYTHON_INCLUDEDIR export
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (12 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 13/25] python-utils-r2.eclass: Remove PYTHON_SITEDIR export Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 15/25] python-utils-r2.eclass: Remove PYTHON_LIBPATH export Michał Górny
                   ` (10 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 971dd4393963..87c7dd506274 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -268,17 +268,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
@@ -392,15 +381,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
@@ -806,8 +801,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] 26+ messages in thread

* [gentoo-dev] [PATCH 15/25] python-utils-r2.eclass: Remove PYTHON_LIBPATH export
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (13 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 14/25] python-utils-r2.eclass: Remove PYTHON_INCLUDEDIR export Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 16/25] python-utils-r2.eclass: Remove PYTHON_CFLAGS export Michał Górny
                   ` (9 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 87c7dd506274..edf030b24683 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -268,16 +268,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
 
@@ -399,18 +389,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] 26+ messages in thread

* [gentoo-dev] [PATCH 16/25] python-utils-r2.eclass: Remove PYTHON_CFLAGS export
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (14 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 15/25] python-utils-r2.eclass: Remove PYTHON_LIBPATH export Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 17/25] python-utils-r2.eclass: Remove PYTHON_LIBS export Michał Górny
                   ` (8 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 edf030b24683..dc5c8dafd12c 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -268,22 +268,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
 
@@ -409,20 +393,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] 26+ messages in thread

* [gentoo-dev] [PATCH 17/25] python-utils-r2.eclass: Remove PYTHON_LIBS export
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (15 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 16/25] python-utils-r2.eclass: Remove PYTHON_CFLAGS export Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 18/25] python-utils-r2.eclass: Remove PYTHON_CONFIG export Michał Górny
                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 dc5c8dafd12c..00bc635ebab4 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -268,22 +268,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
 
@@ -420,20 +404,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] 26+ messages in thread

* [gentoo-dev] [PATCH 18/25] python-utils-r2.eclass: Remove PYTHON_CONFIG export
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (16 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 17/25] python-utils-r2.eclass: Remove PYTHON_LIBS export Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 19/25] python-utils-r2.eclass: Remove PYTHON_SCRIPTDIR export Michał Górny
                   ` (6 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 00bc635ebab4..7c438e59aa6a 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -268,23 +268,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
@@ -431,20 +414,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] 26+ messages in thread

* [gentoo-dev] [PATCH 19/25] python-utils-r2.eclass: Remove PYTHON_SCRIPTDIR export
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (17 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 18/25] python-utils-r2.eclass: Remove PYTHON_CONFIG export Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 20/25] python-single-r2.eclass: PYTHON_MULTI_USEDEP → PYTHON_USEDEP Michał Górny
                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 3863e0679e5b..6a52e261498c 100644
--- a/eclass/distutils-r2.eclass
+++ b/eclass/distutils-r2.eclass
@@ -729,8 +729,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 c5881a21d8cd..f7a92c500317 100644
--- a/eclass/python-r2.eclass
+++ b/eclass/python-r2.eclass
@@ -756,8 +756,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 7c438e59aa6a..8486ee901cd9 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -295,11 +295,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
@@ -443,16 +438,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
@@ -619,9 +613,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] 26+ messages in thread

* [gentoo-dev] [PATCH 20/25] python-single-r2.eclass: PYTHON_MULTI_USEDEP → PYTHON_USEDEP
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (18 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 19/25] python-utils-r2.eclass: Remove PYTHON_SCRIPTDIR export Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 21/25] distutils-r2.eclass: Pass --skip-build to install Michał Górny
                   ` (4 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/eclass/python-single-r2.eclass b/eclass/python-single-r2.eclass
index 2132141c82aa..2c73ec4d11fb 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
@@ -142,7 +142,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
@@ -154,7 +154,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
@@ -163,7 +163,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
 #
@@ -341,7 +341,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.
 #
@@ -349,7 +349,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:
@@ -379,7 +379,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] 26+ messages in thread

* [gentoo-dev] [PATCH 21/25] distutils-r2.eclass: Pass --skip-build to install
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (19 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 20/25] python-single-r2.eclass: PYTHON_MULTI_USEDEP → PYTHON_USEDEP Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 22/25] eclass: python-r2.eclass → python-multi-r2.eclass Michał Górny
                   ` (3 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 6a52e261498c..b155c31d121e 100644
--- a/eclass/distutils-r2.eclass
+++ b/eclass/distutils-r2.eclass
@@ -832,7 +832,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] 26+ messages in thread

* [gentoo-dev] [PATCH 22/25] eclass: python-r2.eclass → python-multi-r2.eclass
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (20 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 21/25] distutils-r2.eclass: Pass --skip-build to install Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 23/25] python-any-r2.eclass: Verbosely report used implementation Michał Górny
                   ` (2 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 b155c31d121e..b1bc7aadae57 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.
 
 case "${EAPI:-0}" in
 	0|1|2|3|4)
@@ -66,8 +66,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
@@ -97,7 +97,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 11ff29167f56..d6523a93646a 100644
--- a/eclass/python-any-r2.eclass
+++ b/eclass/python-any-r2.eclass
@@ -40,8 +40,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
@@ -124,9 +124,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 f7a92c500317..093f794b909b 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.
 
 case "${EAPI:-0}" in
 	0|1|2|3|4)
@@ -37,12 +37,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
@@ -131,9 +131,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
@@ -230,7 +229,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
@@ -779,5 +778,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 2c73ec4d11fb..833622f1a49a 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
@@ -46,8 +46,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
@@ -141,7 +141,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:
@@ -157,8 +157,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 8486ee901cd9..8d1012a40513 100644
--- a/eclass/python-utils-r2.eclass
+++ b/eclass/python-utils-r2.eclass
@@ -193,8 +193,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().
 #
@@ -212,8 +212,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] 26+ messages in thread

* [gentoo-dev] [PATCH 23/25] python-any-r2.eclass: Verbosely report used implementation
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (21 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 22/25] eclass: python-r2.eclass → python-multi-r2.eclass Michał Górny
@ 2020-02-29 20:41 ` Michał Górny
  2020-02-29 20:42 ` [gentoo-dev] [PATCH 24/25] python-single-r2.eclass: Report used impl verbosely Michał Górny
  2020-02-29 20:42 ` [gentoo-dev] [PATCH 25/25] python-multi-r2.eclass: Report python_setup " Michał Górny
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:41 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 | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/eclass/python-any-r2.eclass b/eclass/python-any-r2.eclass
index d6523a93646a..e7e5b3b9c68f 100644
--- a/eclass/python-any-r2.eclass
+++ b/eclass/python-any-r2.eclass
@@ -296,6 +296,7 @@ python_setup() {
 
 		_python_export "${impls[0]}" EPYTHON PYTHON
 		_python_wrapper_setup
+		einfo "Using ${EPYTHON} to build"
 		return
 	fi
 
@@ -304,6 +305,7 @@ python_setup() {
 		if _python_EPYTHON_supported "${EPYTHON}"; then
 			_python_export EPYTHON PYTHON
 			_python_wrapper_setup
+			einfo "Using ${EPYTHON} to build"
 			return
 		fi
 	fi
@@ -319,6 +321,7 @@ python_setup() {
 		elif _python_EPYTHON_supported "${i}"; then
 			_python_export "${i}" EPYTHON PYTHON
 			_python_wrapper_setup
+			einfo "Using ${EPYTHON} to build"
 			return
 		fi
 	done
@@ -329,6 +332,7 @@ python_setup() {
 		_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
-- 
2.25.1



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

* [gentoo-dev] [PATCH 24/25] python-single-r2.eclass: Report used impl verbosely
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (22 preceding siblings ...)
  2020-02-29 20:41 ` [gentoo-dev] [PATCH 23/25] python-any-r2.eclass: Verbosely report used implementation Michał Górny
@ 2020-02-29 20:42 ` Michał Górny
  2020-02-29 20:42 ` [gentoo-dev] [PATCH 25/25] python-multi-r2.eclass: Report python_setup " Michał Górny
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:42 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

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

diff --git a/eclass/python-single-r2.eclass b/eclass/python-single-r2.eclass
index 833622f1a49a..0d86aa0cf512 100644
--- a/eclass/python-single-r2.eclass
+++ b/eclass/python-single-r2.eclass
@@ -463,6 +463,7 @@ python_setup() {
 
 		_python_export "${impls[0]}" EPYTHON PYTHON
 		_python_wrapper_setup
+		einfo "Using ${EPYTHON} to build"
 		return
 	fi
 
@@ -480,6 +481,7 @@ python_setup() {
 
 			_python_export "${impl}" EPYTHON PYTHON
 			_python_wrapper_setup
+			einfo "Using ${EPYTHON} to build"
 		fi
 	done
 
-- 
2.25.1



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

* [gentoo-dev] [PATCH 25/25] python-multi-r2.eclass: Report python_setup impl verbosely
  2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
                   ` (23 preceding siblings ...)
  2020-02-29 20:42 ` [gentoo-dev] [PATCH 24/25] python-single-r2.eclass: Report used impl verbosely Michał Górny
@ 2020-02-29 20:42 ` Michał Górny
  24 siblings, 0 replies; 26+ messages in thread
From: Michał Górny @ 2020-02-29 20:42 UTC (permalink / raw
  To: gentoo-dev; +Cc: python, Michał Górny

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

diff --git a/eclass/python-multi-r2.eclass b/eclass/python-multi-r2.eclass
index 093f794b909b..f7964d0842ae 100644
--- a/eclass/python-multi-r2.eclass
+++ b/eclass/python-multi-r2.eclass
@@ -739,6 +739,7 @@ python_setup() {
 	fi
 
 	_python_wrapper_setup
+	einfo "Using ${EPYTHON} in global scope"
 }
 
 # @FUNCTION: python_replicate_script
-- 
2.25.1



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

end of thread, other threads:[~2020-02-29 20:50 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-02-29 20:41 [gentoo-dev] [PATCH 00/25] python-r2 eclass suite Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 01/25] eclass: Copy python-r1 suite to python-r2 Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 02/25] distutils-r2.eclass: Remove EXAMPLES Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 03/25] distutils-r2.eclass: Remove no-op subphase defaults Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 04/25] distutils-r2.eclass: Remove distutils.eclass checks Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 05/25] distutils-r2.eclass: Make all old QA warnings fatal Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 06/25] python-r2.eclass: Remove python_gen_usedep Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 07/25] python-utils-r2.eclass: Remove python.eclass checks Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 08/25] python-utils-r2.eclass: Mark python_wrapper_setup private Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 09/25] python-utils-r2.eclass: Mark python_is_installed private Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 10/25] python-utils-r2.eclass: Add missing @INTERNAL to private func Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 11/25] python-utils-r2.eclass: Fix obsolete docs on python_export_best Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 12/25] python-utils-r2.eclass: Mark python_export private Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 13/25] python-utils-r2.eclass: Remove PYTHON_SITEDIR export Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 14/25] python-utils-r2.eclass: Remove PYTHON_INCLUDEDIR export Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 15/25] python-utils-r2.eclass: Remove PYTHON_LIBPATH export Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 16/25] python-utils-r2.eclass: Remove PYTHON_CFLAGS export Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 17/25] python-utils-r2.eclass: Remove PYTHON_LIBS export Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 18/25] python-utils-r2.eclass: Remove PYTHON_CONFIG export Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 19/25] python-utils-r2.eclass: Remove PYTHON_SCRIPTDIR export Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 20/25] python-single-r2.eclass: PYTHON_MULTI_USEDEP → PYTHON_USEDEP Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 21/25] distutils-r2.eclass: Pass --skip-build to install Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 22/25] eclass: python-r2.eclass → python-multi-r2.eclass Michał Górny
2020-02-29 20:41 ` [gentoo-dev] [PATCH 23/25] python-any-r2.eclass: Verbosely report used implementation Michał Górny
2020-02-29 20:42 ` [gentoo-dev] [PATCH 24/25] python-single-r2.eclass: Report used impl verbosely Michał Górny
2020-02-29 20:42 ` [gentoo-dev] [PATCH 25/25] python-multi-r2.eclass: Report python_setup " 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