Gentoo Archives: gentoo-dev

From: "Michał Górny" <mgorny@g.o>
To: gentoo-dev@l.g.o
Cc: python@g.o, "Michał Górny" <mgorny@g.o>
Subject: [gentoo-dev] [PATCH 01/25] eclass: Copy python-r1 suite to python-r2
Date: Sat, 29 Feb 2020 20:42:55
Message-Id: 20200229204201.99290-2-mgorny@gentoo.org
In Reply to: [gentoo-dev] [PATCH 00/25] python-r2 eclass suite by "Michał Górny"
1 Signed-off-by: Michał Górny <mgorny@g.o>
2 ---
3 eclass/distutils-r2.eclass | 1198 ++++++++++++++++++++++++
4 eclass/python-any-r2.eclass | 357 ++++++++
5 eclass/python-r2.eclass | 825 +++++++++++++++++
6 eclass/python-single-r2.eclass | 507 +++++++++++
7 eclass/python-utils-r2.eclass | 1518 +++++++++++++++++++++++++++++++
8 eclass/tests/distutils-r2.sh | 98 ++
9 eclass/tests/python-utils-r2.sh | 237 +++++
10 7 files changed, 4740 insertions(+)
11 create mode 100644 eclass/distutils-r2.eclass
12 create mode 100644 eclass/python-any-r2.eclass
13 create mode 100644 eclass/python-r2.eclass
14 create mode 100644 eclass/python-single-r2.eclass
15 create mode 100644 eclass/python-utils-r2.eclass
16 create mode 100755 eclass/tests/distutils-r2.sh
17 create mode 100755 eclass/tests/python-utils-r2.sh
18
19 diff --git a/eclass/distutils-r2.eclass b/eclass/distutils-r2.eclass
20 new file mode 100644
21 index 000000000000..662bad3b9bcd
22 --- /dev/null
23 +++ b/eclass/distutils-r2.eclass
24 @@ -0,0 +1,1198 @@
25 +# Copyright 1999-2020 Gentoo Authors
26 +# Distributed under the terms of the GNU General Public License v2
27 +
28 +# @ECLASS: distutils-r2.eclass
29 +# @MAINTAINER:
30 +# Python team <python@g.o>
31 +# @AUTHOR:
32 +# Author: Michał Górny <mgorny@g.o>
33 +# @SUPPORTED_EAPIS: 5 6 7
34 +# @BLURB: A simple eclass to build Python packages using distutils.
35 +# @DESCRIPTION:
36 +# A simple eclass providing functions to build Python packages using
37 +# the distutils build system. It exports phase functions for all
38 +# the src_* phases. Each of the phases runs two pseudo-phases:
39 +# python_..._all() (e.g. python_prepare_all()) once in ${S}, then
40 +# python_...() (e.g. python_prepare()) for each implementation
41 +# (see: python_foreach_impl() in python-r2).
42 +#
43 +# In distutils-r2_src_prepare(), the 'all' function is run before
44 +# per-implementation ones (because it creates the implementations),
45 +# per-implementation functions are run in a random order.
46 +#
47 +# In remaining phase functions, the per-implementation functions are run
48 +# before the 'all' one, and they are ordered from the least to the most
49 +# preferred implementation (so that 'better' files overwrite 'worse'
50 +# ones).
51 +#
52 +# If the ebuild doesn't specify a particular pseudo-phase function,
53 +# the default one will be used (distutils-r2_...). Defaults are provided
54 +# for all per-implementation pseudo-phases, python_prepare_all()
55 +# and python_install_all(); whenever writing your own pseudo-phase
56 +# functions, you should consider calling the defaults (and especially
57 +# distutils-r2_python_prepare_all).
58 +#
59 +# Please note that distutils-r2 sets RDEPEND and DEPEND unconditionally
60 +# for you.
61 +#
62 +# Also, please note that distutils-r2 will always inherit python-r2
63 +# as well. Thus, all the variables defined and documented there are
64 +# relevant to the packages using distutils-r2.
65 +
66 +case "${EAPI:-0}" in
67 + 0|1|2|3|4)
68 + die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
69 + ;;
70 + 5|6|7)
71 + ;;
72 + *)
73 + die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
74 + ;;
75 +esac
76 +
77 +# @ECLASS-VARIABLE: DISTUTILS_OPTIONAL
78 +# @DEFAULT_UNSET
79 +# @DESCRIPTION:
80 +# If set to a non-null value, distutils part in the ebuild will
81 +# be considered optional. No dependencies will be added and no phase
82 +# functions will be exported.
83 +#
84 +# If you enable DISTUTILS_OPTIONAL, you have to set proper dependencies
85 +# for your package (using ${PYTHON_DEPS}) and to either call
86 +# distutils-r2 default phase functions or call the build system
87 +# manually.
88 +
89 +# @ECLASS-VARIABLE: DISTUTILS_SINGLE_IMPL
90 +# @DEFAULT_UNSET
91 +# @DESCRIPTION:
92 +# If set to a non-null value, the ebuild will support setting a single
93 +# Python implementation only. It will effectively replace the python-r2
94 +# eclass inherit with python-single-r2.
95 +#
96 +# Note that inheriting python-single-r2 will cause pkg_setup()
97 +# to be exported. It must be run in order for the eclass functions
98 +# to function properly.
99 +
100 +# @ECLASS-VARIABLE: DISTUTILS_USE_SETUPTOOLS
101 +# @PRE_INHERIT
102 +# @DESCRIPTION:
103 +# Controls adding dev-python/setuptools dependency. The allowed values
104 +# are:
105 +#
106 +# - no -- do not add the dependency (pure distutils package)
107 +# - bdepend -- add it to BDEPEND (the default)
108 +# - rdepend -- add it to BDEPEND+RDEPEND (when using entry_points)
109 +# - pyproject.toml -- use pyproject2setuptools to install a project
110 +# using pyproject.toml (flit, poetry...)
111 +# - manual -- do not add the depedency and suppress the checks
112 +# (assumes you will take care of doing it correctly)
113 +#
114 +# This variable is effective only if DISTUTILS_OPTIONAL is disabled.
115 +# It needs to be set before the inherit line.
116 +: ${DISTUTILS_USE_SETUPTOOLS:=bdepend}
117 +
118 +if [[ ! ${_DISTUTILS_R2} ]]; then
119 +
120 +[[ ${EAPI} == [456] ]] && inherit eutils
121 +[[ ${EAPI} == [56] ]] && inherit xdg-utils
122 +inherit multiprocessing toolchain-funcs
123 +
124 +if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
125 + inherit python-r2
126 +else
127 + inherit python-single-r2
128 +fi
129 +
130 +fi
131 +
132 +if [[ ! ${DISTUTILS_OPTIONAL} ]]; then
133 + EXPORT_FUNCTIONS src_prepare src_configure src_compile src_test src_install
134 +fi
135 +
136 +if [[ ! ${_DISTUTILS_R2} ]]; then
137 +
138 +_distutils_set_globals() {
139 + local rdep=${PYTHON_DEPS}
140 + local bdep=${rdep}
141 +
142 + if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
143 + local sdep="dev-python/setuptools[${PYTHON_USEDEP}]"
144 + else
145 + local sdep="$(python_gen_cond_dep '
146 + dev-python/setuptools[${PYTHON_MULTI_USEDEP}]
147 + ')"
148 + fi
149 +
150 + case ${DISTUTILS_USE_SETUPTOOLS} in
151 + no|manual)
152 + ;;
153 + bdepend)
154 + bdep+=" ${sdep}"
155 + ;;
156 + rdepend)
157 + bdep+=" ${sdep}"
158 + rdep+=" ${sdep}"
159 + ;;
160 + pyproject.toml)
161 + bdep+=" dev-python/pyproject2setuppy[${PYTHON_USEDEP}]"
162 + ;;
163 + *)
164 + die "Invalid DISTUTILS_USE_SETUPTOOLS=${DISTUTILS_USE_SETUPTOOLS}"
165 + ;;
166 + esac
167 +
168 + RDEPEND=${rdep}
169 + if [[ ${EAPI} != [56] ]]; then
170 + BDEPEND=${bdep}
171 + else
172 + DEPEND=${bdep}
173 + fi
174 + REQUIRED_USE=${PYTHON_REQUIRED_USE}
175 +}
176 +[[ ! ${DISTUTILS_OPTIONAL} ]] && _distutils_set_globals
177 +unset -f _distutils_set_globals
178 +
179 +# @ECLASS-VARIABLE: PATCHES
180 +# @DEFAULT_UNSET
181 +# @DESCRIPTION:
182 +# An array containing patches to be applied to the sources before
183 +# copying them.
184 +#
185 +# If unset, no custom patches will be applied.
186 +#
187 +# Please note, however, that at some point the eclass may apply
188 +# additional distutils patches/quirks independently of this variable.
189 +#
190 +# Example:
191 +# @CODE
192 +# PATCHES=( "${FILESDIR}"/${P}-make-gentoo-happy.patch )
193 +# @CODE
194 +
195 +# @ECLASS-VARIABLE: DOCS
196 +# @DEFAULT_UNSET
197 +# @DESCRIPTION:
198 +# An array containing documents installed using dodoc. The files listed
199 +# there must exist in the directory from which
200 +# distutils-r2_python_install_all() is run (${S} by default).
201 +#
202 +# If unset, the function will instead look up files matching default
203 +# filename pattern list (from the Package Manager Specification),
204 +# and install those found.
205 +#
206 +# Example:
207 +# @CODE
208 +# DOCS=( NEWS README )
209 +# @CODE
210 +
211 +# @ECLASS-VARIABLE: HTML_DOCS
212 +# @DEFAULT_UNSET
213 +# @DESCRIPTION:
214 +# An array containing documents installed using dohtml. The files
215 +# and directories listed there must exist in the directory from which
216 +# distutils-r2_python_install_all() is run (${S} by default).
217 +#
218 +# If unset, no HTML docs will be installed.
219 +#
220 +# Example:
221 +# @CODE
222 +# HTML_DOCS=( doc/html/. )
223 +# @CODE
224 +
225 +# @ECLASS-VARIABLE: EXAMPLES
226 +# @DEFAULT_UNSET
227 +# @DESCRIPTION:
228 +# OBSOLETE: this variable is deprecated and banned in EAPI 6
229 +#
230 +# An array containing examples installed into 'examples' doc
231 +# subdirectory. The files and directories listed there must exist
232 +# in the directory from which distutils-r2_python_install_all() is run
233 +# (${S} by default).
234 +#
235 +# The 'examples' subdirectory will be marked not to be compressed
236 +# automatically.
237 +#
238 +# If unset, no examples will be installed.
239 +#
240 +# Example:
241 +# @CODE
242 +# EXAMPLES=( examples/. demos/. )
243 +# @CODE
244 +
245 +# @ECLASS-VARIABLE: DISTUTILS_IN_SOURCE_BUILD
246 +# @DEFAULT_UNSET
247 +# @DESCRIPTION:
248 +# If set to a non-null value, in-source builds will be enabled.
249 +# If unset, the default is to use in-source builds when python_prepare()
250 +# is declared, and out-of-source builds otherwise.
251 +#
252 +# If in-source builds are used, the eclass will create a copy of package
253 +# sources for each Python implementation in python_prepare_all(),
254 +# and work on that copy afterwards.
255 +#
256 +# If out-of-source builds are used, the eclass will instead work
257 +# on the sources directly, prepending setup.py arguments with
258 +# 'build --build-base ${BUILD_DIR}' to enforce keeping & using built
259 +# files in the specific root.
260 +
261 +# @ECLASS-VARIABLE: DISTUTILS_ALL_SUBPHASE_IMPLS
262 +# @DEFAULT_UNSET
263 +# @DESCRIPTION:
264 +# An array of patterns specifying which implementations can be used
265 +# for *_all() sub-phase functions. If undefined, defaults to '*'
266 +# (allowing any implementation). If multiple values are specified,
267 +# implementations matching any of the patterns will be accepted.
268 +#
269 +# The patterns can be either fnmatch-style patterns (matched via bash
270 +# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
271 +# appropriately all enabled Python 2/3 implementations (alike
272 +# python_is_python3). Remember to escape or quote the fnmatch patterns
273 +# to prevent accidental shell filename expansion.
274 +#
275 +# If the restriction needs to apply conditionally to a USE flag,
276 +# the variable should be set conditionally as well (e.g. in an early
277 +# phase function or other convenient location).
278 +#
279 +# Please remember to add a matching || block to REQUIRED_USE,
280 +# to ensure that at least one implementation matching the patterns will
281 +# be enabled.
282 +#
283 +# Example:
284 +# @CODE
285 +# REQUIRED_USE="doc? ( || ( $(python_gen_useflags 'python2*') ) )"
286 +#
287 +# pkg_setup() {
288 +# use doc && DISTUTILS_ALL_SUBPHASE_IMPLS=( 'python2*' )
289 +# }
290 +# @CODE
291 +
292 +# @ECLASS-VARIABLE: mydistutilsargs
293 +# @DEFAULT_UNSET
294 +# @DESCRIPTION:
295 +# An array containing options to be passed to setup.py.
296 +#
297 +# Example:
298 +# @CODE
299 +# python_configure_all() {
300 +# mydistutilsargs=( --enable-my-hidden-option )
301 +# }
302 +# @CODE
303 +
304 +# @FUNCTION: distutils_enable_sphinx
305 +# @USAGE: <subdir> [--no-autodoc | <plugin-pkgs>...]
306 +# @DESCRIPTION:
307 +# Set up IUSE, BDEPEND, python_check_deps() and python_compile_all() for
308 +# building HTML docs via dev-python/sphinx. python_compile_all() will
309 +# append to HTML_DOCS if docs are enabled.
310 +#
311 +# This helper is meant for the most common case, that is a single Sphinx
312 +# subdirectory with standard layout, building and installing HTML docs
313 +# behind USE=doc. It assumes it's the only consumer of the three
314 +# aforementioned functions. If you need to use a custom implemention,
315 +# you can't use it.
316 +#
317 +# If your package uses additional Sphinx plugins, they should be passed
318 +# (without PYTHON_USEDEP) as <plugin-pkgs>. The function will take care
319 +# of setting appropriate any-of dep and python_check_deps().
320 +#
321 +# If no plugin packages are specified, the eclass will still utilize
322 +# any-r2 API to support autodoc (documenting source code).
323 +# If the package uses neither autodoc nor additional plugins, you should
324 +# pass --no-autodoc to disable this API and simplify the resulting code.
325 +#
326 +# This function must be called in global scope. Take care not to
327 +# overwrite the variables set by it. If you need to extend
328 +# python_compile_all(), you can call the original implementation
329 +# as sphinx_compile_all.
330 +distutils_enable_sphinx() {
331 + debug-print-function ${FUNCNAME} "${@}"
332 + [[ ${#} -ge 1 ]] || die "${FUNCNAME} takes at least one arg: <subdir>"
333 +
334 + _DISTUTILS_SPHINX_SUBDIR=${1}
335 + shift
336 + _DISTUTILS_SPHINX_PLUGINS=( "${@}" )
337 +
338 + local deps autodoc=1 d
339 + for d; do
340 + if [[ ${d} == --no-autodoc ]]; then
341 + autodoc=
342 + else
343 + deps+="
344 + ${d}[\${PYTHON_USEDEP}]"
345 + fi
346 + done
347 +
348 + if [[ ! ${autodoc} && -n ${deps} ]]; then
349 + die "${FUNCNAME}: do not pass --no-autodoc if external plugins are used"
350 + fi
351 + if [[ ${autodoc} ]]; then
352 + deps="$(python_gen_any_dep "
353 + dev-python/sphinx[\${PYTHON_USEDEP}]
354 + ${deps}")"
355 +
356 + python_check_deps() {
357 + use doc || return 0
358 + local p
359 + for p in dev-python/sphinx "${_DISTUTILS_SPHINX_PLUGINS[@]}"; do
360 + has_version "${p}[${PYTHON_USEDEP}]" || return 1
361 + done
362 + }
363 + else
364 + deps="dev-python/sphinx"
365 + fi
366 +
367 + sphinx_compile_all() {
368 + use doc || return
369 +
370 + local confpy=${_DISTUTILS_SPHINX_SUBDIR}/conf.py
371 + [[ -f ${confpy} ]] ||
372 + die "${confpy} not found, distutils_enable_sphinx call wrong"
373 +
374 + if [[ ${_DISTUTILS_SPHINX_PLUGINS[0]} == --no-autodoc ]]; then
375 + if grep -F -q 'sphinx.ext.autodoc' "${confpy}"; then
376 + die "distutils_enable_sphinx: --no-autodoc passed but sphinx.ext.autodoc found in ${confpy}"
377 + fi
378 + else
379 + if ! grep -F -q 'sphinx.ext.autodoc' "${confpy}"; then
380 + die "distutils_enable_sphinx: sphinx.ext.autodoc not found in ${confpy}, pass --no-autodoc"
381 + fi
382 + fi
383 +
384 + build_sphinx "${_DISTUTILS_SPHINX_SUBDIR}"
385 + }
386 + python_compile_all() { sphinx_compile_all; }
387 +
388 + IUSE+=" doc"
389 + if [[ ${EAPI} == [56] ]]; then
390 + DEPEND+=" doc? ( ${deps} )"
391 + else
392 + BDEPEND+=" doc? ( ${deps} )"
393 + fi
394 +
395 + # we need to ensure successful return in case we're called last,
396 + # otherwise Portage may wrongly assume sourcing failed
397 + return 0
398 +}
399 +
400 +# @FUNCTION: distutils_enable_tests
401 +# @USAGE: <test-runner>
402 +# @DESCRIPTION:
403 +# Set up IUSE, RESTRICT, BDEPEND and python_test() for running tests
404 +# with the specified test runner. Also copies the current value
405 +# of RDEPEND to test?-BDEPEND. The test-runner argument must be one of:
406 +#
407 +# - nose: nosetests (dev-python/nose)
408 +# - pytest: dev-python/pytest
409 +# - setup.py: setup.py test (no deps included)
410 +# - unittest: for built-in Python unittest module
411 +#
412 +# This function is meant as a helper for common use cases, and it only
413 +# takes care of basic setup. You still need to list additional test
414 +# dependencies manually. If you have uncommon use case, you should
415 +# not use it and instead enable tests manually.
416 +#
417 +# This function must be called in global scope, after RDEPEND has been
418 +# declared. Take care not to overwrite the variables set by it.
419 +distutils_enable_tests() {
420 + debug-print-function ${FUNCNAME} "${@}"
421 + [[ ${#} -eq 1 ]] || die "${FUNCNAME} takes exactly one argument: test-runner"
422 +
423 + local test_pkg
424 + case ${1} in
425 + nose)
426 + test_pkg="dev-python/nose"
427 + python_test() {
428 + nosetests -v || die "Tests fail with ${EPYTHON}"
429 + }
430 + ;;
431 + pytest)
432 + test_pkg="dev-python/pytest"
433 + python_test() {
434 + pytest -vv || die "Tests fail with ${EPYTHON}"
435 + }
436 + ;;
437 + setup.py)
438 + python_test() {
439 + esetup.py test --verbose
440 + }
441 + ;;
442 + unittest)
443 + python_test() {
444 + "${EPYTHON}" -m unittest discover -v ||
445 + die "Tests fail with ${EPYTHON}"
446 + }
447 + ;;
448 + *)
449 + die "${FUNCNAME}: unsupported argument: ${1}"
450 + esac
451 +
452 + local test_deps=${RDEPEND}
453 + if [[ -n ${test_pkg} ]]; then
454 + if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
455 + test_deps+=" ${test_pkg}[${PYTHON_USEDEP}]"
456 + else
457 + test_deps+=" $(python_gen_cond_dep "
458 + ${test_pkg}[\${PYTHON_MULTI_USEDEP}]
459 + ")"
460 + fi
461 + fi
462 + if [[ -n ${test_deps} ]]; then
463 + IUSE+=" test"
464 + RESTRICT+=" !test? ( test )"
465 + if [[ ${EAPI} == [56] ]]; then
466 + DEPEND+=" test? ( ${test_deps} )"
467 + else
468 + BDEPEND+=" test? ( ${test_deps} )"
469 + fi
470 + fi
471 +
472 + # we need to ensure successful return in case we're called last,
473 + # otherwise Portage may wrongly assume sourcing failed
474 + return 0
475 +}
476 +
477 +# @FUNCTION: _distutils-r2_verify_use_setuptools
478 +# @INTERNAL
479 +# @DESCRIPTION:
480 +# Check setup.py for signs that DISTUTILS_USE_SETUPTOOLS have been set
481 +# incorrectly.
482 +_distutils_verify_use_setuptools() {
483 + [[ ${DISTUTILS_OPTIONAL} ]] && return
484 + [[ ${DISTUTILS_USE_SETUPTOOLS} == manual ]] && return
485 + [[ ${DISTUTILS_USE_SETUPTOOLS} == pyproject.toml ]] && return
486 +
487 + # ok, those are cheap greps. we can try toimprove them if we hit
488 + # false positives.
489 + local expected=no
490 + if [[ ${CATEGORY}/${PN} == dev-python/setuptools ]]; then
491 + # as a special case, setuptools provides itself ;-)
492 + :
493 + elif grep -E -q -s '(from|import)\s+setuptools' setup.py; then
494 + if grep -E -q -s 'entry_points\s*=' setup.py; then
495 + expected=rdepend
496 + elif grep -F -q -s '[options.entry_points]' setup.cfg; then
497 + expected=rdepend
498 + else
499 + expected=bdepend
500 + fi
501 + fi
502 +
503 + if [[ ${DISTUTILS_USE_SETUPTOOLS} != ${expected} ]]; then
504 + if [[ ! ${_DISTUTILS_SETUPTOOLS_WARNED} ]]; then
505 + _DISTUTILS_SETUPTOOLS_WARNED=1
506 + local def=
507 + [[ ${DISTUTILS_USE_SETUPTOOLS} == bdepend ]] && def=' (default?)'
508 +
509 + eqawarn "DISTUTILS_USE_SETUPTOOLS value is probably incorrect"
510 + eqawarn " value: DISTUTILS_USE_SETUPTOOLS=${DISTUTILS_USE_SETUPTOOLS}${def}"
511 + eqawarn " expected: DISTUTILS_USE_SETUPTOOLS=${expected}"
512 + fi
513 + fi
514 +}
515 +
516 +# @FUNCTION: esetup.py
517 +# @USAGE: [<args>...]
518 +# @DESCRIPTION:
519 +# Run setup.py using currently selected Python interpreter
520 +# (if ${EPYTHON} is set; fallback 'python' otherwise).
521 +#
522 +# setup.py will be passed the following, in order:
523 +# 1. ${mydistutilsargs[@]}
524 +# 2. additional arguments passed to the esetup.py function.
525 +#
526 +# Please note that setup.py will respect defaults (unless overridden
527 +# via command-line options) from setup.cfg that is created
528 +# in distutils-r2_python_compile and in distutils-r2_python_install.
529 +#
530 +# This command dies on failure.
531 +esetup.py() {
532 + debug-print-function ${FUNCNAME} "${@}"
533 +
534 + local die_args=()
535 + [[ ${EAPI} != [45] ]] && die_args+=( -n )
536 +
537 + [[ ${BUILD_DIR} ]] && _distutils-r2_create_setup_cfg
538 + _distutils_verify_use_setuptools
539 +
540 + set -- "${EPYTHON:-python}" setup.py "${mydistutilsargs[@]}" "${@}"
541 +
542 + echo "${@}" >&2
543 + "${@}" || die "${die_args[@]}"
544 + local ret=${?}
545 +
546 + if [[ ${BUILD_DIR} ]]; then
547 + rm "${HOME}"/.pydistutils.cfg || die "${die_args[@]}"
548 + fi
549 +
550 + return ${ret}
551 +}
552 +
553 +# @FUNCTION: distutils_install_for_testing
554 +# @USAGE: [<args>...]
555 +# @DESCRIPTION:
556 +# Install the package into a temporary location for running tests.
557 +# Update PYTHONPATH appropriately and set TEST_DIR to the test
558 +# installation root. The Python packages will be installed in 'lib'
559 +# subdir, and scripts in 'scripts' subdir (like in BUILD_DIR).
560 +#
561 +# Please note that this function should be only used if package uses
562 +# namespaces (and therefore proper install needs to be done to enforce
563 +# PYTHONPATH) or tests rely on the results of install command.
564 +# For most of the packages, tests built in BUILD_DIR are good enough.
565 +distutils_install_for_testing() {
566 + debug-print-function ${FUNCNAME} "${@}"
567 +
568 + # A few notes:
569 + # 1) because of namespaces, we can't use 'install --root',
570 + # 2) 'install --home' is terribly broken on pypy, so we need
571 + # to override --install-lib and --install-scripts,
572 + # 3) non-root 'install' complains about PYTHONPATH and missing dirs,
573 + # so we need to set it properly and mkdir them,
574 + # 4) it runs a bunch of commands which write random files to cwd,
575 + # in order to avoid that, we add the necessary path overrides
576 + # in _distutils-r2_create_setup_cfg.
577 +
578 + TEST_DIR=${BUILD_DIR}/test
579 + local bindir=${TEST_DIR}/scripts
580 + local libdir=${TEST_DIR}/lib
581 + PYTHONPATH=${libdir}:${PYTHONPATH}
582 +
583 + local add_args=(
584 + install
585 + --home="${TEST_DIR}"
586 + --install-lib="${libdir}"
587 + --install-scripts="${bindir}"
588 + )
589 +
590 + mkdir -p "${libdir}" || die
591 + esetup.py "${add_args[@]}" "${@}"
592 +}
593 +
594 +# @FUNCTION: _distutils-r2_disable_ez_setup
595 +# @INTERNAL
596 +# @DESCRIPTION:
597 +# Stub out ez_setup.py and distribute_setup.py to prevent packages
598 +# from trying to download a local copy of setuptools.
599 +_distutils-r2_disable_ez_setup() {
600 + local stub="def use_setuptools(*args, **kwargs): pass"
601 + if [[ -f ez_setup.py ]]; then
602 + echo "${stub}" > ez_setup.py || die
603 + fi
604 + if [[ -f distribute_setup.py ]]; then
605 + echo "${stub}" > distribute_setup.py || die
606 + fi
607 +}
608 +
609 +# @FUNCTION: _distutils-r2_handle_pyproject_toml
610 +# @INTERNAL
611 +# @DESCRIPTION:
612 +# Generate setup.py for pyproject.toml if requested.
613 +_distutils-r2_handle_pyproject_toml() {
614 + if [[ ! -f setup.py && -f pyproject.toml ]]; then
615 + if [[ ${DISTUTILS_USE_SETUPTOOLS} == pyproject.toml ]]; then
616 + cat > setup.py <<-EOF || die
617 + #!/usr/bin/env python
618 + from pyproject2setuppy.main import main
619 + main()
620 + EOF
621 + chmod +x setup.py || die
622 + else
623 + eerror "No setup.py found but pyproject.toml is present. In order to enable"
624 + eerror "pyproject.toml support in distutils-r2, set:"
625 + eerror " DISTUTILS_USE_SETUPTOOLS=pyproject.toml"
626 + die "No setup.py found and DISTUTILS_USE_SETUPTOOLS!=pyproject.toml"
627 + fi
628 + fi
629 +}
630 +
631 +# @FUNCTION: distutils-r2_python_prepare_all
632 +# @DESCRIPTION:
633 +# The default python_prepare_all(). It applies the patches from PATCHES
634 +# array, then user patches and finally calls python_copy_sources to
635 +# create copies of resulting sources for each Python implementation.
636 +#
637 +# At some point in the future, it may also apply eclass-specific
638 +# distutils patches and/or quirks.
639 +distutils-r2_python_prepare_all() {
640 + debug-print-function ${FUNCNAME} "${@}"
641 +
642 + if [[ ! ${DISTUTILS_OPTIONAL} ]]; then
643 + if [[ ${EAPI} != [45] ]]; then
644 + default
645 + else
646 + [[ ${PATCHES} ]] && epatch "${PATCHES[@]}"
647 + epatch_user
648 + fi
649 + fi
650 +
651 + # by default, use in-source build if python_prepare() is used
652 + if [[ ! ${DISTUTILS_IN_SOURCE_BUILD+1} ]]; then
653 + if declare -f python_prepare >/dev/null; then
654 + DISTUTILS_IN_SOURCE_BUILD=1
655 + fi
656 + fi
657 +
658 + _distutils-r2_disable_ez_setup
659 + _distutils-r2_handle_pyproject_toml
660 +
661 + if [[ ${DISTUTILS_IN_SOURCE_BUILD} && ! ${DISTUTILS_SINGLE_IMPL} ]]
662 + then
663 + # create source copies for each implementation
664 + python_copy_sources
665 + fi
666 +
667 + _DISTUTILS_DEFAULT_CALLED=1
668 +}
669 +
670 +# @FUNCTION: distutils-r2_python_prepare
671 +# @DESCRIPTION:
672 +# The default python_prepare(). A no-op.
673 +distutils-r2_python_prepare() {
674 + debug-print-function ${FUNCNAME} "${@}"
675 +
676 + [[ ${EAPI} == [45] ]] || die "${FUNCNAME} is banned in EAPI 6 (it was a no-op)"
677 +}
678 +
679 +# @FUNCTION: distutils-r2_python_configure
680 +# @DESCRIPTION:
681 +# The default python_configure(). A no-op.
682 +distutils-r2_python_configure() {
683 + debug-print-function ${FUNCNAME} "${@}"
684 +
685 + [[ ${EAPI} == [45] ]] || die "${FUNCNAME} is banned in EAPI 6 (it was a no-op)"
686 +}
687 +
688 +# @FUNCTION: _distutils-r2_create_setup_cfg
689 +# @INTERNAL
690 +# @DESCRIPTION:
691 +# Create implementation-specific configuration file for distutils,
692 +# setting proper build-dir (and install-dir) paths.
693 +_distutils-r2_create_setup_cfg() {
694 + cat > "${HOME}"/.pydistutils.cfg <<-_EOF_ || die
695 + [build]
696 + build-base = ${BUILD_DIR}
697 +
698 + # using a single directory for them helps us export
699 + # ${PYTHONPATH} and ebuilds find the sources independently
700 + # of whether the package installs extensions or not
701 + #
702 + # note: due to some packages (wxpython) relying on separate
703 + # platlib & purelib dirs, we do not set --build-lib (which
704 + # can not be overridden with --build-*lib)
705 + build-platlib = %(build-base)s/lib
706 + build-purelib = %(build-base)s/lib
707 +
708 + # make the ebuild writer lives easier
709 + build-scripts = %(build-base)s/scripts
710 +
711 + # this is needed by distutils_install_for_testing since
712 + # setuptools like to create .egg files for install --home.
713 + [bdist_egg]
714 + dist-dir = ${BUILD_DIR}/dist
715 + _EOF_
716 +
717 + # we can't refer to ${D} before src_install()
718 + if [[ ${EBUILD_PHASE} == install ]]; then
719 + cat >> "${HOME}"/.pydistutils.cfg <<-_EOF_ || die
720 +
721 + # installation paths -- allow calling extra install targets
722 + # without the default 'install'
723 + [install]
724 + compile = True
725 + optimize = 2
726 + root = ${D%/}
727 + _EOF_
728 +
729 + if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
730 + cat >> "${HOME}"/.pydistutils.cfg <<-_EOF_ || die
731 + install-scripts = $(python_get_scriptdir)
732 + _EOF_
733 + fi
734 + fi
735 +}
736 +
737 +# @FUNCTION: _distutils-r2_copy_egg_info
738 +# @INTERNAL
739 +# @DESCRIPTION:
740 +# Copy egg-info files to the ${BUILD_DIR} (that's going to become
741 +# egg-base in esetup.py). This way, we respect whatever's in upstream
742 +# egg-info.
743 +_distutils-r2_copy_egg_info() {
744 + mkdir -p "${BUILD_DIR}" || die
745 + # stupid freebsd can't do 'cp -t ${BUILD_DIR} {} +'
746 + find -name '*.egg-info' -type d -exec cp -R -p {} "${BUILD_DIR}"/ ';' || die
747 +}
748 +
749 +# @FUNCTION: distutils-r2_python_compile
750 +# @USAGE: [additional-args...]
751 +# @DESCRIPTION:
752 +# The default python_compile(). Runs 'esetup.py build'. Any parameters
753 +# passed to this function will be appended to setup.py invocation,
754 +# i.e. passed as options to the 'build' command.
755 +#
756 +# This phase also sets up initial setup.cfg with build directories
757 +# and copies upstream egg-info files if supplied.
758 +distutils-r2_python_compile() {
759 + debug-print-function ${FUNCNAME} "${@}"
760 +
761 + _distutils-r2_copy_egg_info
762 +
763 + local build_args=()
764 + # distutils is parallel-capable since py3.5
765 + # to avoid breaking stable ebuilds, enable it only if either:
766 + # a. we're dealing with EAPI 7
767 + # b. we're dealing with Python 3.7 or PyPy3
768 + if python_is_python3 && [[ ${EPYTHON} != python3.4 ]]; then
769 + if [[ ${EAPI} != [56] || ${EPYTHON} != python3.[56] ]]; then
770 + local jobs=$(makeopts_jobs "${MAKEOPTS}" INF)
771 + if [[ ${jobs} == INF ]]; then
772 + local nproc=$(get_nproc)
773 + jobs=$(( nproc + 1 ))
774 + fi
775 + build_args+=( -j "${jobs}" )
776 + fi
777 + fi
778 +
779 + esetup.py build "${build_args[@]}" "${@}"
780 +}
781 +
782 +# @FUNCTION: _distutils-r2_wrap_scripts
783 +# @USAGE: <path> <bindir>
784 +# @INTERNAL
785 +# @DESCRIPTION:
786 +# Moves and wraps all installed scripts/executables as necessary.
787 +_distutils-r2_wrap_scripts() {
788 + debug-print-function ${FUNCNAME} "${@}"
789 +
790 + [[ ${#} -eq 2 ]] || die "usage: ${FUNCNAME} <path> <bindir>"
791 + local path=${1}
792 + local bindir=${2}
793 +
794 + local PYTHON_SCRIPTDIR
795 + python_export PYTHON_SCRIPTDIR
796 +
797 + local f python_files=() non_python_files=()
798 +
799 + if [[ -d ${path}${PYTHON_SCRIPTDIR} ]]; then
800 + for f in "${path}${PYTHON_SCRIPTDIR}"/*; do
801 + [[ -d ${f} ]] && die "Unexpected directory: ${f}"
802 + debug-print "${FUNCNAME}: found executable at ${f#${path}/}"
803 +
804 + local shebang
805 + read -r shebang < "${f}"
806 + if [[ ${shebang} == '#!'*${EPYTHON}* ]]; then
807 + debug-print "${FUNCNAME}: matching shebang: ${shebang}"
808 + python_files+=( "${f}" )
809 + else
810 + debug-print "${FUNCNAME}: non-matching shebang: ${shebang}"
811 + non_python_files+=( "${f}" )
812 + fi
813 +
814 + mkdir -p "${path}${bindir}" || die
815 + done
816 +
817 + for f in "${python_files[@]}"; do
818 + local basename=${f##*/}
819 +
820 + debug-print "${FUNCNAME}: installing wrapper at ${bindir}/${basename}"
821 + _python_ln_rel "${path}${EPREFIX}"/usr/lib/python-exec/python-exec2 \
822 + "${path}${bindir}/${basename}" || die
823 + done
824 +
825 + for f in "${non_python_files[@]}"; do
826 + local basename=${f##*/}
827 +
828 + debug-print "${FUNCNAME}: moving ${f#${path}/} to ${bindir}/${basename}"
829 + mv "${f}" "${path}${bindir}/${basename}" || die
830 + done
831 + fi
832 +}
833 +
834 +# @FUNCTION: distutils-r2_python_install
835 +# @USAGE: [additional-args...]
836 +# @DESCRIPTION:
837 +# The default python_install(). Runs 'esetup.py install', doing
838 +# intermediate root install and handling script wrapping afterwards.
839 +# Any parameters passed to this function will be appended
840 +# to the setup.py invocation (i.e. as options to the 'install' command).
841 +#
842 +# This phase updates the setup.cfg file with install directories.
843 +distutils-r2_python_install() {
844 + debug-print-function ${FUNCNAME} "${@}"
845 +
846 + local args=( "${@}" )
847 +
848 + # enable compilation for the install phase.
849 + local -x PYTHONDONTWRITEBYTECODE=
850 +
851 + # python likes to compile any module it sees, which triggers sandbox
852 + # failures if some packages haven't compiled their modules yet.
853 + addpredict "${EPREFIX}/usr/lib/${EPYTHON}"
854 + addpredict "${EPREFIX}/usr/$(get_libdir)/${EPYTHON}"
855 + addpredict /usr/lib/pypy2.7
856 + addpredict /usr/lib/pypy3.6
857 + addpredict /usr/lib/portage/pym
858 + addpredict /usr/local # bug 498232
859 +
860 + if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
861 + # user may override --install-scripts
862 + # note: this is poor but distutils argv parsing is dumb
863 + local mydistutilsargs=( "${mydistutilsargs[@]}" )
864 + local scriptdir=${EPREFIX}/usr/bin
865 +
866 + # construct a list of mydistutilsargs[0] args[0] args[1]...
867 + local arg arg_vars
868 + [[ ${mydistutilsargs[@]} ]] && eval arg_vars+=(
869 + 'mydistutilsargs['{0..$(( ${#mydistutilsargs[@]} - 1 ))}']'
870 + )
871 + [[ ${args[@]} ]] && eval arg_vars+=(
872 + 'args['{0..$(( ${#args[@]} - 1 ))}']'
873 + )
874 +
875 + set -- "${arg_vars[@]}"
876 + while [[ ${@} ]]; do
877 + local arg_var=${1}
878 + shift
879 + local a=${!arg_var}
880 +
881 + case "${a}" in
882 + --install-scripts=*)
883 + scriptdir=${a#--install-scripts=}
884 + unset "${arg_var}"
885 + ;;
886 + --install-scripts)
887 + scriptdir=${!1}
888 + unset "${arg_var}" "${1}"
889 + shift
890 + ;;
891 + esac
892 + done
893 + fi
894 +
895 + local root=${D%/}/_${EPYTHON}
896 + [[ ${DISTUTILS_SINGLE_IMPL} ]] && root=${D%/}
897 +
898 + esetup.py install --root="${root}" "${args[@]}"
899 +
900 + local forbidden_package_names=( examples test tests .pytest_cache )
901 + local p
902 + for p in "${forbidden_package_names[@]}"; do
903 + if [[ -d ${root}$(python_get_sitedir)/${p} ]]; then
904 + die "Package installs '${p}' package which is forbidden and likely a bug in the build system."
905 + fi
906 + done
907 +
908 + local shopt_save=$(shopt -p nullglob)
909 + shopt -s nullglob
910 + local pypy_dirs=(
911 + "${root}/usr/$(get_libdir)"/pypy*/share
912 + "${root}/usr/lib"/pypy*/share
913 + )
914 + ${shopt_save}
915 +
916 + if [[ -n ${pypy_dirs} ]]; then
917 + local cmd=die
918 + [[ ${EAPI} == [45] ]] && cmd=eqawarn
919 + "${cmd}" "Package installs 'share' in PyPy prefix, see bug #465546."
920 + fi
921 +
922 + if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
923 + _distutils-r2_wrap_scripts "${root}" "${scriptdir}"
924 + multibuild_merge_root "${root}" "${D%/}"
925 + fi
926 +}
927 +
928 +# @FUNCTION: distutils-r2_python_install_all
929 +# @DESCRIPTION:
930 +# The default python_install_all(). It installs the documentation.
931 +distutils-r2_python_install_all() {
932 + debug-print-function ${FUNCNAME} "${@}"
933 +
934 + einstalldocs
935 +
936 + if declare -p EXAMPLES &>/dev/null; then
937 + [[ ${EAPI} != [45] ]] && die "EXAMPLES are banned in EAPI ${EAPI}"
938 +
939 + (
940 + docinto examples
941 + dodoc -r "${EXAMPLES[@]}"
942 + )
943 + docompress -x "/usr/share/doc/${PF}/examples"
944 + fi
945 +
946 + _DISTUTILS_DEFAULT_CALLED=1
947 +}
948 +
949 +# @FUNCTION: distutils-r2_run_phase
950 +# @USAGE: [<argv>...]
951 +# @INTERNAL
952 +# @DESCRIPTION:
953 +# Run the given command.
954 +#
955 +# If out-of-source builds are used, the phase function is run in source
956 +# directory, with BUILD_DIR pointing at the build directory
957 +# and PYTHONPATH having an entry for the module build directory.
958 +#
959 +# If in-source builds are used, the command is executed in the directory
960 +# holding the per-implementation copy of sources. BUILD_DIR points
961 +# to the 'build' subdirectory.
962 +distutils-r2_run_phase() {
963 + debug-print-function ${FUNCNAME} "${@}"
964 +
965 + if [[ ${DISTUTILS_IN_SOURCE_BUILD} ]]; then
966 + # only force BUILD_DIR if implementation is explicitly enabled
967 + # for building; any-r2 API may select one that is not
968 + # https://bugs.gentoo.org/701506
969 + if [[ ! ${DISTUTILS_SINGLE_IMPL} ]] &&
970 + has "${EPYTHON/./_}" ${PYTHON_TARGETS}; then
971 + cd "${BUILD_DIR}" || die
972 + fi
973 + local BUILD_DIR=${BUILD_DIR}/build
974 + fi
975 + local -x PYTHONPATH="${BUILD_DIR}/lib:${PYTHONPATH}"
976 +
977 + # Bug 559644
978 + # using PYTHONPATH when the ${BUILD_DIR}/lib is not created yet might lead to
979 + # problems in setup.py scripts that try to import modules/packages from that path
980 + # during the build process (Python at startup evaluates PYTHONPATH, if the dir is
981 + # not valid then associates a NullImporter object to ${BUILD_DIR}/lib storing it
982 + # in the sys.path_importer_cache)
983 + mkdir -p "${BUILD_DIR}/lib" || die
984 +
985 + # Set up build environment, bug #513664.
986 + local -x AR=${AR} CC=${CC} CPP=${CPP} CXX=${CXX}
987 + tc-export AR CC CPP CXX
988 +
989 + # How to build Python modules in different worlds...
990 + local ldopts
991 + case "${CHOST}" in
992 + # provided by haubi, 2014-07-08
993 + *-aix*) ldopts='-shared -Wl,-berok';; # good enough
994 + # provided by grobian, 2014-06-22, bug #513664 c7
995 + *-darwin*) ldopts='-bundle -undefined dynamic_lookup';;
996 + *) ldopts='-shared';;
997 + esac
998 +
999 + local -x LDSHARED="${CC} ${ldopts}" LDCXXSHARED="${CXX} ${ldopts}"
1000 +
1001 + "${@}"
1002 +
1003 + cd "${_DISTUTILS_INITIAL_CWD}" || die
1004 +}
1005 +
1006 +# @FUNCTION: _distutils-r2_run_common_phase
1007 +# @USAGE: [<argv>...]
1008 +# @INTERNAL
1009 +# @DESCRIPTION:
1010 +# Run the given command, restoring the state for a most preferred Python
1011 +# implementation matching DISTUTILS_ALL_SUBPHASE_IMPLS.
1012 +#
1013 +# If in-source build is used, the command will be run in the copy
1014 +# of sources made for the selected Python interpreter.
1015 +_distutils-r2_run_common_phase() {
1016 + local DISTUTILS_ORIG_BUILD_DIR=${BUILD_DIR}
1017 +
1018 + if [[ ${DISTUTILS_SINGLE_IMPL} ]]; then
1019 + # reuse the dedicated code branch
1020 + _distutils-r2_run_foreach_impl "${@}"
1021 + else
1022 + local -x EPYTHON PYTHON
1023 + local -x PATH=${PATH} PKG_CONFIG_PATH=${PKG_CONFIG_PATH}
1024 + python_setup "${DISTUTILS_ALL_SUBPHASE_IMPLS[@]}"
1025 +
1026 + local MULTIBUILD_VARIANTS=( "${EPYTHON/./_}" )
1027 + # store for restoring after distutils-r2_run_phase.
1028 + local _DISTUTILS_INITIAL_CWD=${PWD}
1029 + multibuild_foreach_variant \
1030 + distutils-r2_run_phase "${@}"
1031 + fi
1032 +}
1033 +
1034 +# @FUNCTION: _distutils-r2_run_foreach_impl
1035 +# @INTERNAL
1036 +# @DESCRIPTION:
1037 +# Run the given phase for each implementation if multiple implementations
1038 +# are enabled, once otherwise.
1039 +_distutils-r2_run_foreach_impl() {
1040 + debug-print-function ${FUNCNAME} "${@}"
1041 +
1042 + # store for restoring after distutils-r2_run_phase.
1043 + local _DISTUTILS_INITIAL_CWD=${PWD}
1044 + set -- distutils-r2_run_phase "${@}"
1045 +
1046 + if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
1047 + python_foreach_impl "${@}"
1048 + else
1049 + if [[ ! ${EPYTHON} ]]; then
1050 + die "EPYTHON unset, python-single-r2_pkg_setup not called?!"
1051 + fi
1052 + local BUILD_DIR=${BUILD_DIR:-${S}}
1053 + BUILD_DIR=${BUILD_DIR%%/}_${EPYTHON}
1054 +
1055 + "${@}"
1056 + fi
1057 +}
1058 +
1059 +distutils-r2_src_prepare() {
1060 + debug-print-function ${FUNCNAME} "${@}"
1061 +
1062 + local _DISTUTILS_DEFAULT_CALLED
1063 +
1064 + # common preparations
1065 + if declare -f python_prepare_all >/dev/null; then
1066 + python_prepare_all
1067 + else
1068 + distutils-r2_python_prepare_all
1069 + fi
1070 +
1071 + if [[ ! ${_DISTUTILS_DEFAULT_CALLED} ]]; then
1072 + local cmd=die
1073 + [[ ${EAPI} == [45] ]] && cmd=eqawarn
1074 +
1075 + "${cmd}" "QA: python_prepare_all() didn't call distutils-r2_python_prepare_all"
1076 + fi
1077 +
1078 + if declare -f python_prepare >/dev/null; then
1079 + _distutils-r2_run_foreach_impl python_prepare
1080 + fi
1081 +}
1082 +
1083 +distutils-r2_src_configure() {
1084 + python_export_utf8_locale
1085 + [[ ${EAPI} == [56] ]] && xdg_environment_reset # Bug 577704
1086 +
1087 + if declare -f python_configure >/dev/null; then
1088 + _distutils-r2_run_foreach_impl python_configure
1089 + fi
1090 +
1091 + if declare -f python_configure_all >/dev/null; then
1092 + _distutils-r2_run_common_phase python_configure_all
1093 + fi
1094 +}
1095 +
1096 +distutils-r2_src_compile() {
1097 + debug-print-function ${FUNCNAME} "${@}"
1098 +
1099 + if declare -f python_compile >/dev/null; then
1100 + _distutils-r2_run_foreach_impl python_compile
1101 + else
1102 + _distutils-r2_run_foreach_impl distutils-r2_python_compile
1103 + fi
1104 +
1105 + if declare -f python_compile_all >/dev/null; then
1106 + _distutils-r2_run_common_phase python_compile_all
1107 + fi
1108 +}
1109 +
1110 +# @FUNCTION: _distutils-r2_clean_egg_info
1111 +# @INTERNAL
1112 +# @DESCRIPTION:
1113 +# Clean up potential stray egg-info files left by setuptools test phase.
1114 +# Those files ended up being unversioned, and caused issues:
1115 +# https://bugs.gentoo.org/534058
1116 +_distutils-r2_clean_egg_info() {
1117 + rm -rf "${BUILD_DIR}"/lib/*.egg-info || die
1118 +}
1119 +
1120 +distutils-r2_src_test() {
1121 + debug-print-function ${FUNCNAME} "${@}"
1122 +
1123 + if declare -f python_test >/dev/null; then
1124 + _distutils-r2_run_foreach_impl python_test
1125 + _distutils-r2_run_foreach_impl _distutils-r2_clean_egg_info
1126 + fi
1127 +
1128 + if declare -f python_test_all >/dev/null; then
1129 + _distutils-r2_run_common_phase python_test_all
1130 + fi
1131 +}
1132 +
1133 +# @FUNCTION: _distutils-r2_check_namespace_pth
1134 +# @INTERNAL
1135 +# @DESCRIPTION:
1136 +# Check if any *-nspkg.pth files were installed (by setuptools)
1137 +# and warn about the policy non-conformance if they were.
1138 +_distutils-r2_check_namespace_pth() {
1139 + local f pth=()
1140 +
1141 + while IFS= read -r -d '' f; do
1142 + pth+=( "${f}" )
1143 + done < <(find "${ED%/}" -name '*-nspkg.pth' -print0)
1144 +
1145 + if [[ ${pth[@]} ]]; then
1146 + ewarn "The following *-nspkg.pth files were found installed:"
1147 + ewarn
1148 + for f in "${pth[@]}"; do
1149 + ewarn " ${f#${ED%/}}"
1150 + done
1151 + ewarn
1152 + ewarn "The presence of those files may break namespaces in Python 3.5+. Please"
1153 + ewarn "read our documentation on reliable handling of namespaces and update"
1154 + ewarn "the ebuild accordingly:"
1155 + ewarn
1156 + ewarn " https://wiki.gentoo.org/wiki/Project:Python/Namespace_packages"
1157 + fi
1158 +}
1159 +
1160 +distutils-r2_src_install() {
1161 + debug-print-function ${FUNCNAME} "${@}"
1162 +
1163 + if declare -f python_install >/dev/null; then
1164 + _distutils-r2_run_foreach_impl python_install
1165 + else
1166 + _distutils-r2_run_foreach_impl distutils-r2_python_install
1167 + fi
1168 +
1169 + local _DISTUTILS_DEFAULT_CALLED
1170 +
1171 + if declare -f python_install_all >/dev/null; then
1172 + _distutils-r2_run_common_phase python_install_all
1173 + else
1174 + _distutils-r2_run_common_phase distutils-r2_python_install_all
1175 + fi
1176 +
1177 + if [[ ! ${_DISTUTILS_DEFAULT_CALLED} ]]; then
1178 + local cmd=die
1179 + [[ ${EAPI} == [45] ]] && cmd=eqawarn
1180 +
1181 + "${cmd}" "QA: python_install_all() didn't call distutils-r2_python_install_all"
1182 + fi
1183 +
1184 + _distutils-r2_check_namespace_pth
1185 +}
1186 +
1187 +# -- distutils.eclass functions --
1188 +
1189 +distutils_get_intermediate_installation_image() {
1190 + die "${FUNCNAME}() is invalid for distutils-r2"
1191 +}
1192 +
1193 +distutils_src_unpack() {
1194 + die "${FUNCNAME}() is invalid for distutils-r2, and you don't want it in EAPI ${EAPI} anyway"
1195 +}
1196 +
1197 +distutils_src_prepare() {
1198 + die "${FUNCNAME}() is invalid for distutils-r2, you probably want: ${FUNCNAME/_/-r2_}"
1199 +}
1200 +
1201 +distutils_src_compile() {
1202 + die "${FUNCNAME}() is invalid for distutils-r2, you probably want: ${FUNCNAME/_/-r2_}"
1203 +}
1204 +
1205 +distutils_src_test() {
1206 + die "${FUNCNAME}() is invalid for distutils-r2, you probably want: ${FUNCNAME/_/-r2_}"
1207 +}
1208 +
1209 +distutils_src_install() {
1210 + die "${FUNCNAME}() is invalid for distutils-r2, you probably want: ${FUNCNAME/_/-r2_}"
1211 +}
1212 +
1213 +distutils_pkg_postinst() {
1214 + die "${FUNCNAME}() is invalid for distutils-r2, and pkg_postinst is unnecessary"
1215 +}
1216 +
1217 +distutils_pkg_postrm() {
1218 + die "${FUNCNAME}() is invalid for distutils-r2, and pkg_postrm is unnecessary"
1219 +}
1220 +
1221 +_DISTUTILS_R2=1
1222 +fi
1223 diff --git a/eclass/python-any-r2.eclass b/eclass/python-any-r2.eclass
1224 new file mode 100644
1225 index 000000000000..cf70f23f69d5
1226 --- /dev/null
1227 +++ b/eclass/python-any-r2.eclass
1228 @@ -0,0 +1,357 @@
1229 +# Copyright 1999-2020 Gentoo Authors
1230 +# Distributed under the terms of the GNU General Public License v2
1231 +
1232 +# @ECLASS: python-any-r2.eclass
1233 +# @MAINTAINER:
1234 +# Python team <python@g.o>
1235 +# @AUTHOR:
1236 +# Author: Michał Górny <mgorny@g.o>
1237 +# @SUPPORTED_EAPIS: 5 6 7
1238 +# @BLURB: An eclass for packages having build-time dependency on Python.
1239 +# @DESCRIPTION:
1240 +# A minimal eclass for packages which need any Python interpreter
1241 +# installed without a need for explicit choice and invariability.
1242 +# This usually involves packages requiring Python at build-time
1243 +# but having no other relevance to it.
1244 +#
1245 +# This eclass provides a minimal PYTHON_DEPS variable with a dependency
1246 +# string on any of the supported Python implementations. It also exports
1247 +# pkg_setup() which finds the best supported implementation and sets it
1248 +# as the active one.
1249 +#
1250 +# Optionally, you can define a python_check_deps() function. It will
1251 +# be called by the eclass with EPYTHON set to each matching Python
1252 +# implementation and it is expected to check whether the implementation
1253 +# fulfills the package requirements. You can use the locally exported
1254 +# PYTHON_USEDEP to check USE-dependencies of relevant packages. It
1255 +# should return a true value (0) if the Python implementation fulfills
1256 +# the requirements, a false value (non-zero) otherwise.
1257 +#
1258 +# Please note that python-any-r2 will always inherit python-utils-r2
1259 +# as well. Thus, all the functions defined there can be used in the
1260 +# packages using python-any-r2, and there is no need ever to inherit
1261 +# both.
1262 +
1263 +case "${EAPI:-0}" in
1264 + [0-4]) die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}" ;;
1265 + [5-7]) ;;
1266 + *) die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" ;;
1267 +esac
1268 +
1269 +if [[ ! ${_PYTHON_ANY_R2} ]]; then
1270 +
1271 +if [[ ${_PYTHON_R2} ]]; then
1272 + die 'python-any-r2.eclass can not be used with python-r2.eclass.'
1273 +elif [[ ${_PYTHON_SINGLE_R2} ]]; then
1274 + die 'python-any-r2.eclass can not be used with python-single-r2.eclass.'
1275 +fi
1276 +
1277 +inherit python-utils-r2
1278 +
1279 +fi
1280 +
1281 +EXPORT_FUNCTIONS pkg_setup
1282 +
1283 +# @ECLASS-VARIABLE: PYTHON_COMPAT
1284 +# @REQUIRED
1285 +# @DESCRIPTION:
1286 +# This variable contains a list of Python implementations the package
1287 +# supports. It must be set before the `inherit' call. It has to be
1288 +# an array.
1289 +#
1290 +# Example:
1291 +# @CODE
1292 +# PYTHON_COMPAT=( python{2_5,2_6,2_7} )
1293 +# @CODE
1294 +
1295 +# @ECLASS-VARIABLE: PYTHON_COMPAT_OVERRIDE
1296 +# @INTERNAL
1297 +# @DESCRIPTION:
1298 +# This variable can be used when working with ebuilds to override
1299 +# the in-ebuild PYTHON_COMPAT. It is a string naming the implementation
1300 +# which will be used to build the package. It needs to be specified
1301 +# in the calling environment, and not in ebuilds.
1302 +#
1303 +# It should be noted that in order to preserve metadata immutability,
1304 +# PYTHON_COMPAT_OVERRIDE does not affect dependencies. The value of
1305 +# EPYTHON and eselect-python preferences are ignored. Dependencies need
1306 +# to be satisfied manually.
1307 +#
1308 +# Example:
1309 +# @CODE
1310 +# PYTHON_COMPAT_OVERRIDE='pypy' emerge -1v dev-python/bar
1311 +# @CODE
1312 +
1313 +# @ECLASS-VARIABLE: PYTHON_REQ_USE
1314 +# @DEFAULT_UNSET
1315 +# @DESCRIPTION:
1316 +# The list of USEflags required to be enabled on the Python
1317 +# implementations, formed as a USE-dependency string. It should be valid
1318 +# for all implementations in PYTHON_COMPAT, so it may be necessary to
1319 +# use USE defaults.
1320 +#
1321 +# Example:
1322 +# @CODE
1323 +# PYTHON_REQ_USE="gdbm,ncurses(-)?"
1324 +# @CODE
1325 +#
1326 +# It will cause the Python dependencies to look like:
1327 +# @CODE
1328 +# || ( dev-lang/python:X.Y[gdbm,ncurses(-)?] ... )
1329 +# @CODE
1330 +
1331 +# @ECLASS-VARIABLE: PYTHON_DEPS
1332 +# @DESCRIPTION:
1333 +# This is an eclass-generated Python dependency string for all
1334 +# implementations listed in PYTHON_COMPAT.
1335 +#
1336 +# Any of the supported interpreters will satisfy the dependency.
1337 +#
1338 +# Example use:
1339 +# @CODE
1340 +# DEPEND="${RDEPEND}
1341 +# ${PYTHON_DEPS}"
1342 +# @CODE
1343 +#
1344 +# Example value:
1345 +# @CODE
1346 +# || ( dev-lang/python:2.7[gdbm]
1347 +# dev-lang/python:2.6[gdbm] )
1348 +# @CODE
1349 +
1350 +# @ECLASS-VARIABLE: PYTHON_USEDEP
1351 +# @DESCRIPTION:
1352 +# An eclass-generated USE-dependency string for the currently tested
1353 +# implementation. It is set locally for python_check_deps() call.
1354 +#
1355 +# The generate USE-flag list is compatible with packages using python-r2,
1356 +# python-single-r2 and python-distutils-ng eclasses. It must not be used
1357 +# on packages using python.eclass.
1358 +#
1359 +# Example use:
1360 +# @CODE
1361 +# python_check_deps() {
1362 +# has_version "dev-python/foo[${PYTHON_USEDEP}]"
1363 +# }
1364 +# @CODE
1365 +#
1366 +# Example value:
1367 +# @CODE
1368 +# python_targets_python2_7(-)?,python_single_target_python2_7(+)?
1369 +# @CODE
1370 +
1371 +_python_any_set_globals() {
1372 + local usestr deps i PYTHON_PKG_DEP
1373 + [[ ${PYTHON_REQ_USE} ]] && usestr="[${PYTHON_REQ_USE}]"
1374 +
1375 + _python_set_impls
1376 +
1377 + for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
1378 + python_export "${i}" PYTHON_PKG_DEP
1379 +
1380 + # note: need to strip '=' slot operator for || deps
1381 + deps="${PYTHON_PKG_DEP/:0=/:0} ${deps}"
1382 + done
1383 + deps="|| ( ${deps})"
1384 +
1385 + if [[ ${PYTHON_DEPS+1} ]]; then
1386 + if [[ ${PYTHON_DEPS} != "${deps}" ]]; then
1387 + eerror "PYTHON_DEPS have changed between inherits (PYTHON_REQ_USE?)!"
1388 + eerror "Before: ${PYTHON_DEPS}"
1389 + eerror "Now : ${deps}"
1390 + die "PYTHON_DEPS integrity check failed"
1391 + fi
1392 + else
1393 + PYTHON_DEPS=${deps}
1394 + readonly PYTHON_DEPS
1395 + fi
1396 +
1397 + if [[ ! ${PYTHON_REQUIRED_USE+1} ]]; then
1398 + # fake var to catch mistaken usage
1399 + PYTHON_REQUIRED_USE='I-DO-NOT-EXIST-IN-PYTHON-ANY-R1'
1400 + readonly PYTHON_REQUIRED_USE
1401 + fi
1402 +}
1403 +_python_any_set_globals
1404 +unset -f _python_any_set_globals
1405 +
1406 +if [[ ! ${_PYTHON_ANY_R2} ]]; then
1407 +
1408 +# @FUNCTION: python_gen_any_dep
1409 +# @USAGE: <dependency-block>
1410 +# @DESCRIPTION:
1411 +# Generate an any-of dependency that enforces a version match between
1412 +# the Python interpreter and Python packages. <dependency-block> needs
1413 +# to list one or more dependencies with verbatim '${PYTHON_USEDEP}'
1414 +# references (quoted!) that will get expanded inside the function.
1415 +#
1416 +# This should be used along with an appropriate python_check_deps()
1417 +# that checks which of the any-of blocks were matched.
1418 +#
1419 +# Example use:
1420 +# @CODE
1421 +# DEPEND="$(python_gen_any_dep '
1422 +# dev-python/foo[${PYTHON_USEDEP}]
1423 +# || ( dev-python/bar[${PYTHON_USEDEP}]
1424 +# dev-python/baz[${PYTHON_USEDEP}] )')"
1425 +#
1426 +# python_check_deps() {
1427 +# has_version "dev-python/foo[${PYTHON_USEDEP}]" \
1428 +# && { has_version "dev-python/bar[${PYTHON_USEDEP}]" \
1429 +# || has_version "dev-python/baz[${PYTHON_USEDEP}]"; }
1430 +# }
1431 +# @CODE
1432 +#
1433 +# Example value:
1434 +# @CODE
1435 +# || (
1436 +# (
1437 +# dev-lang/python:2.7
1438 +# dev-python/foo[python_targets_python2_7(-)?,python_single_target_python2_7(+)?]
1439 +# || ( dev-python/bar[python_targets_python2_7(-)?,python_single_target_python2_7(+)?]
1440 +# dev-python/baz[python_targets_python2_7(-)?,python_single_target_python2_7(+)?] )
1441 +# )
1442 +# (
1443 +# dev-lang/python:3.3
1444 +# dev-python/foo[python_targets_python3_3(-)?,python_single_target_python3_3(+)?]
1445 +# || ( dev-python/bar[python_targets_python3_3(-)?,python_single_target_python3_3(+)?]
1446 +# dev-python/baz[python_targets_python3_3(-)?,python_single_target_python3_3(+)?] )
1447 +# )
1448 +# )
1449 +# @CODE
1450 +python_gen_any_dep() {
1451 + debug-print-function ${FUNCNAME} "${@}"
1452 +
1453 + local depstr=${1}
1454 + [[ ${depstr} ]] || die "No dependency string provided"
1455 +
1456 + local i PYTHON_PKG_DEP out=
1457 + for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
1458 + local PYTHON_USEDEP="python_targets_${i}(-),python_single_target_${i}(+)"
1459 + python_export "${i}" PYTHON_PKG_DEP
1460 +
1461 + local i_depstr=${depstr//\$\{PYTHON_USEDEP\}/${PYTHON_USEDEP}}
1462 + # note: need to strip '=' slot operator for || deps
1463 + out="( ${PYTHON_PKG_DEP%=} ${i_depstr} ) ${out}"
1464 + done
1465 + echo "|| ( ${out})"
1466 +}
1467 +
1468 +# @FUNCTION: _python_EPYTHON_supported
1469 +# @USAGE: <epython>
1470 +# @INTERNAL
1471 +# @DESCRIPTION:
1472 +# Check whether the specified implementation is supported by package
1473 +# (specified in PYTHON_COMPAT). Calls python_check_deps() if declared.
1474 +_python_EPYTHON_supported() {
1475 + debug-print-function ${FUNCNAME} "${@}"
1476 +
1477 + local EPYTHON=${1}
1478 + local i=${EPYTHON/./_}
1479 +
1480 + case "${i}" in
1481 + python*|jython*|pypy*)
1482 + ;;
1483 + *)
1484 + ewarn "Invalid EPYTHON: ${EPYTHON}"
1485 + return 1
1486 + ;;
1487 + esac
1488 +
1489 + if has "${i}" "${_PYTHON_SUPPORTED_IMPLS[@]}"; then
1490 + if python_is_installed "${i}"; then
1491 + if declare -f python_check_deps >/dev/null; then
1492 + local PYTHON_USEDEP="python_targets_${i}(-),python_single_target_${i}(+)"
1493 + python_check_deps
1494 + return ${?}
1495 + fi
1496 +
1497 + return 0
1498 + fi
1499 + elif ! has "${i}" "${_PYTHON_ALL_IMPLS[@]}"; then
1500 + ewarn "Invalid EPYTHON: ${EPYTHON}"
1501 + fi
1502 + return 1
1503 +}
1504 +
1505 +# @FUNCTION: python_setup
1506 +# @DESCRIPTION:
1507 +# Determine what the best installed (and supported) Python
1508 +# implementation is, and set the Python build environment up for it.
1509 +#
1510 +# This function will call python_check_deps() if defined.
1511 +python_setup() {
1512 + debug-print-function ${FUNCNAME} "${@}"
1513 +
1514 + # support developer override
1515 + if [[ ${PYTHON_COMPAT_OVERRIDE} ]]; then
1516 + local impls=( ${PYTHON_COMPAT_OVERRIDE} )
1517 + [[ ${#impls[@]} -eq 1 ]] || die "PYTHON_COMPAT_OVERRIDE must name exactly one implementation for python-any-r2"
1518 +
1519 + ewarn "WARNING: PYTHON_COMPAT_OVERRIDE in effect. The following Python"
1520 + ewarn "implementation will be used:"
1521 + ewarn
1522 + ewarn " ${PYTHON_COMPAT_OVERRIDE}"
1523 + ewarn
1524 + ewarn "Dependencies won't be satisfied, and EPYTHON/eselect-python will be ignored."
1525 +
1526 + python_export "${impls[0]}" EPYTHON PYTHON
1527 + python_wrapper_setup
1528 + return
1529 + fi
1530 +
1531 + # first, try ${EPYTHON}... maybe it's good enough for us.
1532 + if [[ ${EPYTHON} ]]; then
1533 + if _python_EPYTHON_supported "${EPYTHON}"; then
1534 + python_export EPYTHON PYTHON
1535 + python_wrapper_setup
1536 + return
1537 + fi
1538 + fi
1539 +
1540 + # then, try eselect-python
1541 + local variant i
1542 + for variant in '' '--python2' '--python3'; do
1543 + i=$(eselect python --show ${variant} 2>/dev/null)
1544 +
1545 + if [[ ! ${i} ]]; then
1546 + # no eselect-python?
1547 + break
1548 + elif _python_EPYTHON_supported "${i}"; then
1549 + python_export "${i}" EPYTHON PYTHON
1550 + python_wrapper_setup
1551 + return
1552 + fi
1553 + done
1554 +
1555 + # fallback to best installed impl.
1556 + # (reverse iteration over _PYTHON_SUPPORTED_IMPLS)
1557 + for (( i = ${#_PYTHON_SUPPORTED_IMPLS[@]} - 1; i >= 0; i-- )); do
1558 + python_export "${_PYTHON_SUPPORTED_IMPLS[i]}" EPYTHON PYTHON
1559 + if _python_EPYTHON_supported "${EPYTHON}"; then
1560 + python_wrapper_setup
1561 + return
1562 + fi
1563 + done
1564 +
1565 + eerror "No Python implementation found for the build. This is usually"
1566 + eerror "a bug in the ebuild. Please report it to bugs.gentoo.org"
1567 + eerror "along with the build log."
1568 + echo
1569 + die "No supported Python implementation installed."
1570 +}
1571 +
1572 +# @FUNCTION: python-any-r2_pkg_setup
1573 +# @DESCRIPTION:
1574 +# Runs python_setup during from-source installs.
1575 +#
1576 +# In a binary package installs is a no-op. If you need Python in pkg_*
1577 +# phases of a binary package, call python_setup directly.
1578 +python-any-r2_pkg_setup() {
1579 + debug-print-function ${FUNCNAME} "${@}"
1580 +
1581 + [[ ${MERGE_TYPE} != binary ]] && python_setup
1582 +}
1583 +
1584 +_PYTHON_ANY_R2=1
1585 +fi
1586 diff --git a/eclass/python-r2.eclass b/eclass/python-r2.eclass
1587 new file mode 100644
1588 index 000000000000..8bf0b1a1ac29
1589 --- /dev/null
1590 +++ b/eclass/python-r2.eclass
1591 @@ -0,0 +1,825 @@
1592 +# Copyright 1999-2020 Gentoo Authors
1593 +# Distributed under the terms of the GNU General Public License v2
1594 +
1595 +# @ECLASS: python-r2.eclass
1596 +# @MAINTAINER:
1597 +# Python team <python@g.o>
1598 +# @AUTHOR:
1599 +# Author: Michał Górny <mgorny@g.o>
1600 +# @SUPPORTED_EAPIS: 5 6 7
1601 +# @BLURB: A common, simple eclass for Python packages.
1602 +# @DESCRIPTION:
1603 +# A common eclass providing helper functions to build and install
1604 +# packages supporting being installed for multiple Python
1605 +# implementations.
1606 +#
1607 +# This eclass sets correct IUSE. Modification of REQUIRED_USE has to
1608 +# be done by the author of the ebuild (but PYTHON_REQUIRED_USE is
1609 +# provided for convenience, see below). python-r2 exports PYTHON_DEPS
1610 +# and PYTHON_USEDEP so you can create correct dependencies for your
1611 +# package easily. It also provides methods to easily run a command for
1612 +# each enabled Python implementation and duplicate the sources for them.
1613 +#
1614 +# Please note that python-r2 will always inherit python-utils-r2 as
1615 +# well. Thus, all the functions defined there can be used
1616 +# in the packages using python-r2, and there is no need ever to inherit
1617 +# both.
1618 +
1619 +case "${EAPI:-0}" in
1620 + 0|1|2|3|4)
1621 + die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
1622 + ;;
1623 + 5|6|7)
1624 + # EAPI=5 is required for sane USE_EXPAND dependencies
1625 + ;;
1626 + *)
1627 + die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
1628 + ;;
1629 +esac
1630 +
1631 +if [[ ! ${_PYTHON_R2} ]]; then
1632 +
1633 +if [[ ${_PYTHON_SINGLE_R2} ]]; then
1634 + die 'python-r2.eclass can not be used with python-single-r2.eclass.'
1635 +elif [[ ${_PYTHON_ANY_R2} ]]; then
1636 + die 'python-r2.eclass can not be used with python-any-r2.eclass.'
1637 +fi
1638 +
1639 +[[ ${EAPI} == [45] ]] && inherit eutils
1640 +inherit multibuild python-utils-r2
1641 +
1642 +fi
1643 +
1644 +# @ECLASS-VARIABLE: PYTHON_COMPAT
1645 +# @REQUIRED
1646 +# @DESCRIPTION:
1647 +# This variable contains a list of Python implementations the package
1648 +# supports. It must be set before the `inherit' call. It has to be
1649 +# an array.
1650 +#
1651 +# Example:
1652 +# @CODE
1653 +# PYTHON_COMPAT=( python2_7 python3_3 python3_4 )
1654 +# @CODE
1655 +#
1656 +# Please note that you can also use bash brace expansion if you like:
1657 +# @CODE
1658 +# PYTHON_COMPAT=( python2_7 python3_{3,4} )
1659 +# @CODE
1660 +
1661 +# @ECLASS-VARIABLE: PYTHON_COMPAT_OVERRIDE
1662 +# @INTERNAL
1663 +# @DESCRIPTION:
1664 +# This variable can be used when working with ebuilds to override
1665 +# the in-ebuild PYTHON_COMPAT. It is a string listing all
1666 +# the implementations which package will be built for. It need be
1667 +# specified in the calling environment, and not in ebuilds.
1668 +#
1669 +# It should be noted that in order to preserve metadata immutability,
1670 +# PYTHON_COMPAT_OVERRIDE does not affect IUSE nor dependencies.
1671 +# The state of PYTHON_TARGETS is ignored, and all the implementations
1672 +# in PYTHON_COMPAT_OVERRIDE are built. Dependencies need to be satisfied
1673 +# manually.
1674 +#
1675 +# Example:
1676 +# @CODE
1677 +# PYTHON_COMPAT_OVERRIDE='pypy python3_3' emerge -1v dev-python/foo
1678 +# @CODE
1679 +
1680 +# @ECLASS-VARIABLE: PYTHON_REQ_USE
1681 +# @DEFAULT_UNSET
1682 +# @DESCRIPTION:
1683 +# The list of USEflags required to be enabled on the chosen Python
1684 +# implementations, formed as a USE-dependency string. It should be valid
1685 +# for all implementations in PYTHON_COMPAT, so it may be necessary to
1686 +# use USE defaults.
1687 +#
1688 +# This should be set before calling `inherit'.
1689 +#
1690 +# Example:
1691 +# @CODE
1692 +# PYTHON_REQ_USE="gdbm,ncurses(-)?"
1693 +# @CODE
1694 +#
1695 +# It will cause the Python dependencies to look like:
1696 +# @CODE
1697 +# python_targets_pythonX_Y? ( dev-lang/python:X.Y[gdbm,ncurses(-)?] )
1698 +# @CODE
1699 +
1700 +# @ECLASS-VARIABLE: PYTHON_DEPS
1701 +# @DESCRIPTION:
1702 +# This is an eclass-generated Python dependency string for all
1703 +# implementations listed in PYTHON_COMPAT.
1704 +#
1705 +# Example use:
1706 +# @CODE
1707 +# RDEPEND="${PYTHON_DEPS}
1708 +# dev-foo/mydep"
1709 +# DEPEND="${RDEPEND}"
1710 +# @CODE
1711 +#
1712 +# Example value:
1713 +# @CODE
1714 +# dev-lang/python-exec:=
1715 +# python_targets_python2_7? ( dev-lang/python:2.7[gdbm] )
1716 +# python_targets_pypy? ( dev-python/pypy[gdbm] )
1717 +# @CODE
1718 +
1719 +# @ECLASS-VARIABLE: PYTHON_USEDEP
1720 +# @DESCRIPTION:
1721 +# This is an eclass-generated USE-dependency string which can be used to
1722 +# depend on another Python package being built for the same Python
1723 +# implementations.
1724 +#
1725 +# The generate USE-flag list is compatible with packages using python-r2
1726 +# and python-distutils-ng eclasses. It must not be used on packages
1727 +# using python.eclass.
1728 +#
1729 +# Example use:
1730 +# @CODE
1731 +# RDEPEND="dev-python/foo[${PYTHON_USEDEP}]"
1732 +# @CODE
1733 +#
1734 +# Example value:
1735 +# @CODE
1736 +# python_targets_python2_7(-)?,python_targets_python3_4(-)?
1737 +# @CODE
1738 +
1739 +# @ECLASS-VARIABLE: PYTHON_REQUIRED_USE
1740 +# @DESCRIPTION:
1741 +# This is an eclass-generated required-use expression which ensures at
1742 +# least one Python implementation has been enabled.
1743 +#
1744 +# This expression should be utilized in an ebuild by including it in
1745 +# REQUIRED_USE, optionally behind a use flag.
1746 +#
1747 +# Example use:
1748 +# @CODE
1749 +# REQUIRED_USE="python? ( ${PYTHON_REQUIRED_USE} )"
1750 +# @CODE
1751 +#
1752 +# Example value:
1753 +# @CODE
1754 +# || ( python_targets_python2_7 python_targets_python3_4 )
1755 +# @CODE
1756 +
1757 +_python_set_globals() {
1758 + local deps i PYTHON_PKG_DEP
1759 +
1760 + _python_set_impls
1761 +
1762 + for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
1763 + python_export "${i}" PYTHON_PKG_DEP
1764 + deps+="python_targets_${i}? ( ${PYTHON_PKG_DEP} ) "
1765 + done
1766 +
1767 + local flags=( "${_PYTHON_SUPPORTED_IMPLS[@]/#/python_targets_}" )
1768 + local optflags=${flags[@]/%/(-)?}
1769 +
1770 + # A nice QA trick here. Since a python-single-r2 package has to have
1771 + # at least one PYTHON_SINGLE_TARGET enabled (REQUIRED_USE),
1772 + # the following check will always fail on those packages. Therefore,
1773 + # it should prevent developers from mistakenly depending on packages
1774 + # not supporting multiple Python implementations.
1775 +
1776 + local flags_st=( "${_PYTHON_SUPPORTED_IMPLS[@]/#/-python_single_target_}" )
1777 + optflags+=,${flags_st[@]/%/(-)}
1778 + local requse="|| ( ${flags[*]} )"
1779 + local usedep=${optflags// /,}
1780 +
1781 + # 1) well, python-exec would suffice as an RDEP
1782 + # but no point in making this overcomplex, BDEP doesn't hurt anyone
1783 + # 2) python-exec should be built with all targets forced anyway
1784 + # but if new targets were added, we may need to force a rebuild
1785 + deps+=">=dev-lang/python-exec-2:=[${usedep}]"
1786 +
1787 + if [[ ${PYTHON_DEPS+1} ]]; then
1788 + # IUSE is magical, so we can't really check it
1789 + # (but we verify PYTHON_COMPAT already)
1790 +
1791 + if [[ ${PYTHON_DEPS} != "${deps}" ]]; then
1792 + eerror "PYTHON_DEPS have changed between inherits (PYTHON_REQ_USE?)!"
1793 + eerror "Before: ${PYTHON_DEPS}"
1794 + eerror "Now : ${deps}"
1795 + die "PYTHON_DEPS integrity check failed"
1796 + fi
1797 +
1798 + # these two are formality -- they depend on PYTHON_COMPAT only
1799 + if [[ ${PYTHON_REQUIRED_USE} != ${requse} ]]; then
1800 + eerror "PYTHON_REQUIRED_USE have changed between inherits!"
1801 + eerror "Before: ${PYTHON_REQUIRED_USE}"
1802 + eerror "Now : ${requse}"
1803 + die "PYTHON_REQUIRED_USE integrity check failed"
1804 + fi
1805 +
1806 + if [[ ${PYTHON_USEDEP} != "${usedep}" ]]; then
1807 + eerror "PYTHON_USEDEP have changed between inherits!"
1808 + eerror "Before: ${PYTHON_USEDEP}"
1809 + eerror "Now : ${usedep}"
1810 + die "PYTHON_USEDEP integrity check failed"
1811 + fi
1812 + else
1813 + IUSE=${flags[*]}
1814 +
1815 + PYTHON_DEPS=${deps}
1816 + PYTHON_REQUIRED_USE=${requse}
1817 + PYTHON_USEDEP=${usedep}
1818 + readonly PYTHON_DEPS PYTHON_REQUIRED_USE
1819 + fi
1820 +}
1821 +_python_set_globals
1822 +unset -f _python_set_globals
1823 +
1824 +if [[ ! ${_PYTHON_R2} ]]; then
1825 +
1826 +# @FUNCTION: _python_validate_useflags
1827 +# @INTERNAL
1828 +# @DESCRIPTION:
1829 +# Enforce the proper setting of PYTHON_TARGETS, if PYTHON_COMPAT_OVERRIDE
1830 +# is not in effect. If it is, just warn that the flags will be ignored.
1831 +_python_validate_useflags() {
1832 + debug-print-function ${FUNCNAME} "${@}"
1833 +
1834 + if [[ ${PYTHON_COMPAT_OVERRIDE} ]]; then
1835 + if [[ ! ${_PYTHON_COMPAT_OVERRIDE_WARNED} ]]; then
1836 + ewarn "WARNING: PYTHON_COMPAT_OVERRIDE in effect. The following Python"
1837 + ewarn "implementations will be enabled:"
1838 + ewarn
1839 + ewarn " ${PYTHON_COMPAT_OVERRIDE}"
1840 + ewarn
1841 + ewarn "Dependencies won't be satisfied, and PYTHON_TARGETS will be ignored."
1842 + _PYTHON_COMPAT_OVERRIDE_WARNED=1
1843 + fi
1844 + # we do not use flags with PCO
1845 + return
1846 + fi
1847 +
1848 + local i
1849 +
1850 + for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
1851 + use "python_targets_${i}" && return 0
1852 + done
1853 +
1854 + eerror "No Python implementation selected for the build. Please add one"
1855 + eerror "of the following values to your PYTHON_TARGETS (in make.conf):"
1856 + eerror
1857 + eerror "${PYTHON_COMPAT[@]}"
1858 + echo
1859 + die "No supported Python implementation in PYTHON_TARGETS."
1860 +}
1861 +
1862 +# @FUNCTION: _python_gen_usedep
1863 +# @INTERNAL
1864 +# @USAGE: [<pattern>...]
1865 +# @DESCRIPTION:
1866 +# Output a USE dependency string for Python implementations which
1867 +# are both in PYTHON_COMPAT and match any of the patterns passed
1868 +# as parameters to the function.
1869 +#
1870 +# The patterns can be either fnmatch-style patterns (matched via bash
1871 +# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
1872 +# appropriately all enabled Python 2/3 implementations (alike
1873 +# python_is_python3). Remember to escape or quote the fnmatch patterns
1874 +# to prevent accidental shell filename expansion.
1875 +#
1876 +# This is an internal function used to implement python_gen_cond_dep
1877 +# and deprecated python_gen_usedep.
1878 +_python_gen_usedep() {
1879 + debug-print-function ${FUNCNAME} "${@}"
1880 +
1881 + local impl matches=()
1882 +
1883 + for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
1884 + if _python_impl_matches "${impl}" "${@}"; then
1885 + matches+=(
1886 + "python_targets_${impl}(-)?"
1887 + "-python_single_target_${impl}(-)"
1888 + )
1889 + fi
1890 + done
1891 +
1892 + [[ ${matches[@]} ]] || die "No supported implementations match python_gen_usedep patterns: ${@}"
1893 +
1894 + local out=${matches[@]}
1895 + echo "${out// /,}"
1896 +}
1897 +
1898 +# @FUNCTION: python_gen_usedep
1899 +# @USAGE: <pattern> [...]
1900 +# @DESCRIPTION:
1901 +# DEPRECATED. Please use python_gen_cond_dep instead.
1902 +#
1903 +# Output a USE dependency string for Python implementations which
1904 +# are both in PYTHON_COMPAT and match any of the patterns passed
1905 +# as parameters to the function.
1906 +#
1907 +# The patterns can be either fnmatch-style patterns (matched via bash
1908 +# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
1909 +# appropriately all enabled Python 2/3 implementations (alike
1910 +# python_is_python3). Remember to escape or quote the fnmatch patterns
1911 +# to prevent accidental shell filename expansion.
1912 +#
1913 +# When all implementations are requested, please use ${PYTHON_USEDEP}
1914 +# instead. Please also remember to set an appropriate REQUIRED_USE
1915 +# to avoid ineffective USE flags.
1916 +#
1917 +# Example:
1918 +# @CODE
1919 +# PYTHON_COMPAT=( python{2_7,3_4} )
1920 +# DEPEND="doc? ( dev-python/epydoc[$(python_gen_usedep 'python2*')] )"
1921 +# @CODE
1922 +#
1923 +# It will cause the dependency to look like:
1924 +# @CODE
1925 +# DEPEND="doc? ( dev-python/epydoc[python_targets_python2_7?] )"
1926 +# @CODE
1927 +python_gen_usedep() {
1928 + debug-print-function ${FUNCNAME} "${@}"
1929 +
1930 + # output only once, during some reasonable phase
1931 + # (avoid spamming cache regen runs)
1932 + if [[ ${EBUILD_PHASE} == setup ]]; then
1933 + eqawarn "python_gen_usedep() is deprecated. Please use python_gen_cond_dep instead."
1934 + fi
1935 + _python_gen_usedep "${@}"
1936 +}
1937 +
1938 +# @FUNCTION: python_gen_useflags
1939 +# @USAGE: [<pattern>...]
1940 +# @DESCRIPTION:
1941 +# Output a list of USE flags for Python implementations which
1942 +# are both in PYTHON_COMPAT and match any of the patterns passed
1943 +# as parameters to the function.
1944 +#
1945 +# The patterns can be either fnmatch-style patterns (matched via bash
1946 +# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
1947 +# appropriately all enabled Python 2/3 implementations (alike
1948 +# python_is_python3). Remember to escape or quote the fnmatch patterns
1949 +# to prevent accidental shell filename expansion.
1950 +#
1951 +# Example:
1952 +# @CODE
1953 +# PYTHON_COMPAT=( python{2_7,3_4} )
1954 +# REQUIRED_USE="doc? ( || ( $(python_gen_useflags python2*) ) )"
1955 +# @CODE
1956 +#
1957 +# It will cause the variable to look like:
1958 +# @CODE
1959 +# REQUIRED_USE="doc? ( || ( python_targets_python2_7 ) )"
1960 +# @CODE
1961 +python_gen_useflags() {
1962 + debug-print-function ${FUNCNAME} "${@}"
1963 +
1964 + local impl matches=()
1965 +
1966 + for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
1967 + if _python_impl_matches "${impl}" "${@}"; then
1968 + matches+=( "python_targets_${impl}" )
1969 + fi
1970 + done
1971 +
1972 + echo "${matches[@]}"
1973 +}
1974 +
1975 +# @FUNCTION: python_gen_cond_dep
1976 +# @USAGE: <dependency> [<pattern>...]
1977 +# @DESCRIPTION:
1978 +# Output a list of <dependency>-ies made conditional to USE flags
1979 +# of Python implementations which are both in PYTHON_COMPAT and match
1980 +# any of the patterns passed as the remaining parameters.
1981 +#
1982 +# The patterns can be either fnmatch-style patterns (matched via bash
1983 +# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
1984 +# appropriately all enabled Python 2/3 implementations (alike
1985 +# python_is_python3). Remember to escape or quote the fnmatch patterns
1986 +# to prevent accidental shell filename expansion.
1987 +#
1988 +# In order to enforce USE constraints on the packages, verbatim
1989 +# '${PYTHON_USEDEP}' (quoted!) may be placed in the dependency
1990 +# specification. It will get expanded within the function into a proper
1991 +# USE dependency string.
1992 +#
1993 +# Example:
1994 +# @CODE
1995 +# PYTHON_COMPAT=( python{2_7,3_{3,4}} pypy )
1996 +# RDEPEND="$(python_gen_cond_dep \
1997 +# 'dev-python/unittest2[${PYTHON_USEDEP}]' python2_7 pypy )"
1998 +# @CODE
1999 +#
2000 +# It will cause the variable to look like:
2001 +# @CODE
2002 +# RDEPEND="python_targets_python2_7? (
2003 +# dev-python/unittest2[python_targets_python2_7?] )
2004 +# python_targets_pypy? (
2005 +# dev-python/unittest2[python_targets_pypy?] )"
2006 +# @CODE
2007 +python_gen_cond_dep() {
2008 + debug-print-function ${FUNCNAME} "${@}"
2009 +
2010 + local impl matches=()
2011 + local dep=${1}
2012 + shift
2013 +
2014 + for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
2015 + if _python_impl_matches "${impl}" "${@}"; then
2016 + # substitute ${PYTHON_USEDEP} if used
2017 + # (since python_gen_usedep() will not return ${PYTHON_USEDEP}
2018 + # the code is run at most once)
2019 + if [[ ${dep} == *'${PYTHON_USEDEP}'* ]]; then
2020 + local usedep=$(_python_gen_usedep "${@}")
2021 + dep=${dep//\$\{PYTHON_USEDEP\}/${usedep}}
2022 + fi
2023 +
2024 + matches+=( "python_targets_${impl}? ( ${dep} )" )
2025 + fi
2026 + done
2027 +
2028 + echo "${matches[@]}"
2029 +}
2030 +
2031 +# @FUNCTION: python_gen_impl_dep
2032 +# @USAGE: [<requested-use-flags> [<impl-pattern>...]]
2033 +# @DESCRIPTION:
2034 +# Output a dependency on Python implementations with the specified USE
2035 +# dependency string appended, or no USE dependency string if called
2036 +# without the argument (or with empty argument). If any implementation
2037 +# patterns are passed, the output dependencies will be generated only
2038 +# for the implementations matching them.
2039 +#
2040 +# The patterns can be either fnmatch-style patterns (matched via bash
2041 +# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
2042 +# appropriately all enabled Python 2/3 implementations (alike
2043 +# python_is_python3). Remember to escape or quote the fnmatch patterns
2044 +# to prevent accidental shell filename expansion.
2045 +#
2046 +# Use this function when you need to request different USE flags
2047 +# on the Python interpreter depending on package's USE flags. If you
2048 +# only need a single set of interpreter USE flags, just set
2049 +# PYTHON_REQ_USE and use ${PYTHON_DEPS} globally.
2050 +#
2051 +# Example:
2052 +# @CODE
2053 +# PYTHON_COMPAT=( python{2_7,3_{3,4}} pypy )
2054 +# RDEPEND="foo? ( $(python_gen_impl_dep 'xml(+)') )"
2055 +# @CODE
2056 +#
2057 +# It will cause the variable to look like:
2058 +# @CODE
2059 +# RDEPEND="foo? (
2060 +# python_targets_python2_7? (
2061 +# dev-lang/python:2.7[xml(+)] )
2062 +# python_targets_pypy? (
2063 +# dev-python/pypy[xml(+)] ) )"
2064 +# @CODE
2065 +python_gen_impl_dep() {
2066 + debug-print-function ${FUNCNAME} "${@}"
2067 +
2068 + local impl matches=()
2069 + local PYTHON_REQ_USE=${1}
2070 + shift
2071 +
2072 + for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
2073 + if _python_impl_matches "${impl}" "${@}"; then
2074 + local PYTHON_PKG_DEP
2075 + python_export "${impl}" PYTHON_PKG_DEP
2076 + matches+=( "python_targets_${impl}? ( ${PYTHON_PKG_DEP} )" )
2077 + fi
2078 + done
2079 +
2080 + echo "${matches[@]}"
2081 +}
2082 +
2083 +# @FUNCTION: python_gen_any_dep
2084 +# @USAGE: <dependency-block> [<impl-pattern>...]
2085 +# @DESCRIPTION:
2086 +# Generate an any-of dependency that enforces a version match between
2087 +# the Python interpreter and Python packages. <dependency-block> needs
2088 +# to list one or more dependencies with verbatim '${PYTHON_USEDEP}'
2089 +# references (quoted!) that will get expanded inside the function.
2090 +# Optionally, patterns may be specified to restrict the dependency
2091 +# to a subset of Python implementations supported by the ebuild.
2092 +#
2093 +# The patterns can be either fnmatch-style patterns (matched via bash
2094 +# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
2095 +# appropriately all enabled Python 2/3 implementations (alike
2096 +# python_is_python3). Remember to escape or quote the fnmatch patterns
2097 +# to prevent accidental shell filename expansion.
2098 +#
2099 +# This should be used along with an appropriate python_check_deps()
2100 +# that checks which of the any-of blocks were matched, and python_setup
2101 +# call that enables use of the matched implementation.
2102 +#
2103 +# Example use:
2104 +# @CODE
2105 +# DEPEND="$(python_gen_any_dep '
2106 +# dev-python/foo[${PYTHON_USEDEP}]
2107 +# || ( dev-python/bar[${PYTHON_USEDEP}]
2108 +# dev-python/baz[${PYTHON_USEDEP}] )' -2)"
2109 +#
2110 +# python_check_deps() {
2111 +# has_version "dev-python/foo[${PYTHON_USEDEP}]" \
2112 +# && { has_version "dev-python/bar[${PYTHON_USEDEP}]" \
2113 +# || has_version "dev-python/baz[${PYTHON_USEDEP}]"; }
2114 +# }
2115 +#
2116 +# src_compile() {
2117 +# python_foreach_impl usual_code
2118 +#
2119 +# # some common post-build task that requires Python 2
2120 +# python_setup -2
2121 +# emake frobnicate
2122 +# }
2123 +# @CODE
2124 +#
2125 +# Example value:
2126 +# @CODE
2127 +# || (
2128 +# (
2129 +# dev-lang/python:2.7
2130 +# dev-python/foo[python_targets_python2_7(-)?,python_single_target_python2_7(+)?]
2131 +# || ( dev-python/bar[python_targets_python2_7(-)?,python_single_target_python2_7(+)?]
2132 +# dev-python/baz[python_targets_python2_7(-)?,python_single_target_python2_7(+)?] )
2133 +# )
2134 +# (
2135 +# dev-lang/python:3.3
2136 +# dev-python/foo[python_targets_python3_3(-)?,python_single_target_python3_3(+)?]
2137 +# || ( dev-python/bar[python_targets_python3_3(-)?,python_single_target_python3_3(+)?]
2138 +# dev-python/baz[python_targets_python3_3(-)?,python_single_target_python3_3(+)?] )
2139 +# )
2140 +# )
2141 +# @CODE
2142 +python_gen_any_dep() {
2143 + debug-print-function ${FUNCNAME} "${@}"
2144 +
2145 + local depstr=${1}
2146 + [[ ${depstr} ]] || die "No dependency string provided"
2147 + shift
2148 +
2149 + local i PYTHON_PKG_DEP out=
2150 + for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
2151 + if _python_impl_matches "${i}" "${@}"; then
2152 + local PYTHON_USEDEP="python_targets_${i}(-),python_single_target_${i}(+)"
2153 + python_export "${i}" PYTHON_PKG_DEP
2154 +
2155 + local i_depstr=${depstr//\$\{PYTHON_USEDEP\}/${PYTHON_USEDEP}}
2156 + # note: need to strip '=' slot operator for || deps
2157 + out="( ${PYTHON_PKG_DEP/:0=/:0} ${i_depstr} ) ${out}"
2158 + fi
2159 + done
2160 + echo "|| ( ${out})"
2161 +}
2162 +
2163 +# @ECLASS-VARIABLE: BUILD_DIR
2164 +# @DESCRIPTION:
2165 +# The current build directory. In global scope, it is supposed to
2166 +# contain an initial build directory; if unset, it defaults to ${S}.
2167 +#
2168 +# In functions run by python_foreach_impl(), the BUILD_DIR is locally
2169 +# set to an implementation-specific build directory. That path is
2170 +# created through appending a hyphen and the implementation name
2171 +# to the final component of the initial BUILD_DIR.
2172 +#
2173 +# Example value:
2174 +# @CODE
2175 +# ${WORKDIR}/foo-1.3-python2_7
2176 +# @CODE
2177 +
2178 +# @FUNCTION: python_copy_sources
2179 +# @DESCRIPTION:
2180 +# Create a single copy of the package sources for each enabled Python
2181 +# implementation.
2182 +#
2183 +# The sources are always copied from initial BUILD_DIR (or S if unset)
2184 +# to implementation-specific build directory matching BUILD_DIR used by
2185 +# python_foreach_abi().
2186 +python_copy_sources() {
2187 + debug-print-function ${FUNCNAME} "${@}"
2188 +
2189 + local MULTIBUILD_VARIANTS
2190 + _python_obtain_impls
2191 +
2192 + multibuild_copy_sources
2193 +}
2194 +
2195 +# @FUNCTION: _python_obtain_impls
2196 +# @INTERNAL
2197 +# @DESCRIPTION:
2198 +# Set up the enabled implementation list.
2199 +_python_obtain_impls() {
2200 + _python_validate_useflags
2201 +
2202 + if [[ ${PYTHON_COMPAT_OVERRIDE} ]]; then
2203 + MULTIBUILD_VARIANTS=( ${PYTHON_COMPAT_OVERRIDE} )
2204 + return
2205 + fi
2206 +
2207 + MULTIBUILD_VARIANTS=()
2208 +
2209 + local impl
2210 + for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
2211 + has "${impl}" "${PYTHON_COMPAT[@]}" && \
2212 + use "python_targets_${impl}" && MULTIBUILD_VARIANTS+=( "${impl}" )
2213 + done
2214 +}
2215 +
2216 +# @FUNCTION: _python_multibuild_wrapper
2217 +# @USAGE: <command> [<args>...]
2218 +# @INTERNAL
2219 +# @DESCRIPTION:
2220 +# Initialize the environment for Python implementation selected
2221 +# for multibuild.
2222 +_python_multibuild_wrapper() {
2223 + debug-print-function ${FUNCNAME} "${@}"
2224 +
2225 + local -x EPYTHON PYTHON
2226 + local -x PATH=${PATH} PKG_CONFIG_PATH=${PKG_CONFIG_PATH}
2227 + python_export "${MULTIBUILD_VARIANT}" EPYTHON PYTHON
2228 + python_wrapper_setup
2229 +
2230 + "${@}"
2231 +}
2232 +
2233 +# @FUNCTION: python_foreach_impl
2234 +# @USAGE: <command> [<args>...]
2235 +# @DESCRIPTION:
2236 +# Run the given command for each of the enabled Python implementations.
2237 +# If additional parameters are passed, they will be passed through
2238 +# to the command.
2239 +#
2240 +# The function will return 0 status if all invocations succeed.
2241 +# Otherwise, the return code from first failing invocation will
2242 +# be returned.
2243 +#
2244 +# For each command being run, EPYTHON, PYTHON and BUILD_DIR are set
2245 +# locally, and the former two are exported to the command environment.
2246 +python_foreach_impl() {
2247 + debug-print-function ${FUNCNAME} "${@}"
2248 +
2249 + local MULTIBUILD_VARIANTS
2250 + _python_obtain_impls
2251 +
2252 + multibuild_foreach_variant _python_multibuild_wrapper "${@}"
2253 +}
2254 +
2255 +# @FUNCTION: python_setup
2256 +# @USAGE: [<impl-pattern>...]
2257 +# @DESCRIPTION:
2258 +# Find the best (most preferred) Python implementation that is suitable
2259 +# for running common Python code. Set the Python build environment up
2260 +# for that implementation. This function has two modes of operation:
2261 +# pure and any-of dep.
2262 +#
2263 +# The pure mode is used if python_check_deps() function is not declared.
2264 +# In this case, an implementation is considered suitable if it is
2265 +# supported (in PYTHON_COMPAT), enabled (via USE flags) and matches
2266 +# at least one of the patterns passed (or '*' if no patterns passed).
2267 +#
2268 +# Implementation restrictions in the pure mode need to be accompanied
2269 +# by appropriate REQUIRED_USE constraints. Otherwise, the eclass may
2270 +# fail at build time due to unsatisfied dependencies.
2271 +#
2272 +# The any-of dep mode is used if python_check_deps() is declared.
2273 +# In this mode, an implementation is considered suitable if it is
2274 +# supported, matches at least one of the patterns and python_check_deps()
2275 +# has successful return code. USE flags are not considered.
2276 +#
2277 +# The python_check_deps() function in the any-of mode needs to be
2278 +# accompanied by appropriate any-of dependencies.
2279 +#
2280 +# The patterns can be either fnmatch-style patterns (matched via bash
2281 +# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
2282 +# appropriately all enabled Python 2/3 implementations (alike
2283 +# python_is_python3). Remember to escape or quote the fnmatch patterns
2284 +# to prevent accidental shell filename expansion.
2285 +#
2286 +# This function needs to be used when Python is being called outside
2287 +# of python_foreach_impl calls (e.g. for shared processes like doc
2288 +# building). python_foreach_impl sets up the build environment itself.
2289 +#
2290 +# Pure mode example:
2291 +# @CODE
2292 +# DEPEND="doc? ( dev-python/epydoc[$(python_gen_usedep 'python2*')] )"
2293 +# REQUIRED_USE="doc? ( $(python_gen_useflags 'python2*') )"
2294 +#
2295 +# src_compile() {
2296 +# #...
2297 +# if use doc; then
2298 +# python_setup 'python2*'
2299 +# make doc
2300 +# fi
2301 +# }
2302 +# @CODE
2303 +#
2304 +# Any-of mode example:
2305 +# @CODE
2306 +# DEPEND="doc? (
2307 +# $(python_gen_any_dep 'dev-python/epydoc[${PYTHON_USEDEP}]' 'python2*') )"
2308 +#
2309 +# python_check_deps() {
2310 +# has_version "dev-python/epydoc[${PYTHON_USEDEP}]"
2311 +# }
2312 +#
2313 +# src_compile() {
2314 +# #...
2315 +# if use doc; then
2316 +# python_setup 'python2*'
2317 +# make doc
2318 +# fi
2319 +# }
2320 +# @CODE
2321 +python_setup() {
2322 + debug-print-function ${FUNCNAME} "${@}"
2323 +
2324 + _python_validate_useflags
2325 + local pycompat=( "${PYTHON_COMPAT[@]}" )
2326 + if [[ ${PYTHON_COMPAT_OVERRIDE} ]]; then
2327 + pycompat=( ${PYTHON_COMPAT_OVERRIDE} )
2328 + fi
2329 +
2330 + local has_check_deps
2331 + declare -f python_check_deps >/dev/null && has_check_deps=1
2332 +
2333 + # (reverse iteration -- newest impl first)
2334 + local found
2335 + for (( i = ${#_PYTHON_SUPPORTED_IMPLS[@]} - 1; i >= 0; i-- )); do
2336 + local impl=${_PYTHON_SUPPORTED_IMPLS[i]}
2337 +
2338 + # check PYTHON_COMPAT[_OVERRIDE]
2339 + has "${impl}" "${pycompat[@]}" || continue
2340 +
2341 + # match USE flags only if override is not in effect
2342 + # and python_check_deps() is not defined
2343 + if [[ ! ${PYTHON_COMPAT_OVERRIDE} && ! ${has_check_deps} ]]; then
2344 + use "python_targets_${impl}" || continue
2345 + fi
2346 +
2347 + # check patterns
2348 + _python_impl_matches "${impl}" "${@}" || continue
2349 +
2350 + python_export "${impl}" EPYTHON PYTHON
2351 +
2352 + # if python_check_deps() is declared, switch into any-of mode
2353 + if [[ ${has_check_deps} ]]; then
2354 + # first check if the interpreter is installed
2355 + python_is_installed "${impl}" || continue
2356 + # then run python_check_deps
2357 + local PYTHON_USEDEP="python_targets_${impl}(-),python_single_target_${impl}(+)"
2358 + python_check_deps || continue
2359 + fi
2360 +
2361 + found=1
2362 + break
2363 + done
2364 +
2365 + if [[ ! ${found} ]]; then
2366 + eerror "${FUNCNAME}: none of the enabled implementation matched the patterns."
2367 + eerror " patterns: ${@-'(*)'}"
2368 + eerror "Likely a REQUIRED_USE constraint (possibly USE-conditional) is missing."
2369 + eerror " suggested: || ( \$(python_gen_useflags ${@}) )"
2370 + eerror "(remember to quote all the patterns with '')"
2371 + die "${FUNCNAME}: no enabled implementation satisfy requirements"
2372 + fi
2373 +
2374 + python_wrapper_setup
2375 +}
2376 +
2377 +# @FUNCTION: python_replicate_script
2378 +# @USAGE: <path>...
2379 +# @DESCRIPTION:
2380 +# Copy the given script to variants for all enabled Python
2381 +# implementations, then replace it with a symlink to the wrapper.
2382 +#
2383 +# All specified files must start with a 'python' shebang. A file not
2384 +# having a matching shebang will be refused.
2385 +python_replicate_script() {
2386 + debug-print-function ${FUNCNAME} "${@}"
2387 +
2388 + _python_replicate_script() {
2389 + local _PYTHON_FIX_SHEBANG_QUIET=1
2390 +
2391 + local PYTHON_SCRIPTDIR
2392 + python_export PYTHON_SCRIPTDIR
2393 +
2394 + (
2395 + exeopts -m 0755
2396 + exeinto "${PYTHON_SCRIPTDIR#${EPREFIX}}"
2397 + doexe "${files[@]}"
2398 + )
2399 +
2400 + python_fix_shebang -q \
2401 + "${files[@]/*\//${D%/}/${PYTHON_SCRIPTDIR}/}"
2402 + }
2403 +
2404 + local files=( "${@}" )
2405 + python_foreach_impl _python_replicate_script
2406 + unset -f _python_replicate_script
2407 +
2408 + # install the wrappers
2409 + local f
2410 + for f; do
2411 + _python_ln_rel "${ED%/}/usr/lib/python-exec/python-exec2" "${f}" || die
2412 + done
2413 +}
2414 +
2415 +_PYTHON_R2=1
2416 +fi
2417 diff --git a/eclass/python-single-r2.eclass b/eclass/python-single-r2.eclass
2418 new file mode 100644
2419 index 000000000000..5bf6ea7221bc
2420 --- /dev/null
2421 +++ b/eclass/python-single-r2.eclass
2422 @@ -0,0 +1,507 @@
2423 +# Copyright 1999-2020 Gentoo Authors
2424 +# Distributed under the terms of the GNU General Public License v2
2425 +
2426 +# @ECLASS: python-single-r2.eclass
2427 +# @MAINTAINER:
2428 +# Python team <python@g.o>
2429 +# @AUTHOR:
2430 +# Author: Michał Górny <mgorny@g.o>
2431 +# @SUPPORTED_EAPIS: 5 6 7
2432 +# @BLURB: An eclass for Python packages not installed for multiple implementations.
2433 +# @DESCRIPTION:
2434 +# An extension of the python-r2 eclass suite for packages which
2435 +# don't support being installed for multiple Python implementations.
2436 +# This mostly includes tools embedding Python and packages using foreign
2437 +# build systems.
2438 +#
2439 +# This eclass sets correct IUSE. It also provides PYTHON_DEPS
2440 +# and PYTHON_REQUIRED_USE that need to be added to appropriate ebuild
2441 +# metadata variables.
2442 +#
2443 +# The eclass exports PYTHON_SINGLE_USEDEP that is suitable for depending
2444 +# on other packages using the eclass. Dependencies on packages using
2445 +# python-r2 should be created via python_gen_cond_dep() function,
2446 +# using PYTHON_MULTI_USEDEP placeholder.
2447 +#
2448 +# Please note that packages support multiple Python implementations
2449 +# (using python-r2 eclass) can not depend on packages not supporting
2450 +# them (using this eclass).
2451 +#
2452 +# Please note that python-single-r2 will always inherit python-utils-r2
2453 +# as well. Thus, all the functions defined there can be used
2454 +# in the packages using python-single-r2, and there is no need ever
2455 +# to inherit both.
2456 +
2457 +case "${EAPI:-0}" in
2458 + 0|1|2|3|4)
2459 + die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
2460 + ;;
2461 + 5|6|7)
2462 + # EAPI=5 is required for sane USE_EXPAND dependencies
2463 + ;;
2464 + *)
2465 + die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
2466 + ;;
2467 +esac
2468 +
2469 +if [[ ! ${_PYTHON_SINGLE_R2} ]]; then
2470 +
2471 +if [[ ${_PYTHON_R2} ]]; then
2472 + die 'python-single-r2.eclass can not be used with python-r2.eclass.'
2473 +elif [[ ${_PYTHON_ANY_R2} ]]; then
2474 + die 'python-single-r2.eclass can not be used with python-any-r2.eclass.'
2475 +fi
2476 +
2477 +inherit python-utils-r2
2478 +
2479 +fi
2480 +
2481 +EXPORT_FUNCTIONS pkg_setup
2482 +
2483 +# @ECLASS-VARIABLE: PYTHON_COMPAT
2484 +# @REQUIRED
2485 +# @DESCRIPTION:
2486 +# This variable contains a list of Python implementations the package
2487 +# supports. It must be set before the `inherit' call. It has to be
2488 +# an array.
2489 +#
2490 +# Example:
2491 +# @CODE
2492 +# PYTHON_COMPAT=( python2_7 python3_3 python3_4 )
2493 +# @CODE
2494 +#
2495 +# Please note that you can also use bash brace expansion if you like:
2496 +# @CODE
2497 +# PYTHON_COMPAT=( python2_7 python3_{3,4} )
2498 +# @CODE
2499 +
2500 +# @ECLASS-VARIABLE: PYTHON_COMPAT_OVERRIDE
2501 +# @INTERNAL
2502 +# @DESCRIPTION:
2503 +# This variable can be used when working with ebuilds to override
2504 +# the in-ebuild PYTHON_COMPAT. It is a string naming the implementation
2505 +# which package will be built for. It needs to be specified
2506 +# in the calling environment, and not in ebuilds.
2507 +#
2508 +# It should be noted that in order to preserve metadata immutability,
2509 +# PYTHON_COMPAT_OVERRIDE does not affect IUSE nor dependencies.
2510 +# The state of PYTHON_SINGLE_TARGET is ignored, and the implementation
2511 +# in PYTHON_COMPAT_OVERRIDE is built instead. Dependencies need to be
2512 +# satisfied manually.
2513 +#
2514 +# Example:
2515 +# @CODE
2516 +# PYTHON_COMPAT_OVERRIDE='pypy' emerge -1v dev-python/bar
2517 +# @CODE
2518 +
2519 +# @ECLASS-VARIABLE: PYTHON_REQ_USE
2520 +# @DEFAULT_UNSET
2521 +# @DESCRIPTION:
2522 +# The list of USEflags required to be enabled on the chosen Python
2523 +# implementations, formed as a USE-dependency string. It should be valid
2524 +# for all implementations in PYTHON_COMPAT, so it may be necessary to
2525 +# use USE defaults.
2526 +#
2527 +# This should be set before calling `inherit'.
2528 +#
2529 +# Example:
2530 +# @CODE
2531 +# PYTHON_REQ_USE="gdbm,ncurses(-)?"
2532 +# @CODE
2533 +#
2534 +# It will cause the Python dependencies to look like:
2535 +# @CODE
2536 +# python_single_target_pythonX_Y? ( dev-lang/python:X.Y[gdbm,ncurses(-)?] )
2537 +# @CODE
2538 +
2539 +# @ECLASS-VARIABLE: PYTHON_DEPS
2540 +# @DESCRIPTION:
2541 +# This is an eclass-generated Python dependency string for all
2542 +# implementations listed in PYTHON_COMPAT.
2543 +#
2544 +# The dependency string is conditional on PYTHON_SINGLE_TARGET.
2545 +#
2546 +# Example use:
2547 +# @CODE
2548 +# RDEPEND="${PYTHON_DEPS}
2549 +# dev-foo/mydep"
2550 +# DEPEND="${RDEPEND}"
2551 +# @CODE
2552 +#
2553 +# Example value:
2554 +# @CODE
2555 +# dev-lang/python-exec:=
2556 +# python_single_target_python2_7? ( dev-lang/python:2.7[gdbm] )
2557 +# python_single_target_pypy? ( dev-python/pypy[gdbm] )
2558 +# @CODE
2559 +
2560 +# @ECLASS-VARIABLE: PYTHON_SINGLE_USEDEP
2561 +# @DESCRIPTION:
2562 +# This is an eclass-generated USE-dependency string which can be used to
2563 +# depend on another python-single-r2 package being built for the same
2564 +# Python implementations.
2565 +#
2566 +# If you need to depend on a multi-impl (python-r2) package, use
2567 +# python_gen_cond_dep with PYTHON_MULTI_USEDEP placeholder instead.
2568 +#
2569 +# Example use:
2570 +# @CODE
2571 +# RDEPEND="dev-python/foo[${PYTHON_SINGLE_USEDEP}]"
2572 +# @CODE
2573 +#
2574 +# Example value:
2575 +# @CODE
2576 +# python_single_target_python3_4(-)?
2577 +# @CODE
2578 +
2579 +# @ECLASS-VARIABLE: PYTHON_MULTI_USEDEP
2580 +# @DESCRIPTION:
2581 +# This is a placeholder variable supported by python_gen_cond_dep,
2582 +# in order to depend on python-r2 packages built for the same Python
2583 +# implementations.
2584 +#
2585 +# Example use:
2586 +# @CODE
2587 +# RDEPEND="$(python_gen_cond_dep '
2588 +# dev-python/foo[${PYTHON_MULTI_USEDEP}]
2589 +# ')"
2590 +# @CODE
2591 +#
2592 +# Example value:
2593 +# @CODE
2594 +# python_targets_python3_4(-)
2595 +# @CODE
2596 +
2597 +# @ECLASS-VARIABLE: PYTHON_REQUIRED_USE
2598 +# @DESCRIPTION:
2599 +# This is an eclass-generated required-use expression which ensures
2600 +# that exactly one PYTHON_SINGLE_TARGET value has been enabled.
2601 +#
2602 +# This expression should be utilized in an ebuild by including it in
2603 +# REQUIRED_USE, optionally behind a use flag.
2604 +#
2605 +# Example use:
2606 +# @CODE
2607 +# REQUIRED_USE="python? ( ${PYTHON_REQUIRED_USE} )"
2608 +# @CODE
2609 +#
2610 +# Example value:
2611 +# @CODE
2612 +# ^^ ( python_single_target_python2_7 python_single_target_python3_3 )
2613 +# @CODE
2614 +
2615 +_python_single_set_globals() {
2616 + _python_set_impls
2617 +
2618 + local flags=( "${_PYTHON_SUPPORTED_IMPLS[@]/#/python_single_target_}" )
2619 +
2620 + if [[ ${#_PYTHON_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
2621 + # if only one implementation is supported, use IUSE defaults
2622 + # to avoid requesting the user to enable it
2623 + IUSE="+${flags[0]}"
2624 + else
2625 + IUSE="${flags[*]}"
2626 + fi
2627 +
2628 + local requse="^^ ( ${flags[*]} )"
2629 + local single_flags="${flags[@]/%/(-)?}"
2630 + local single_usedep=${single_flags// /,}
2631 +
2632 + local deps= i PYTHON_PKG_DEP
2633 + for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
2634 + python_export "${i}" PYTHON_PKG_DEP
2635 + # 1) well, python-exec would suffice as an RDEP
2636 + # but no point in making this overcomplex, BDEP doesn't hurt anyone
2637 + # 2) python-exec should be built with all targets forced anyway
2638 + # but if new targets were added, we may need to force a rebuild
2639 + deps+="python_single_target_${i}? (
2640 + ${PYTHON_PKG_DEP}
2641 + >=dev-lang/python-exec-2:=[python_targets_${i}]
2642 + ) "
2643 + done
2644 +
2645 + if [[ ${PYTHON_DEPS+1} ]]; then
2646 + if [[ ${PYTHON_DEPS} != "${deps}" ]]; then
2647 + eerror "PYTHON_DEPS have changed between inherits (PYTHON_REQ_USE?)!"
2648 + eerror "Before: ${PYTHON_DEPS}"
2649 + eerror "Now : ${deps}"
2650 + die "PYTHON_DEPS integrity check failed"
2651 + fi
2652 +
2653 + # these two are formality -- they depend on PYTHON_COMPAT only
2654 + if [[ ${PYTHON_REQUIRED_USE} != ${requse} ]]; then
2655 + eerror "PYTHON_REQUIRED_USE have changed between inherits!"
2656 + eerror "Before: ${PYTHON_REQUIRED_USE}"
2657 + eerror "Now : ${requse}"
2658 + die "PYTHON_REQUIRED_USE integrity check failed"
2659 + fi
2660 +
2661 + if [[ ${PYTHON_SINGLE_USEDEP} != "${single_usedep}" ]]; then
2662 + eerror "PYTHON_SINGLE_USEDEP have changed between inherits!"
2663 + eerror "Before: ${PYTHON_SINGLE_USEDEP}"
2664 + eerror "Now : ${single_usedep}"
2665 + die "PYTHON_SINGLE_USEDEP integrity check failed"
2666 + fi
2667 + else
2668 + PYTHON_DEPS=${deps}
2669 + PYTHON_REQUIRED_USE=${requse}
2670 + PYTHON_USEDEP='%PYTHON_USEDEP-HAS-BEEN-REMOVED%'
2671 + PYTHON_SINGLE_USEDEP=${single_usedep}
2672 + readonly PYTHON_DEPS PYTHON_REQUIRED_USE PYTHON_SINGLE_USEDEP \
2673 + PYTHON_USEDEP
2674 + fi
2675 +}
2676 +_python_single_set_globals
2677 +unset -f _python_single_set_globals
2678 +
2679 +if [[ ! ${_PYTHON_SINGLE_R2} ]]; then
2680 +
2681 +# @FUNCTION: _python_gen_usedep
2682 +# @INTERNAL
2683 +# @USAGE: [<pattern>...]
2684 +# @DESCRIPTION:
2685 +# Output a USE dependency string for Python implementations which
2686 +# are both in PYTHON_COMPAT and match any of the patterns passed
2687 +# as parameters to the function.
2688 +#
2689 +# The patterns can be either fnmatch-style patterns (matched via bash
2690 +# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
2691 +# appropriately all enabled Python 2/3 implementations (alike
2692 +# python_is_python3). Remember to escape or quote the fnmatch patterns
2693 +# to prevent accidental shell filename expansion.
2694 +#
2695 +# This is an internal function used to implement python_gen_cond_dep.
2696 +_python_gen_usedep() {
2697 + debug-print-function ${FUNCNAME} "${@}"
2698 +
2699 + local impl matches=()
2700 +
2701 + for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
2702 + if _python_impl_matches "${impl}" "${@}"; then
2703 + matches+=(
2704 + "python_single_target_${impl}(-)?"
2705 + )
2706 + fi
2707 + done
2708 +
2709 + [[ ${matches[@]} ]] || die "No supported implementations match python_gen_usedep patterns: ${@}"
2710 +
2711 + local out=${matches[@]}
2712 + echo "${out// /,}"
2713 +}
2714 +
2715 +# @FUNCTION: python_gen_useflags
2716 +# @USAGE: [<pattern>...]
2717 +# @DESCRIPTION:
2718 +# Output a list of USE flags for Python implementations which
2719 +# are both in PYTHON_COMPAT and match any of the patterns passed
2720 +# as parameters to the function.
2721 +#
2722 +# The patterns can be either fnmatch-style patterns (matched via bash
2723 +# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
2724 +# appropriately all enabled Python 2/3 implementations (alike
2725 +# python_is_python3). Remember to escape or quote the fnmatch patterns
2726 +# to prevent accidental shell filename expansion.
2727 +#
2728 +# Example:
2729 +# @CODE
2730 +# PYTHON_COMPAT=( python{2_7,3_4} )
2731 +# REQUIRED_USE="doc? ( ^^ ( $(python_gen_useflags 'python2*') ) )"
2732 +# @CODE
2733 +#
2734 +# It will cause the variable to look like:
2735 +# @CODE
2736 +# REQUIRED_USE="doc? ( ^^ ( python_single_target_python2_7 ) )"
2737 +# @CODE
2738 +python_gen_useflags() {
2739 + debug-print-function ${FUNCNAME} "${@}"
2740 +
2741 + local impl matches=()
2742 +
2743 + for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
2744 + if _python_impl_matches "${impl}" "${@}"; then
2745 + matches+=( "python_single_target_${impl}" )
2746 + fi
2747 + done
2748 +
2749 + echo "${matches[@]}"
2750 +}
2751 +
2752 +# @FUNCTION: python_gen_cond_dep
2753 +# @USAGE: <dependency> [<pattern>...]
2754 +# @DESCRIPTION:
2755 +# Output a list of <dependency>-ies made conditional to USE flags
2756 +# of Python implementations which are both in PYTHON_COMPAT and match
2757 +# any of the patterns passed as the remaining parameters.
2758 +#
2759 +# The patterns can be either fnmatch-style patterns (matched via bash
2760 +# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
2761 +# appropriately all enabled Python 2/3 implementations (alike
2762 +# python_is_python3). Remember to escape or quote the fnmatch patterns
2763 +# to prevent accidental shell filename expansion.
2764 +#
2765 +# In order to enforce USE constraints on the packages, verbatim
2766 +# '${PYTHON_SINGLE_USEDEP}' and '${PYTHON_MULTI_USEDEP}' (quoted!) may
2767 +# be placed in the dependency specification. It will get expanded within
2768 +# the function into a proper USE dependency string.
2769 +#
2770 +# Example:
2771 +# @CODE
2772 +# PYTHON_COMPAT=( python{2_7,3_{3,4}} pypy )
2773 +# RDEPEND="$(python_gen_cond_dep \
2774 +# 'dev-python/unittest2[${PYTHON_MULTI_USEDEP}]' python2_7 pypy )"
2775 +# @CODE
2776 +#
2777 +# It will cause the variable to look like:
2778 +# @CODE
2779 +# RDEPEND="python_single_target_python2_7? (
2780 +# dev-python/unittest2[python_targets_python2_7(-)?,...] )
2781 +# python_single_target_pypy? (
2782 +# dev-python/unittest2[python_targets_pypy(-)?,...] )"
2783 +# @CODE
2784 +python_gen_cond_dep() {
2785 + debug-print-function ${FUNCNAME} "${@}"
2786 +
2787 + local impl matches=()
2788 +
2789 + local dep=${1}
2790 + shift
2791 +
2792 + for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
2793 + if _python_impl_matches "${impl}" "${@}"; then
2794 + # substitute ${PYTHON_SINGLE_USEDEP} if used
2795 + # (since python_gen_usedep() will not return
2796 + # ${PYTHON_SINGLE_USEDEP}, the code is run at most once)
2797 + if [[ ${dep} == *'${PYTHON_SINGLE_USEDEP}'* ]]; then
2798 + local usedep=$(_python_gen_usedep "${@}")
2799 + dep=${dep//\$\{PYTHON_SINGLE_USEDEP\}/${usedep}}
2800 + fi
2801 + local multi_usedep="python_targets_${impl}(-)"
2802 +
2803 + matches+=( "python_single_target_${impl}? (
2804 + ${dep//\$\{PYTHON_MULTI_USEDEP\}/${multi_usedep}} )" )
2805 + fi
2806 + done
2807 +
2808 + echo "${matches[@]}"
2809 +}
2810 +
2811 +# @FUNCTION: python_gen_impl_dep
2812 +# @USAGE: [<requested-use-flags> [<impl-pattern>...]]
2813 +# @DESCRIPTION:
2814 +# Output a dependency on Python implementations with the specified USE
2815 +# dependency string appended, or no USE dependency string if called
2816 +# without the argument (or with empty argument). If any implementation
2817 +# patterns are passed, the output dependencies will be generated only
2818 +# for the implementations matching them.
2819 +#
2820 +# The patterns can be either fnmatch-style patterns (matched via bash
2821 +# == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
2822 +# appropriately all enabled Python 2/3 implementations (alike
2823 +# python_is_python3). Remember to escape or quote the fnmatch patterns
2824 +# to prevent accidental shell filename expansion.
2825 +#
2826 +# Use this function when you need to request different USE flags
2827 +# on the Python interpreter depending on package's USE flags. If you
2828 +# only need a single set of interpreter USE flags, just set
2829 +# PYTHON_REQ_USE and use ${PYTHON_DEPS} globally.
2830 +#
2831 +# Example:
2832 +# @CODE
2833 +# PYTHON_COMPAT=( python{2_7,3_{3,4}} pypy )
2834 +# RDEPEND="foo? ( $(python_gen_impl_dep 'xml(+)') )"
2835 +# @CODE
2836 +#
2837 +# It will cause the variable to look like:
2838 +# @CODE
2839 +# RDEPEND="foo? (
2840 +# python_single_target_python2_7? (
2841 +# dev-lang/python:2.7[xml(+)] )
2842 +# python_single_target_pypy? (
2843 +# dev-python/pypy[xml(+)] ) )"
2844 +# @CODE
2845 +python_gen_impl_dep() {
2846 + debug-print-function ${FUNCNAME} "${@}"
2847 +
2848 + local impl
2849 + local matches=()
2850 +
2851 + local PYTHON_REQ_USE=${1}
2852 + shift
2853 +
2854 + for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
2855 + if _python_impl_matches "${impl}" "${@}"; then
2856 + local PYTHON_PKG_DEP
2857 + python_export "${impl}" PYTHON_PKG_DEP
2858 + matches+=( "python_single_target_${impl}? ( ${PYTHON_PKG_DEP} )" )
2859 + fi
2860 + done
2861 +
2862 + echo "${matches[@]}"
2863 +}
2864 +
2865 +# @FUNCTION: python_setup
2866 +# @DESCRIPTION:
2867 +# Determine what the selected Python implementation is and set
2868 +# the Python build environment up for it.
2869 +python_setup() {
2870 + debug-print-function ${FUNCNAME} "${@}"
2871 +
2872 + unset EPYTHON
2873 +
2874 + # support developer override
2875 + if [[ ${PYTHON_COMPAT_OVERRIDE} ]]; then
2876 + local impls=( ${PYTHON_COMPAT_OVERRIDE} )
2877 + [[ ${#impls[@]} -eq 1 ]] || die "PYTHON_COMPAT_OVERRIDE must name exactly one implementation for python-single-r2"
2878 +
2879 + ewarn "WARNING: PYTHON_COMPAT_OVERRIDE in effect. The following Python"
2880 + ewarn "implementation will be used:"
2881 + ewarn
2882 + ewarn " ${PYTHON_COMPAT_OVERRIDE}"
2883 + ewarn
2884 + ewarn "Dependencies won't be satisfied, and PYTHON_SINGLE_TARGET flags will be ignored."
2885 +
2886 + python_export "${impls[0]}" EPYTHON PYTHON
2887 + python_wrapper_setup
2888 + return
2889 + fi
2890 +
2891 + local impl
2892 + for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
2893 + if use "python_single_target_${impl}"; then
2894 + if [[ ${EPYTHON} ]]; then
2895 + eerror "Your PYTHON_SINGLE_TARGET setting lists more than a single Python"
2896 + eerror "implementation. Please set it to just one value. If you need"
2897 + eerror "to override the value for a single package, please use package.env"
2898 + eerror "or an equivalent solution (man 5 portage)."
2899 + echo
2900 + die "More than one implementation in PYTHON_SINGLE_TARGET."
2901 + fi
2902 +
2903 + python_export "${impl}" EPYTHON PYTHON
2904 + python_wrapper_setup
2905 + fi
2906 + done
2907 +
2908 + if [[ ! ${EPYTHON} ]]; then
2909 + eerror "No Python implementation selected for the build. Please set"
2910 + eerror "the PYTHON_SINGLE_TARGET variable in your make.conf to one"
2911 + eerror "of the following values:"
2912 + eerror
2913 + eerror "${_PYTHON_SUPPORTED_IMPLS[@]}"
2914 + echo
2915 + die "No supported Python implementation in PYTHON_SINGLE_TARGET."
2916 + fi
2917 +}
2918 +
2919 +# @FUNCTION: python-single-r2_pkg_setup
2920 +# @DESCRIPTION:
2921 +# Runs python_setup.
2922 +python-single-r2_pkg_setup() {
2923 + debug-print-function ${FUNCNAME} "${@}"
2924 +
2925 + [[ ${MERGE_TYPE} != binary ]] && python_setup
2926 +}
2927 +
2928 +_PYTHON_SINGLE_R2=1
2929 +fi
2930 diff --git a/eclass/python-utils-r2.eclass b/eclass/python-utils-r2.eclass
2931 new file mode 100644
2932 index 000000000000..9821c043021a
2933 --- /dev/null
2934 +++ b/eclass/python-utils-r2.eclass
2935 @@ -0,0 +1,1518 @@
2936 +# Copyright 1999-2020 Gentoo Authors
2937 +# Distributed under the terms of the GNU General Public License v2
2938 +
2939 +# @ECLASS: python-utils-r2.eclass
2940 +# @MAINTAINER:
2941 +# Python team <python@g.o>
2942 +# @AUTHOR:
2943 +# Author: Michał Górny <mgorny@g.o>
2944 +# @SUPPORTED_EAPIS: 5 6 7
2945 +# @BLURB: Utility functions for packages with Python parts.
2946 +# @DESCRIPTION:
2947 +# A utility eclass providing functions to query Python implementations,
2948 +# install Python modules and scripts.
2949 +#
2950 +# This eclass does not set any metadata variables nor export any phase
2951 +# functions. It can be inherited safely.
2952 +
2953 +case "${EAPI:-0}" in
2954 + [0-4]) die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}" ;;
2955 + [5-7]) ;;
2956 + *) die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" ;;
2957 +esac
2958 +
2959 +if [[ ${_PYTHON_UTILS_R1} ]]; then
2960 + die 'python-r2 suite eclasses can not be combined with python-r1 suite.'
2961 +fi
2962 +
2963 +if [[ ! ${_PYTHON_UTILS_R2} ]]; then
2964 +
2965 +[[ ${EAPI} == 5 ]] && inherit eutils multilib
2966 +inherit toolchain-funcs
2967 +
2968 +# @ECLASS-VARIABLE: _PYTHON_ALL_IMPLS
2969 +# @INTERNAL
2970 +# @DESCRIPTION:
2971 +# All supported Python implementations, most preferred last.
2972 +_PYTHON_ALL_IMPLS=(
2973 + pypy3
2974 + python2_7
2975 + python3_6 python3_7 python3_8
2976 +)
2977 +readonly _PYTHON_ALL_IMPLS
2978 +
2979 +# @ECLASS-VARIABLE: PYTHON_COMPAT_NO_STRICT
2980 +# @INTERNAL
2981 +# @DESCRIPTION:
2982 +# Set to a non-empty value in order to make eclass tolerate (ignore)
2983 +# unknown implementations in PYTHON_COMPAT.
2984 +#
2985 +# This is intended to be set by the user when using ebuilds that may
2986 +# have unknown (newer) implementations in PYTHON_COMPAT. The assumption
2987 +# is that the ebuilds are intended to be used within multiple contexts
2988 +# which can involve revisions of this eclass that support a different
2989 +# set of Python implementations.
2990 +
2991 +# @FUNCTION: _python_impl_supported
2992 +# @USAGE: <impl>
2993 +# @INTERNAL
2994 +# @DESCRIPTION:
2995 +# Check whether the implementation <impl> (PYTHON_COMPAT-form)
2996 +# is still supported.
2997 +#
2998 +# Returns 0 if the implementation is valid and supported. If it is
2999 +# unsupported, returns 1 -- and the caller should ignore the entry.
3000 +# If it is invalid, dies with an appopriate error messages.
3001 +_python_impl_supported() {
3002 + debug-print-function ${FUNCNAME} "${@}"
3003 +
3004 + [[ ${#} -eq 1 ]] || die "${FUNCNAME}: takes exactly 1 argument (impl)."
3005 +
3006 + local impl=${1}
3007 +
3008 + # keep in sync with _PYTHON_ALL_IMPLS!
3009 + # (not using that list because inline patterns shall be faster)
3010 + case "${impl}" in
3011 + python2_7|python3_[678]|pypy3)
3012 + return 0
3013 + ;;
3014 + jython2_7|pypy|pypy1_[89]|pypy2_0|python2_[56]|python3_[12345])
3015 + return 1
3016 + ;;
3017 + *)
3018 + [[ ${PYTHON_COMPAT_NO_STRICT} ]] && return 1
3019 + die "Invalid implementation in PYTHON_COMPAT: ${impl}"
3020 + esac
3021 +}
3022 +
3023 +# @FUNCTION: _python_set_impls
3024 +# @INTERNAL
3025 +# @DESCRIPTION:
3026 +# Check PYTHON_COMPAT for well-formedness and validity, then set
3027 +# two global variables:
3028 +#
3029 +# - _PYTHON_SUPPORTED_IMPLS containing valid implementations supported
3030 +# by the ebuild (PYTHON_COMPAT - dead implementations),
3031 +#
3032 +# - and _PYTHON_UNSUPPORTED_IMPLS containing valid implementations that
3033 +# are not supported by the ebuild.
3034 +#
3035 +# Implementations in both variables are ordered using the pre-defined
3036 +# eclass implementation ordering.
3037 +#
3038 +# This function must be called once in global scope by an eclass
3039 +# utilizing PYTHON_COMPAT.
3040 +_python_set_impls() {
3041 + local i
3042 +
3043 + if ! declare -p PYTHON_COMPAT &>/dev/null; then
3044 + die 'PYTHON_COMPAT not declared.'
3045 + fi
3046 + if [[ $(declare -p PYTHON_COMPAT) != "declare -a"* ]]; then
3047 + die 'PYTHON_COMPAT must be an array.'
3048 + fi
3049 + for i in "${PYTHON_COMPAT[@]}"; do
3050 + # trigger validity checks
3051 + _python_impl_supported "${i}"
3052 + done
3053 +
3054 + local supp=() unsupp=()
3055 +
3056 + for i in "${_PYTHON_ALL_IMPLS[@]}"; do
3057 + if has "${i}" "${PYTHON_COMPAT[@]}"; then
3058 + supp+=( "${i}" )
3059 + else
3060 + unsupp+=( "${i}" )
3061 + fi
3062 + done
3063 +
3064 + if [[ ! ${supp[@]} ]]; then
3065 + die "No supported implementation in PYTHON_COMPAT."
3066 + fi
3067 +
3068 + if [[ ${_PYTHON_SUPPORTED_IMPLS[@]} ]]; then
3069 + # set once already, verify integrity
3070 + if [[ ${_PYTHON_SUPPORTED_IMPLS[@]} != ${supp[@]} ]]; then
3071 + eerror "Supported impls (PYTHON_COMPAT) changed between inherits!"
3072 + eerror "Before: ${_PYTHON_SUPPORTED_IMPLS[*]}"
3073 + eerror "Now : ${supp[*]}"
3074 + die "_PYTHON_SUPPORTED_IMPLS integrity check failed"
3075 + fi
3076 + if [[ ${_PYTHON_UNSUPPORTED_IMPLS[@]} != ${unsupp[@]} ]]; then
3077 + eerror "Unsupported impls changed between inherits!"
3078 + eerror "Before: ${_PYTHON_UNSUPPORTED_IMPLS[*]}"
3079 + eerror "Now : ${unsupp[*]}"
3080 + die "_PYTHON_UNSUPPORTED_IMPLS integrity check failed"
3081 + fi
3082 + else
3083 + _PYTHON_SUPPORTED_IMPLS=( "${supp[@]}" )
3084 + _PYTHON_UNSUPPORTED_IMPLS=( "${unsupp[@]}" )
3085 + readonly _PYTHON_SUPPORTED_IMPLS _PYTHON_UNSUPPORTED_IMPLS
3086 + fi
3087 +}
3088 +
3089 +# @FUNCTION: _python_impl_matches
3090 +# @USAGE: <impl> [<pattern>...]
3091 +# @INTERNAL
3092 +# @DESCRIPTION:
3093 +# Check whether the specified <impl> matches at least one
3094 +# of the patterns following it. Return 0 if it does, 1 otherwise.
3095 +# Matches if no patterns are provided.
3096 +#
3097 +# <impl> can be in PYTHON_COMPAT or EPYTHON form. The patterns can be
3098 +# either:
3099 +# a) fnmatch-style patterns, e.g. 'python2*', 'pypy'...
3100 +# b) '-2' to indicate all Python 2 variants (= !python_is_python3)
3101 +# c) '-3' to indicate all Python 3 variants (= python_is_python3)
3102 +_python_impl_matches() {
3103 + [[ ${#} -ge 1 ]] || die "${FUNCNAME}: takes at least 1 parameter"
3104 + [[ ${#} -eq 1 ]] && return 0
3105 +
3106 + local impl=${1} pattern
3107 + shift
3108 +
3109 + for pattern; do
3110 + if [[ ${pattern} == -2 ]]; then
3111 + python_is_python3 "${impl}" || return 0
3112 + elif [[ ${pattern} == -3 ]]; then
3113 + python_is_python3 "${impl}" && return 0
3114 + return
3115 + # unify value style to allow lax matching
3116 + elif [[ ${impl/./_} == ${pattern/./_} ]]; then
3117 + return 0
3118 + fi
3119 + done
3120 +
3121 + return 1
3122 +}
3123 +
3124 +# @ECLASS-VARIABLE: PYTHON
3125 +# @DEFAULT_UNSET
3126 +# @DESCRIPTION:
3127 +# The absolute path to the current Python interpreter.
3128 +#
3129 +# This variable is set automatically in the following contexts:
3130 +#
3131 +# python-r2: Set in functions called by python_foreach_impl() or after
3132 +# calling python_export_best().
3133 +#
3134 +# python-single-r2: Set after calling python-single-r2_pkg_setup().
3135 +#
3136 +# distutils-r2: Set within any of the python sub-phase functions.
3137 +#
3138 +# Example value:
3139 +# @CODE
3140 +# /usr/bin/python2.7
3141 +# @CODE
3142 +
3143 +# @ECLASS-VARIABLE: EPYTHON
3144 +# @DEFAULT_UNSET
3145 +# @DESCRIPTION:
3146 +# The executable name of the current Python interpreter.
3147 +#
3148 +# This variable is set automatically in the following contexts:
3149 +#
3150 +# python-r2: Set in functions called by python_foreach_impl() or after
3151 +# calling python_export_best().
3152 +#
3153 +# python-single-r2: Set after calling python-single-r2_pkg_setup().
3154 +#
3155 +# distutils-r2: Set within any of the python sub-phase functions.
3156 +#
3157 +# Example value:
3158 +# @CODE
3159 +# python2.7
3160 +# @CODE
3161 +
3162 +# @ECLASS-VARIABLE: PYTHON_SITEDIR
3163 +# @DEFAULT_UNSET
3164 +# @DESCRIPTION:
3165 +# The path to Python site-packages directory.
3166 +#
3167 +# Set and exported on request using python_export().
3168 +# Requires a proper build-time dependency on the Python implementation.
3169 +#
3170 +# Example value:
3171 +# @CODE
3172 +# /usr/lib64/python2.7/site-packages
3173 +# @CODE
3174 +
3175 +# @ECLASS-VARIABLE: PYTHON_INCLUDEDIR
3176 +# @DEFAULT_UNSET
3177 +# @DESCRIPTION:
3178 +# The path to Python include directory.
3179 +#
3180 +# Set and exported on request using python_export().
3181 +# Requires a proper build-time dependency on the Python implementation.
3182 +#
3183 +# Example value:
3184 +# @CODE
3185 +# /usr/include/python2.7
3186 +# @CODE
3187 +
3188 +# @ECLASS-VARIABLE: PYTHON_LIBPATH
3189 +# @DEFAULT_UNSET
3190 +# @DESCRIPTION:
3191 +# The path to Python library.
3192 +#
3193 +# Set and exported on request using python_export().
3194 +# Valid only for CPython. Requires a proper build-time dependency
3195 +# on the Python implementation.
3196 +#
3197 +# Example value:
3198 +# @CODE
3199 +# /usr/lib64/libpython2.7.so
3200 +# @CODE
3201 +
3202 +# @ECLASS-VARIABLE: PYTHON_CFLAGS
3203 +# @DEFAULT_UNSET
3204 +# @DESCRIPTION:
3205 +# Proper C compiler flags for building against Python. Obtained from
3206 +# pkg-config or python-config.
3207 +#
3208 +# Set and exported on request using python_export().
3209 +# Valid only for CPython. Requires a proper build-time dependency
3210 +# on the Python implementation and on pkg-config.
3211 +#
3212 +# Example value:
3213 +# @CODE
3214 +# -I/usr/include/python2.7
3215 +# @CODE
3216 +
3217 +# @ECLASS-VARIABLE: PYTHON_LIBS
3218 +# @DEFAULT_UNSET
3219 +# @DESCRIPTION:
3220 +# Proper C compiler flags for linking against Python. Obtained from
3221 +# pkg-config or python-config.
3222 +#
3223 +# Set and exported on request using python_export().
3224 +# Valid only for CPython. Requires a proper build-time dependency
3225 +# on the Python implementation and on pkg-config.
3226 +#
3227 +# Example value:
3228 +# @CODE
3229 +# -lpython2.7
3230 +# @CODE
3231 +
3232 +# @ECLASS-VARIABLE: PYTHON_CONFIG
3233 +# @DEFAULT_UNSET
3234 +# @DESCRIPTION:
3235 +# Path to the python-config executable.
3236 +#
3237 +# Set and exported on request using python_export().
3238 +# Valid only for CPython. Requires a proper build-time dependency
3239 +# on the Python implementation and on pkg-config.
3240 +#
3241 +# Example value:
3242 +# @CODE
3243 +# /usr/bin/python2.7-config
3244 +# @CODE
3245 +
3246 +# @ECLASS-VARIABLE: PYTHON_PKG_DEP
3247 +# @DEFAULT_UNSET
3248 +# @DESCRIPTION:
3249 +# The complete dependency on a particular Python package as a string.
3250 +#
3251 +# Set and exported on request using python_export().
3252 +#
3253 +# Example value:
3254 +# @CODE
3255 +# dev-lang/python:2.7[xml]
3256 +# @CODE
3257 +
3258 +# @ECLASS-VARIABLE: PYTHON_SCRIPTDIR
3259 +# @DEFAULT_UNSET
3260 +# @DESCRIPTION:
3261 +# The location where Python scripts must be installed for current impl.
3262 +#
3263 +# Set and exported on request using python_export().
3264 +#
3265 +# Example value:
3266 +# @CODE
3267 +# /usr/lib/python-exec/python2.7
3268 +# @CODE
3269 +
3270 +# @FUNCTION: python_export
3271 +# @USAGE: [<impl>] <variables>...
3272 +# @DESCRIPTION:
3273 +# Set and export the Python implementation-relevant variables passed
3274 +# as parameters.
3275 +#
3276 +# The optional first parameter may specify the requested Python
3277 +# implementation (either as PYTHON_TARGETS value, e.g. python2_7,
3278 +# or an EPYTHON one, e.g. python2.7). If no implementation passed,
3279 +# the current one will be obtained from ${EPYTHON}.
3280 +#
3281 +# The variables which can be exported are: PYTHON, EPYTHON,
3282 +# PYTHON_SITEDIR. They are described more completely in the eclass
3283 +# variable documentation.
3284 +python_export() {
3285 + debug-print-function ${FUNCNAME} "${@}"
3286 +
3287 + local impl var
3288 +
3289 + case "${1}" in
3290 + python*|jython*)
3291 + impl=${1/_/.}
3292 + shift
3293 + ;;
3294 + pypy|pypy3)
3295 + impl=${1}
3296 + shift
3297 + ;;
3298 + *)
3299 + impl=${EPYTHON}
3300 + if [[ -z ${impl} ]]; then
3301 + die "python_export called without a python implementation and EPYTHON is unset"
3302 + fi
3303 + ;;
3304 + esac
3305 + debug-print "${FUNCNAME}: implementation: ${impl}"
3306 +
3307 + for var; do
3308 + case "${var}" in
3309 + EPYTHON)
3310 + export EPYTHON=${impl}
3311 + debug-print "${FUNCNAME}: EPYTHON = ${EPYTHON}"
3312 + ;;
3313 + PYTHON)
3314 + export PYTHON=${EPREFIX}/usr/bin/${impl}
3315 + debug-print "${FUNCNAME}: PYTHON = ${PYTHON}"
3316 + ;;
3317 + PYTHON_SITEDIR)
3318 + [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
3319 + # sysconfig can't be used because:
3320 + # 1) pypy doesn't give site-packages but stdlib
3321 + # 2) jython gives paths with wrong case
3322 + PYTHON_SITEDIR=$("${PYTHON}" -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_lib())') || die
3323 + export PYTHON_SITEDIR
3324 + debug-print "${FUNCNAME}: PYTHON_SITEDIR = ${PYTHON_SITEDIR}"
3325 + ;;
3326 + PYTHON_INCLUDEDIR)
3327 + [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
3328 + PYTHON_INCLUDEDIR=$("${PYTHON}" -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_inc())') || die
3329 + export PYTHON_INCLUDEDIR
3330 + debug-print "${FUNCNAME}: PYTHON_INCLUDEDIR = ${PYTHON_INCLUDEDIR}"
3331 +
3332 + # Jython gives a non-existing directory
3333 + if [[ ! -d ${PYTHON_INCLUDEDIR} ]]; then
3334 + die "${impl} does not install any header files!"
3335 + fi
3336 + ;;
3337 + PYTHON_LIBPATH)
3338 + [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
3339 + 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
3340 + export PYTHON_LIBPATH
3341 + debug-print "${FUNCNAME}: PYTHON_LIBPATH = ${PYTHON_LIBPATH}"
3342 +
3343 + if [[ ! ${PYTHON_LIBPATH} ]]; then
3344 + die "${impl} lacks a (usable) dynamic library"
3345 + fi
3346 + ;;
3347 + PYTHON_CFLAGS)
3348 + local val
3349 +
3350 + case "${impl}" in
3351 + python*)
3352 + # python-2.7, python-3.2, etc.
3353 + val=$($(tc-getPKG_CONFIG) --cflags ${impl/n/n-}) || die
3354 + ;;
3355 + *)
3356 + die "${impl}: obtaining ${var} not supported"
3357 + ;;
3358 + esac
3359 +
3360 + export PYTHON_CFLAGS=${val}
3361 + debug-print "${FUNCNAME}: PYTHON_CFLAGS = ${PYTHON_CFLAGS}"
3362 + ;;
3363 + PYTHON_LIBS)
3364 + local val
3365 +
3366 + case "${impl}" in
3367 + python*)
3368 + # python-2.7, python-3.2, etc.
3369 + val=$($(tc-getPKG_CONFIG) --libs ${impl/n/n-}) || die
3370 + ;;
3371 + *)
3372 + die "${impl}: obtaining ${var} not supported"
3373 + ;;
3374 + esac
3375 +
3376 + export PYTHON_LIBS=${val}
3377 + debug-print "${FUNCNAME}: PYTHON_LIBS = ${PYTHON_LIBS}"
3378 + ;;
3379 + PYTHON_CONFIG)
3380 + local flags val
3381 +
3382 + case "${impl}" in
3383 + python*)
3384 + [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
3385 + flags=$("${PYTHON}" -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS") or "")') || die
3386 + val=${PYTHON}${flags}-config
3387 + ;;
3388 + *)
3389 + die "${impl}: obtaining ${var} not supported"
3390 + ;;
3391 + esac
3392 +
3393 + export PYTHON_CONFIG=${val}
3394 + debug-print "${FUNCNAME}: PYTHON_CONFIG = ${PYTHON_CONFIG}"
3395 + ;;
3396 + PYTHON_PKG_DEP)
3397 + local d
3398 + case ${impl} in
3399 + python2.7)
3400 + PYTHON_PKG_DEP='>=dev-lang/python-2.7.5-r2:2.7';;
3401 + python3.3)
3402 + PYTHON_PKG_DEP='>=dev-lang/python-3.3.2-r2:3.3';;
3403 + python*)
3404 + PYTHON_PKG_DEP="dev-lang/python:${impl#python}";;
3405 + pypy)
3406 + PYTHON_PKG_DEP='>=dev-python/pypy-5:0=';;
3407 + pypy3)
3408 + PYTHON_PKG_DEP='>=dev-python/pypy3-5:0=';;
3409 + jython2.7)
3410 + PYTHON_PKG_DEP='dev-java/jython:2.7';;
3411 + *)
3412 + die "Invalid implementation: ${impl}"
3413 + esac
3414 +
3415 + # use-dep
3416 + if [[ ${PYTHON_REQ_USE} ]]; then
3417 + PYTHON_PKG_DEP+=[${PYTHON_REQ_USE}]
3418 + fi
3419 +
3420 + export PYTHON_PKG_DEP
3421 + debug-print "${FUNCNAME}: PYTHON_PKG_DEP = ${PYTHON_PKG_DEP}"
3422 + ;;
3423 + PYTHON_SCRIPTDIR)
3424 + local dir
3425 + export PYTHON_SCRIPTDIR=${EPREFIX}/usr/lib/python-exec/${impl}
3426 + debug-print "${FUNCNAME}: PYTHON_SCRIPTDIR = ${PYTHON_SCRIPTDIR}"
3427 + ;;
3428 + *)
3429 + die "python_export: unknown variable ${var}"
3430 + esac
3431 + done
3432 +}
3433 +
3434 +# @FUNCTION: python_get_sitedir
3435 +# @USAGE: [<impl>]
3436 +# @DESCRIPTION:
3437 +# Obtain and print the 'site-packages' path for the given
3438 +# implementation. If no implementation is provided, ${EPYTHON} will
3439 +# be used.
3440 +#
3441 +# If you just need to have PYTHON_SITEDIR set (and exported), then it is
3442 +# better to use python_export() directly instead.
3443 +python_get_sitedir() {
3444 + debug-print-function ${FUNCNAME} "${@}"
3445 +
3446 + python_export "${@}" PYTHON_SITEDIR
3447 + echo "${PYTHON_SITEDIR}"
3448 +}
3449 +
3450 +# @FUNCTION: python_get_includedir
3451 +# @USAGE: [<impl>]
3452 +# @DESCRIPTION:
3453 +# Obtain and print the include path for the given implementation. If no
3454 +# implementation is provided, ${EPYTHON} will be used.
3455 +#
3456 +# If you just need to have PYTHON_INCLUDEDIR set (and exported), then it
3457 +# is better to use python_export() directly instead.
3458 +python_get_includedir() {
3459 + debug-print-function ${FUNCNAME} "${@}"
3460 +
3461 + python_export "${@}" PYTHON_INCLUDEDIR
3462 + echo "${PYTHON_INCLUDEDIR}"
3463 +}
3464 +
3465 +# @FUNCTION: python_get_library_path
3466 +# @USAGE: [<impl>]
3467 +# @DESCRIPTION:
3468 +# Obtain and print the Python library path for the given implementation.
3469 +# If no implementation is provided, ${EPYTHON} will be used.
3470 +#
3471 +# Please note that this function can be used with CPython only. Use
3472 +# in another implementation will result in a fatal failure.
3473 +python_get_library_path() {
3474 + debug-print-function ${FUNCNAME} "${@}"
3475 +
3476 + python_export "${@}" PYTHON_LIBPATH
3477 + echo "${PYTHON_LIBPATH}"
3478 +}
3479 +
3480 +# @FUNCTION: python_get_CFLAGS
3481 +# @USAGE: [<impl>]
3482 +# @DESCRIPTION:
3483 +# Obtain and print the compiler flags for building against Python,
3484 +# for the given implementation. If no implementation is provided,
3485 +# ${EPYTHON} will be used.
3486 +#
3487 +# Please note that this function can be used with CPython only.
3488 +# It requires Python and pkg-config installed, and therefore proper
3489 +# build-time dependencies need be added to the ebuild.
3490 +python_get_CFLAGS() {
3491 + debug-print-function ${FUNCNAME} "${@}"
3492 +
3493 + python_export "${@}" PYTHON_CFLAGS
3494 + echo "${PYTHON_CFLAGS}"
3495 +}
3496 +
3497 +# @FUNCTION: python_get_LIBS
3498 +# @USAGE: [<impl>]
3499 +# @DESCRIPTION:
3500 +# Obtain and print the compiler flags for linking against Python,
3501 +# for the given implementation. If no implementation is provided,
3502 +# ${EPYTHON} will be used.
3503 +#
3504 +# Please note that this function can be used with CPython only.
3505 +# It requires Python and pkg-config installed, and therefore proper
3506 +# build-time dependencies need be added to the ebuild.
3507 +python_get_LIBS() {
3508 + debug-print-function ${FUNCNAME} "${@}"
3509 +
3510 + python_export "${@}" PYTHON_LIBS
3511 + echo "${PYTHON_LIBS}"
3512 +}
3513 +
3514 +# @FUNCTION: python_get_PYTHON_CONFIG
3515 +# @USAGE: [<impl>]
3516 +# @DESCRIPTION:
3517 +# Obtain and print the PYTHON_CONFIG location for the given
3518 +# implementation. If no implementation is provided, ${EPYTHON} will be
3519 +# used.
3520 +#
3521 +# Please note that this function can be used with CPython only.
3522 +# It requires Python installed, and therefore proper build-time
3523 +# dependencies need be added to the ebuild.
3524 +python_get_PYTHON_CONFIG() {
3525 + debug-print-function ${FUNCNAME} "${@}"
3526 +
3527 + python_export "${@}" PYTHON_CONFIG
3528 + echo "${PYTHON_CONFIG}"
3529 +}
3530 +
3531 +# @FUNCTION: python_get_scriptdir
3532 +# @USAGE: [<impl>]
3533 +# @DESCRIPTION:
3534 +# Obtain and print the script install path for the given
3535 +# implementation. If no implementation is provided, ${EPYTHON} will
3536 +# be used.
3537 +python_get_scriptdir() {
3538 + debug-print-function ${FUNCNAME} "${@}"
3539 +
3540 + python_export "${@}" PYTHON_SCRIPTDIR
3541 + echo "${PYTHON_SCRIPTDIR}"
3542 +}
3543 +
3544 +# @FUNCTION: _python_ln_rel
3545 +# @USAGE: <from> <to>
3546 +# @INTERNAL
3547 +# @DESCRIPTION:
3548 +# Create a relative symlink.
3549 +_python_ln_rel() {
3550 + debug-print-function ${FUNCNAME} "${@}"
3551 +
3552 + local target=${1}
3553 + local symname=${2}
3554 +
3555 + local tgpath=${target%/*}/
3556 + local sympath=${symname%/*}/
3557 + local rel_target=
3558 +
3559 + while [[ ${sympath} ]]; do
3560 + local tgseg= symseg=
3561 +
3562 + while [[ ! ${tgseg} && ${tgpath} ]]; do
3563 + tgseg=${tgpath%%/*}
3564 + tgpath=${tgpath#${tgseg}/}
3565 + done
3566 +
3567 + while [[ ! ${symseg} && ${sympath} ]]; do
3568 + symseg=${sympath%%/*}
3569 + sympath=${sympath#${symseg}/}
3570 + done
3571 +
3572 + if [[ ${tgseg} != ${symseg} ]]; then
3573 + rel_target=../${rel_target}${tgseg:+${tgseg}/}
3574 + fi
3575 + done
3576 + rel_target+=${tgpath}${target##*/}
3577 +
3578 + debug-print "${FUNCNAME}: ${symname} -> ${target}"
3579 + debug-print "${FUNCNAME}: rel_target = ${rel_target}"
3580 +
3581 + ln -fs "${rel_target}" "${symname}"
3582 +}
3583 +
3584 +# @FUNCTION: python_optimize
3585 +# @USAGE: [<directory>...]
3586 +# @DESCRIPTION:
3587 +# Compile and optimize Python modules in specified directories (absolute
3588 +# paths). If no directories are provided, the default system paths
3589 +# are used (prepended with ${D}).
3590 +python_optimize() {
3591 + debug-print-function ${FUNCNAME} "${@}"
3592 +
3593 + if [[ ${EBUILD_PHASE} == pre* || ${EBUILD_PHASE} == post* ]]; then
3594 + eerror "The new Python eclasses expect the compiled Python files to"
3595 + eerror "be controlled by the Package Manager. For this reason,"
3596 + eerror "the python_optimize function can be used only during src_* phases"
3597 + eerror "(src_install most commonly) and not during pkg_* phases."
3598 + echo
3599 + die "python_optimize is not to be used in pre/post* phases"
3600 + fi
3601 +
3602 + [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
3603 +
3604 + local PYTHON=${PYTHON}
3605 + [[ ${PYTHON} ]] || python_export PYTHON
3606 +
3607 + # default to sys.path
3608 + if [[ ${#} -eq 0 ]]; then
3609 + local f
3610 + while IFS= read -r -d '' f; do
3611 + # 1) accept only absolute paths
3612 + # (i.e. skip '', '.' or anything like that)
3613 + # 2) skip paths which do not exist
3614 + # (python2.6 complains about them verbosely)
3615 +
3616 + if [[ ${f} == /* && -d ${D%/}${f} ]]; then
3617 + set -- "${D%/}${f}" "${@}"
3618 + fi
3619 + done < <("${PYTHON}" -c 'import sys; print("".join(x + "\0" for x in sys.path))' || die)
3620 +
3621 + debug-print "${FUNCNAME}: using sys.path: ${*/%/;}"
3622 + fi
3623 +
3624 + local d
3625 + for d; do
3626 + # make sure to get a nice path without //
3627 + local instpath=${d#${D%/}}
3628 + instpath=/${instpath##/}
3629 +
3630 + case "${EPYTHON}" in
3631 + python2.7|python3.[34])
3632 + "${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
3633 + "${PYTHON}" -OO -m compileall -q -f -d "${instpath}" "${d}"
3634 + ;;
3635 + python*|pypy3)
3636 + # both levels of optimization are separate since 3.5
3637 + "${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
3638 + "${PYTHON}" -O -m compileall -q -f -d "${instpath}" "${d}"
3639 + "${PYTHON}" -OO -m compileall -q -f -d "${instpath}" "${d}"
3640 + ;;
3641 + *)
3642 + "${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
3643 + ;;
3644 + esac
3645 + done
3646 +}
3647 +
3648 +# @FUNCTION: python_scriptinto
3649 +# @USAGE: <new-path>
3650 +# @DESCRIPTION:
3651 +# Set the directory to which files passed to python_doexe(),
3652 +# python_doscript(), python_newexe() and python_newscript()
3653 +# are going to be installed. The new value needs to be relative
3654 +# to the installation root (${ED}).
3655 +#
3656 +# If not set explicitly, the directory defaults to /usr/bin.
3657 +#
3658 +# Example:
3659 +# @CODE
3660 +# src_install() {
3661 +# python_scriptinto /usr/sbin
3662 +# python_foreach_impl python_doscript foo
3663 +# }
3664 +# @CODE
3665 +python_scriptinto() {
3666 + debug-print-function ${FUNCNAME} "${@}"
3667 +
3668 + python_scriptroot=${1}
3669 +}
3670 +
3671 +# @FUNCTION: python_doexe
3672 +# @USAGE: <files>...
3673 +# @DESCRIPTION:
3674 +# Install the given executables into the executable install directory,
3675 +# for the current Python implementation (${EPYTHON}).
3676 +#
3677 +# The executable will be wrapped properly for the Python implementation,
3678 +# though no shebang mangling will be performed.
3679 +python_doexe() {
3680 + debug-print-function ${FUNCNAME} "${@}"
3681 +
3682 + local f
3683 + for f; do
3684 + python_newexe "${f}" "${f##*/}"
3685 + done
3686 +}
3687 +
3688 +# @FUNCTION: python_newexe
3689 +# @USAGE: <path> <new-name>
3690 +# @DESCRIPTION:
3691 +# Install the given executable into the executable install directory,
3692 +# for the current Python implementation (${EPYTHON}).
3693 +#
3694 +# The executable will be wrapped properly for the Python implementation,
3695 +# though no shebang mangling will be performed. It will be renamed
3696 +# to <new-name>.
3697 +python_newexe() {
3698 + debug-print-function ${FUNCNAME} "${@}"
3699 +
3700 + [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
3701 + [[ ${#} -eq 2 ]] || die "Usage: ${FUNCNAME} <path> <new-name>"
3702 +
3703 + local wrapd=${python_scriptroot:-/usr/bin}
3704 +
3705 + local f=${1}
3706 + local newfn=${2}
3707 +
3708 + local PYTHON_SCRIPTDIR d
3709 + python_export PYTHON_SCRIPTDIR
3710 + d=${PYTHON_SCRIPTDIR#${EPREFIX}}
3711 +
3712 + (
3713 + dodir "${wrapd}"
3714 + exeopts -m 0755
3715 + exeinto "${d}"
3716 + newexe "${f}" "${newfn}" || return ${?}
3717 + )
3718 +
3719 + # install the wrapper
3720 + _python_ln_rel "${ED%/}"/usr/lib/python-exec/python-exec2 \
3721 + "${ED%/}/${wrapd}/${newfn}" || die
3722 +
3723 + # don't use this at home, just call python_doscript() instead
3724 + if [[ ${_PYTHON_REWRITE_SHEBANG} ]]; then
3725 + python_fix_shebang -q "${ED%/}/${d}/${newfn}"
3726 + fi
3727 +}
3728 +
3729 +# @FUNCTION: python_doscript
3730 +# @USAGE: <files>...
3731 +# @DESCRIPTION:
3732 +# Install the given scripts into the executable install directory,
3733 +# for the current Python implementation (${EPYTHON}).
3734 +#
3735 +# All specified files must start with a 'python' shebang. The shebang
3736 +# will be converted, and the files will be wrapped properly
3737 +# for the Python implementation.
3738 +#
3739 +# Example:
3740 +# @CODE
3741 +# src_install() {
3742 +# python_foreach_impl python_doscript ${PN}
3743 +# }
3744 +# @CODE
3745 +python_doscript() {
3746 + debug-print-function ${FUNCNAME} "${@}"
3747 +
3748 + local _PYTHON_REWRITE_SHEBANG=1
3749 + python_doexe "${@}"
3750 +}
3751 +
3752 +# @FUNCTION: python_newscript
3753 +# @USAGE: <path> <new-name>
3754 +# @DESCRIPTION:
3755 +# Install the given script into the executable install directory
3756 +# for the current Python implementation (${EPYTHON}), and name it
3757 +# <new-name>.
3758 +#
3759 +# The file must start with a 'python' shebang. The shebang will be
3760 +# converted, and the file will be wrapped properly for the Python
3761 +# implementation. It will be renamed to <new-name>.
3762 +#
3763 +# Example:
3764 +# @CODE
3765 +# src_install() {
3766 +# python_foreach_impl python_newscript foo.py foo
3767 +# }
3768 +# @CODE
3769 +python_newscript() {
3770 + debug-print-function ${FUNCNAME} "${@}"
3771 +
3772 + local _PYTHON_REWRITE_SHEBANG=1
3773 + python_newexe "${@}"
3774 +}
3775 +
3776 +# @FUNCTION: python_moduleinto
3777 +# @USAGE: <new-path>
3778 +# @DESCRIPTION:
3779 +# Set the Python module install directory for python_domodule().
3780 +# The <new-path> can either be an absolute target system path (in which
3781 +# case it needs to start with a slash, and ${ED} will be prepended to
3782 +# it) or relative to the implementation's site-packages directory
3783 +# (then it must not start with a slash). The relative path can be
3784 +# specified either using the Python package notation (separated by dots)
3785 +# or the directory notation (using slashes).
3786 +#
3787 +# When not set explicitly, the modules are installed to the top
3788 +# site-packages directory.
3789 +#
3790 +# In the relative case, the exact path is determined directly
3791 +# by each python_doscript/python_newscript function. Therefore,
3792 +# python_moduleinto can be safely called before establishing the Python
3793 +# interpreter and/or a single call can be used to set the path correctly
3794 +# for multiple implementations, as can be seen in the following example.
3795 +#
3796 +# Example:
3797 +# @CODE
3798 +# src_install() {
3799 +# python_moduleinto bar
3800 +# # installs ${PYTHON_SITEDIR}/bar/baz.py
3801 +# python_foreach_impl python_domodule baz.py
3802 +# }
3803 +# @CODE
3804 +python_moduleinto() {
3805 + debug-print-function ${FUNCNAME} "${@}"
3806 +
3807 + python_moduleroot=${1}
3808 +}
3809 +
3810 +# @FUNCTION: python_domodule
3811 +# @USAGE: <files>...
3812 +# @DESCRIPTION:
3813 +# Install the given modules (or packages) into the current Python module
3814 +# installation directory. The list can mention both modules (files)
3815 +# and packages (directories). All listed files will be installed
3816 +# for all enabled implementations, and compiled afterwards.
3817 +#
3818 +# Example:
3819 +# @CODE
3820 +# src_install() {
3821 +# # (${PN} being a directory)
3822 +# python_foreach_impl python_domodule ${PN}
3823 +# }
3824 +# @CODE
3825 +python_domodule() {
3826 + debug-print-function ${FUNCNAME} "${@}"
3827 +
3828 + [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
3829 +
3830 + local d
3831 + if [[ ${python_moduleroot} == /* ]]; then
3832 + # absolute path
3833 + d=${python_moduleroot}
3834 + else
3835 + # relative to site-packages
3836 + local PYTHON_SITEDIR=${PYTHON_SITEDIR}
3837 + [[ ${PYTHON_SITEDIR} ]] || python_export PYTHON_SITEDIR
3838 +
3839 + d=${PYTHON_SITEDIR#${EPREFIX}}/${python_moduleroot//.//}
3840 + fi
3841 +
3842 + (
3843 + insopts -m 0644
3844 + insinto "${d}"
3845 + doins -r "${@}" || return ${?}
3846 + )
3847 +
3848 + python_optimize "${ED%/}/${d}"
3849 +}
3850 +
3851 +# @FUNCTION: python_doheader
3852 +# @USAGE: <files>...
3853 +# @DESCRIPTION:
3854 +# Install the given headers into the implementation-specific include
3855 +# directory. This function is unconditionally recursive, i.e. you can
3856 +# pass directories instead of files.
3857 +#
3858 +# Example:
3859 +# @CODE
3860 +# src_install() {
3861 +# python_foreach_impl python_doheader foo.h bar.h
3862 +# }
3863 +# @CODE
3864 +python_doheader() {
3865 + debug-print-function ${FUNCNAME} "${@}"
3866 +
3867 + [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
3868 +
3869 + local d PYTHON_INCLUDEDIR=${PYTHON_INCLUDEDIR}
3870 + [[ ${PYTHON_INCLUDEDIR} ]] || python_export PYTHON_INCLUDEDIR
3871 +
3872 + d=${PYTHON_INCLUDEDIR#${EPREFIX}}
3873 +
3874 + (
3875 + insopts -m 0644
3876 + insinto "${d}"
3877 + doins -r "${@}" || return ${?}
3878 + )
3879 +}
3880 +
3881 +# @FUNCTION: python_wrapper_setup
3882 +# @USAGE: [<path> [<impl>]]
3883 +# @DESCRIPTION:
3884 +# Create proper 'python' executable and pkg-config wrappers
3885 +# (if available) in the directory named by <path>. Set up PATH
3886 +# and PKG_CONFIG_PATH appropriately. <path> defaults to ${T}/${EPYTHON}.
3887 +#
3888 +# The wrappers will be created for implementation named by <impl>,
3889 +# or for one named by ${EPYTHON} if no <impl> passed.
3890 +#
3891 +# If the named directory contains a python symlink already, it will
3892 +# be assumed to contain proper wrappers already and only environment
3893 +# setup will be done. If wrapper update is requested, the directory
3894 +# shall be removed first.
3895 +python_wrapper_setup() {
3896 + debug-print-function ${FUNCNAME} "${@}"
3897 +
3898 + local workdir=${1:-${T}/${EPYTHON}}
3899 + local impl=${2:-${EPYTHON}}
3900 +
3901 + [[ ${workdir} ]] || die "${FUNCNAME}: no workdir specified."
3902 + [[ ${impl} ]] || die "${FUNCNAME}: no impl nor EPYTHON specified."
3903 +
3904 + if [[ ! -x ${workdir}/bin/python ]]; then
3905 + _python_check_dead_variables
3906 +
3907 + mkdir -p "${workdir}"/{bin,pkgconfig} || die
3908 +
3909 + # Clean up, in case we were supposed to do a cheap update.
3910 + rm -f "${workdir}"/bin/python{,2,3}{,-config} || die
3911 + rm -f "${workdir}"/bin/2to3 || die
3912 + rm -f "${workdir}"/pkgconfig/python{,2,3}.pc || die
3913 +
3914 + local EPYTHON PYTHON
3915 + python_export "${impl}" EPYTHON PYTHON
3916 +
3917 + local pyver pyother
3918 + if python_is_python3; then
3919 + pyver=3
3920 + pyother=2
3921 + else
3922 + pyver=2
3923 + pyother=3
3924 + fi
3925 +
3926 + # Python interpreter
3927 + # note: we don't use symlinks because python likes to do some
3928 + # symlink reading magic that breaks stuff
3929 + # https://bugs.gentoo.org/show_bug.cgi?id=555752
3930 + cat > "${workdir}/bin/python" <<-_EOF_ || die
3931 + #!/bin/sh
3932 + exec "${PYTHON}" "\${@}"
3933 + _EOF_
3934 + cp "${workdir}/bin/python" "${workdir}/bin/python${pyver}" || die
3935 + chmod +x "${workdir}/bin/python" "${workdir}/bin/python${pyver}" || die
3936 +
3937 + local nonsupp=( "python${pyother}" "python${pyother}-config" )
3938 +
3939 + # CPython-specific
3940 + if [[ ${EPYTHON} == python* ]]; then
3941 + cat > "${workdir}/bin/python-config" <<-_EOF_ || die
3942 + #!/bin/sh
3943 + exec "${PYTHON}-config" "\${@}"
3944 + _EOF_
3945 + cp "${workdir}/bin/python-config" \
3946 + "${workdir}/bin/python${pyver}-config" || die
3947 + chmod +x "${workdir}/bin/python-config" \
3948 + "${workdir}/bin/python${pyver}-config" || die
3949 +
3950 + # Python 2.6+.
3951 + ln -s "${PYTHON/python/2to3-}" "${workdir}"/bin/2to3 || die
3952 +
3953 + # Python 2.7+.
3954 + ln -s "${EPREFIX}"/usr/$(get_libdir)/pkgconfig/${EPYTHON/n/n-}.pc \
3955 + "${workdir}"/pkgconfig/python.pc || die
3956 + ln -s python.pc "${workdir}"/pkgconfig/python${pyver}.pc || die
3957 + else
3958 + nonsupp+=( 2to3 python-config "python${pyver}-config" )
3959 + fi
3960 +
3961 + local x
3962 + for x in "${nonsupp[@]}"; do
3963 + cat >"${workdir}"/bin/${x} <<-_EOF_ || die
3964 + #!/bin/sh
3965 + echo "${ECLASS}: ${FUNCNAME}: ${x} is not supported by ${EPYTHON} (PYTHON_COMPAT)" >&2
3966 + exit 127
3967 + _EOF_
3968 + chmod +x "${workdir}"/bin/${x} || die
3969 + done
3970 + fi
3971 +
3972 + # Now, set the environment.
3973 + # But note that ${workdir} may be shared with something else,
3974 + # and thus already on top of PATH.
3975 + if [[ ${PATH##:*} != ${workdir}/bin ]]; then
3976 + PATH=${workdir}/bin${PATH:+:${PATH}}
3977 + fi
3978 + if [[ ${PKG_CONFIG_PATH##:*} != ${workdir}/pkgconfig ]]; then
3979 + PKG_CONFIG_PATH=${workdir}/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}
3980 + fi
3981 + export PATH PKG_CONFIG_PATH
3982 +}
3983 +
3984 +# @FUNCTION: python_is_python3
3985 +# @USAGE: [<impl>]
3986 +# @DESCRIPTION:
3987 +# Check whether <impl> (or ${EPYTHON}) is a Python3k variant
3988 +# (i.e. uses syntax and stdlib of Python 3.*).
3989 +#
3990 +# Returns 0 (true) if it is, 1 (false) otherwise.
3991 +python_is_python3() {
3992 + local impl=${1:-${EPYTHON}}
3993 + [[ ${impl} ]] || die "python_is_python3: no impl nor EPYTHON"
3994 +
3995 + [[ ${impl} == python3* || ${impl} == pypy3 ]]
3996 +}
3997 +
3998 +# @FUNCTION: python_is_installed
3999 +# @USAGE: [<impl>]
4000 +# @DESCRIPTION:
4001 +# Check whether the interpreter for <impl> (or ${EPYTHON}) is installed.
4002 +# Uses has_version with a proper dependency string.
4003 +#
4004 +# Returns 0 (true) if it is, 1 (false) otherwise.
4005 +python_is_installed() {
4006 + local impl=${1:-${EPYTHON}}
4007 + [[ ${impl} ]] || die "${FUNCNAME}: no impl nor EPYTHON"
4008 + local hasv_args=()
4009 +
4010 + case ${EAPI} in
4011 + 5|6)
4012 + hasv_args+=( --host-root )
4013 + ;;
4014 + *)
4015 + hasv_args+=( -b )
4016 + ;;
4017 + esac
4018 +
4019 + case "${impl}" in
4020 + pypy|pypy3)
4021 + local append=
4022 + if [[ ${PYTHON_REQ_USE} ]]; then
4023 + append=[${PYTHON_REQ_USE}]
4024 + fi
4025 +
4026 + # be happy with just the interpeter, no need for the virtual
4027 + has_version "${hasv_args[@]}" "dev-python/${impl}${append}" \
4028 + || has_version "${hasv_args[@]}" "dev-python/${impl}-bin${append}"
4029 + ;;
4030 + *)
4031 + local PYTHON_PKG_DEP
4032 + python_export "${impl}" PYTHON_PKG_DEP
4033 + has_version "${hasv_args[@]}" "${PYTHON_PKG_DEP}"
4034 + ;;
4035 + esac
4036 +}
4037 +
4038 +# @FUNCTION: python_fix_shebang
4039 +# @USAGE: [-f|--force] [-q|--quiet] <path>...
4040 +# @DESCRIPTION:
4041 +# Replace the shebang in Python scripts with the current Python
4042 +# implementation (EPYTHON). If a directory is passed, works recursively
4043 +# on all Python scripts.
4044 +#
4045 +# Only files having a 'python*' shebang will be modified. Files with
4046 +# other shebang will either be skipped when working recursively
4047 +# on a directory or treated as error when specified explicitly.
4048 +#
4049 +# Shebangs matching explicitly current Python version will be left
4050 +# unmodified. Shebangs requesting another Python version will be treated
4051 +# as fatal error, unless --force is given.
4052 +#
4053 +# --force causes the function to replace even shebangs that require
4054 +# incompatible Python version. --quiet causes the function not to list
4055 +# modified files verbosely.
4056 +python_fix_shebang() {
4057 + debug-print-function ${FUNCNAME} "${@}"
4058 +
4059 + [[ ${EPYTHON} ]] || die "${FUNCNAME}: EPYTHON unset (pkg_setup not called?)"
4060 +
4061 + local force quiet
4062 + while [[ ${@} ]]; do
4063 + case "${1}" in
4064 + -f|--force) force=1; shift;;
4065 + -q|--quiet) quiet=1; shift;;
4066 + --) shift; break;;
4067 + *) break;;
4068 + esac
4069 + done
4070 +
4071 + [[ ${1} ]] || die "${FUNCNAME}: no paths given"
4072 +
4073 + local path f
4074 + for path; do
4075 + local any_correct any_fixed is_recursive
4076 +
4077 + [[ -d ${path} ]] && is_recursive=1
4078 +
4079 + while IFS= read -r -d '' f; do
4080 + local shebang i
4081 + local error= from=
4082 +
4083 + # note: we can't ||die here since read will fail if file
4084 + # has no newline characters
4085 + IFS= read -r shebang <"${f}"
4086 +
4087 + # First, check if it's shebang at all...
4088 + if [[ ${shebang} == '#!'* ]]; then
4089 + local split_shebang=()
4090 + read -r -a split_shebang <<<${shebang} || die
4091 +
4092 + # Match left-to-right in a loop, to avoid matching random
4093 + # repetitions like 'python2.7 python2'.
4094 + for i in "${split_shebang[@]}"; do
4095 + case "${i}" in
4096 + *"${EPYTHON}")
4097 + debug-print "${FUNCNAME}: in file ${f#${D%/}}"
4098 + debug-print "${FUNCNAME}: shebang matches EPYTHON: ${shebang}"
4099 +
4100 + # Nothing to do, move along.
4101 + any_correct=1
4102 + from=${EPYTHON}
4103 + break
4104 + ;;
4105 + *python|*python[23])
4106 + debug-print "${FUNCNAME}: in file ${f#${D%/}}"
4107 + debug-print "${FUNCNAME}: rewriting shebang: ${shebang}"
4108 +
4109 + if [[ ${i} == *python2 ]]; then
4110 + from=python2
4111 + if [[ ! ${force} ]]; then
4112 + python_is_python3 "${EPYTHON}" && error=1
4113 + fi
4114 + elif [[ ${i} == *python3 ]]; then
4115 + from=python3
4116 + if [[ ! ${force} ]]; then
4117 + python_is_python3 "${EPYTHON}" || error=1
4118 + fi
4119 + else
4120 + from=python
4121 + fi
4122 + break
4123 + ;;
4124 + *python[23].[0123456789]|*pypy|*pypy3|*jython[23].[0123456789])
4125 + # Explicit mismatch.
4126 + if [[ ! ${force} ]]; then
4127 + error=1
4128 + else
4129 + case "${i}" in
4130 + *python[23].[0123456789])
4131 + from="python[23].[0123456789]";;
4132 + *pypy)
4133 + from="pypy";;
4134 + *pypy3)
4135 + from="pypy3";;
4136 + *jython[23].[0123456789])
4137 + from="jython[23].[0123456789]";;
4138 + *)
4139 + die "${FUNCNAME}: internal error in 2nd pattern match";;
4140 + esac
4141 + fi
4142 + break
4143 + ;;
4144 + esac
4145 + done
4146 + fi
4147 +
4148 + if [[ ! ${error} && ! ${from} ]]; then
4149 + # Non-Python shebang. Allowed in recursive mode,
4150 + # disallowed when specifying file explicitly.
4151 + [[ ${is_recursive} ]] && continue
4152 + error=1
4153 + fi
4154 +
4155 + if [[ ! ${quiet} ]]; then
4156 + einfo "Fixing shebang in ${f#${D%/}}."
4157 + fi
4158 +
4159 + if [[ ! ${error} ]]; then
4160 + # We either want to match ${from} followed by space
4161 + # or at end-of-string.
4162 + if [[ ${shebang} == *${from}" "* ]]; then
4163 + sed -i -e "1s:${from} :${EPYTHON} :" "${f}" || die
4164 + else
4165 + sed -i -e "1s:${from}$:${EPYTHON}:" "${f}" || die
4166 + fi
4167 + any_fixed=1
4168 + else
4169 + eerror "The file has incompatible shebang:"
4170 + eerror " file: ${f#${D%/}}"
4171 + eerror " current shebang: ${shebang}"
4172 + eerror " requested impl: ${EPYTHON}"
4173 + die "${FUNCNAME}: conversion of incompatible shebang requested"
4174 + fi
4175 + done < <(find -H "${path}" -type f -print0 || die)
4176 +
4177 + if [[ ! ${any_fixed} ]]; then
4178 + local cmd=eerror
4179 + [[ ${EAPI} == 5 ]] && cmd=eqawarn
4180 +
4181 + "${cmd}" "QA warning: ${FUNCNAME}, ${path#${D%/}} did not match any fixable files."
4182 + if [[ ${any_correct} ]]; then
4183 + "${cmd}" "All files have ${EPYTHON} shebang already."
4184 + else
4185 + "${cmd}" "There are no Python files in specified directory."
4186 + fi
4187 +
4188 + [[ ${cmd} == eerror ]] && die "${FUNCNAME} did not match any fixable files (QA warning fatal in EAPI ${EAPI})"
4189 + fi
4190 + done
4191 +}
4192 +
4193 +# @FUNCTION: _python_check_locale_sanity
4194 +# @USAGE: <locale>
4195 +# @RETURN: 0 if sane, 1 otherwise
4196 +# @DESCRIPTION:
4197 +# Check whether the specified locale sanely maps between lowercase
4198 +# and uppercase ASCII characters.
4199 +_python_check_locale_sanity() {
4200 + local -x LC_ALL=${1}
4201 + local IFS=
4202 +
4203 + local lc=( {a..z} )
4204 + local uc=( {A..Z} )
4205 + local input="${lc[*]}${uc[*]}"
4206 +
4207 + local output=$(tr '[:lower:][:upper:]' '[:upper:][:lower:]' <<<"${input}")
4208 + [[ ${output} == "${uc[*]}${lc[*]}" ]]
4209 +}
4210 +
4211 +# @FUNCTION: python_export_utf8_locale
4212 +# @RETURN: 0 on success, 1 on failure.
4213 +# @DESCRIPTION:
4214 +# Attempts to export a usable UTF-8 locale in the LC_CTYPE variable. Does
4215 +# nothing if LC_ALL is defined, or if the current locale uses a UTF-8 charmap.
4216 +# This may be used to work around the quirky open() behavior of python3.
4217 +python_export_utf8_locale() {
4218 + debug-print-function ${FUNCNAME} "${@}"
4219 +
4220 + # If the locale program isn't available, just return.
4221 + type locale >/dev/null || return 0
4222 +
4223 + if [[ $(locale charmap) != UTF-8 ]]; then
4224 + # Try English first, then everything else.
4225 + local lang locales="C.UTF-8 en_US.UTF-8 en_GB.UTF-8 $(locale -a)"
4226 +
4227 + for lang in ${locales}; do
4228 + if [[ $(LC_ALL=${lang} locale charmap 2>/dev/null) == UTF-8 ]]; then
4229 + if _python_check_locale_sanity "${lang}"; then
4230 + export LC_CTYPE=${lang}
4231 + if [[ -n ${LC_ALL} ]]; then
4232 + export LC_NUMERIC=${LC_ALL}
4233 + export LC_TIME=${LC_ALL}
4234 + export LC_COLLATE=${LC_ALL}
4235 + export LC_MONETARY=${LC_ALL}
4236 + export LC_MESSAGES=${LC_ALL}
4237 + export LC_PAPER=${LC_ALL}
4238 + export LC_NAME=${LC_ALL}
4239 + export LC_ADDRESS=${LC_ALL}
4240 + export LC_TELEPHONE=${LC_ALL}
4241 + export LC_MEASUREMENT=${LC_ALL}
4242 + export LC_IDENTIFICATION=${LC_ALL}
4243 + export LC_ALL=
4244 + fi
4245 + return 0
4246 + fi
4247 + fi
4248 + done
4249 +
4250 + ewarn "Could not find a UTF-8 locale. This may trigger build failures in"
4251 + ewarn "some python packages. Please ensure that a UTF-8 locale is listed in"
4252 + ewarn "/etc/locale.gen and run locale-gen."
4253 + return 1
4254 + fi
4255 +
4256 + return 0
4257 +}
4258 +
4259 +# @FUNCTION: build_sphinx
4260 +# @USAGE: <directory>
4261 +# @DESCRIPTION:
4262 +# Build HTML documentation using dev-python/sphinx in the specified
4263 +# <directory>. Takes care of disabling Intersphinx and appending
4264 +# to HTML_DOCS.
4265 +#
4266 +# If <directory> is relative to the current directory, care needs
4267 +# to be taken to run einstalldocs from the same directory
4268 +# (usually ${S}).
4269 +build_sphinx() {
4270 + debug-print-function ${FUNCNAME} "${@}"
4271 + [[ ${#} -eq 1 ]] || die "${FUNCNAME} takes 1 arg: <directory>"
4272 +
4273 + local dir=${1}
4274 +
4275 + sed -i -e 's:^intersphinx_mapping:disabled_&:' \
4276 + "${dir}"/conf.py || die
4277 + # not all packages include the Makefile in pypi tarball
4278 + sphinx-build -b html -d "${dir}"/_build/doctrees "${dir}" \
4279 + "${dir}"/_build/html || die
4280 +
4281 + HTML_DOCS+=( "${dir}/_build/html/." )
4282 +}
4283 +
4284 +# -- python.eclass functions --
4285 +
4286 +_python_check_dead_variables() {
4287 + local v
4288 +
4289 + for v in PYTHON_DEPEND PYTHON_USE_WITH{,_OR,_OPT} {RESTRICT,SUPPORT}_PYTHON_ABIS
4290 + do
4291 + if [[ ${!v} ]]; then
4292 + die "${v} is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Ebuild_head"
4293 + fi
4294 + done
4295 +
4296 + for v in PYTHON_{CPPFLAGS,CFLAGS,CXXFLAGS,LDFLAGS}
4297 + do
4298 + if [[ ${!v} ]]; then
4299 + die "${v} is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#PYTHON_CFLAGS"
4300 + fi
4301 + done
4302 +
4303 + for v in PYTHON_TESTS_RESTRICTED_ABIS PYTHON_EXPORT_PHASE_FUNCTIONS \
4304 + PYTHON_VERSIONED_{SCRIPTS,EXECUTABLES} PYTHON_NONVERSIONED_EXECUTABLES
4305 + do
4306 + if [[ ${!v} ]]; then
4307 + die "${v} is invalid for python-r2 suite"
4308 + fi
4309 + done
4310 +
4311 + for v in DISTUTILS_USE_SEPARATE_SOURCE_DIRECTORIES DISTUTILS_SETUP_FILES \
4312 + DISTUTILS_GLOBAL_OPTIONS DISTUTILS_SRC_TEST PYTHON_MODNAME
4313 + do
4314 + if [[ ${!v} ]]; then
4315 + die "${v} is invalid for distutils-r2, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#${v}"
4316 + fi
4317 + done
4318 +
4319 + if [[ ${DISTUTILS_DISABLE_TEST_DEPENDENCY} ]]; then
4320 + die "${v} is invalid for distutils-r2, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#DISTUTILS_SRC_TEST"
4321 + fi
4322 +
4323 + # python.eclass::progress
4324 + for v in PYTHON_BDEPEND PYTHON_MULTIPLE_ABIS PYTHON_ABI_TYPE \
4325 + PYTHON_RESTRICTED_ABIS PYTHON_TESTS_FAILURES_TOLERANT_ABIS \
4326 + PYTHON_CFFI_MODULES_GENERATION_COMMANDS
4327 + do
4328 + if [[ ${!v} ]]; then
4329 + die "${v} is invalid for python-r2 suite"
4330 + fi
4331 + done
4332 +}
4333 +
4334 +python_pkg_setup() {
4335 + die "${FUNCNAME}() is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#pkg_setup"
4336 +}
4337 +
4338 +python_convert_shebangs() {
4339 + 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"
4340 +}
4341 +
4342 +python_clean_py-compile_files() {
4343 + die "${FUNCNAME}() is invalid for python-r2 suite"
4344 +}
4345 +
4346 +python_clean_installation_image() {
4347 + die "${FUNCNAME}() is invalid for python-r2 suite"
4348 +}
4349 +
4350 +python_execute_function() {
4351 + 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"
4352 +}
4353 +
4354 +python_generate_wrapper_scripts() {
4355 + die "${FUNCNAME}() is invalid for python-r2 suite"
4356 +}
4357 +
4358 +python_merge_intermediate_installation_images() {
4359 + die "${FUNCNAME}() is invalid for python-r2 suite"
4360 +}
4361 +
4362 +python_set_active_version() {
4363 + die "${FUNCNAME}() is invalid for python-r2 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#pkg_setup"
4364 +}
4365 +
4366 +python_need_rebuild() {
4367 + die "${FUNCNAME}() is invalid for python-r2 suite"
4368 +}
4369 +
4370 +PYTHON() {
4371 + 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"
4372 +}
4373 +
4374 +python_get_implementation() {
4375 + die "${FUNCNAME}() is invalid for python-r2 suite"
4376 +}
4377 +
4378 +python_get_implementational_package() {
4379 + die "${FUNCNAME}() is invalid for python-r2 suite"
4380 +}
4381 +
4382 +python_get_libdir() {
4383 + die "${FUNCNAME}() is invalid for python-r2 suite"
4384 +}
4385 +
4386 +python_get_library() {
4387 + die "${FUNCNAME}() is invalid for python-r2 suite"
4388 +}
4389 +
4390 +python_get_version() {
4391 + die "${FUNCNAME}() is invalid for python-r2 suite"
4392 +}
4393 +
4394 +python_get_implementation_and_version() {
4395 + die "${FUNCNAME}() is invalid for python-r2 suite"
4396 +}
4397 +
4398 +python_execute_nosetests() {
4399 + die "${FUNCNAME}() is invalid for python-r2 suite"
4400 +}
4401 +
4402 +python_execute_py.test() {
4403 + die "${FUNCNAME}() is invalid for python-r2 suite"
4404 +}
4405 +
4406 +python_execute_trial() {
4407 + die "${FUNCNAME}() is invalid for python-r2 suite"
4408 +}
4409 +
4410 +python_enable_pyc() {
4411 + die "${FUNCNAME}() is invalid for python-r2 suite"
4412 +}
4413 +
4414 +python_disable_pyc() {
4415 + die "${FUNCNAME}() is invalid for python-r2 suite"
4416 +}
4417 +
4418 +python_mod_optimize() {
4419 + 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"
4420 +}
4421 +
4422 +python_mod_cleanup() {
4423 + 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"
4424 +}
4425 +
4426 +# python.eclass::progress
4427 +
4428 +python_abi_depend() {
4429 + die "${FUNCNAME}() is invalid for python-r2 suite"
4430 +}
4431 +
4432 +python_install_executables() {
4433 + die "${FUNCNAME}() is invalid for python-r2 suite"
4434 +}
4435 +
4436 +python_get_extension_module_suffix() {
4437 + die "${FUNCNAME}() is invalid for python-r2 suite"
4438 +}
4439 +
4440 +python_byte-compile_modules() {
4441 + die "${FUNCNAME}() is invalid for python-r2 suite"
4442 +}
4443 +
4444 +python_clean_byte-compiled_modules() {
4445 + die "${FUNCNAME}() is invalid for python-r2 suite"
4446 +}
4447 +
4448 +python_generate_cffi_modules() {
4449 + die "${FUNCNAME}() is invalid for python-r2 suite"
4450 +}
4451 +
4452 +_PYTHON_UTILS_R2=1
4453 +fi
4454 diff --git a/eclass/tests/distutils-r2.sh b/eclass/tests/distutils-r2.sh
4455 new file mode 100755
4456 index 000000000000..15f59bcd7d48
4457 --- /dev/null
4458 +++ b/eclass/tests/distutils-r2.sh
4459 @@ -0,0 +1,98 @@
4460 +#!/bin/bash
4461 +# Copyright 1999-2015 Gentoo Foundation
4462 +# Distributed under the terms of the GNU General Public License v2
4463 +
4464 +EAPI=5
4465 +PYTHON_COMPAT=( python2_7 )
4466 +source tests-common.sh
4467 +
4468 +test-phase_name_free() {
4469 + local ph=${1}
4470 +
4471 + if declare -f "${ph}"; then
4472 + die "${ph} function declared while name reserved for phase!"
4473 + fi
4474 + if declare -f "${ph}_all"; then
4475 + die "${ph}_all function declared while name reserved for phase!"
4476 + fi
4477 +}
4478 +
4479 +test-distutils_enable_tests() {
4480 + local runner=${1}
4481 + local exp_IUSE=${2}
4482 + local exp_RESTRICT=${3}
4483 + local exp_DEPEND=${4}
4484 +
4485 + local IUSE=${IUSE}
4486 + local RESTRICT=${RESTRICT}
4487 + local DEPEND=${DEPEND}
4488 +
4489 + tbegin "${runner}"
4490 +
4491 + distutils_enable_tests "${runner}"
4492 +
4493 + local ret var
4494 + for var in IUSE RESTRICT DEPEND; do
4495 + local exp_var=exp_${var}
4496 + if [[ ${!var} != "${!exp_var}" ]]; then
4497 + eindent
4498 + eerror "${var} expected: ${!exp_var}"
4499 + eerror "${var} actual: ${!var}"
4500 + eoutdent
4501 + ret=1
4502 + tret=1
4503 + fi
4504 + done
4505 +
4506 + tend ${ret}
4507 +}
4508 +
4509 +DISTUTILS_USE_SETUPTOOLS=no
4510 +inherit distutils-r2
4511 +
4512 +tbegin "sane function names"
4513 +
4514 +test-phase_name_free python_prepare
4515 +test-phase_name_free python_configure
4516 +test-phase_name_free python_compile
4517 +test-phase_name_free python_test
4518 +test-phase_name_free python_install
4519 +
4520 +tend
4521 +
4522 +einfo distutils_enable_tests
4523 +eindent
4524 +BASE_IUSE="python_targets_python2_7"
4525 +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(-)]"
4526 +TEST_RESTRICT=" !test? ( test )"
4527 +
4528 +einfo "empty RDEPEND"
4529 +eindent
4530 +RDEPEND=""
4531 +test-distutils_enable_tests pytest \
4532 + "${BASE_IUSE} test" "${TEST_RESTRICT}" "${BASE_DEPS} test? ( dev-python/pytest[${PYTHON_USEDEP}] )"
4533 +test-distutils_enable_tests nose \
4534 + "${BASE_IUSE} test" "${TEST_RESTRICT}" "${BASE_DEPS} test? ( dev-python/nose[${PYTHON_USEDEP}] )"
4535 +test-distutils_enable_tests unittest \
4536 + "${BASE_IUSE}" "" "${BASE_DEPS}"
4537 +test-distutils_enable_tests setup.py \
4538 + "${BASE_IUSE}" "" "${BASE_DEPS}"
4539 +eoutdent
4540 +
4541 +einfo "non-empty RDEPEND"
4542 +eindent
4543 +BASE_RDEPEND="dev-python/foo[${PYTHON_USEDEP}]"
4544 +RDEPEND=${BASE_RDEPEND}
4545 +test-distutils_enable_tests pytest \
4546 + "${BASE_IUSE} test" "${TEST_RESTRICT}" "${BASE_DEPS} test? ( ${BASE_RDEPEND} dev-python/pytest[${PYTHON_USEDEP}] )"
4547 +test-distutils_enable_tests nose \
4548 + "${BASE_IUSE} test" "${TEST_RESTRICT}" "${BASE_DEPS} test? ( ${BASE_RDEPEND} dev-python/nose[${PYTHON_USEDEP}] )"
4549 +test-distutils_enable_tests unittest \
4550 + "${BASE_IUSE} test" "${TEST_RESTRICT}" "${BASE_DEPS} test? ( ${BASE_RDEPEND} )"
4551 +test-distutils_enable_tests setup.py \
4552 + "${BASE_IUSE} test" "${TEST_RESTRICT}" "${BASE_DEPS} test? ( ${BASE_RDEPEND} )"
4553 +eoutdent
4554 +
4555 +eoutdent
4556 +
4557 +texit
4558 diff --git a/eclass/tests/python-utils-r2.sh b/eclass/tests/python-utils-r2.sh
4559 new file mode 100755
4560 index 000000000000..64490cb0d24a
4561 --- /dev/null
4562 +++ b/eclass/tests/python-utils-r2.sh
4563 @@ -0,0 +1,237 @@
4564 +#!/bin/bash
4565 +# Copyright 1999-2019 Gentoo Authors
4566 +# Distributed under the terms of the GNU General Public License v2
4567 +
4568 +EAPI=7
4569 +source tests-common.sh
4570 +
4571 +test_var() {
4572 + local var=${1}
4573 + local impl=${2}
4574 + local expect=${3}
4575 +
4576 + tbegin "${var} for ${impl}"
4577 +
4578 + local ${var}
4579 + python_export ${impl} PYTHON ${var}
4580 + [[ ${!var} == ${expect} ]] || eerror "(${impl}: ${var}: ${!var} != ${expect}"
4581 +
4582 + tend ${?}
4583 +}
4584 +
4585 +test_is() {
4586 + local func=${1}
4587 + local expect=${2}
4588 +
4589 + tbegin "${func} (expecting: ${expect})"
4590 +
4591 + ${func}
4592 + [[ ${?} == ${expect} ]]
4593 +
4594 + tend ${?}
4595 +}
4596 +
4597 +test_fix_shebang() {
4598 + local from=${1}
4599 + local to=${2}
4600 + local expect=${3}
4601 + local args=( "${@:4}" )
4602 +
4603 + tbegin "python_fix_shebang${args[@]+ ${args[*]}} from ${from} to ${to} (exp: ${expect})"
4604 +
4605 + echo "${from}" > "${tmpfile}"
4606 + output=$( EPYTHON=${to} python_fix_shebang "${args[@]}" -q "${tmpfile}" 2>&1 )
4607 +
4608 + if [[ ${?} != 0 ]]; then
4609 + if [[ ${expect} != FAIL ]]; then
4610 + echo "${output}"
4611 + tend 1
4612 + else
4613 + tend 0
4614 + fi
4615 + else
4616 + [[ $(<"${tmpfile}") == ${expect} ]] \
4617 + || eerror "${from} -> ${to}: $(<"${tmpfile}") != ${expect}"
4618 + tend ${?}
4619 + fi
4620 +}
4621 +
4622 +tmpfile=$(mktemp)
4623 +
4624 +inherit python-utils-r2
4625 +
4626 +test_var EPYTHON python2_7 python2.7
4627 +test_var PYTHON python2_7 /usr/bin/python2.7
4628 +if [[ -x /usr/bin/python2.7 ]]; then
4629 + test_var PYTHON_SITEDIR python2_7 "/usr/lib*/python2.7/site-packages"
4630 + test_var PYTHON_INCLUDEDIR python2_7 /usr/include/python2.7
4631 + test_var PYTHON_LIBPATH python2_7 "/usr/lib*/libpython2.7$(get_libname)"
4632 + test_var PYTHON_CONFIG python2_7 /usr/bin/python2.7-config
4633 + test_var PYTHON_CFLAGS python2_7 "*-I/usr/include/python2.7*"
4634 + test_var PYTHON_LIBS python2_7 "*-lpython2.7*"
4635 +fi
4636 +test_var PYTHON_PKG_DEP python2_7 '*dev-lang/python*:2.7'
4637 +test_var PYTHON_SCRIPTDIR python2_7 /usr/lib/python-exec/python2.7
4638 +
4639 +test_var EPYTHON python3_6 python3.6
4640 +test_var PYTHON python3_6 /usr/bin/python3.6
4641 +if [[ -x /usr/bin/python3.6 ]]; then
4642 + abiflags=$(/usr/bin/python3.6 -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS"))')
4643 + test_var PYTHON_SITEDIR python3_6 "/usr/lib*/python3.6/site-packages"
4644 + test_var PYTHON_INCLUDEDIR python3_6 "/usr/include/python3.6${abiflags}"
4645 + test_var PYTHON_LIBPATH python3_6 "/usr/lib*/libpython3.6${abiflags}$(get_libname)"
4646 + test_var PYTHON_CONFIG python3_6 "/usr/bin/python3.6${abiflags}-config"
4647 + test_var PYTHON_CFLAGS python3_6 "*-I/usr/include/python3.6*"
4648 + test_var PYTHON_LIBS python3_6 "*-lpython3.6*"
4649 +fi
4650 +test_var PYTHON_PKG_DEP python3_6 '*dev-lang/python*:3.6'
4651 +test_var PYTHON_SCRIPTDIR python3_6 /usr/lib/python-exec/python3.6
4652 +
4653 +test_var EPYTHON python3_7 python3.7
4654 +test_var PYTHON python3_7 /usr/bin/python3.7
4655 +if [[ -x /usr/bin/python3.7 ]]; then
4656 + abiflags=$(/usr/bin/python3.7 -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS"))')
4657 + test_var PYTHON_SITEDIR python3_7 "/usr/lib/python3.7/site-packages"
4658 + test_var PYTHON_INCLUDEDIR python3_7 "/usr/include/python3.7${abiflags}"
4659 + test_var PYTHON_LIBPATH python3_7 "/usr/lib*/libpython3.7${abiflags}$(get_libname)"
4660 + test_var PYTHON_CONFIG python3_7 "/usr/bin/python3.7${abiflags}-config"
4661 + test_var PYTHON_CFLAGS python3_7 "*-I/usr/include/python3.7*"
4662 + test_var PYTHON_LIBS python3_7 "*-lpython3.7*"
4663 +fi
4664 +test_var PYTHON_PKG_DEP python3_7 '*dev-lang/python*:3.7'
4665 +test_var PYTHON_SCRIPTDIR python3_7 /usr/lib/python-exec/python3.7
4666 +
4667 +test_var EPYTHON jython2_7 jython2.7
4668 +test_var PYTHON jython2_7 /usr/bin/jython2.7
4669 +if [[ -x /usr/bin/jython2.7 ]]; then
4670 + test_var PYTHON_SITEDIR jython2_7 /usr/share/jython-2.7/Lib/site-packages
4671 +fi
4672 +test_var PYTHON_PKG_DEP jython2_7 '*dev-java/jython*:2.7'
4673 +test_var PYTHON_SCRIPTDIR jython2_7 /usr/lib/python-exec/jython2.7
4674 +
4675 +test_var EPYTHON pypy pypy
4676 +test_var PYTHON pypy /usr/bin/pypy
4677 +if [[ -x /usr/bin/pypy ]]; then
4678 + test_var PYTHON_SITEDIR pypy "/usr/lib*/pypy2.7/site-packages"
4679 + test_var PYTHON_INCLUDEDIR pypy "/usr/lib*/pypy2.7/include"
4680 +fi
4681 +test_var PYTHON_PKG_DEP pypy '*dev-python/pypy*:0='
4682 +test_var PYTHON_SCRIPTDIR pypy /usr/lib/python-exec/pypy
4683 +
4684 +test_var EPYTHON pypy3 pypy3
4685 +test_var PYTHON pypy3 /usr/bin/pypy3
4686 +if [[ -x /usr/bin/pypy3 ]]; then
4687 + test_var PYTHON_SITEDIR pypy3 "/usr/lib*/pypy3.?/site-packages"
4688 + test_var PYTHON_INCLUDEDIR pypy3 "/usr/lib*/pypy3.?/include"
4689 +fi
4690 +test_var PYTHON_PKG_DEP pypy3 '*dev-python/pypy3*:0='
4691 +test_var PYTHON_SCRIPTDIR pypy3 /usr/lib/python-exec/pypy3
4692 +
4693 +test_is "python_is_python3 python2.7" 1
4694 +test_is "python_is_python3 python3.2" 0
4695 +test_is "python_is_python3 jython2.7" 1
4696 +test_is "python_is_python3 pypy" 1
4697 +test_is "python_is_python3 pypy3" 0
4698 +
4699 +# generic shebangs
4700 +test_fix_shebang '#!/usr/bin/python' python2.7 '#!/usr/bin/python2.7'
4701 +test_fix_shebang '#!/usr/bin/python' python3.6 '#!/usr/bin/python3.6'
4702 +test_fix_shebang '#!/usr/bin/python' pypy '#!/usr/bin/pypy'
4703 +test_fix_shebang '#!/usr/bin/python' pypy3 '#!/usr/bin/pypy3'
4704 +test_fix_shebang '#!/usr/bin/python' jython2.7 '#!/usr/bin/jython2.7'
4705 +
4706 +# python2/python3 matching
4707 +test_fix_shebang '#!/usr/bin/python2' python2.7 '#!/usr/bin/python2.7'
4708 +test_fix_shebang '#!/usr/bin/python3' python2.7 FAIL
4709 +test_fix_shebang '#!/usr/bin/python3' python2.7 '#!/usr/bin/python2.7' --force
4710 +test_fix_shebang '#!/usr/bin/python3' python3.6 '#!/usr/bin/python3.6'
4711 +test_fix_shebang '#!/usr/bin/python2' python3.6 FAIL
4712 +test_fix_shebang '#!/usr/bin/python2' python3.6 '#!/usr/bin/python3.6' --force
4713 +
4714 +# pythonX.Y matching (those mostly test the patterns)
4715 +test_fix_shebang '#!/usr/bin/python2.7' python2.7 '#!/usr/bin/python2.7'
4716 +test_fix_shebang '#!/usr/bin/python2.7' python3.2 FAIL
4717 +test_fix_shebang '#!/usr/bin/python2.7' python3.2 '#!/usr/bin/python3.2' --force
4718 +test_fix_shebang '#!/usr/bin/python3.2' python3.2 '#!/usr/bin/python3.2'
4719 +test_fix_shebang '#!/usr/bin/python3.2' python2.7 FAIL
4720 +test_fix_shebang '#!/usr/bin/python3.2' python2.7 '#!/usr/bin/python2.7' --force
4721 +test_fix_shebang '#!/usr/bin/pypy' pypy '#!/usr/bin/pypy'
4722 +test_fix_shebang '#!/usr/bin/pypy' python2.7 FAIL
4723 +test_fix_shebang '#!/usr/bin/pypy' python2.7 '#!/usr/bin/python2.7' --force
4724 +test_fix_shebang '#!/usr/bin/jython2.7' jython2.7 '#!/usr/bin/jython2.7'
4725 +test_fix_shebang '#!/usr/bin/jython2.7' jython3.2 FAIL
4726 +test_fix_shebang '#!/usr/bin/jython2.7' jython3.2 '#!/usr/bin/jython3.2' --force
4727 +
4728 +# fancy path handling
4729 +test_fix_shebang '#!/mnt/python2/usr/bin/python' python3.6 \
4730 + '#!/mnt/python2/usr/bin/python3.6'
4731 +test_fix_shebang '#!/mnt/python2/usr/bin/python2' python2.7 \
4732 + '#!/mnt/python2/usr/bin/python2.7'
4733 +test_fix_shebang '#!/mnt/python2/usr/bin/env python' python2.7 \
4734 + '#!/mnt/python2/usr/bin/env python2.7'
4735 +test_fix_shebang '#!/mnt/python2/usr/bin/python2 python2' python2.7 \
4736 + '#!/mnt/python2/usr/bin/python2.7 python2'
4737 +test_fix_shebang '#!/mnt/python2/usr/bin/python3 python2' python2.7 FAIL
4738 +test_fix_shebang '#!/mnt/python2/usr/bin/python3 python2' python2.7 \
4739 + '#!/mnt/python2/usr/bin/python2.7 python2' --force
4740 +test_fix_shebang '#!/usr/bin/foo' python2.7 FAIL
4741 +
4742 +# regression test for bug #522080
4743 +test_fix_shebang '#!/usr/bin/python ' python2.7 '#!/usr/bin/python2.7 '
4744 +
4745 +# make sure we don't break pattern matching
4746 +test_is "_python_impl_supported python2_5" 1
4747 +test_is "_python_impl_supported python2_6" 1
4748 +test_is "_python_impl_supported python2_7" 0
4749 +test_is "_python_impl_supported python3_1" 1
4750 +test_is "_python_impl_supported python3_2" 1
4751 +test_is "_python_impl_supported python3_3" 1
4752 +test_is "_python_impl_supported python3_4" 1
4753 +test_is "_python_impl_supported python3_5" 1
4754 +test_is "_python_impl_supported python3_6" 0
4755 +test_is "_python_impl_supported python3_7" 0
4756 +test_is "_python_impl_supported python3_8" 0
4757 +test_is "_python_impl_supported pypy1_8" 1
4758 +test_is "_python_impl_supported pypy1_9" 1
4759 +test_is "_python_impl_supported pypy2_0" 1
4760 +test_is "_python_impl_supported pypy" 1
4761 +test_is "_python_impl_supported pypy3" 0
4762 +test_is "_python_impl_supported jython2_7" 1
4763 +
4764 +# check _python_impl_matches behavior
4765 +test_is "_python_impl_matches python2_7 -2" 0
4766 +test_is "_python_impl_matches python3_6 -2" 1
4767 +test_is "_python_impl_matches python3_7 -2" 1
4768 +test_is "_python_impl_matches pypy -2" 0
4769 +test_is "_python_impl_matches pypy3 -2" 1
4770 +test_is "_python_impl_matches python2_7 -3" 1
4771 +test_is "_python_impl_matches python3_6 -3" 0
4772 +test_is "_python_impl_matches python3_7 -3" 0
4773 +test_is "_python_impl_matches pypy -3" 1
4774 +test_is "_python_impl_matches pypy3 -3" 0
4775 +test_is "_python_impl_matches python2_7 -2 python3_6" 0
4776 +test_is "_python_impl_matches python3_6 -2 python3_6" 0
4777 +test_is "_python_impl_matches python3_7 -2 python3_6" 1
4778 +test_is "_python_impl_matches pypy -2 python3_6" 0
4779 +test_is "_python_impl_matches pypy3 -2 python3_6" 1
4780 +test_is "_python_impl_matches python2_7 pypy3 -2 python3_6" 0
4781 +test_is "_python_impl_matches python3_6 pypy3 -2 python3_6" 0
4782 +test_is "_python_impl_matches python3_7 pypy3 -2 python3_6" 1
4783 +test_is "_python_impl_matches pypy pypy3 -2 python3_6" 0
4784 +test_is "_python_impl_matches pypy3 pypy3 -2 python3_6" 0
4785 +set -f
4786 +test_is "_python_impl_matches python2_7 pypy*" 1
4787 +test_is "_python_impl_matches python3_6 pypy*" 1
4788 +test_is "_python_impl_matches python3_7 pypy*" 1
4789 +test_is "_python_impl_matches pypy pypy*" 0
4790 +test_is "_python_impl_matches pypy3 pypy*" 0
4791 +test_is "_python_impl_matches python2_7 python*" 0
4792 +test_is "_python_impl_matches python3_6 python*" 0
4793 +test_is "_python_impl_matches python3_7 python*" 0
4794 +test_is "_python_impl_matches pypy python*" 1
4795 +test_is "_python_impl_matches pypy3 python*" 1
4796 +set +f
4797 +
4798 +rm "${tmpfile}"
4799 +
4800 +texit
4801 --
4802 2.25.1