Migration guides¶
Migrating from old PYTHON_USEDEP syntax in python-single-r1¶
Prior to February 2020, python-single-r1
used to provide a single
PYTHON_USEDEP
variable alike the two other eclasses. However,
getting it to work correctly both on single-impl and multi-impl packages
required a gross hack.
The current eclass API requires using python_gen_cond_dep
function
to generate multi-impl deps instead, with PYTHON_USEDEP
serving
as a placeholder. Single-impl deps can be expressed with
PYTHON_SINGLE_USEDEP
that can be used either as placeholder,
or directly as a variable.
During a transitional period, PYTHON_USEDEP
was banned entirely
and PYTHON_MULTI_USEDEP
was used instead. As of EAPI 8,
the opposite is true — PYTHON_USEDEP
is to be used,
and PYTHON_MULTI_USEDEP
was removed.
The recommended rule of thumb for migrating old ebuilds is to:
Replace all instances of
${PYTHON_USEDEP}
for simple-impl deps with${PYTHON_SINGLE_USEDEP}
. If you don’t know the type of given dep, dependency check (repoman, pkgcheck) will tell you if you chose wrong.Wrap the dependencies using
${PYTHON_USEDEP}
in a singlepython_gen_cond_dep
block (reordering may be desirable).Run
pkgcheck scan
orrepoman full
. If you get syntax errors, you probably missedpython_gen_cond_dep
or did not escape the$
in placeholder properly. If you get unmatched dependency, you probably got single-impl vs. multi-impl wrong.
This way, you can generally convert ebuilds using trial-and-error method.
Migrating from EAPI 7 to EAPI 8¶
EAPI 8 has banned everything that’s been deprecated in EAPI 7, as well as some other obsolete stuff. The following table lists all banned things along with their suggested replacements.
Deprecated thing
Replacement
Private eclass API
python_export
python_setup / getters
python_wrapper_setup
python_setup
Obsolete API
distutils_install_for_testing
--via-home
no argument (
--via-root
) or--via-venv
python_gen_usedep
python_gen_cond_dep
PYTHON_MULTI_USEDEP
PYTHON_USEDEP
mydistutilsargs rename
mydistutilsargs
DISTUTILS_ARGS
Post-Python 2 cleanup
python_gen* -2 / python2 / pypy
remove entirely
python_gen* -3
make unconditional
python_is_python3
always assume true
The changes can be split roughly into four groups: ban of now-private eclass API, ban of obsolete API functions, mydistutilsargs rename and bans related to post-Python 2 cleanup.
The private eclass API part involves python_export
and python_wrapper_setup
. Both were deprecated in March 2020,
and they were never covered in this guide. The former was historically
used to get information about the Python interpreter (either the current
${EPYTHON}
or an arbitrary choice), the latter to create the wrapper
directory containing python
and other executables.
When the functions were used to establish a Python build environment,
the replacement for both is a single python_setup
call. When
python_export
was used to grab additional details about the Python
interpreter, the various python_get*
functions should be used
instead.
src_configure() {
# ...
# OLD:
local PYTHON_INCLUDEDIR PYTHON_LIBPATH
python_export PYTHON_INCLUDEDIR PYTHON_LIBPATH
mycmakeargs+=(
-DPython3_INCLUDE_DIR="${PYTHON_INCLUDEDIR}"
-DPython3_LIBRARY="${PYTHON_LIBPATH}"
)
# NEW:
mycmakeargs+=(
-DPython3_INCLUDE_DIR="$(python_get_includedir)"
-DPython3_LIBRARY="$(python_get_library_path)"
)
}
The second group involves sundry API that were deprecated earlier. These are:
distutils_install_for_testing --via-home
layout that stopped working correctly at some point. The default--via-root
should work most of the time, and-via-venv
replace the remaining cases for the removed layout.python_gen_usedep
function that was historically used to generate partial USE dependencies, and was generally combined withREQUIRED_USE
to force specific (usually old) Python interpreters for specific features. This was really ugly. Nowadays, you should really usepython_gen_cond_dep
instead.PYTHON_MULTI_USEDEP
placeholder that was temporarily used in python-single-r1 ebuilds.PYTHON_USEDEP
is equivalent now.
The third group is a sole rename of mydistutilsargs
variable.
Since you usually need to pass the same arguments in all phase
functions, this variable was not really used in local scope. It has
been renamed to uppercase DISTUTILS_ARGS
to follow the common
pattern for global scope variables.
Finally, the fourth group involves banning some of the features that were specifically used in order to support distinguish between Python 2 and Python 3. This is meant to force cleaning up old cruft from ebuilds. It comes in three parts:
Banning arguments to
python_gen*
that reference Python 2 (e.g.-2
,python2*
,python2_7
,pypy
). Since Python 2 is no longer supported in the relevant code paths, the relevant calls should just be removed.Banning the
-3
short-hand topython_gen*
. Since all supported interpreters are compatible with Python 3 now, the relevant code should be made unconditional. Note thatpython3*
is still useful, as it distinguishes CPython from PyPy3.Banning the
python_is_python3
function. Since the removal of Python 2 support, it always evaluated to true.
All the aforementioned replacements are available in all EAPIs.
Migrating to PEP 517 builds¶
As of January 2022, the distutils-r1
can use PEP 517 build backends
instead of calling setuptools directly. The new mode is particularly
useful for:
packages using flit and poetry, as a better replacement for the deprecated
dev-python/pyproject2setuppy
hackpackages using other PEP 517 build systems (such as pdm) that are not supported in legacy mode at all
packages using setuptools without
setup.py
packages using plain distutils, as the mode handles the switch from deprecated stdlib distutils to the version vendored in setuptools safely
The PEP 517 mode provides the test phase with venv-style installed
package tree (alike distutils_install_for_testing --via-venv
)
that should make testing more streamlined.
Unfortunately, the new mode can cause issues with customized distutils and setuptools build systems. It is important to verify the installed file list after the migration. Packages that require custom configure phases or passing arguments are not supported at the moment.
For simple packages, the migration consists of:
Adding
DISTUTILS_USE_PEP517
above the inherit line. The value indicates the build system used, e.g.flit
,poetry
,setuptools
(used also for distutils).Removing
DISTUTILS_USE_SETUPTOOLS
. If the previous value wasrdepend
(and indeed a runtime dependency is required), thendev-python/setuptools
needs to be explicitly added toRDEPEND
.Removing
distutils_install_for_testing
and/or--install
option todistutils_enable_tests
. This should no longer be necessary and tests should work out of the box.
multipart vs. python-multipart packages¶
Prior to November 2024, two PyPI packages claimed the multipart
import name: multipart and python-multipart. Originally, Gentoo
packaged only the latter, as it was necessary to satisfy dependencies.
However, with the former being listed as the recommended replacement
for the deprecated cgi module, new packages started depending on it.
At this point, Gentoo decided to package multipart as well,
and to rename python-multipart in anticipation of upstream rename
already in progress, in >=dev-python/python-multipart-0.0.12-r100
.
However, it should be noted that the Gentoo rename does not install
a compatibility loader to permit importing it via multipart
import
name, as that would work only if dev-python/multipart
was not installed. Instead, packages need to be explicitly patched
to use the new import name of python_multipart
.
Therefore, the dependencies on these packages should be handled in the following manner:
If the package depends on multipart, a dependency on
dev-python/multipart
should be added.If the package bundles multipart, the dependency should be unbundled.
If the package depends on python-multipart and uses the new import name (i.e.
import python_multipart
), a dependency on>=dev-python/python-multipart-0.0.12-r100
(or a newer version) should be added.If the package depends on python-multipart and uses the old import name (i.e.
import multipart
), it should be patched to use the new import name instead, and the dependency should be added as above.
The following snippet provides an example of patching the python-multipart import:
RDEPEND="
>=dev-python/python-multipart-0.0.12-r100[${PYTHON_USEDEP}]
"
src_prepare() {
distutils-r1_src_prepare
# python-multipart package renamed in Gentoo to python_multipart
find -name "*.py" -exec sed \
-e "s:from multipart:from python_multipart:" \
-e "s:import multipart:import python_multipart as multipart:" \
-i {} + || die
}