python-r1 Developer's Guide
1.
Introductory information
Purpose of the eclasses
The python‑r1 suite consists of five eclasses:
-
python-utils-r1,
-
python-r1,
-
python-single-r1,
-
python-any-r1,
-
distutils-r1.
The python‑utils‑r1 eclass is the utility eclass
in the suite. It does not export any phase functions nor set
any metadata. It does not require the package to fit
any specific model.
The python‑r1 eclass is the second fundamental eclass.
It extends the former eclass with the metadata and variables
suited for packages supporting multiple Python implementations:
the implementation choice flags, dependency strings. It does
not, however, enforce any dependencies directly nor export phase
functions.
The python‑single‑r1 eclass is an alternative
to python‑r1 for packages which do not support being
installed for multiple Python implementations. It exports
similar metadata and variables, and a pkg_setup phase
function handling the target implementation choice.
The python‑any‑r1 eclass is designed to be used
on packages which do not need explicit implementation choice
or rely on specific implementation installed being invariable.
This mostly involves packages having strictly build-time
dependency on Python. It exports metadata suitable for setting
an appropriate dependency, and a pkg_setup phase function
handling finding the best installed implementation.
The distutils‑r1 eclass extends the suite with a set
of basic phase functions to build and install packages using
the distutils build system of the inbuilt Python module
distutils. It follows the common practices for build
system eclasses, including patching and installing
documentation.
The choice of eclass for your package could follow the following
algorithm:
-
If the package uses the distutils build system,
then use distutils‑r1.
-
If the package installs Python modules or scripts which can
be simultaneously installed for multiple Python
implementations, use python‑r1.
-
If the package installs Python modules or scripts which can
be installed for a single Python implementation only,
or embeds Python, then use python‑single‑r1.
-
If the package has a strictly build-time dependency on Python,
then use python‑any‑r1.
A conversion from python.eclass can follow the following
algorithm:
-
If the package inherits distutils, then use
distutils‑r1.
-
If the package enables SUPPORT_PYTHON_ABIS, then use
python‑r1.
-
If the package has run-time dependency on Python,
then use python‑single‑r1.
-
If the package has only build-time dependency on Python,
then use python‑any‑r1.
Note:
Please note that you always inherit only the best match
of the fore-mentioned eclasses. Other relevant eclasses
are inherited implicitly.
|
The active Python interpreter in ebuild scope
A key concept in the workflow of python‑r1 suite is the setting
of the active Python interpreter. Its value is stored
and exported in the EPYTHON environment variable.
The setting of active Python interpreter can affect;
-
the interpreter used to run external Python scripts,
-
the implementation used by helpers,
such as python_domodule and python_doscript,
-
the default implementation for python_export
and the associated getter functions.
The EPYTHON variable is set implicitly in the following
scopes;
-
in commands and functions run by python_foreach_impl,
-
in implementation-specific sub-phases of distutils‑r1,
-
in ebuilds using the python‑single‑r1 eclass after
running python‑single‑r1_pkg_setup.
If it is otherwise necessary to set the active Python
interpreter, it can be either set using the python_export
function or by setting the EPYTHON variable directly.
For the details on the former solution, please refer to the Obtaining
Python implementation information section.
If EPYTHON is set directly, it needs to have one
of the following values;
-
pythonX.Y for CPython X.Y;
-
pypy-cX.Y for PyPy X.Y;
-
jythonX.Y for Jython X.Y.
Note:
Please note that for EPYTHON to be effective to external
programs, it needs to be exported.
|
Code Listing 1.1: Setting EPYTHON for the function scope |
pkg_setup() {
python_export python2_7
}
src_compile() {
local EPYTHON PYTHON
python_export python2_7
}
src_install() {
local EPYTHON=python2.7
}
|
2.
Common metadata variables
General notes
Note:
The variables listed in this section apply to ebuilds using
python‑r1, distutils‑r1
and python‑single‑r1 eclasses.
|
Listing supported Python implementations
(PYTHON_COMPAT)
The first and most important task in writing ebuilds both
for python‑r1 and distutils‑r1 is to specify the list of Python
implementations supported by the ebuild.
This list is specified using the PYTHON_COMPAT variable.
It is an obligatory array which need be declared before
the inherit command. It should list all supported
implementations using the following naming scheme:
-
pythonX_Y for CPython X.Y;
-
pypyX_Y for PyPy X.Y;
-
jythonX_Y for Jython X.Y.
PYTHON_COMPAT should be treated with respect similar
to the KEYWORDS variable. No implementation should
be added there without prior testing, and all package
dependencies must support that implementation.
The PYTHON_COMPAT variable can be considered
a replacement for python.eclass' PYTHON_DEPEND
and RESTRICT_PYTHON_ABIS variables.
Code Listing 2.1: Examples of PYTHON_COMPAT |
PYTHON_COMPAT=( python2_5 python2_6 python2_7 )
PYTHON_COMPAT=( python{2_5,2_6,2_7,3_1,3_2,3_3} )
PYTHON_COMPAT=( python{2_6,2_7} pypy{1_9,2_0} )
inherit python-r1
|
Depending on Python (PYTHON_DEPS)
Note:
Please note that this section applies to the sole use
of python‑r1 or python‑single‑r1 only.
The distutils‑r1 eclass unconditionally adds this
dependency.
|
In order to efficiently handle various kinds of package
dependencies on Python, the python‑r1 eclass does not set
the ebuild dependencies directly. Instead, it prepares
the proper dependency string and stores it in a variable named
PYTHON_DEPS.
The PYTHON_DEPS variable is unconditionally set
by the eclass to a list of proper USE-conditional dependencies
on enabled Python implementations. It also holds any additional
dependencies necessary — most notably, a dependency
on dev-python/python-exec.
The ebuild should reference the PYTHON_DEPS variable
in RDEPEND and/or DEPEND as necessary. Those
dependencies may require use of an appropriate USE-conditional
block.
Code Listing 2.2: Example uses of PYTHON_DEPS |
RDEPEND=${PYTHON_DEPS}
DEPEND=${RDEPEND}
DEPEND=${PYTHON_DEPS}
RDEPEND="python? ( ${PYTHON_DEPS} )"
|
The actual value assigned to this variable differs according
to the inherited eclass as listed in the following table:
| Eclass |
Dependency type |
Example value |
| python‑r1 |
USE-conditional upon PYTHON_TARGETS
|
python_targets_python2_6? ( dev-lang/python:2.6 )
python_targets_python2_7? ( dev-lang/python:2.7 )
|
| python‑single‑r1 |
USE-conditional upon PYTHON_SINGLE_TARGET
|
python_single_target_python2_6? ( dev-lang/python:2.6 )
python_single_target_python2_7? ( dev-lang/python:2.7 )
|
| python‑any‑r1 |
unconditional, satisfied by any supported version
|
|| ( dev-lang/python:2.7 dev-lang/python:2.6 )
|
Depending on other Python packages (PYTHON_USEDEP)
Whenever two Python packages involve one of the packages loading
Python modules installed by the other, both packages need
to have the support for the same Python implementations enabled.
That constraint needs to be enforced through the use
of PYTHON_USEDEP variable.
The PYTHON_USEDEP variable is set unconditionally
by the eclass. It contains a bare compact USE dependency string
which can be used directly in dependency specifications.
It should be noted that dependencies not involving direct Python
module loading do not require PYTHON_USEDEP. For example,
running external Python scripts does not need those constraints
enforced.
PYTHON_USEDEP can not be used against packages
not supporting PYTHON_TARGETS. Developers are strongly
encouraged to convert dependencies before committing the actual
package. If that is not feasible, the dependency has to omit
the use of PYTHON_USEDEP.
Code Listing 2.3: Example use of PYTHON_USEDEP |
RDEPEND="dev-python/setuptools[${PYTHON_USEDEP}]"
RDEPEND="dev-python/lxml[threads,${PYTHON_USEDEP}]"
RDEPEND="dev-python/wxpython:2.8"
|
The compatibilities of PYTHON_USEDEP with packages
using different eclasses according to the inherited eclass
of the ebuild being developed are listed in the following table:
| Eclass |
Compatible with packages using |
Example value |
| python‑r1 |
python‑r1, python‑distutils‑ng
|
python_targets_python2_6?,python_targets_python2_7?
|
| python‑single‑r1 |
python‑r1,
python‑distutils‑ng,
python‑single‑r1
|
python_targets_python2_6?,python_targets_python2_7?,python_single_target_python2_6(+)?,python_single_target_python2_7(+)?
|
| python‑any‑r1 |
not used in eclass
|
n/a
|
Requesting optional Python features (PYTHON_REQ_USE)
Sometimes it is necessary to depend on a feature or module which
belongs to the Python implementation itself but is not always
available. The availability can depend both on Python version
and USE flags. These features can be divided into two types;
those having replacement packages and those lacking them.
If a particular module has a replacement package, the correct
way to require it is to depend on the respective virtual
package. For example, a script using the argparse module
should depend on virtual/python-argparse. The virtual
will either enforce a particular USE constraints or pull in
the replacement package as necessary.
If a particular module or feature is provided by the Python
implementation only, and is conditional upon the setting
of a USE flag, PYTHON_REQ_USE should be used instead.
The PYTHON_REQ_USE variable is an optional variable which
can be used to enforce a set of USE flag requirements
upon the Python implementation. It takes a bare USE dependency
string and appends it to the dependency on every Python
implementation supported. Sometimes it may be necessary to use
EAPI 4 USE defaults to handle cases when a particular flag
is enabled unconditionally in some of the supported
implementations.
The PYTHON_REQ_USE variable can be considered
a replacement for python.eclass' PYTHON_USE_WITH
variable.
Code Listing 2.4: Example uses of virtuals and PYTHON_REQ_USE |
RDEPEND="virtual/python-argparse[${PYTHON_USEDEP}]"
PYTHON_REQ_USE="ncurses"
PYTHON_REQ_USE="bzip2(+)"
|
3.
The distutils‑r1 eclass
Tasks performed by distutils‑r1
The distutils‑r1 exports a set of phase functions performing
common tasks related to building and installing the package.
In many cases, those tasks will suffice for a typical Python
package.
The tasks performed by distutils‑r1 are (in execution order):
- applying patches listed in the PATCHES array;
- applying user patches (the epatch_user function);
- building and installing the package using setup.py;
- ensuring that Python scripts are installed in multiple
variants according to the enabled Python implementations;
- installing additional documentation (using DOCS
and HTML_DOCS arrays).
Code Listing 3.1: Example on enabling patching and additional documentation |
PATCHES=(
"${FILESDIR}"/${P}-foo.patch
"${FILESDIR}"/${P}-bar.patch
)
DOCS=( README.md )
HTML_DOCS=( doc/html/ )
|
Note:
The listed variables can be either set in the global scope
or in the scope of the respective phase function.
The PATCHES variable can be set in src_prepare()
or python_prepare_all() instead, while DOCS
and HTML_DOCS can be set in src_install()
or python_install_all().
|
The ‘partial’ phase functions
The distutils‑r1 eclass utilises a mechanism inspired by phase
functions to make writing ebuilds relatively easy. For each
of the src_* phases, two ‘partial’ phases are used;
the implementation-specific sub-phase
and the implementation-common sub-phase.
Each of the implementation-specific sub-phases is named
according to its corresponding src_* phase but with
the src_ prefix replaced with python_.
For example, src_compile() becomes
python_compile(). It is called once for each enabled
Python implementation. For the call scope, the default set
of informational variables is exported (EPYTHON,
PYTHON, BUILD_DIR, PYTHONPATH
if necessary).
Each of the implementation-common sub-phases has
the suffix _all appended. For example,
the python_install_all() sub-phase corresponds
to src_install(). It is called only once during the build
process. It is invoked in the main source directory.
For the call scope, the variables corresponding to the best
enabled Python implementation are exported.
The distutils‑r1 eclass provides default functions for all
implementation-specific sub-phases
and for python_prepare_all and python_install_all.
If you are defining any of those phase functions, you ought
call the respective distutils‑r1 phase function.
Code Listing 3.2: Example of defining sub-phase functions |
python_compile_all() {
if use doc; then
python_export_best
"${PYTHON}" setup.py doc || die
fi
}
python_test() {
"${PYTHON}" setup.py test || die
}
python_install_all() {
use doc && local HTML_DOCS=( doc/* )
distutils-r1_python_install_all
} |
Out-of-source and in-source builds
There are two modes of building packages with distutils‑r1;
‘out-of-source builds’ (the default) and ‘in-source builds’.
When an out-of-source build is performed, the build directory
(${BUILD_DIR}) is used to store output files, while
the sources are kept in their original location. Therefore,
the build system must not attempt to modify any of the input
files or write to ${S}.
In order to support out-of-source builds, the build directory
is appended to PYTHONPATH and esetup.py command
adds build directory paths to the setup.py invocation.
Due to technical limitations of distutils, this results
in the package being built on the first esetup.py
invocation.
The in-source builds are implemented for packages where
out-of-source builds are problematic. They are enabled either
explicitly when the DISTUTILS_IN_SOURCE_BUILD variable
is set (to any value), or implicitly
when the python_prepare sub-phase is declared.
When an in-source build is performed, the build directory acts
both as a source and output directory. The package sources
are copied there first, and all implementation-specific
sub-phases are executed in the build directory. Therefore,
the build system is allowed to modify the sources freely.
Parallel build support
A parallel build occurs when more than one task is performed
concurrently. For example, many common build systems including
autotools and cmake compile multiple files in parallel to make
a better use of the computing power of modern multicore CPUs
and multiprocessor systems.
Sadly, distutils itself is not capable of parallel builds,
making the build of multiple Python extensions inefficient
and time-consuming. In order to circumvent that limitation,
the distutils‑r1 eclass runs the whole build process
for multiple Python implementations in parallel.
This usually causes no issues itself but it can trigger issues
consequent to the modifying of source files by the build system.
Those issues can generally be managed by enabling the in-source
build option by setting DISTUTILS_IN_SOURCE_BUILD
to a non-null value.
When a parallel build is performed, the ebuild is disallowed
from modifying installed files during
the implementation-specific sub-phase. Any changes necessary
need be delayed until the implementation-common sub-phase.
Otherwise, the files are prone to being clobbered in the middle
of performing the change.
If the build system itself actually uses a parallel build
(e.g. distutils running make) or any other issue
makes parallel build undesirable, it can be disabled by setting
DISTUTILS_NO_PARALLEL_BUILD to a non-null value.
4.
Advanced python‑r1 functions
Repeating commands for multiple Python implementations
Note:
This function is mostly useful for ebuilds not using
the distutils‑r1 eclass. For those using it, placing
the commands in an appropriate sub-phase function is preferred.
|
If it is necessary to run a command repeatedly for multiple
Python implementations, the python_foreach_impl function
can be used. It takes a command and a list of its parameters
and runs it once for each Python implementation enabled.
The command can also name a local function.
The commands are run with the following environment variables
set:
| Variable name |
Description |
Example value |
| EPYTHON |
The Python implementation name.
|
python2.7, pypy-c2.0
|
| PYTHON |
Absolute path to the Python interpreter.
|
/usr/bin/python2.7
|
| BUILD_DIR |
The ‘standard’ build directory path for the implementation.
|
${WORKDIR}/frobnicate-1.3-python2.7
|
Warning:
Please note that python_foreach_impl does not create
the BUILD_DIR automatically. Unless the build system
does so, the ebuild author is responsible for creating it.
|
Code Listing 4.1: Running commands for each enabled implementation |
src_install() {
sub_install() {
python_domodule "${BUILD_DIR}"/mymodule
}
python_foreach_impl sub_install
python_foreach_impl python_doscript mymodule-ui
}
|
5.
Eclasses for use of a single Python implementation
Introduction
The python‑r1 suite provides two eclasses for work with a single
Python implementation:
-
python-single-r1,
-
python-any-r1.
The python‑single‑r1 eclass is intended for packages where
the choice of the used Python implementation is made available
to the user. This group includes packages which install Python
modules or scripts specific to the chosen implementation.
The python‑any‑r1 eclass is intended for packages which
are not bound to a single Python implementation and its
selection, therefore, is unimportant. These are mostly
packages with build-time tools written in Python.
Both eclasses share the same core API being a superset of the core
python‑r1 API. It includes;
-
use of PYTHON_COMPAT to list supported Python
implementations,
-
setting of PYTHON_DEPS to a proper dependency string,
respecting PYTHON_REQ_USE,
-
export of pkg_setup() phase function which performs
the choice of Python implementation and exports
implementation-specific variables.
It should be noted that if the Python-related code in the ebuild
is conditional upon a USE flag, a proper USE-conditional need
be used around ${PYTHON_DEPS}
and the python-single-r1_pkg_setup
or python-any-r1_pkg_setup invocation need be used
conditionally.
Note:
The setting of active Python interpreter is done automatically
in the pkg_setup phase. Therefore, there is no need
for a function similar to python_set_active_version.
|
Code Listing 5.1: Example conditional use of python‑single‑r1 |
PYTHON_COMPAT=( python{2_6,2_7} )
inherit python-single-r1
IUSE="python"
RDEPEND="python? ( ${PYTHON_DEPS} )"
DEPEND=${RDEPEND}
pkg_setup() {
use python && python-single-r1_pkg_setup
}
|
python‑single‑r1
The python‑single‑r1 eclass, much alike python‑r1, provides
an explicit implementation choice with the help of USE flags.
However, in order not to collide with common setups enabling
multiple Python implementations, it uses a different variable —
PYTHON_SINGLE_TARGET.
The python-single-r1_pkg_setup phase function obtains
the value of PYTHON_SINGLE_TARGET and exports the default
set of variables specific to the chosen Python implementation.
python‑any‑r1
The python‑any‑r1 eclass performs an implicit choice of Python
implementation. It accepts any of the supported Python
interpreters (therefore using an any-of dependency
in PYTHON_DEPS), and chooses the best installed one.
The python-any-r1_pkg_setup phase function obtains
the best Python implementation installed. The choice algorithm
follows one used by python‑exec tool, that is in order:
-
the implementation specified in EPYTHON,
-
the implementation chosen by eselect‑python,
-
the default implementation preference.
6.
Helper functions in python‑utils‑r1 eclass
General notes
Note:
The functions listed in this section are directly available
to packages using any of the eclasses in python‑r1 suite, except
where noted otherwise.
|
Obtaining Python implementation information
Sometimes it is necessary to obtain information specific
to a particular Python implementations, in particular
interpreter-specific paths. The python‑utils‑r1 eclass
provides the following means of obtaining that information:
-
python_export function,
-
python_export_best function,
- getter functions.
The python_export and python_export_best functions
take an optional list of variable names and export
the requested variables. When no variable names are passed,
the default variable list is used.
The python_export function can additionally take a Python
implementation as a first argument, either in the form of a USE
flag or an EPYTHON value. If such a form is used,
the values specific to the passed implementation are exported.
Otherwise, the currently active implementation is used.
The python_export_best exports variables for the ‘best’
of the currently enabled implementations; that is, the newest
interpreter version from the most preferred group. These groups
are, in order of preference:
- CPython 2,
- CPython 3,
- PyPy,
- Jython.
Note:
The python_export_best function is available
in the python‑r1 eclass only. The python‑utils‑r1
eclass does not trace enabled implementations,
and python‑single‑r1 sets the only enabled implementation
as the current one, making direct python_export
sufficient.
|
The getter functions print the value of a specific property
to standard output. The output can be captured using bash
command substitution. These functions take an optional parameter
specifying the requested Python implementation.
If not specified, the implementation set as EPYTHON will
be used.
The following table lists all the available variables, along
with the respective getter functions:
| Variable name |
Getter function |
Default? |
Description |
| EPYTHON |
python_get_EPYTHON |
yes |
The Python implementation name (Gentoo-specific).
|
| PYTHON |
python_get_PYTHON |
yes |
Absolute path to the Python interpreter.
|
| PYTHON_SITEDIR |
python_get_sitedir |
no |
Path to the Python site-packages directory (where modules
should be installed).
|
Installing Python scripts and modules manually
The python‑utils‑r1 eclass provides two major helpers
which could be used to install Python scripts and modules
manually. They can be used whenever the build system
is not capable of installing them correctly, or the package
maintainer wishes to install additional files.
These functions are:
-
python_domodule,
-
python_doscript.
The python_domodule helper takes a list of file
and/or directory names and installs the named modules
and packages recursively. The files are installed
in the site-packages directory by default.
The destination can be changed through setting
the python_moduleroot variable or using
the python_moduleinto function. It can be either
an absolute path or relative to the site-packages root.
The installed modules will be byte-compiled using the currently
active Python implementation. The selected implementation
determines the site-packages location as well.
Code Listing 6.1: Installing Python modules and packages |
src_install() {
python_export python2_7 EPYTHON PYTHON PYTHON_SITEDIR
python_domodule mypackage
python_domodule epython.py
python_moduleinto foo
python_domodule bar.py
python_moduleinto /usr/lib/portage
python_domodule pym
local python_moduleroot
python_foreach_impl python_domodule mypackage
}
|
The python_doscript helper takes a list of script names
and installs them. The files are installed
in /usr/bin by default. The destination can
be changed through setting the python_scriptpath variable
or using the python_scriptinto function.
The installed scripts will be renamed to end
with an implementation-specific suffix specific to the currently
active Python interpreter. A wrapper will be linked in place
of the original name.
Code Listing 6.2: Installing Python scripts |
src_install() {
python_export python3_2 EPYTHON
python_doscript frobnicate
python_scriptinto /usr/sbin
python_doscript whyamihere
local python_scriptroot
python_foreach_impl python_doscript myscript
}
|
Compiling installed Python modules
There are a few packages which are able to install the Python
modules correctly but either do not compile them at all, or fail
to do it properly. For those packages, python_optimize
is the tool of choice.
The python_optimize function takes an optional list
of directory paths. If the list is provided, it compiles
all Python modules in the directories listed. Otherwise,
it compiles the modules installed into the standard module
install locations, including the site-packages
directory.
The modules are compiled using the currently active Python
implementation.
Code Listing 6.3: Compiling Python modules |
src_install() {
python_export python2_7 EPYTHON PYTHON
python_optimize "${D}"/usr/lib/portage/pym
python_foreach_impl python_optimize
}
|
The contents of this document, unless otherwise expressly stated, are
licensed under the CC-BY-SA-3.0 license. The Gentoo Name and Logo Usage Guidelines apply.
|