1 # Copyright 1999-2015 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
5 # @ECLASS: python.eclass
7 # Gentoo Python Project <python@gentoo.org>
8 # @BLURB: Eclass for Python packages
10 # The python eclass contains miscellaneous, useful functions for Python packages.
12 # This eclass is DEPRECATED. Please use python-r1, python-single-r1
13 # or python-any-r1 instead.
15 if [[ ${EAPI} == 6 ]]; then
16 die "${ECLASS}.eclass is banned in EAPI ${EAPI}"
19 if [[ ${_PYTHON_UTILS_R1} ]]; then
20 die 'python.eclass can not be used with python-r1 suite eclasses.'
23 # Must call inherit before EXPORT_FUNCTIONS to avoid QA warning.
24 if [[ -z "${_PYTHON_ECLASS_INHERITED}" ]]; then
28 # Export pkg_setup every time to avoid issues with eclass inheritance order.
29 if ! has "${EAPI:-0}" 0 1 2 3 || { has "${EAPI:-0}" 2 3 && [[ -n "${PYTHON_USE_WITH}" || -n "${PYTHON_USE_WITH_OR}" ]]; }; then
30 EXPORT_FUNCTIONS pkg_setup
33 # Avoid processing this eclass more than once.
34 if [[ -z "${_PYTHON_ECLASS_INHERITED}" ]]; then
35 _PYTHON_ECLASS_INHERITED="1"
37 if ! has "${EAPI:-0}" 0 1 2 3 4 5; then
38 die "API of python.eclass in EAPI=\"${EAPI}\" not established"
41 # Please do not add any new versions of Python here! Instead, please
42 # focus on converting packages to use the new eclasses.
44 _CPYTHON2_GLOBALLY_SUPPORTED_ABIS=(2.4 2.5 2.6 2.7)
45 _CPYTHON3_GLOBALLY_SUPPORTED_ABIS=(3.1 3.2 3.3)
46 _JYTHON_GLOBALLY_SUPPORTED_ABIS=(2.5-jython 2.7-jython)
47 _PYPY_GLOBALLY_SUPPORTED_ABIS=(2.7-pypy-1.7 2.7-pypy-1.8 2.7-pypy-1.9 2.7-pypy-2.0)
48 _PYTHON_GLOBALLY_SUPPORTED_ABIS=(${_CPYTHON2_GLOBALLY_SUPPORTED_ABIS[@]} ${_CPYTHON3_GLOBALLY_SUPPORTED_ABIS[@]} ${_JYTHON_GLOBALLY_SUPPORTED_ABIS[@]} ${_PYPY_GLOBALLY_SUPPORTED_ABIS[@]})
50 # ================================================================================================
51 # ===================================== HANDLING OF METADATA =====================================
52 # ================================================================================================
54 _PYTHON_ABI_PATTERN_REGEX="([[:alnum:]]|\.|-|\*|\[|\])+"
56 _python_check_python_abi_matching() {
57 local pattern patterns patterns_list="0" PYTHON_ABI
69 die "${FUNCNAME}(): Unrecognized option '$1'"
78 if [[ "$#" -ne 2 ]]; then
79 die "${FUNCNAME}() requires 2 arguments"
84 if [[ "${patterns_list}" == "0" ]]; then
87 if [[ "${pattern}" == *"-cpython" ]]; then
88 [[ "${PYTHON_ABI}" =~ ^[[:digit:]]+\.[[:digit:]]+$ && "${PYTHON_ABI}" == ${pattern%-cpython} ]]
89 elif [[ "${pattern}" == *"-jython" ]]; then
90 [[ "${PYTHON_ABI}" == ${pattern} ]]
91 elif [[ "${pattern}" == *"-pypy-"* ]]; then
92 [[ "${PYTHON_ABI}" == ${pattern} ]]
94 if [[ "${PYTHON_ABI}" =~ ^[[:digit:]]+\.[[:digit:]]+$ ]]; then
95 [[ "${PYTHON_ABI}" == ${pattern} ]]
96 elif [[ "${PYTHON_ABI}" =~ ^[[:digit:]]+\.[[:digit:]]+-jython$ ]]; then
97 [[ "${PYTHON_ABI%-jython}" == ${pattern} ]]
98 elif [[ "${PYTHON_ABI}" =~ ^[[:digit:]]+\.[[:digit:]]+-pypy-[[:digit:]]+\.[[:digit:]]+$ ]]; then
99 [[ "${PYTHON_ABI%-pypy-*}" == ${pattern} ]]
101 die "${FUNCNAME}(): Unrecognized Python ABI '${PYTHON_ABI}'"
105 patterns="${2// /$'\n'}"
107 while read pattern; do
108 if _python_check_python_abi_matching "${PYTHON_ABI}" "${pattern}"; then
111 done <<< "${patterns}"
117 _python_implementation() {
118 if [[ "${CATEGORY}/${PN}" == "dev-lang/python" ]]; then
120 elif [[ "${CATEGORY}/${PN}" == "dev-java/jython" ]]; then
122 elif [[ "${CATEGORY}/${PN}" == "virtual/pypy" ]]; then
129 _python_package_supporting_installation_for_multiple_python_abis() {
130 [[ -n "${SUPPORT_PYTHON_ABIS}" ]]
133 # @ECLASS-VARIABLE: PYTHON_DEPEND
135 # Specification of dependency on dev-lang/python.
137 # PYTHON_DEPEND: [[!]USE_flag? ]<version_components_group>[ version_components_group]
138 # version_components_group: <major_version[:[minimal_version][:maximal_version]]>
139 # major_version: <2|3|*>
140 # minimal_version: <minimal_major_version.minimal_minor_version>
141 # maximal_version: <maximal_major_version.maximal_minor_version>
143 _python_parse_PYTHON_DEPEND() {
144 local major_version maximal_version minimal_version python_all="0" python_maximal_version python_minimal_version python_versions=() python2="0" python2_maximal_version python2_minimal_version python3="0" python3_maximal_version python3_minimal_version USE_flag= version_components_group version_components_group_regex version_components_groups
146 version_components_group_regex="(2|3|\*)(:([[:digit:]]+\.[[:digit:]]+)?(:([[:digit:]]+\.[[:digit:]]+)?)?)?"
147 version_components_groups="${PYTHON_DEPEND}"
149 if [[ "${version_components_groups}" =~ ^((\!)?[[:alnum:]_-]+\?\ )?${version_components_group_regex}(\ ${version_components_group_regex})?$ ]]; then
150 if [[ "${version_components_groups}" =~ ^(\!)?[[:alnum:]_-]+\? ]]; then
151 USE_flag="${version_components_groups%\? *}"
152 version_components_groups="${version_components_groups#* }"
154 if [[ "${version_components_groups}" =~ ("*".*" "|" *"|^2.*\ (2|\*)|^3.*\ (3|\*)) ]]; then
155 die "Invalid syntax of PYTHON_DEPEND: Incorrectly specified groups of versions"
158 version_components_groups="${version_components_groups// /$'\n'}"
159 while read version_components_group; do
160 major_version="${version_components_group:0:1}"
161 minimal_version="${version_components_group:2}"
162 minimal_version="${minimal_version%:*}"
163 maximal_version="${version_components_group:$((3 + ${#minimal_version}))}"
165 if [[ "${major_version}" =~ ^(2|3)$ ]]; then
166 if [[ -n "${minimal_version}" && "${major_version}" != "${minimal_version:0:1}" ]]; then
167 die "Invalid syntax of PYTHON_DEPEND: Minimal version '${minimal_version}' not in specified group of versions"
169 if [[ -n "${maximal_version}" && "${major_version}" != "${maximal_version:0:1}" ]]; then
170 die "Invalid syntax of PYTHON_DEPEND: Maximal version '${maximal_version}' not in specified group of versions"
174 if [[ "${major_version}" == "2" ]]; then
176 python_versions=("${_CPYTHON2_GLOBALLY_SUPPORTED_ABIS[@]}")
177 python2_minimal_version="${minimal_version}"
178 python2_maximal_version="${maximal_version}"
179 elif [[ "${major_version}" == "3" ]]; then
181 python_versions=("${_CPYTHON3_GLOBALLY_SUPPORTED_ABIS[@]}")
182 python3_minimal_version="${minimal_version}"
183 python3_maximal_version="${maximal_version}"
186 python_versions=("${_CPYTHON2_GLOBALLY_SUPPORTED_ABIS[@]}" "${_CPYTHON3_GLOBALLY_SUPPORTED_ABIS[@]}")
187 python_minimal_version="${minimal_version}"
188 python_maximal_version="${maximal_version}"
191 if [[ -n "${minimal_version}" ]] && ! has "${minimal_version}" "${python_versions[@]}"; then
192 die "Invalid syntax of PYTHON_DEPEND: Unrecognized minimal version '${minimal_version}'"
194 if [[ -n "${maximal_version}" ]] && ! has "${maximal_version}" "${python_versions[@]}"; then
195 die "Invalid syntax of PYTHON_DEPEND: Unrecognized maximal version '${maximal_version}'"
198 if [[ -n "${minimal_version}" && -n "${maximal_version}" && "${minimal_version}" > "${maximal_version}" ]]; then
199 die "Invalid syntax of PYTHON_DEPEND: Minimal version '${minimal_version}' greater than maximal version '${maximal_version}'"
201 done <<< "${version_components_groups}"
205 _append_accepted_versions_range() {
206 local accepted_version="0" i
207 for ((i = "${#python_versions[@]}"; i >= 0; i--)); do
208 if [[ "${python_versions[${i}]}" == "${python_maximal_version}" ]]; then
211 if [[ "${accepted_version}" == "1" ]]; then
212 _PYTHON_ATOMS+=("=dev-lang/python-${python_versions[${i}]}*")
214 if [[ "${python_versions[${i}]}" == "${python_minimal_version}" ]]; then
220 if [[ "${python_all}" == "1" ]]; then
221 if [[ -z "${python_minimal_version}" && -z "${python_maximal_version}" ]]; then
222 _PYTHON_ATOMS+=("dev-lang/python")
224 python_versions=("${_CPYTHON2_GLOBALLY_SUPPORTED_ABIS[@]}" "${_CPYTHON3_GLOBALLY_SUPPORTED_ABIS[@]}")
225 python_minimal_version="${python_minimal_version:-${python_versions[0]}}"
226 python_maximal_version="${python_maximal_version:-${python_versions[${#python_versions[@]}-1]}}"
227 _append_accepted_versions_range
230 if [[ "${python3}" == "1" ]]; then
231 if [[ -z "${python3_minimal_version}" && -z "${python3_maximal_version}" ]]; then
232 _PYTHON_ATOMS+=("=dev-lang/python-3*")
234 python_versions=("${_CPYTHON3_GLOBALLY_SUPPORTED_ABIS[@]}")
235 python_minimal_version="${python3_minimal_version:-${python_versions[0]}}"
236 python_maximal_version="${python3_maximal_version:-${python_versions[${#python_versions[@]}-1]}}"
237 _append_accepted_versions_range
240 if [[ "${python2}" == "1" ]]; then
241 if [[ -z "${python2_minimal_version}" && -z "${python2_maximal_version}" ]]; then
242 _PYTHON_ATOMS+=("=dev-lang/python-2*")
244 python_versions=("${_CPYTHON2_GLOBALLY_SUPPORTED_ABIS[@]}")
245 python_minimal_version="${python2_minimal_version:-${python_versions[0]}}"
246 python_maximal_version="${python2_maximal_version:-${python_versions[${#python_versions[@]}-1]}}"
247 _append_accepted_versions_range
252 unset -f _append_accepted_versions_range
254 if [[ "${#_PYTHON_ATOMS[@]}" -gt 1 ]]; then
255 DEPEND+="${DEPEND:+ }${USE_flag}${USE_flag:+? ( }|| ( ${_PYTHON_ATOMS[@]} )${USE_flag:+ )}"
256 RDEPEND+="${RDEPEND:+ }${USE_flag}${USE_flag:+? ( }|| ( ${_PYTHON_ATOMS[@]} )${USE_flag:+ )}"
258 DEPEND+="${DEPEND:+ }${USE_flag}${USE_flag:+? ( }${_PYTHON_ATOMS[@]}${USE_flag:+ )}"
259 RDEPEND+="${RDEPEND:+ }${USE_flag}${USE_flag:+? ( }${_PYTHON_ATOMS[@]}${USE_flag:+ )}"
262 die "Invalid syntax of PYTHON_DEPEND"
266 if _python_implementation; then
267 DEPEND=">=app-eselect/eselect-python-20091230"
269 PDEPEND="app-admin/python-updater"
272 if [[ -n "${PYTHON_DEPEND}" ]]; then
273 _python_parse_PYTHON_DEPEND
275 _PYTHON_ATOMS=("dev-lang/python")
277 unset -f _python_parse_PYTHON_DEPEND
279 if [[ -n "${NEED_PYTHON}" ]]; then
280 eerror "Use PYTHON_DEPEND variable instead of NEED_PYTHON variable."
281 die "NEED_PYTHON variable is banned"
284 # @ECLASS-VARIABLE: PYTHON_USE_WITH
286 # Set this to a space separated list of USE flags the Python slot in use must be built with.
288 # @ECLASS-VARIABLE: PYTHON_USE_WITH_OR
290 # Set this to a space separated list of USE flags of which one must be turned on for the slot in use.
292 # @ECLASS-VARIABLE: PYTHON_USE_WITH_OPT
294 # Set this to a name of a USE flag if you need to make either PYTHON_USE_WITH or
295 # PYTHON_USE_WITH_OR atoms conditional under a USE flag.
297 if ! has "${EAPI:-0}" 0 1 && [[ -n ${PYTHON_USE_WITH} || -n ${PYTHON_USE_WITH_OR} ]]; then
298 _PYTHON_USE_WITH_ATOMS_ARRAY=()
299 if [[ -n "${PYTHON_USE_WITH}" ]]; then
300 for _PYTHON_ATOM in "${_PYTHON_ATOMS[@]}"; do
301 _PYTHON_USE_WITH_ATOMS_ARRAY+=("${_PYTHON_ATOM}[${PYTHON_USE_WITH// /,}]")
303 elif [[ -n "${PYTHON_USE_WITH_OR}" ]]; then
304 for _USE_flag in ${PYTHON_USE_WITH_OR}; do
305 for _PYTHON_ATOM in "${_PYTHON_ATOMS[@]}"; do
306 _PYTHON_USE_WITH_ATOMS_ARRAY+=("${_PYTHON_ATOM}[${_USE_flag}]")
311 if [[ "${#_PYTHON_USE_WITH_ATOMS_ARRAY[@]}" -gt 1 ]]; then
312 _PYTHON_USE_WITH_ATOMS="|| ( ${_PYTHON_USE_WITH_ATOMS_ARRAY[@]} )"
314 _PYTHON_USE_WITH_ATOMS="${_PYTHON_USE_WITH_ATOMS_ARRAY[@]}"
316 if [[ -n "${PYTHON_USE_WITH_OPT}" ]]; then
317 _PYTHON_USE_WITH_ATOMS="${PYTHON_USE_WITH_OPT}? ( ${_PYTHON_USE_WITH_ATOMS} )"
319 DEPEND+="${DEPEND:+ }${_PYTHON_USE_WITH_ATOMS}"
320 RDEPEND+="${RDEPEND:+ }${_PYTHON_USE_WITH_ATOMS}"
321 unset _PYTHON_ATOM _PYTHON_USE_WITH_ATOMS _PYTHON_USE_WITH_ATOMS_ARRAY
326 # ================================================================================================
327 # =================================== MISCELLANEOUS FUNCTIONS ====================================
328 # ================================================================================================
330 _python_abi-specific_local_scope() {
331 [[ " ${FUNCNAME[@]:2} " =~ " "(_python_final_sanity_checks|python_execute_function|python_mod_optimize|python_mod_cleanup)" " ]]
334 _python_initialize_prefix_variables() {
335 if has "${EAPI:-0}" 0 1 2; then
336 if [[ -n "${ROOT}" && -z "${EROOT}" ]]; then
337 EROOT="${ROOT%/}${EPREFIX}/"
339 if [[ -n "${D}" && -z "${ED}" ]]; then
340 ED="${D%/}${EPREFIX}/"
345 unset PYTHON_SANITY_CHECKS_EXECUTED PYTHON_SKIP_SANITY_CHECKS
347 _python_initial_sanity_checks() {
351 _python_final_sanity_checks() {
352 if ! _python_implementation && [[ "$(declare -p PYTHON_SANITY_CHECKS_EXECUTED 2> /dev/null)" != "declare -- PYTHON_SANITY_CHECKS_EXECUTED="* || " ${FUNCNAME[@]:1} " =~ " "(python_set_active_version|python_pkg_setup)" " && -z "${PYTHON_SKIP_SANITY_CHECKS}" ]]; then
353 local PYTHON_ABI="${PYTHON_ABI}"
354 for PYTHON_ABI in ${PYTHON_ABIS-${PYTHON_ABI}}; do
355 # Ensure that appropriate version of Python is installed.
356 if ! has_version "$(python_get_implementational_package)"; then
357 die "$(python_get_implementational_package) is not installed"
360 # Ensure that EPYTHON variable is respected.
361 if [[ "$(EPYTHON="$(PYTHON)" python -c "${_PYTHON_ABI_EXTRACTION_COMMAND}")" != "${PYTHON_ABI}" ]]; then
362 eerror "Path to 'python': '$(type -p python)'"
363 eerror "ABI: '${ABI}'"
364 eerror "DEFAULT_ABI: '${DEFAULT_ABI}'"
365 eerror "EPYTHON: '$(PYTHON)'"
366 eerror "PYTHON_ABI: '${PYTHON_ABI}'"
367 eerror "Locally active version of Python: '$(EPYTHON="$(PYTHON)" python -c "${_PYTHON_ABI_EXTRACTION_COMMAND}")'"
368 die "'python' does not respect EPYTHON variable"
372 PYTHON_SANITY_CHECKS_EXECUTED="1"
375 # @ECLASS-VARIABLE: PYTHON_COLORS
377 # User-configurable colored output.
378 PYTHON_COLORS="${PYTHON_COLORS:-0}"
380 _python_set_color_variables() {
381 if [[ "${PYTHON_COLORS}" != "0" && "${NOCOLOR:-false}" =~ ^(false|no)$ ]]; then
398 _python_check_python_pkg_setup_execution() {
399 [[ " ${FUNCNAME[@]:1} " =~ " "(python_set_active_version|python_pkg_setup)" " ]] && return
401 if ! has "${EAPI:-0}" 0 1 2 3 && [[ -z "${PYTHON_PKG_SETUP_EXECUTED}" ]]; then
402 die "python_pkg_setup() not called"
406 # @FUNCTION: python_pkg_setup
408 # Perform sanity checks and initialize environment.
410 # This function is exported in EAPI 2 and 3 when PYTHON_USE_WITH or PYTHON_USE_WITH_OR variable
411 # is set and always in EAPI >=4. Calling of this function is mandatory in EAPI >=4.
413 if [[ "${EBUILD_PHASE}" != "setup" ]]; then
414 die "${FUNCNAME}() can be used only in pkg_setup() phase"
417 if [[ "$#" -ne 0 ]]; then
418 die "${FUNCNAME}() does not accept arguments"
421 export JYTHON_SYSTEM_CACHEDIR="1"
422 addwrite "${EPREFIX}/var/cache/jython"
424 if _python_package_supporting_installation_for_multiple_python_abis; then
425 _python_calculate_PYTHON_ABIS
426 export EPYTHON="$(PYTHON -f)"
428 PYTHON_ABI="${PYTHON_ABI:-$(PYTHON --ABI)}"
431 if ! has "${EAPI:-0}" 0 1 && [[ -n "${PYTHON_USE_WITH}" || -n "${PYTHON_USE_WITH_OR}" ]]; then
432 if [[ "${PYTHON_USE_WITH_OPT}" ]]; then
433 if [[ "${PYTHON_USE_WITH_OPT}" == !* ]]; then
434 use ${PYTHON_USE_WITH_OPT#!} && return
436 use !${PYTHON_USE_WITH_OPT} && return
440 python_pkg_setup_check_USE_flags() {
441 local python_atom USE_flag
442 python_atom="$(python_get_implementational_package)"
444 for USE_flag in ${PYTHON_USE_WITH}; do
445 if ! has_version "${python_atom}[${USE_flag}]"; then
446 eerror "Please rebuild ${python_atom} with the following USE flags enabled: ${PYTHON_USE_WITH}"
447 die "Please rebuild ${python_atom} with the following USE flags enabled: ${PYTHON_USE_WITH}"
451 for USE_flag in ${PYTHON_USE_WITH_OR}; do
452 if has_version "${python_atom}[${USE_flag}]"; then
457 if [[ ${PYTHON_USE_WITH_OR} ]]; then
458 eerror "Please rebuild ${python_atom} with at least one of the following USE flags enabled: ${PYTHON_USE_WITH_OR}"
459 die "Please rebuild ${python_atom} with at least one of the following USE flags enabled: ${PYTHON_USE_WITH_OR}"
463 if _python_package_supporting_installation_for_multiple_python_abis; then
464 PYTHON_SKIP_SANITY_CHECKS="1" python_execute_function -q python_pkg_setup_check_USE_flags
466 python_pkg_setup_check_USE_flags
469 unset -f python_pkg_setup_check_USE_flags
472 PYTHON_PKG_SETUP_EXECUTED="1"
475 _PYTHON_SHEBANG_BASE_PART_REGEX='^#![[:space:]]*([^[:space:]]*/usr/bin/env[[:space:]]+)?([^[:space:]]*/)?(jython|pypy-c|python)'
477 # @FUNCTION: python_convert_shebangs
478 # @USAGE: [-q|--quiet] [-r|--recursive] [-x|--only-executables] [--] <Python_ABI|Python_version> <file|directory> [files|directories]
480 # Convert shebangs in specified files. Directories can be specified only with --recursive option.
481 python_convert_shebangs() {
482 _python_check_python_pkg_setup_execution
484 local argument file files=() only_executables="0" python_interpreter quiet="0" recursive="0" shebangs_converted="0"
494 -x|--only-executables)
502 die "${FUNCNAME}(): Unrecognized option '$1'"
511 if [[ "$#" -eq 0 ]]; then
512 die "${FUNCNAME}(): Missing Python version and files or directories"
513 elif [[ "$#" -eq 1 ]]; then
514 die "${FUNCNAME}(): Missing files or directories"
517 if [[ -n "$(_python_get_implementation --ignore-invalid "$1")" ]]; then
518 python_interpreter="$(PYTHON "$1")"
520 python_interpreter="python$1"
524 for argument in "$@"; do
525 if [[ ! -e "${argument}" ]]; then
526 die "${FUNCNAME}(): '${argument}' does not exist"
527 elif [[ -f "${argument}" ]]; then
528 files+=("${argument}")
529 elif [[ -d "${argument}" ]]; then
530 if [[ "${recursive}" == "1" ]]; then
531 while read -d $'\0' -r file; do
533 done < <(find "${argument}" $([[ "${only_executables}" == "1" ]] && echo -perm /111) -type f -print0)
535 die "${FUNCNAME}(): '${argument}' is not a regular file"
538 die "${FUNCNAME}(): '${argument}' is not a regular file or a directory"
542 for file in "${files[@]}"; do
544 [[ "${only_executables}" == "1" && ! -x "${file}" ]] && continue
546 if [[ "$(head -n1 "${file}")" =~ ${_PYTHON_SHEBANG_BASE_PART_REGEX} ]]; then
547 [[ "$(sed -ne "2p" "${file}")" =~ ^"# Gentoo '".*"' wrapper script generated by python_generate_wrapper_scripts()"$ ]] && continue
549 shebangs_converted="1"
551 if [[ "${quiet}" == "0" ]]; then
552 einfo "Converting shebang in '${file}'"
555 sed -e "1s:^#![[:space:]]*\([^[:space:]]*/usr/bin/env[[:space:]]\)\?[[:space:]]*\([^[:space:]]*/\)\?\(jython\|pypy-c\|python\)\([[:digit:]]\+\(\.[[:digit:]]\+\)\?\)\?\(\$\|[[:space:]].*\):#!\1\2${python_interpreter}\6:" -i "${file}" || die "Conversion of shebang in '${file}' failed"
559 if [[ "${shebangs_converted}" == "0" ]]; then
560 ewarn "${FUNCNAME}(): Python scripts not found"
564 # @FUNCTION: python_clean_py-compile_files
565 # @USAGE: [-q|--quiet]
567 # Clean py-compile files to disable byte-compilation.
568 python_clean_py-compile_files() {
569 _python_check_python_pkg_setup_execution
571 local file files=() quiet="0"
579 die "${FUNCNAME}(): Unrecognized option '$1'"
582 die "${FUNCNAME}(): Invalid usage"
588 while read -d $'\0' -r file; do
589 files+=("${file#./}")
590 done < <(find -name py-compile -type f -print0)
592 for file in "${files[@]}"; do
593 if [[ "${quiet}" == "0" ]]; then
594 einfo "Cleaning '${file}' file"
596 echo "#!/bin/sh" > "${file}"
600 # @FUNCTION: python_clean_installation_image
601 # @USAGE: [-q|--quiet]
603 # Delete needless files in installation image.
605 # This function can be used only in src_install() phase.
606 python_clean_installation_image() {
607 if [[ "${EBUILD_PHASE}" != "install" ]]; then
608 die "${FUNCNAME}() can be used only in src_install() phase"
611 _python_check_python_pkg_setup_execution
612 _python_initialize_prefix_variables
614 local file files=() quiet="0"
622 die "${FUNCNAME}(): Unrecognized option '$1'"
625 die "${FUNCNAME}(): Invalid usage"
631 while read -d $'\0' -r file; do
633 done < <(find "${ED}" "(" -name "*.py[co]" -o -name "*\$py.class" ")" -type f -print0)
635 if [[ "${#files[@]}" -gt 0 ]]; then
636 if [[ "${quiet}" == "0" ]]; then
637 ewarn "Deleting byte-compiled Python modules needlessly generated by build system:"
639 for file in "${files[@]}"; do
640 if [[ "${quiet}" == "0" ]]; then
645 # Delete empty __pycache__ directories.
646 if [[ "${file%/*}" == *"/__pycache__" ]]; then
647 rmdir "${file%/*}" 2> /dev/null
652 python_clean_sitedirs() {
653 if [[ -d "${ED}$(python_get_sitedir)" ]]; then
654 find "${ED}$(python_get_sitedir)" "(" -name "*.c" -o -name "*.h" -o -name "*.la" ")" -type f -print0 | xargs -0 rm -f
657 if _python_package_supporting_installation_for_multiple_python_abis; then
658 python_execute_function -q python_clean_sitedirs
660 python_clean_sitedirs
663 unset -f python_clean_sitedirs
666 # ================================================================================================
667 # =========== FUNCTIONS FOR PACKAGES SUPPORTING INSTALLATION FOR MULTIPLE PYTHON ABIS ============
668 # ================================================================================================
670 # @ECLASS-VARIABLE: SUPPORT_PYTHON_ABIS
672 # Set this in EAPI <= 4 to indicate that current package supports installation for
673 # multiple Python ABIs.
675 # @ECLASS-VARIABLE: PYTHON_TESTS_RESTRICTED_ABIS
677 # Space-separated list of Python ABI patterns. Testing in Python ABIs matching any Python ABI
678 # patterns specified in this list is skipped.
680 # @ECLASS-VARIABLE: PYTHON_EXPORT_PHASE_FUNCTIONS
682 # Set this to export phase functions for the following ebuild phases:
683 # src_prepare(), src_configure(), src_compile(), src_test(), src_install().
684 if ! has "${EAPI:-0}" 0 1; then
685 python_src_prepare() {
686 if [[ "${EBUILD_PHASE}" != "prepare" ]]; then
687 die "${FUNCNAME}() can be used only in src_prepare() phase"
690 if ! _python_package_supporting_installation_for_multiple_python_abis; then
691 die "${FUNCNAME}() cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
694 _python_check_python_pkg_setup_execution
696 if [[ "$#" -ne 0 ]]; then
697 die "${FUNCNAME}() does not accept arguments"
703 for python_default_function in src_configure src_compile src_test; do
704 eval "python_${python_default_function}() {
705 if [[ \"\${EBUILD_PHASE}\" != \"${python_default_function#src_}\" ]]; then
706 die \"\${FUNCNAME}() can be used only in ${python_default_function}() phase\"
709 if ! _python_package_supporting_installation_for_multiple_python_abis; then
710 die \"\${FUNCNAME}() cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs\"
713 _python_check_python_pkg_setup_execution
715 python_execute_function -d -s -- \"\$@\"
718 unset python_default_function
720 python_src_install() {
721 if [[ "${EBUILD_PHASE}" != "install" ]]; then
722 die "${FUNCNAME}() can be used only in src_install() phase"
725 if ! _python_package_supporting_installation_for_multiple_python_abis; then
726 die "${FUNCNAME}() cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
729 _python_check_python_pkg_setup_execution
731 if has "${EAPI:-0}" 0 1 2 3; then
732 python_execute_function -d -s -- "$@"
734 python_installation() {
735 emake DESTDIR="${T}/images/${PYTHON_ABI}" install "$@"
737 python_execute_function -s python_installation "$@"
738 unset python_installation
740 python_merge_intermediate_installation_images "${T}/images"
744 if [[ -n "${PYTHON_EXPORT_PHASE_FUNCTIONS}" ]]; then
745 EXPORT_FUNCTIONS src_prepare src_configure src_compile src_test src_install
751 _python_calculate_PYTHON_ABIS() {
752 if ! _python_package_supporting_installation_for_multiple_python_abis; then
753 die "${FUNCNAME}() cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
756 _python_initial_sanity_checks
758 if [[ "$(declare -p PYTHON_ABIS 2> /dev/null)" != "declare -x PYTHON_ABIS="* ]]; then
761 if [[ "$(declare -p USE_PYTHON 2> /dev/null)" == "declare -x USE_PYTHON="* ]]; then
762 local cpython_enabled="0"
764 if [[ -z "${USE_PYTHON}" ]]; then
765 die "USE_PYTHON variable is empty"
768 for PYTHON_ABI in ${USE_PYTHON}; do
769 if ! has "${PYTHON_ABI}" "${_PYTHON_GLOBALLY_SUPPORTED_ABIS[@]}"; then
770 die "USE_PYTHON variable contains invalid value '${PYTHON_ABI}'"
773 if has "${PYTHON_ABI}" "${_CPYTHON2_GLOBALLY_SUPPORTED_ABIS[@]}" "${_CPYTHON3_GLOBALLY_SUPPORTED_ABIS[@]}"; then
777 if ! _python_check_python_abi_matching --patterns-list "${PYTHON_ABI}" "${RESTRICT_PYTHON_ABIS}"; then
778 export PYTHON_ABIS+="${PYTHON_ABIS:+ }${PYTHON_ABI}"
782 if [[ -z "${PYTHON_ABIS//[${IFS}]/}" ]]; then
783 die "USE_PYTHON variable does not enable any Python ABI supported by ${CATEGORY}/${PF}"
786 if [[ "${cpython_enabled}" == "0" ]]; then
787 die "USE_PYTHON variable does not enable any CPython ABI"
790 local python_version python2_version python3_version support_python_major_version
792 if ! has_version "dev-lang/python"; then
793 die "${FUNCNAME}(): 'dev-lang/python' is not installed"
796 python_version="$("${EPREFIX}/usr/bin/python" -c 'from sys import version_info; print(".".join(str(x) for x in version_info[:2]))')"
798 if has_version "=dev-lang/python-2*"; then
799 python2_version="$("${EPREFIX}/usr/bin/python2" -c 'from sys import version_info; print(".".join(str(x) for x in version_info[:2]))')"
801 support_python_major_version="0"
802 for PYTHON_ABI in "${_CPYTHON2_GLOBALLY_SUPPORTED_ABIS[@]}"; do
803 if ! _python_check_python_abi_matching --patterns-list "${PYTHON_ABI}" "${RESTRICT_PYTHON_ABIS}"; then
804 support_python_major_version="1"
808 if [[ "${support_python_major_version}" == "1" ]]; then
809 if _python_check_python_abi_matching --patterns-list "${python2_version}" "${RESTRICT_PYTHON_ABIS}"; then
810 die "Active version of CPython 2 is not supported by ${CATEGORY}/${PF}"
817 if has_version "=dev-lang/python-3*"; then
818 python3_version="$("${EPREFIX}/usr/bin/python3" -c 'from sys import version_info; print(".".join(str(x) for x in version_info[:2]))')"
820 support_python_major_version="0"
821 for PYTHON_ABI in "${_CPYTHON3_GLOBALLY_SUPPORTED_ABIS[@]}"; do
822 if ! _python_check_python_abi_matching --patterns-list "${PYTHON_ABI}" "${RESTRICT_PYTHON_ABIS}"; then
823 support_python_major_version="1"
827 if [[ "${support_python_major_version}" == "1" ]]; then
828 if _python_check_python_abi_matching --patterns-list "${python3_version}" "${RESTRICT_PYTHON_ABIS}"; then
829 die "Active version of CPython 3 is not supported by ${CATEGORY}/${PF}"
836 if [[ -z "${python2_version}" && -z "${python3_version}" ]]; then
837 eerror "${CATEGORY}/${PF} requires at least one of the following packages:"
838 for PYTHON_ABI in "${_CPYTHON2_GLOBALLY_SUPPORTED_ABIS[@]}" "${_CPYTHON3_GLOBALLY_SUPPORTED_ABIS[@]}"; do
839 if ! _python_check_python_abi_matching --patterns-list "${PYTHON_ABI}" "${RESTRICT_PYTHON_ABIS}"; then
840 eerror " dev-lang/python:${PYTHON_ABI}"
843 die "No supported version of CPython installed"
846 if [[ -n "${python2_version}" && "${python_version}" == "2."* && "${python_version}" != "${python2_version}" ]]; then
847 eerror "Python wrapper is configured incorrectly or '${EPREFIX}/usr/bin/python2' symlink"
848 eerror "is set incorrectly. Use \`eselect python\` to fix configuration."
849 die "Incorrect configuration of Python"
851 if [[ -n "${python3_version}" && "${python_version}" == "3."* && "${python_version}" != "${python3_version}" ]]; then
852 eerror "Python wrapper is configured incorrectly or '${EPREFIX}/usr/bin/python3' symlink"
853 eerror "is set incorrectly. Use \`eselect python\` to fix configuration."
854 die "Incorrect configuration of Python"
857 PYTHON_ABIS="${python2_version} ${python3_version}"
858 PYTHON_ABIS="${PYTHON_ABIS# }"
859 export PYTHON_ABIS="${PYTHON_ABIS% }"
863 _python_final_sanity_checks
866 _python_prepare_flags() {
867 local array=() deleted_flag element flags new_value old_flag old_value operator pattern prefix variable
869 for variable in CPPFLAGS CFLAGS CXXFLAGS LDFLAGS; do
870 eval "_PYTHON_SAVED_${variable}=\"\${!variable}\""
871 for prefix in PYTHON_USER_ PYTHON_; do
872 if [[ "$(declare -p ${prefix}${variable} 2> /dev/null)" == "declare -a ${prefix}${variable}="* ]]; then
873 eval "array=(\"\${${prefix}${variable}[@]}\")"
874 for element in "${array[@]}"; do
875 if [[ "${element}" =~ ^${_PYTHON_ABI_PATTERN_REGEX}\ (\+|-)\ .+ ]]; then
876 pattern="${element%% *}"
877 element="${element#* }"
878 operator="${element%% *}"
879 flags="${element#* }"
880 if _python_check_python_abi_matching "${PYTHON_ABI}" "${pattern}"; then
881 if [[ "${operator}" == "+" ]]; then
882 eval "export ${variable}+=\"\${variable:+ }${flags}\""
883 elif [[ "${operator}" == "-" ]]; then
884 flags="${flags// /$'\n'}"
885 old_value="${!variable// /$'\n'}"
887 while read old_flag; do
888 while read deleted_flag; do
889 if [[ "${old_flag}" == ${deleted_flag} ]]; then
893 new_value+="${new_value:+ }${old_flag}"
894 done <<< "${old_value}"
895 eval "export ${variable}=\"\${new_value}\""
899 die "Element '${element}' of ${prefix}${variable} array has invalid syntax"
902 elif [[ -n "$(declare -p ${prefix}${variable} 2> /dev/null)" ]]; then
903 die "${prefix}${variable} should be indexed array"
909 _python_restore_flags() {
912 for variable in CPPFLAGS CFLAGS CXXFLAGS LDFLAGS; do
913 eval "${variable}=\"\${_PYTHON_SAVED_${variable}}\""
914 unset _PYTHON_SAVED_${variable}
918 # @FUNCTION: python_execute_function
919 # @USAGE: [--action-message message] [-d|--default-function] [--failure-message message] [-f|--final-ABI] [--nonfatal] [-q|--quiet] [-s|--separate-build-dirs] [--source-dir source_directory] [--] <function> [arguments]
921 # Execute specified function for each value of PYTHON_ABIS, optionally passing additional
922 # arguments. The specified function can use PYTHON_ABI and BUILDDIR variables.
923 python_execute_function() {
924 if ! _python_package_supporting_installation_for_multiple_python_abis; then
925 die "${FUNCNAME}() cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
928 _python_check_python_pkg_setup_execution
929 _python_set_color_variables
931 local action action_message action_message_template default_function="0" failure_message failure_message_template final_ABI="0" function iterated_PYTHON_ABIS nonfatal="0" previous_directory previous_directory_stack previous_directory_stack_length PYTHON_ABI quiet="0" return_code separate_build_dirs="0" source_dir
936 action_message_template="$2"
939 -d|--default-function)
943 failure_message_template="$2"
955 -s|--separate-build-dirs)
956 separate_build_dirs="1"
967 die "${FUNCNAME}(): Unrecognized option '$1'"
976 if [[ -n "${source_dir}" && "${separate_build_dirs}" == 0 ]]; then
977 die "${FUNCNAME}(): '--source-dir' option can be specified only with '--separate-build-dirs' option"
980 if [[ "${default_function}" == "0" ]]; then
981 if [[ "$#" -eq 0 ]]; then
982 die "${FUNCNAME}(): Missing function name"
987 if [[ -z "$(type -t "${function}")" ]]; then
988 die "${FUNCNAME}(): '${function}' function is not defined"
991 if has "${EAPI:-0}" 0 1; then
992 die "${FUNCNAME}(): '--default-function' option cannot be used in this EAPI"
995 if [[ "${EBUILD_PHASE}" == "configure" ]]; then
996 if has "${EAPI}" 2 3; then
997 python_default_function() {
1001 python_default_function() {
1005 elif [[ "${EBUILD_PHASE}" == "compile" ]]; then
1006 python_default_function() {
1009 elif [[ "${EBUILD_PHASE}" == "test" ]]; then
1010 python_default_function() {
1011 # Stolen from portage's _eapi0_src_test()
1012 local emake_cmd="${MAKE:-make} ${MAKEOPTS} ${EXTRA_EMAKE}"
1013 if ${emake_cmd} -j1 -n check &> /dev/null; then
1014 ${emake_cmd} -j1 check "$@"
1015 elif ${emake_cmd} -j1 -n test &> /dev/null; then
1016 ${emake_cmd} -j1 test "$@"
1019 elif [[ "${EBUILD_PHASE}" == "install" ]]; then
1020 python_default_function() {
1021 emake DESTDIR="${D}" install "$@"
1024 die "${FUNCNAME}(): '--default-function' option cannot be used in this ebuild phase"
1026 function="python_default_function"
1029 # Ensure that python_execute_function() cannot be directly or indirectly called by python_execute_function().
1030 if _python_abi-specific_local_scope; then
1031 die "${FUNCNAME}(): Invalid call stack"
1034 if [[ "${quiet}" == "0" ]]; then
1035 [[ "${EBUILD_PHASE}" == "setup" ]] && action="Setting up"
1036 [[ "${EBUILD_PHASE}" == "unpack" ]] && action="Unpacking"
1037 [[ "${EBUILD_PHASE}" == "prepare" ]] && action="Preparation"
1038 [[ "${EBUILD_PHASE}" == "configure" ]] && action="Configuration"
1039 [[ "${EBUILD_PHASE}" == "compile" ]] && action="Building"
1040 [[ "${EBUILD_PHASE}" == "test" ]] && action="Testing"
1041 [[ "${EBUILD_PHASE}" == "install" ]] && action="Installation"
1042 [[ "${EBUILD_PHASE}" == "preinst" ]] && action="Preinstallation"
1043 [[ "${EBUILD_PHASE}" == "postinst" ]] && action="Postinstallation"
1044 [[ "${EBUILD_PHASE}" == "prerm" ]] && action="Preuninstallation"
1045 [[ "${EBUILD_PHASE}" == "postrm" ]] && action="Postuninstallation"
1048 _python_calculate_PYTHON_ABIS
1049 if [[ "${final_ABI}" == "1" ]]; then
1050 iterated_PYTHON_ABIS="$(PYTHON -f --ABI)"
1052 iterated_PYTHON_ABIS="${PYTHON_ABIS}"
1054 for PYTHON_ABI in ${iterated_PYTHON_ABIS}; do
1055 if [[ "${EBUILD_PHASE}" == "test" ]] && _python_check_python_abi_matching --patterns-list "${PYTHON_ABI}" "${PYTHON_TESTS_RESTRICTED_ABIS}"; then
1056 if [[ "${quiet}" == "0" ]]; then
1057 echo " ${_GREEN}*${_NORMAL} ${_BLUE}Testing of ${CATEGORY}/${PF} with $(python_get_implementation_and_version) skipped${_NORMAL}"
1062 _python_prepare_flags
1064 if [[ "${quiet}" == "0" ]]; then
1065 if [[ -n "${action_message_template}" ]]; then
1066 eval "action_message=\"${action_message_template}\""
1068 action_message="${action} of ${CATEGORY}/${PF} with $(python_get_implementation_and_version)..."
1070 echo " ${_GREEN}*${_NORMAL} ${_BLUE}${action_message}${_NORMAL}"
1073 if [[ "${separate_build_dirs}" == "1" ]]; then
1074 if [[ -n "${source_dir}" ]]; then
1075 export BUILDDIR="${S}/${source_dir}-${PYTHON_ABI}"
1077 export BUILDDIR="${S}-${PYTHON_ABI}"
1079 pushd "${BUILDDIR}" > /dev/null || die "pushd failed"
1081 export BUILDDIR="${S}"
1084 previous_directory="$(pwd)"
1085 previous_directory_stack="$(dirs -p)"
1086 previous_directory_stack_length="$(dirs -p | wc -l)"
1088 if ! has "${EAPI}" 0 1 2 3 && has "${PYTHON_ABI}" ${FAILURE_TOLERANT_PYTHON_ABIS}; then
1089 EPYTHON="$(PYTHON)" nonfatal "${function}" "$@"
1091 EPYTHON="$(PYTHON)" "${function}" "$@"
1096 _python_restore_flags
1098 if [[ "${return_code}" -ne 0 ]]; then
1099 if [[ -n "${failure_message_template}" ]]; then
1100 eval "failure_message=\"${failure_message_template}\""
1102 failure_message="${action} failed with $(python_get_implementation_and_version) in ${function}() function"
1105 if [[ "${nonfatal}" == "1" ]]; then
1106 if [[ "${quiet}" == "0" ]]; then
1107 ewarn "${failure_message}"
1109 elif [[ "${final_ABI}" == "0" ]] && has "${PYTHON_ABI}" ${FAILURE_TOLERANT_PYTHON_ABIS}; then
1110 if [[ "${EBUILD_PHASE}" != "test" ]] || ! has test-fail-continue ${FEATURES}; then
1111 local enabled_PYTHON_ABIS= other_PYTHON_ABI
1112 for other_PYTHON_ABI in ${PYTHON_ABIS}; do
1113 [[ "${other_PYTHON_ABI}" != "${PYTHON_ABI}" ]] && enabled_PYTHON_ABIS+="${enabled_PYTHON_ABIS:+ }${other_PYTHON_ABI}"
1115 export PYTHON_ABIS="${enabled_PYTHON_ABIS}"
1117 if [[ "${quiet}" == "0" ]]; then
1118 ewarn "${failure_message}"
1120 if [[ -z "${PYTHON_ABIS}" ]]; then
1121 die "${function}() function failed with all enabled Python ABIs"
1124 die "${failure_message}"
1128 # Ensure that directory stack has not been decreased.
1129 if [[ "$(dirs -p | wc -l)" -lt "${previous_directory_stack_length}" ]]; then
1130 die "Directory stack decreased illegally"
1133 # Avoid side effects of earlier returning from the specified function.
1134 while [[ "$(dirs -p | wc -l)" -gt "${previous_directory_stack_length}" ]]; do
1135 popd > /dev/null || die "popd failed"
1138 # Ensure that the bottom part of directory stack has not been changed. Restore
1139 # previous directory (from before running of the specified function) before
1140 # comparison of directory stacks to avoid mismatch of directory stacks after
1141 # potential using of 'cd' to change current directory. Restoration of previous
1142 # directory allows to safely use 'cd' to change current directory in the
1143 # specified function without changing it back to original directory.
1144 cd "${previous_directory}"
1145 if [[ "$(dirs -p)" != "${previous_directory_stack}" ]]; then
1146 die "Directory stack changed illegally"
1149 if [[ "${separate_build_dirs}" == "1" ]]; then
1150 popd > /dev/null || die "popd failed"
1155 if [[ "${default_function}" == "1" ]]; then
1156 unset -f python_default_function
1160 # @FUNCTION: python_copy_sources
1161 # @USAGE: <directory="${S}"> [directory]
1163 # Copy unpacked sources of current package to separate build directory for each Python ABI.
1164 python_copy_sources() {
1165 if ! _python_package_supporting_installation_for_multiple_python_abis; then
1166 die "${FUNCNAME}() cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
1169 _python_check_python_pkg_setup_execution
1171 local dir dirs=() PYTHON_ABI
1173 if [[ "$#" -eq 0 ]]; then
1174 if [[ "${WORKDIR}" == "${S}" ]]; then
1175 die "${FUNCNAME}() cannot be used with current value of S variable"
1182 _python_calculate_PYTHON_ABIS
1183 for PYTHON_ABI in ${PYTHON_ABIS}; do
1184 for dir in "${dirs[@]}"; do
1185 cp -pr "${dir}" "${dir}-${PYTHON_ABI}" > /dev/null || die "Copying of sources failed"
1190 # @FUNCTION: python_generate_wrapper_scripts
1191 # @USAGE: [-E|--respect-EPYTHON] [-f|--force] [-q|--quiet] [--] <file> [files]
1193 # Generate wrapper scripts. Existing files are overwritten only with --force option.
1194 # If --respect-EPYTHON option is specified, then generated wrapper scripts will
1195 # respect EPYTHON variable at run time.
1197 # This function can be used only in src_install() phase.
1198 python_generate_wrapper_scripts() {
1199 if [[ "${EBUILD_PHASE}" != "install" ]]; then
1200 die "${FUNCNAME}() can be used only in src_install() phase"
1203 if ! _python_package_supporting_installation_for_multiple_python_abis; then
1204 die "${FUNCNAME}() cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
1207 _python_check_python_pkg_setup_execution
1208 _python_initialize_prefix_variables
1210 local eselect_python_option file force="0" quiet="0" PYTHON_ABI PYTHON_ABIS_list python2_enabled="0" python3_enabled="0" respect_EPYTHON="0"
1214 -E|--respect-EPYTHON)
1228 die "${FUNCNAME}(): Unrecognized option '$1'"
1237 if [[ "$#" -eq 0 ]]; then
1238 die "${FUNCNAME}(): Missing arguments"
1241 _python_calculate_PYTHON_ABIS
1242 for PYTHON_ABI in "${_CPYTHON2_GLOBALLY_SUPPORTED_ABIS[@]}"; do
1243 if has "${PYTHON_ABI}" ${PYTHON_ABIS}; then
1247 for PYTHON_ABI in "${_CPYTHON3_GLOBALLY_SUPPORTED_ABIS[@]}"; do
1248 if has "${PYTHON_ABI}" ${PYTHON_ABIS}; then
1253 if [[ "${python2_enabled}" == "1" && "${python3_enabled}" == "1" ]]; then
1254 eselect_python_option=
1255 elif [[ "${python2_enabled}" == "1" && "${python3_enabled}" == "0" ]]; then
1256 eselect_python_option="--python2"
1257 elif [[ "${python2_enabled}" == "0" && "${python3_enabled}" == "1" ]]; then
1258 eselect_python_option="--python3"
1260 die "${FUNCNAME}(): Unsupported environment"
1263 PYTHON_ABIS_list="$("$(PYTHON -f)" -c "print(', '.join('\"%s\"' % x for x in reversed('${PYTHON_ABIS}'.split())))")"
1265 for file in "$@"; do
1266 if [[ -f "${file}" && "${force}" == "0" ]]; then
1267 die "${FUNCNAME}(): '${file}' already exists"
1270 if [[ "${quiet}" == "0" ]]; then
1271 einfo "Generating '${file#${ED%/}}' wrapper script"
1274 cat << EOF > "${file}"
1275 #!/usr/bin/env python
1276 # Gentoo '${file##*/}' wrapper script generated by python_generate_wrapper_scripts()
1283 cpython_ABI_re = re.compile(r"^(\d+\.\d+)$")
1284 jython_ABI_re = re.compile(r"^(\d+\.\d+)-jython$")
1285 pypy_ABI_re = re.compile(r"^\d+\.\d+-pypy-(\d+\.\d+)$")
1286 cpython_interpreter_re = re.compile(r"^python(\d+\.\d+)$")
1287 jython_interpreter_re = re.compile(r"^jython(\d+\.\d+)$")
1288 pypy_interpreter_re = re.compile(r"^pypy-c(\d+\.\d+)$")
1289 cpython_shebang_re = re.compile(r"^#![ \t]*(?:${EPREFIX}/usr/bin/python|(?:${EPREFIX})?/usr/bin/env[ \t]+(?:${EPREFIX}/usr/bin/)?python)")
1290 python_shebang_options_re = re.compile(r"^#![ \t]*${EPREFIX}/usr/bin/(?:jython|pypy-c|python)(?:\d+(?:\.\d+)?)?[ \t]+(-\S)")
1291 python_verification_output_re = re.compile("^GENTOO_PYTHON_TARGET_SCRIPT_PATH supported\n$")
1293 #pypy_versions_mapping = {
1302 def get_PYTHON_ABI(python_interpreter):
1303 cpython_matched = cpython_interpreter_re.match(python_interpreter)
1304 jython_matched = jython_interpreter_re.match(python_interpreter)
1305 pypy_matched = pypy_interpreter_re.match(python_interpreter)
1306 if cpython_matched is not None:
1307 PYTHON_ABI = cpython_matched.group(1)
1308 elif jython_matched is not None:
1309 PYTHON_ABI = jython_matched.group(1) + "-jython"
1310 elif pypy_matched is not None:
1311 #PYTHON_ABI = pypy_versions_mapping[pypy_matched.group(1)] + "-pypy-" + pypy_matched.group(1)
1312 PYTHON_ABI = "2.7-pypy-" + pypy_matched.group(1)
1317 def get_python_interpreter(PYTHON_ABI):
1318 cpython_matched = cpython_ABI_re.match(PYTHON_ABI)
1319 jython_matched = jython_ABI_re.match(PYTHON_ABI)
1320 pypy_matched = pypy_ABI_re.match(PYTHON_ABI)
1321 if cpython_matched is not None:
1322 python_interpreter = "python" + cpython_matched.group(1)
1323 elif jython_matched is not None:
1324 python_interpreter = "jython" + jython_matched.group(1)
1325 elif pypy_matched is not None:
1326 python_interpreter = "pypy-c" + pypy_matched.group(1)
1328 python_interpreter = None
1329 return python_interpreter
1332 if [[ "$?" != "0" ]]; then
1333 die "${FUNCNAME}(): Generation of '$1' failed"
1335 if [[ "${respect_EPYTHON}" == "1" ]]; then
1336 cat << EOF >> "${file}"
1337 python_interpreter = os.environ.get("EPYTHON")
1338 if python_interpreter:
1339 PYTHON_ABI = get_PYTHON_ABI(python_interpreter)
1340 if PYTHON_ABI is None:
1341 sys.stderr.write("%s: EPYTHON variable has unrecognized value '%s'\n" % (sys.argv[0], python_interpreter))
1345 environment = os.environ.copy()
1346 environment["ROOT"] = "/"
1347 eselect_process = subprocess.Popen(["${EPREFIX}/usr/bin/eselect", "python", "show"${eselect_python_option:+, $(echo "\"")}${eselect_python_option}${eselect_python_option:+$(echo "\"")}], env=environment, stdout=subprocess.PIPE)
1348 if eselect_process.wait() != 0:
1350 except (OSError, ValueError):
1351 sys.stderr.write("%s: Execution of 'eselect python show${eselect_python_option:+ }${eselect_python_option}' failed\n" % sys.argv[0])
1354 python_interpreter = eselect_process.stdout.read()
1355 if not isinstance(python_interpreter, str):
1357 python_interpreter = python_interpreter.decode()
1358 python_interpreter = python_interpreter.rstrip("\n")
1360 PYTHON_ABI = get_PYTHON_ABI(python_interpreter)
1361 if PYTHON_ABI is None:
1362 sys.stderr.write("%s: 'eselect python show${eselect_python_option:+ }${eselect_python_option}' printed unrecognized value '%s'\n" % (sys.argv[0], python_interpreter))
1365 wrapper_script_path = os.path.realpath(sys.argv[0])
1366 target_executable_path = "%s-%s" % (wrapper_script_path, PYTHON_ABI)
1367 if not os.path.exists(target_executable_path):
1368 sys.stderr.write("%s: '%s' does not exist\n" % (sys.argv[0], target_executable_path))
1371 if [[ "$?" != "0" ]]; then
1372 die "${FUNCNAME}(): Generation of '$1' failed"
1375 cat << EOF >> "${file}"
1377 environment = os.environ.copy()
1378 environment["ROOT"] = "/"
1379 eselect_process = subprocess.Popen(["${EPREFIX}/usr/bin/eselect", "python", "show"${eselect_python_option:+, $(echo "\"")}${eselect_python_option}${eselect_python_option:+$(echo "\"")}], env=environment, stdout=subprocess.PIPE)
1380 if eselect_process.wait() != 0:
1382 except (OSError, ValueError):
1383 sys.stderr.write("%s: Execution of 'eselect python show${eselect_python_option:+ }${eselect_python_option}' failed\n" % sys.argv[0])
1386 python_interpreter = eselect_process.stdout.read()
1387 if not isinstance(python_interpreter, str):
1389 python_interpreter = python_interpreter.decode()
1390 python_interpreter = python_interpreter.rstrip("\n")
1392 PYTHON_ABI = get_PYTHON_ABI(python_interpreter)
1393 if PYTHON_ABI is None:
1394 sys.stderr.write("%s: 'eselect python show${eselect_python_option:+ }${eselect_python_option}' printed unrecognized value '%s'\n" % (sys.argv[0], python_interpreter))
1397 wrapper_script_path = os.path.realpath(sys.argv[0])
1398 for PYTHON_ABI in [PYTHON_ABI, ${PYTHON_ABIS_list}]:
1399 target_executable_path = "%s-%s" % (wrapper_script_path, PYTHON_ABI)
1400 if os.path.exists(target_executable_path):
1403 sys.stderr.write("%s: No target script exists for '%s'\n" % (sys.argv[0], wrapper_script_path))
1406 python_interpreter = get_python_interpreter(PYTHON_ABI)
1407 if python_interpreter is None:
1408 sys.stderr.write("%s: Unrecognized Python ABI '%s'\n" % (sys.argv[0], PYTHON_ABI))
1411 if [[ "$?" != "0" ]]; then
1412 die "${FUNCNAME}(): Generation of '$1' failed"
1415 cat << EOF >> "${file}"
1417 target_executable = open(target_executable_path, "rb")
1418 target_executable_first_line = target_executable.readline()
1419 target_executable.close()
1420 if not isinstance(target_executable_first_line, str):
1422 target_executable_first_line = target_executable_first_line.decode("utf_8", "replace")
1425 python_shebang_options_matched = python_shebang_options_re.match(target_executable_first_line)
1426 if python_shebang_options_matched is not None:
1427 options = [python_shebang_options_matched.group(1)]
1429 cpython_shebang_matched = cpython_shebang_re.match(target_executable_first_line)
1431 if cpython_shebang_matched is not None:
1433 python_interpreter_path = "${EPREFIX}/usr/bin/%s" % python_interpreter
1434 os.environ["GENTOO_PYTHON_TARGET_SCRIPT_PATH_VERIFICATION"] = "1"
1435 python_verification_process = subprocess.Popen([python_interpreter_path, "-c", "pass"], stdout=subprocess.PIPE)
1436 del os.environ["GENTOO_PYTHON_TARGET_SCRIPT_PATH_VERIFICATION"]
1437 if python_verification_process.wait() != 0:
1440 python_verification_output = python_verification_process.stdout.read()
1441 if not isinstance(python_verification_output, str):
1443 python_verification_output = python_verification_output.decode()
1445 if not python_verification_output_re.match(python_verification_output):
1448 if cpython_interpreter_re.match(python_interpreter) is not None:
1449 os.environ["GENTOO_PYTHON_PROCESS_NAME"] = os.path.basename(sys.argv[0])
1450 os.environ["GENTOO_PYTHON_WRAPPER_SCRIPT_PATH"] = sys.argv[0]
1451 os.environ["GENTOO_PYTHON_TARGET_SCRIPT_PATH"] = target_executable_path
1453 if hasattr(os, "execv"):
1454 os.execv(python_interpreter_path, [python_interpreter_path] + options + sys.argv)
1456 sys.exit(subprocess.Popen([python_interpreter_path] + options + sys.argv).wait())
1457 except (KeyboardInterrupt, SystemExit):
1461 for variable in ("GENTOO_PYTHON_PROCESS_NAME", "GENTOO_PYTHON_WRAPPER_SCRIPT_PATH", "GENTOO_PYTHON_TARGET_SCRIPT_PATH", "GENTOO_PYTHON_TARGET_SCRIPT_PATH_VERIFICATION"):
1462 if variable in os.environ:
1463 del os.environ[variable]
1465 if hasattr(os, "execv"):
1466 os.execv(target_executable_path, sys.argv)
1468 sys.exit(subprocess.Popen([target_executable_path] + sys.argv[1:]).wait())
1470 if [[ "$?" != "0" ]]; then
1471 die "${FUNCNAME}(): Generation of '$1' failed"
1473 fperms +x "${file#${ED%/}}" || die "fperms '${file}' failed"
1477 # @ECLASS-VARIABLE: PYTHON_VERSIONED_SCRIPTS
1479 # Array of regular expressions of paths to versioned Python scripts.
1480 # Python scripts in /usr/bin and /usr/sbin are versioned by default.
1482 # @ECLASS-VARIABLE: PYTHON_VERSIONED_EXECUTABLES
1484 # Array of regular expressions of paths to versioned executables (including Python scripts).
1486 # @ECLASS-VARIABLE: PYTHON_NONVERSIONED_EXECUTABLES
1488 # Array of regular expressions of paths to nonversioned executables (including Python scripts).
1490 # @FUNCTION: python_merge_intermediate_installation_images
1491 # @USAGE: [-q|--quiet] [--] <intermediate_installation_images_directory>
1493 # Merge intermediate installation images into installation image.
1495 # This function can be used only in src_install() phase.
1496 python_merge_intermediate_installation_images() {
1497 if [[ "${EBUILD_PHASE}" != "install" ]]; then
1498 die "${FUNCNAME}() can be used only in src_install() phase"
1501 if ! _python_package_supporting_installation_for_multiple_python_abis; then
1502 die "${FUNCNAME}() cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
1505 _python_check_python_pkg_setup_execution
1506 _python_initialize_prefix_variables
1508 local absolute_file b file files=() intermediate_installation_images_directory PYTHON_ABI quiet="0" regex shebang version_executable wrapper_scripts=() wrapper_scripts_set=()
1520 die "${FUNCNAME}(): Unrecognized option '$1'"
1529 if [[ "$#" -ne 1 ]]; then
1530 die "${FUNCNAME}() requires 1 argument"
1533 intermediate_installation_images_directory="$1"
1535 if [[ ! -d "${intermediate_installation_images_directory}" ]]; then
1536 die "${FUNCNAME}(): Intermediate installation images directory '${intermediate_installation_images_directory}' does not exist"
1539 _python_calculate_PYTHON_ABIS
1540 if [[ "$(PYTHON -f --ABI)" == 3.* ]]; then
1544 while read -d $'\0' -r file; do
1546 done < <("$(PYTHON -f)" -c \
1550 if hasattr(sys.stdout, 'buffer'):
1552 stdout = sys.stdout.buffer
1559 os.chdir(${b}'${intermediate_installation_images_directory}')
1561 for PYTHON_ABI in ${b}'${PYTHON_ABIS}'.split():
1562 for root, dirs, files in os.walk(PYTHON_ABI + ${b}'${EPREFIX}'):
1563 root = root[len(PYTHON_ABI + ${b}'${EPREFIX}')+1:]
1564 files_set.update(root + ${b}'/' + file for file in files)
1566 for file in sorted(files_set):
1568 stdout.write(${b}'\x00')" || die "${FUNCNAME}(): Failure of extraction of files in intermediate installation images")
1570 for PYTHON_ABI in ${PYTHON_ABIS}; do
1571 if [[ ! -d "${intermediate_installation_images_directory}/${PYTHON_ABI}" ]]; then
1572 die "${FUNCNAME}(): Intermediate installation image for Python ABI '${PYTHON_ABI}' does not exist"
1575 pushd "${intermediate_installation_images_directory}/${PYTHON_ABI}${EPREFIX}" > /dev/null || die "pushd failed"
1577 for file in "${files[@]}"; do
1578 version_executable="0"
1579 for regex in "/usr/bin/.*" "/usr/sbin/.*" "${PYTHON_VERSIONED_SCRIPTS[@]}"; do
1580 if [[ "/${file}" =~ ^${regex}$ ]]; then
1581 version_executable="1"
1585 for regex in "${PYTHON_VERSIONED_EXECUTABLES[@]}"; do
1586 if [[ "/${file}" =~ ^${regex}$ ]]; then
1587 version_executable="2"
1591 if [[ "${version_executable}" != "0" ]]; then
1592 for regex in "${PYTHON_NONVERSIONED_EXECUTABLES[@]}"; do
1593 if [[ "/${file}" =~ ^${regex}$ ]]; then
1594 version_executable="0"
1600 [[ "${version_executable}" == "0" ]] && continue
1602 if [[ -L "${file}" ]]; then
1603 absolute_file="$(readlink "${file}")"
1604 if [[ "${absolute_file}" == /* ]]; then
1605 absolute_file="${intermediate_installation_images_directory}/${PYTHON_ABI}${EPREFIX}/${absolute_file##/}"
1607 if [[ "${file}" == */* ]]; then
1608 absolute_file="${intermediate_installation_images_directory}/${PYTHON_ABI}${EPREFIX}/${file%/*}/${absolute_file}"
1610 absolute_file="${intermediate_installation_images_directory}/${PYTHON_ABI}${EPREFIX}/${absolute_file}"
1614 absolute_file="${intermediate_installation_images_directory}/${PYTHON_ABI}${EPREFIX}/${file}"
1617 [[ ! -x "${absolute_file}" ]] && continue
1619 shebang="$(head -n1 "${absolute_file}")" || die "Extraction of shebang from '${absolute_file}' failed"
1621 if [[ "${version_executable}" == "2" ]]; then
1622 wrapper_scripts+=("${ED}${file}")
1623 elif [[ "${version_executable}" == "1" ]]; then
1624 if [[ "${shebang}" =~ ${_PYTHON_SHEBANG_BASE_PART_REGEX}([[:digit:]]+(\.[[:digit:]]+)?)?($|[[:space:]]+) ]]; then
1625 wrapper_scripts+=("${ED}${file}")
1627 version_executable="0"
1631 [[ "${version_executable}" == "0" ]] && continue
1633 if [[ -e "${file}-${PYTHON_ABI}" ]]; then
1634 die "${FUNCNAME}(): '${EPREFIX}/${file}-${PYTHON_ABI}' already exists"
1637 mv "${file}" "${file}-${PYTHON_ABI}" || die "Renaming of '${file}' failed"
1639 if [[ "${shebang}" =~ ${_PYTHON_SHEBANG_BASE_PART_REGEX}[[:digit:]]*($|[[:space:]]+) ]]; then
1640 if [[ -L "${file}-${PYTHON_ABI}" ]]; then
1641 python_convert_shebangs $([[ "${quiet}" == "1" ]] && echo --quiet) "${PYTHON_ABI}" "${absolute_file}"
1643 python_convert_shebangs $([[ "${quiet}" == "1" ]] && echo --quiet) "${PYTHON_ABI}" "${file}-${PYTHON_ABI}"
1648 popd > /dev/null || die "popd failed"
1650 # This is per bug #390691, without the duplication refactor, and with
1651 # the 3-way structure per comment #6. This enable users with old
1652 # coreutils to upgrade a lot easier (you need to upgrade python+portage
1653 # before coreutils can be upgraded).
1654 if ROOT="/" has_version '>=sys-apps/coreutils-6.9.90'; then
1655 cp -fr --preserve=all --no-preserve=context "${intermediate_installation_images_directory}/${PYTHON_ABI}/"* "${D}" || die "Merging of intermediate installation image for Python ABI '${PYTHON_ABI} into installation image failed"
1656 elif ROOT="/" has_version sys-apps/coreutils; then
1657 cp -fr --preserve=all "${intermediate_installation_images_directory}/${PYTHON_ABI}/"* "${D}" || die "Merging of intermediate installation image for Python ABI '${PYTHON_ABI} into installation image failed"
1659 cp -fpr "${intermediate_installation_images_directory}/${PYTHON_ABI}/"* "${D}" || die "Merging of intermediate installation image for Python ABI '${PYTHON_ABI} into installation image failed"
1663 rm -fr "${intermediate_installation_images_directory}"
1665 if [[ "${#wrapper_scripts[@]}" -ge 1 ]]; then
1666 rm -f "${T}/python_wrapper_scripts"
1668 for file in "${wrapper_scripts[@]}"; do
1669 echo -n "${file}" >> "${T}/python_wrapper_scripts"
1670 echo -en "\x00" >> "${T}/python_wrapper_scripts"
1673 while read -d $'\0' -r file; do
1674 wrapper_scripts_set+=("${file}")
1675 done < <("$(PYTHON -f)" -c \
1678 if hasattr(sys.stdout, 'buffer'):
1680 stdout = sys.stdout.buffer
1685 python_wrapper_scripts_file = open('${T}/python_wrapper_scripts', 'rb')
1686 files = set(python_wrapper_scripts_file.read().rstrip(${b}'\x00').split(${b}'\x00'))
1687 python_wrapper_scripts_file.close()
1689 for file in sorted(files):
1691 stdout.write(${b}'\x00')" || die "${FUNCNAME}(): Failure of extraction of set of wrapper scripts")
1693 python_generate_wrapper_scripts $([[ "${quiet}" == "1" ]] && echo --quiet) "${wrapper_scripts_set[@]}"
1697 # ================================================================================================
1698 # ========= FUNCTIONS FOR PACKAGES NOT SUPPORTING INSTALLATION FOR MULTIPLE PYTHON ABIS ==========
1699 # ================================================================================================
1701 unset EPYTHON PYTHON_ABI
1703 # @FUNCTION: python_set_active_version
1704 # @USAGE: <Python_ABI|2|3>
1706 # Set locally active version of Python.
1707 # If Python_ABI argument is specified, then version of Python corresponding to Python_ABI is used.
1708 # If 2 argument is specified, then active version of CPython 2 is used.
1709 # If 3 argument is specified, then active version of CPython 3 is used.
1711 # This function can be used only in pkg_setup() phase.
1712 python_set_active_version() {
1713 if [[ "${EBUILD_PHASE}" != "setup" ]]; then
1714 die "${FUNCNAME}() can be used only in pkg_setup() phase"
1717 if _python_package_supporting_installation_for_multiple_python_abis; then
1718 die "${FUNCNAME}() cannot be used in ebuilds of packages supporting installation for multiple Python ABIs"
1721 if [[ "$#" -ne 1 ]]; then
1722 die "${FUNCNAME}() requires 1 argument"
1725 _python_initial_sanity_checks
1727 if [[ -z "${PYTHON_ABI}" ]]; then
1728 if [[ -n "$(_python_get_implementation --ignore-invalid "$1")" ]]; then
1729 # PYTHON_ABI variable is intended to be used only in ebuilds/eclasses,
1730 # so it does not need to be exported to subprocesses.
1732 if ! _python_implementation && ! has_version "$(python_get_implementational_package)"; then
1733 die "${FUNCNAME}(): '$(python_get_implementational_package)' is not installed"
1735 export EPYTHON="$(PYTHON "$1")"
1736 elif [[ "$1" == "2" ]]; then
1737 if ! _python_implementation && ! has_version "=dev-lang/python-2*"; then
1738 die "${FUNCNAME}(): '=dev-lang/python-2*' is not installed"
1740 export EPYTHON="$(PYTHON -2)"
1741 PYTHON_ABI="${EPYTHON#python}"
1742 PYTHON_ABI="${PYTHON_ABI%%-*}"
1743 elif [[ "$1" == "3" ]]; then
1744 if ! _python_implementation && ! has_version "=dev-lang/python-3*"; then
1745 die "${FUNCNAME}(): '=dev-lang/python-3*' is not installed"
1747 export EPYTHON="$(PYTHON -3)"
1748 PYTHON_ABI="${EPYTHON#python}"
1749 PYTHON_ABI="${PYTHON_ABI%%-*}"
1751 die "${FUNCNAME}(): Unrecognized argument '$1'"
1755 _python_final_sanity_checks
1757 # python-updater checks PYTHON_REQUESTED_ACTIVE_VERSION variable.
1758 PYTHON_REQUESTED_ACTIVE_VERSION="$1"
1761 # @FUNCTION: python_need_rebuild
1763 # Mark current package for rebuilding by python-updater after
1764 # switching of active version of Python.
1765 python_need_rebuild() {
1766 if _python_package_supporting_installation_for_multiple_python_abis; then
1767 die "${FUNCNAME}() cannot be used in ebuilds of packages supporting installation for multiple Python ABIs"
1770 _python_check_python_pkg_setup_execution
1772 if [[ "$#" -ne 0 ]]; then
1773 die "${FUNCNAME}() does not accept arguments"
1776 export PYTHON_NEED_REBUILD="$(PYTHON --ABI)"
1779 # ================================================================================================
1780 # ======================================= GETTER FUNCTIONS =======================================
1781 # ================================================================================================
1783 _PYTHON_ABI_EXTRACTION_COMMAND=\
1786 sys.stdout.write(".".join(str(x) for x in sys.version_info[:2]))
1787 if platform.system()[:4] == "Java":
1788 sys.stdout.write("-jython")
1789 elif hasattr(platform, "python_implementation") and platform.python_implementation() == "PyPy":
1790 sys.stdout.write("-pypy-" + ".".join(str(x) for x in sys.pypy_version_info[:2]))'
1792 _python_get_implementation() {
1793 local ignore_invalid="0"
1805 die "${FUNCNAME}(): Unrecognized option '$1'"
1814 if [[ "$#" -ne 1 ]]; then
1815 die "${FUNCNAME}() requires 1 argument"
1818 if [[ "$1" =~ ^[[:digit:]]+\.[[:digit:]]+$ ]]; then
1820 elif [[ "$1" =~ ^[[:digit:]]+\.[[:digit:]]+-jython$ ]]; then
1822 elif [[ "$1" =~ ^[[:digit:]]+\.[[:digit:]]+-pypy-[[:digit:]]+\.[[:digit:]]+$ ]]; then
1825 if [[ "${ignore_invalid}" == "0" ]]; then
1826 die "${FUNCNAME}(): Unrecognized Python ABI '$1'"
1832 # @USAGE: [-2] [-3] [--ABI] [-a|--absolute-path] [-f|--final-ABI] [--] <Python_ABI="${PYTHON_ABI}">
1834 # Print filename of Python interpreter for specified Python ABI. If Python_ABI argument
1835 # is ommitted, then PYTHON_ABI environment variable must be set and is used.
1836 # If -2 option is specified, then active version of CPython 2 is used.
1837 # If -3 option is specified, then active version of CPython 3 is used.
1838 # If --final-ABI option is specified, then final ABI from the list of enabled ABIs is used.
1839 # -2, -3 and --final-ABI options and Python_ABI argument cannot be specified simultaneously.
1840 # If --ABI option is specified, then only specified Python ABI is printed instead of
1841 # filename of Python interpreter.
1842 # If --absolute-path option is specified, then absolute path to Python interpreter is printed.
1843 # --ABI and --absolute-path options cannot be specified simultaneously.
1845 _python_check_python_pkg_setup_execution
1847 local ABI_output="0" absolute_path_output="0" final_ABI="0" PYTHON_ABI="${PYTHON_ABI}" python_interpreter python2="0" python3="0"
1861 absolute_path_output="1"
1871 die "${FUNCNAME}(): Unrecognized option '$1'"
1880 if [[ "${ABI_output}" == "1" && "${absolute_path_output}" == "1" ]]; then
1881 die "${FUNCNAME}(): '--ABI' and '--absolute-path' options cannot be specified simultaneously"
1884 if [[ "$((${python2} + ${python3} + ${final_ABI}))" -gt 1 ]]; then
1885 die "${FUNCNAME}(): '-2', '-3' or '--final-ABI' options cannot be specified simultaneously"
1888 if [[ "$#" -eq 0 ]]; then
1889 if [[ "${final_ABI}" == "1" ]]; then
1890 if ! _python_package_supporting_installation_for_multiple_python_abis; then
1891 die "${FUNCNAME}(): '--final-ABI' option cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
1893 _python_calculate_PYTHON_ABIS
1894 PYTHON_ABI="${PYTHON_ABIS##* }"
1895 elif [[ "${python2}" == "1" ]]; then
1896 PYTHON_ABI="$(ROOT="/" eselect python show --python2 --ABI)"
1897 if [[ -z "${PYTHON_ABI}" ]]; then
1898 die "${FUNCNAME}(): Active version of CPython 2 not set"
1899 elif [[ "${PYTHON_ABI}" != "2."* ]]; then
1900 die "${FUNCNAME}(): Internal error in \`eselect python show --python2\`"
1902 elif [[ "${python3}" == "1" ]]; then
1903 PYTHON_ABI="$(ROOT="/" eselect python show --python3 --ABI)"
1904 if [[ -z "${PYTHON_ABI}" ]]; then
1905 die "${FUNCNAME}(): Active version of CPython 3 not set"
1906 elif [[ "${PYTHON_ABI}" != "3."* ]]; then
1907 die "${FUNCNAME}(): Internal error in \`eselect python show --python3\`"
1909 elif _python_package_supporting_installation_for_multiple_python_abis; then
1910 if ! _python_abi-specific_local_scope; then
1911 die "${FUNCNAME}() should be used in ABI-specific local scope"
1914 PYTHON_ABI="$("${EPREFIX}/usr/bin/python" -c "${_PYTHON_ABI_EXTRACTION_COMMAND}")"
1915 if [[ -z "${PYTHON_ABI}" ]]; then
1916 die "${FUNCNAME}(): Failure of extraction of locally active version of Python"
1919 elif [[ "$#" -eq 1 ]]; then
1920 if [[ "${final_ABI}" == "1" ]]; then
1921 die "${FUNCNAME}(): '--final-ABI' option and Python ABI cannot be specified simultaneously"
1923 if [[ "${python2}" == "1" ]]; then
1924 die "${FUNCNAME}(): '-2' option and Python ABI cannot be specified simultaneously"
1926 if [[ "${python3}" == "1" ]]; then
1927 die "${FUNCNAME}(): '-3' option and Python ABI cannot be specified simultaneously"
1931 die "${FUNCNAME}(): Invalid usage"
1934 if [[ "${ABI_output}" == "1" ]]; then
1935 echo -n "${PYTHON_ABI}"
1938 if [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "CPython" ]]; then
1939 python_interpreter="python${PYTHON_ABI}"
1940 elif [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "Jython" ]]; then
1941 python_interpreter="jython${PYTHON_ABI%-jython}"
1942 elif [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "PyPy" ]]; then
1943 python_interpreter="pypy-c${PYTHON_ABI#*-pypy-}"
1946 if [[ "${absolute_path_output}" == "1" ]]; then
1947 echo -n "${EPREFIX}/usr/bin/${python_interpreter}"
1949 echo -n "${python_interpreter}"
1953 if [[ -n "${ABI}" && "${ABI}" != "${DEFAULT_ABI}" && "${DEFAULT_ABI}" != "default" ]]; then
1958 # @FUNCTION: python_get_implementation
1959 # @USAGE: [-f|--final-ABI]
1961 # Print name of Python implementation.
1962 # If --final-ABI option is specified, then final ABI from the list of enabled ABIs is used.
1963 python_get_implementation() {
1964 _python_check_python_pkg_setup_execution
1966 local final_ABI="0" PYTHON_ABI="${PYTHON_ABI}"
1974 die "${FUNCNAME}(): Unrecognized option '$1'"
1977 die "${FUNCNAME}(): Invalid usage"
1983 if [[ "${final_ABI}" == "1" ]]; then
1984 if ! _python_package_supporting_installation_for_multiple_python_abis; then
1985 die "${FUNCNAME}(): '--final-ABI' option cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
1987 PYTHON_ABI="$(PYTHON -f --ABI)"
1989 if _python_package_supporting_installation_for_multiple_python_abis; then
1990 if ! _python_abi-specific_local_scope; then
1991 die "${FUNCNAME}() should be used in ABI-specific local scope"
1994 PYTHON_ABI="${PYTHON_ABI:-$(PYTHON --ABI)}"
1998 echo "$(_python_get_implementation "${PYTHON_ABI}")"
2001 # @FUNCTION: python_get_implementational_package
2002 # @USAGE: [-f|--final-ABI]
2004 # Print category, name and slot of package providing Python implementation.
2005 # If --final-ABI option is specified, then final ABI from the list of enabled ABIs is used.
2006 python_get_implementational_package() {
2007 _python_check_python_pkg_setup_execution
2009 local final_ABI="0" PYTHON_ABI="${PYTHON_ABI}"
2017 die "${FUNCNAME}(): Unrecognized option '$1'"
2020 die "${FUNCNAME}(): Invalid usage"
2026 if [[ "${final_ABI}" == "1" ]]; then
2027 if ! _python_package_supporting_installation_for_multiple_python_abis; then
2028 die "${FUNCNAME}(): '--final-ABI' option cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
2030 PYTHON_ABI="$(PYTHON -f --ABI)"
2032 if _python_package_supporting_installation_for_multiple_python_abis; then
2033 if ! _python_abi-specific_local_scope; then
2034 die "${FUNCNAME}() should be used in ABI-specific local scope"
2037 PYTHON_ABI="${PYTHON_ABI:-$(PYTHON --ABI)}"
2041 if [[ "${EAPI:-0}" == "0" ]]; then
2042 if [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "CPython" ]]; then
2043 echo "=dev-lang/python-${PYTHON_ABI}*"
2044 elif [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "Jython" ]]; then
2045 echo "=dev-java/jython-${PYTHON_ABI%-jython}*"
2046 elif [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "PyPy" ]]; then
2047 echo "=virtual/pypy-${PYTHON_ABI#*-pypy-}*"
2050 if [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "CPython" ]]; then
2051 echo "dev-lang/python:${PYTHON_ABI}"
2052 elif [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "Jython" ]]; then
2053 echo "dev-java/jython:${PYTHON_ABI%-jython}"
2054 elif [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "PyPy" ]]; then
2055 echo "virtual/pypy:${PYTHON_ABI#*-pypy-}"
2060 # @FUNCTION: python_get_includedir
2061 # @USAGE: [-b|--base-path] [-f|--final-ABI]
2063 # Print path to Python include directory.
2064 # If --base-path option is specified, then path not prefixed with "/" is printed.
2065 # If --final-ABI option is specified, then final ABI from the list of enabled ABIs is used.
2066 python_get_includedir() {
2067 _python_check_python_pkg_setup_execution
2069 local base_path="0" final_ABI="0" prefix PYTHON_ABI="${PYTHON_ABI}"
2080 die "${FUNCNAME}(): Unrecognized option '$1'"
2083 die "${FUNCNAME}(): Invalid usage"
2089 if [[ "${base_path}" == "0" ]]; then
2093 if [[ "${final_ABI}" == "1" ]]; then
2094 if ! _python_package_supporting_installation_for_multiple_python_abis; then
2095 die "${FUNCNAME}(): '--final-ABI' option cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
2097 PYTHON_ABI="$(PYTHON -f --ABI)"
2099 if _python_package_supporting_installation_for_multiple_python_abis; then
2100 if ! _python_abi-specific_local_scope; then
2101 die "${FUNCNAME}() should be used in ABI-specific local scope"
2104 PYTHON_ABI="${PYTHON_ABI:-$(PYTHON --ABI)}"
2108 if [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "CPython" ]]; then
2109 echo "${prefix}usr/include/python${PYTHON_ABI}"
2110 elif [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "Jython" ]]; then
2111 echo "${prefix}usr/share/jython-${PYTHON_ABI%-jython}/Include"
2112 elif [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "PyPy" ]]; then
2113 echo "${prefix}usr/$(get_libdir)/pypy${PYTHON_ABI#*-pypy-}/include"
2117 # @FUNCTION: python_get_libdir
2118 # @USAGE: [-b|--base-path] [-f|--final-ABI]
2120 # Print path to Python standard library directory.
2121 # If --base-path option is specified, then path not prefixed with "/" is printed.
2122 # If --final-ABI option is specified, then final ABI from the list of enabled ABIs is used.
2123 python_get_libdir() {
2124 _python_check_python_pkg_setup_execution
2126 local base_path="0" final_ABI="0" prefix PYTHON_ABI="${PYTHON_ABI}"
2137 die "${FUNCNAME}(): Unrecognized option '$1'"
2140 die "${FUNCNAME}(): Invalid usage"
2146 if [[ "${base_path}" == "0" ]]; then
2150 if [[ "${final_ABI}" == "1" ]]; then
2151 if ! _python_package_supporting_installation_for_multiple_python_abis; then
2152 die "${FUNCNAME}(): '--final-ABI' option cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
2154 PYTHON_ABI="$(PYTHON -f --ABI)"
2156 if _python_package_supporting_installation_for_multiple_python_abis; then
2157 if ! _python_abi-specific_local_scope; then
2158 die "${FUNCNAME}() should be used in ABI-specific local scope"
2161 PYTHON_ABI="${PYTHON_ABI:-$(PYTHON --ABI)}"
2165 if [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "CPython" ]]; then
2166 echo "${prefix}usr/$(get_libdir)/python${PYTHON_ABI}"
2167 elif [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "Jython" ]]; then
2168 echo "${prefix}usr/share/jython-${PYTHON_ABI%-jython}/Lib"
2169 elif [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "PyPy" ]]; then
2170 die "${FUNCNAME}(): PyPy has multiple standard library directories"
2174 # @FUNCTION: python_get_sitedir
2175 # @USAGE: [-b|--base-path] [-f|--final-ABI]
2177 # Print path to Python site-packages directory.
2178 # If --base-path option is specified, then path not prefixed with "/" is printed.
2179 # If --final-ABI option is specified, then final ABI from the list of enabled ABIs is used.
2180 python_get_sitedir() {
2181 _python_check_python_pkg_setup_execution
2183 local base_path="0" final_ABI="0" prefix PYTHON_ABI="${PYTHON_ABI}"
2194 die "${FUNCNAME}(): Unrecognized option '$1'"
2197 die "${FUNCNAME}(): Invalid usage"
2203 if [[ "${base_path}" == "0" ]]; then
2207 if [[ "${final_ABI}" == "1" ]]; then
2208 if ! _python_package_supporting_installation_for_multiple_python_abis; then
2209 die "${FUNCNAME}(): '--final-ABI' option cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
2211 PYTHON_ABI="$(PYTHON -f --ABI)"
2213 if _python_package_supporting_installation_for_multiple_python_abis; then
2214 if ! _python_abi-specific_local_scope; then
2215 die "${FUNCNAME}() should be used in ABI-specific local scope"
2218 PYTHON_ABI="${PYTHON_ABI:-$(PYTHON --ABI)}"
2222 if [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "CPython" ]]; then
2223 echo "${prefix}usr/$(get_libdir)/python${PYTHON_ABI}/site-packages"
2224 elif [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "Jython" ]]; then
2225 echo "${prefix}usr/share/jython-${PYTHON_ABI%-jython}/Lib/site-packages"
2226 elif [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "PyPy" ]]; then
2227 echo "${prefix}usr/$(get_libdir)/pypy${PYTHON_ABI#*-pypy-}/site-packages"
2231 # @FUNCTION: python_get_library
2232 # @USAGE: [-b|--base-path] [-f|--final-ABI] [-l|--linker-option]
2234 # Print path to Python library.
2235 # If --base-path option is specified, then path not prefixed with "/" is printed.
2236 # If --linker-option is specified, then "-l${library}" linker option is printed.
2237 # If --final-ABI option is specified, then final ABI from the list of enabled ABIs is used.
2238 python_get_library() {
2239 _python_check_python_pkg_setup_execution
2241 local base_path="0" final_ABI="0" linker_option="0" prefix PYTHON_ABI="${PYTHON_ABI}"
2255 die "${FUNCNAME}(): Unrecognized option '$1'"
2258 die "${FUNCNAME}(): Invalid usage"
2264 if [[ "${base_path}" == "0" ]]; then
2268 if [[ "${base_path}" == "1" && "${linker_option}" == "1" ]]; then
2269 die "${FUNCNAME}(): '--base-path' and '--linker-option' options cannot be specified simultaneously"
2272 if [[ "${final_ABI}" == "1" ]]; then
2273 if ! _python_package_supporting_installation_for_multiple_python_abis; then
2274 die "${FUNCNAME}(): '--final-ABI' option cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
2276 PYTHON_ABI="$(PYTHON -f --ABI)"
2278 if _python_package_supporting_installation_for_multiple_python_abis; then
2279 if ! _python_abi-specific_local_scope; then
2280 die "${FUNCNAME}() should be used in ABI-specific local scope"
2283 PYTHON_ABI="${PYTHON_ABI:-$(PYTHON --ABI)}"
2287 if [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "CPython" ]]; then
2288 if [[ "${linker_option}" == "1" ]]; then
2289 echo "-lpython${PYTHON_ABI}"
2291 echo "${prefix}usr/$(get_libdir)/libpython${PYTHON_ABI}$(get_libname)"
2293 elif [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "Jython" ]]; then
2294 die "${FUNCNAME}(): Jython does not have shared library"
2295 elif [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "PyPy" ]]; then
2296 die "${FUNCNAME}(): PyPy does not have shared library"
2300 # @FUNCTION: python_get_version
2301 # @USAGE: [-f|--final-ABI] [-l|--language] [--full] [--major] [--minor] [--micro]
2303 # Print version of Python implementation.
2304 # --full, --major, --minor and --micro options cannot be specified simultaneously.
2305 # If --full, --major, --minor and --micro options are not specified, then "${major_version}.${minor_version}" is printed.
2306 # If --language option is specified, then version of Python language is printed.
2307 # --language and --full options cannot be specified simultaneously.
2308 # --language and --micro options cannot be specified simultaneously.
2309 # If --final-ABI option is specified, then final ABI from the list of enabled ABIs is used.
2310 python_get_version() {
2311 _python_check_python_pkg_setup_execution
2313 local final_ABI="0" language="0" language_version full="0" major="0" minor="0" micro="0" PYTHON_ABI="${PYTHON_ABI}" python_command
2336 die "${FUNCNAME}(): Unrecognized option '$1'"
2339 die "${FUNCNAME}(): Invalid usage"
2345 if [[ "${final_ABI}" == "1" ]]; then
2346 if ! _python_package_supporting_installation_for_multiple_python_abis; then
2347 die "${FUNCNAME}(): '--final-ABI' option cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
2350 if _python_package_supporting_installation_for_multiple_python_abis && ! _python_abi-specific_local_scope; then
2351 die "${FUNCNAME}() should be used in ABI-specific local scope"
2355 if [[ "$((${full} + ${major} + ${minor} + ${micro}))" -gt 1 ]]; then
2356 die "${FUNCNAME}(): '--full', '--major', '--minor' or '--micro' options cannot be specified simultaneously"
2359 if [[ "${language}" == "1" ]]; then
2360 if [[ "${final_ABI}" == "1" ]]; then
2361 PYTHON_ABI="$(PYTHON -f --ABI)"
2362 elif [[ -z "${PYTHON_ABI}" ]]; then
2363 PYTHON_ABI="$(PYTHON --ABI)"
2365 language_version="${PYTHON_ABI%%-*}"
2366 if [[ "${full}" == "1" ]]; then
2367 die "${FUNCNAME}(): '--language' and '--full' options cannot be specified simultaneously"
2368 elif [[ "${major}" == "1" ]]; then
2369 echo "${language_version%.*}"
2370 elif [[ "${minor}" == "1" ]]; then
2371 echo "${language_version#*.}"
2372 elif [[ "${micro}" == "1" ]]; then
2373 die "${FUNCNAME}(): '--language' and '--micro' options cannot be specified simultaneously"
2375 echo "${language_version}"
2378 if [[ "${full}" == "1" ]]; then
2379 python_command="import sys; print('.'.join(str(x) for x in getattr(sys, 'pypy_version_info', sys.version_info)[:3]))"
2380 elif [[ "${major}" == "1" ]]; then
2381 python_command="import sys; print(getattr(sys, 'pypy_version_info', sys.version_info)[0])"
2382 elif [[ "${minor}" == "1" ]]; then
2383 python_command="import sys; print(getattr(sys, 'pypy_version_info', sys.version_info)[1])"
2384 elif [[ "${micro}" == "1" ]]; then
2385 python_command="import sys; print(getattr(sys, 'pypy_version_info', sys.version_info)[2])"
2387 if [[ -n "${PYTHON_ABI}" && "${final_ABI}" == "0" ]]; then
2388 if [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "CPython" ]]; then
2389 echo "${PYTHON_ABI}"
2390 elif [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "Jython" ]]; then
2391 echo "${PYTHON_ABI%-jython}"
2392 elif [[ "$(_python_get_implementation "${PYTHON_ABI}")" == "PyPy" ]]; then
2393 echo "${PYTHON_ABI#*-pypy-}"
2397 python_command="from sys import version_info; print('.'.join(str(x) for x in version_info[:2]))"
2400 if [[ "${final_ABI}" == "1" ]]; then
2401 "$(PYTHON -f)" -c "${python_command}"
2403 "$(PYTHON ${PYTHON_ABI})" -c "${python_command}"
2408 # @FUNCTION: python_get_implementation_and_version
2409 # @USAGE: [-f|--final-ABI]
2411 # Print name and version of Python implementation.
2412 # If version of Python implementation is not bound to version of Python language, then
2413 # version of Python language is additionally printed.
2414 # If --final-ABI option is specified, then final ABI from the list of enabled ABIs is used.
2415 python_get_implementation_and_version() {
2416 _python_check_python_pkg_setup_execution
2418 local final_ABI="0" PYTHON_ABI="${PYTHON_ABI}"
2426 die "${FUNCNAME}(): Unrecognized option '$1'"
2429 die "${FUNCNAME}(): Invalid usage"
2435 if [[ "${final_ABI}" == "1" ]]; then
2436 if ! _python_package_supporting_installation_for_multiple_python_abis; then
2437 die "${FUNCNAME}(): '--final-ABI' option cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
2439 PYTHON_ABI="$(PYTHON -f --ABI)"
2441 if _python_package_supporting_installation_for_multiple_python_abis; then
2442 if ! _python_abi-specific_local_scope; then
2443 die "${FUNCNAME}() should be used in ABI-specific local scope"
2446 PYTHON_ABI="${PYTHON_ABI:-$(PYTHON --ABI)}"
2450 if [[ "${PYTHON_ABI}" =~ ^[[:digit:]]+\.[[:digit:]]+-[[:alnum:]]+-[[:digit:]]+\.[[:digit:]]+$ ]]; then
2451 echo "$(_python_get_implementation "${PYTHON_ABI}") ${PYTHON_ABI##*-} (Python ${PYTHON_ABI%%-*})"
2453 echo "$(_python_get_implementation "${PYTHON_ABI}") ${PYTHON_ABI%%-*}"
2457 # ================================================================================================
2458 # ================================ FUNCTIONS FOR RUNNING OF TESTS ================================
2459 # ================================================================================================
2461 # @ECLASS-VARIABLE: PYTHON_TEST_VERBOSITY
2463 # User-configurable verbosity of tests of Python modules.
2464 # Supported values: 0, 1, 2, 3, 4.
2465 PYTHON_TEST_VERBOSITY="${PYTHON_TEST_VERBOSITY:-1}"
2467 _python_test_hook() {
2468 if [[ "$#" -ne 1 ]]; then
2469 die "${FUNCNAME}() requires 1 argument"
2472 if _python_package_supporting_installation_for_multiple_python_abis && [[ "$(type -t "${_PYTHON_TEST_FUNCTION}_$1_hook")" == "function" ]]; then
2473 "${_PYTHON_TEST_FUNCTION}_$1_hook"
2477 # @FUNCTION: python_execute_nosetests
2478 # @USAGE: [-P|--PYTHONPATH PYTHONPATH] [-s|--separate-build-dirs] [--] [arguments]
2480 # Execute nosetests for all enabled Python ABIs.
2481 # In ebuilds of packages supporting installation for multiple Python ABIs, this function calls
2482 # python_execute_nosetests_pre_hook() and python_execute_nosetests_post_hook(), if they are defined.
2483 python_execute_nosetests() {
2484 _python_check_python_pkg_setup_execution
2485 _python_set_color_variables
2487 local PYTHONPATH_template separate_build_dirs
2492 PYTHONPATH_template="$2"
2495 -s|--separate-build-dirs)
2496 separate_build_dirs="1"
2503 die "${FUNCNAME}(): Unrecognized option '$1'"
2512 python_test_function() {
2513 local evaluated_PYTHONPATH
2515 eval "evaluated_PYTHONPATH=\"${PYTHONPATH_template}\""
2517 _PYTHON_TEST_FUNCTION="python_execute_nosetests" _python_test_hook pre
2519 if [[ -n "${evaluated_PYTHONPATH}" ]]; then
2520 echo ${_BOLD}PYTHONPATH="${evaluated_PYTHONPATH}" nosetests --verbosity="${PYTHON_TEST_VERBOSITY}" "$@"${_NORMAL}
2521 PYTHONPATH="${evaluated_PYTHONPATH}" nosetests --verbosity="${PYTHON_TEST_VERBOSITY}" "$@" || return "$?"
2523 echo ${_BOLD}nosetests --verbosity="${PYTHON_TEST_VERBOSITY}" "$@"${_NORMAL}
2524 nosetests --verbosity="${PYTHON_TEST_VERBOSITY}" "$@" || return "$?"
2527 _PYTHON_TEST_FUNCTION="python_execute_nosetests" _python_test_hook post
2529 if _python_package_supporting_installation_for_multiple_python_abis; then
2530 python_execute_function ${separate_build_dirs:+-s} python_test_function "$@"
2532 if [[ -n "${separate_build_dirs}" ]]; then
2533 die "${FUNCNAME}(): Invalid usage"
2535 python_test_function "$@" || die "Testing failed"
2538 unset -f python_test_function
2541 # @FUNCTION: python_execute_py.test
2542 # @USAGE: [-P|--PYTHONPATH PYTHONPATH] [-s|--separate-build-dirs] [--] [arguments]
2544 # Execute py.test for all enabled Python ABIs.
2545 # In ebuilds of packages supporting installation for multiple Python ABIs, this function calls
2546 # python_execute_py.test_pre_hook() and python_execute_py.test_post_hook(), if they are defined.
2547 python_execute_py.test() {
2548 _python_check_python_pkg_setup_execution
2549 _python_set_color_variables
2551 local PYTHONPATH_template separate_build_dirs
2556 PYTHONPATH_template="$2"
2559 -s|--separate-build-dirs)
2560 separate_build_dirs="1"
2567 die "${FUNCNAME}(): Unrecognized option '$1'"
2576 python_test_function() {
2577 local evaluated_PYTHONPATH
2579 eval "evaluated_PYTHONPATH=\"${PYTHONPATH_template}\""
2581 _PYTHON_TEST_FUNCTION="python_execute_py.test" _python_test_hook pre
2583 if [[ -n "${evaluated_PYTHONPATH}" ]]; then
2584 echo ${_BOLD}PYTHONPATH="${evaluated_PYTHONPATH}" py.test $([[ "${PYTHON_TEST_VERBOSITY}" -ge 2 ]] && echo -v) "$@"${_NORMAL}
2585 PYTHONPATH="${evaluated_PYTHONPATH}" py.test $([[ "${PYTHON_TEST_VERBOSITY}" -ge 2 ]] && echo -v) "$@" || return "$?"
2587 echo ${_BOLD}py.test $([[ "${PYTHON_TEST_VERBOSITY}" -gt 1 ]] && echo -v) "$@"${_NORMAL}
2588 py.test $([[ "${PYTHON_TEST_VERBOSITY}" -gt 1 ]] && echo -v) "$@" || return "$?"
2591 _PYTHON_TEST_FUNCTION="python_execute_py.test" _python_test_hook post
2593 if _python_package_supporting_installation_for_multiple_python_abis; then
2594 python_execute_function ${separate_build_dirs:+-s} python_test_function "$@"
2596 if [[ -n "${separate_build_dirs}" ]]; then
2597 die "${FUNCNAME}(): Invalid usage"
2599 python_test_function "$@" || die "Testing failed"
2602 unset -f python_test_function
2605 # @FUNCTION: python_execute_trial
2606 # @USAGE: [-P|--PYTHONPATH PYTHONPATH] [-s|--separate-build-dirs] [--] [arguments]
2608 # Execute trial for all enabled Python ABIs.
2609 # In ebuilds of packages supporting installation for multiple Python ABIs, this function
2610 # calls python_execute_trial_pre_hook() and python_execute_trial_post_hook(), if they are defined.
2611 python_execute_trial() {
2612 _python_check_python_pkg_setup_execution
2613 _python_set_color_variables
2615 local PYTHONPATH_template separate_build_dirs
2620 PYTHONPATH_template="$2"
2623 -s|--separate-build-dirs)
2624 separate_build_dirs="1"
2631 die "${FUNCNAME}(): Unrecognized option '$1'"
2640 python_test_function() {
2641 local evaluated_PYTHONPATH
2643 eval "evaluated_PYTHONPATH=\"${PYTHONPATH_template}\""
2645 _PYTHON_TEST_FUNCTION="python_execute_trial" _python_test_hook pre
2647 if [[ -n "${evaluated_PYTHONPATH}" ]]; then
2648 echo ${_BOLD}PYTHONPATH="${evaluated_PYTHONPATH}" trial $([[ "${PYTHON_TEST_VERBOSITY}" -ge 4 ]] && echo --spew) "$@"${_NORMAL}
2649 PYTHONPATH="${evaluated_PYTHONPATH}" trial $([[ "${PYTHON_TEST_VERBOSITY}" -ge 4 ]] && echo --spew) "$@" || return "$?"
2651 echo ${_BOLD}trial $([[ "${PYTHON_TEST_VERBOSITY}" -ge 4 ]] && echo --spew) "$@"${_NORMAL}
2652 trial $([[ "${PYTHON_TEST_VERBOSITY}" -ge 4 ]] && echo --spew) "$@" || return "$?"
2655 _PYTHON_TEST_FUNCTION="python_execute_trial" _python_test_hook post
2657 if _python_package_supporting_installation_for_multiple_python_abis; then
2658 python_execute_function ${separate_build_dirs:+-s} python_test_function "$@"
2660 if [[ -n "${separate_build_dirs}" ]]; then
2661 die "${FUNCNAME}(): Invalid usage"
2663 python_test_function "$@" || die "Testing failed"
2666 unset -f python_test_function
2669 # ================================================================================================
2670 # ======================= FUNCTIONS FOR HANDLING OF BYTE-COMPILED MODULES ========================
2671 # ================================================================================================
2673 # @FUNCTION: python_enable_pyc
2675 # Tell Python to automatically recompile modules to .pyc/.pyo if the
2676 # timestamps/version stamps have changed.
2677 python_enable_pyc() {
2678 _python_check_python_pkg_setup_execution
2680 if [[ "$#" -ne 0 ]]; then
2681 die "${FUNCNAME}() does not accept arguments"
2684 unset PYTHONDONTWRITEBYTECODE
2687 # @FUNCTION: python_disable_pyc
2689 # Tell Python not to automatically recompile modules to .pyc/.pyo
2690 # even if the timestamps/version stamps do not match. This is done
2691 # to protect sandbox.
2692 python_disable_pyc() {
2693 _python_check_python_pkg_setup_execution
2695 if [[ "$#" -ne 0 ]]; then
2696 die "${FUNCNAME}() does not accept arguments"
2699 export PYTHONDONTWRITEBYTECODE="1"
2703 [[ -z ${PORTAGE_VERBOSE} ]] || echo "$@"
2706 _python_clean_compiled_modules() {
2707 _python_initialize_prefix_variables
2708 _python_set_color_variables
2710 [[ "${FUNCNAME[1]}" =~ ^(python_mod_optimize|python_mod_cleanup)$ ]] || die "${FUNCNAME}(): Invalid usage"
2712 local base_module_name compiled_file compiled_files=() dir path py_file root
2714 # Strip trailing slash from EROOT.
2717 for path in "$@"; do
2719 if [[ -d "${path}" ]]; then
2720 while read -d $'\0' -r compiled_file; do
2721 compiled_files+=("${compiled_file}")
2722 done < <(find "${path}" "(" -name "*.py[co]" -o -name "*\$py.class" ")" -print0)
2724 if [[ "${EBUILD_PHASE}" == "postrm" ]]; then
2725 # Delete empty child directories.
2726 find "${path}" -type d | sort -r | while read -r dir; do
2727 if rmdir "${dir}" 2> /dev/null; then
2728 _python_vecho "<<< ${dir}"
2732 elif [[ "${path}" == *.py ]]; then
2733 base_module_name="${path##*/}"
2734 base_module_name="${base_module_name%.py}"
2735 if [[ -d "${path%/*}/__pycache__" ]]; then
2736 while read -d $'\0' -r compiled_file; do
2737 compiled_files+=("${compiled_file}")
2738 done < <(find "${path%/*}/__pycache__" "(" -name "${base_module_name}.*.py[co]" -o -name "${base_module_name}\$py.class" ")" -print0)
2740 compiled_files+=("${path}c" "${path}o" "${path%.py}\$py.class")
2743 for compiled_file in "${compiled_files[@]}"; do
2744 [[ ! -f "${compiled_file}" ]] && continue
2745 dir="${compiled_file%/*}"
2747 if [[ "${compiled_file}" == *.py[co] ]]; then
2748 if [[ "${dir}" == "__pycache__" ]]; then
2749 base_module_name="${compiled_file##*/}"
2750 base_module_name="${base_module_name%.*py[co]}"
2751 base_module_name="${base_module_name%.*}"
2752 py_file="${compiled_file%__pycache__/*}${base_module_name}.py"
2754 py_file="${compiled_file%[co]}"
2756 if [[ "${EBUILD_PHASE}" == "postinst" ]]; then
2757 [[ -f "${py_file}" && "${compiled_file}" -nt "${py_file}" ]] && continue
2759 [[ -f "${py_file}" ]] && continue
2761 _python_vecho "<<< ${compiled_file%[co]}[co]"
2762 rm -f "${compiled_file%[co]}"[co]
2763 elif [[ "${compiled_file}" == *\$py.class ]]; then
2764 if [[ "${dir}" == "__pycache__" ]]; then
2765 base_module_name="${compiled_file##*/}"
2766 base_module_name="${base_module_name%\$py.class}"
2767 py_file="${compiled_file%__pycache__/*}${base_module_name}.py"
2769 py_file="${compiled_file%\$py.class}.py"
2771 if [[ "${EBUILD_PHASE}" == "postinst" ]]; then
2772 [[ -f "${py_file}" && "${compiled_file}" -nt "${py_file}" ]] && continue
2774 [[ -f "${py_file}" ]] && continue
2776 _python_vecho "<<< ${compiled_file}"
2777 rm -f "${compiled_file}"
2779 die "${FUNCNAME}(): Unrecognized file type: '${compiled_file}'"
2782 # Delete empty parent directories.
2783 dir="${compiled_file%/*}"
2784 while [[ "${dir}" != "${root}" ]]; do
2785 if rmdir "${dir}" 2> /dev/null; then
2786 _python_vecho "<<< ${dir}"
2796 # @FUNCTION: python_mod_optimize
2797 # @USAGE: [--allow-evaluated-non-sitedir-paths] [-d directory] [-f] [-l] [-q] [-x regular_expression] [--] <file|directory> [files|directories]
2799 # Byte-compile specified Python modules.
2800 # -d, -f, -l, -q and -x options passed to this function are passed to compileall.py.
2802 # This function can be used only in pkg_postinst() phase.
2803 python_mod_optimize() {
2804 if [[ "${EBUILD_PHASE}" != "postinst" ]]; then
2805 die "${FUNCNAME}() can be used only in pkg_postinst() phase"
2808 _python_check_python_pkg_setup_execution
2809 _python_initialize_prefix_variables
2811 if ! has "${EAPI:-0}" 0 1 2 || _python_package_supporting_installation_for_multiple_python_abis || _python_implementation || [[ "${CATEGORY}/${PN}" == "sys-apps/portage" ]]; then
2812 # PYTHON_ABI variable cannot be local in packages not supporting installation for multiple Python ABIs.
2813 local allow_evaluated_non_sitedir_paths="0" dir dirs=() evaluated_dirs=() evaluated_files=() file files=() iterated_PYTHON_ABIS options=() other_dirs=() other_files=() previous_PYTHON_ABI="${PYTHON_ABI}" return_code root site_packages_dirs=() site_packages_files=() stderr stderr_line
2815 if _python_package_supporting_installation_for_multiple_python_abis; then
2816 if has "${EAPI:-0}" 0 1 2 3 && [[ -z "${PYTHON_ABIS}" ]]; then
2817 die "${FUNCNAME}(): python_pkg_setup() or python_execute_function() not called"
2819 iterated_PYTHON_ABIS="${PYTHON_ABIS}"
2821 if has "${EAPI:-0}" 0 1 2 3; then
2822 iterated_PYTHON_ABIS="${PYTHON_ABI:=$(PYTHON --ABI)}"
2824 iterated_PYTHON_ABIS="${PYTHON_ABI}"
2828 # Strip trailing slash from EROOT.
2833 --allow-evaluated-non-sitedir-paths)
2834 allow_evaluated_non_sitedir_paths="1"
2840 options+=("$1" "$2")
2848 die "${FUNCNAME}(): Unrecognized option '$1'"
2857 if [[ "${allow_evaluated_non_sitedir_paths}" == "1" ]] && ! _python_package_supporting_installation_for_multiple_python_abis; then
2858 die "${FUNCNAME}(): '--allow-evaluated-non-sitedir-paths' option cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
2861 if [[ "$#" -eq 0 ]]; then
2862 die "${FUNCNAME}(): Missing files or directories"
2866 if [[ "$1" =~ ^($|(\.|\.\.|/)($|/)) ]]; then
2867 die "${FUNCNAME}(): Invalid argument '$1'"
2868 elif ! _python_implementation && [[ "$1" =~ ^/usr/lib(32|64)?/python[[:digit:]]+\.[[:digit:]]+ ]]; then
2869 die "${FUNCNAME}(): Paths of directories / files in site-packages directories must be relative to site-packages directories"
2870 elif [[ "$1" =~ ^/ ]]; then
2871 if _python_package_supporting_installation_for_multiple_python_abis; then
2872 if [[ "${allow_evaluated_non_sitedir_paths}" != "1" ]]; then
2873 die "${FUNCNAME}(): Absolute paths cannot be used in ebuilds of packages supporting installation for multiple Python ABIs"
2875 if [[ "$1" != *\$* ]]; then
2876 die "${FUNCNAME}(): '$1' has invalid syntax"
2878 if [[ "$1" == *.py ]]; then
2879 evaluated_files+=("$1")
2881 evaluated_dirs+=("$1")
2884 if [[ -d "${root}$1" ]]; then
2885 other_dirs+=("${root}$1")
2886 elif [[ -f "${root}$1" ]]; then
2887 other_files+=("${root}$1")
2888 elif [[ -e "${root}$1" ]]; then
2889 eerror "${FUNCNAME}(): '${root}$1' is not a regular file or a directory"
2891 eerror "${FUNCNAME}(): '${root}$1' does not exist"
2895 for PYTHON_ABI in ${iterated_PYTHON_ABIS}; do
2896 if [[ -d "${root}$(python_get_sitedir)/$1" ]]; then
2897 site_packages_dirs+=("$1")
2899 elif [[ -f "${root}$(python_get_sitedir)/$1" ]]; then
2900 site_packages_files+=("$1")
2902 elif [[ -e "${root}$(python_get_sitedir)/$1" ]]; then
2903 eerror "${FUNCNAME}(): '$1' is not a regular file or a directory"
2905 eerror "${FUNCNAME}(): '$1' does not exist"
2912 # Set additional options.
2915 for PYTHON_ABI in ${iterated_PYTHON_ABIS}; do
2916 if ((${#site_packages_dirs[@]})) || ((${#site_packages_files[@]})) || ((${#evaluated_dirs[@]})) || ((${#evaluated_files[@]})); then
2919 ebegin "Compilation and optimization of Python modules for $(python_get_implementation_and_version)"
2920 if ((${#site_packages_dirs[@]})) || ((${#evaluated_dirs[@]})); then
2921 for dir in "${site_packages_dirs[@]}"; do
2922 dirs+=("${root}$(python_get_sitedir)/${dir}")
2924 for dir in "${evaluated_dirs[@]}"; do
2925 eval "dirs+=(\"\${root}${dir}\")"
2927 stderr+="${stderr:+$'\n'}$("$(PYTHON)" -m compileall "${options[@]}" "${dirs[@]}" 2>&1)" || return_code="1"
2928 if ! has "$(_python_get_implementation "${PYTHON_ABI}")" Jython PyPy; then
2929 "$(PYTHON)" -O -m compileall "${options[@]}" "${dirs[@]}" &> /dev/null || return_code="1"
2931 _python_clean_compiled_modules "${dirs[@]}"
2933 if ((${#site_packages_files[@]})) || ((${#evaluated_files[@]})); then
2934 for file in "${site_packages_files[@]}"; do
2935 files+=("${root}$(python_get_sitedir)/${file}")
2937 for file in "${evaluated_files[@]}"; do
2938 eval "files+=(\"\${root}${file}\")"
2940 stderr+="${stderr:+$'\n'}$("$(PYTHON)" -m py_compile "${files[@]}" 2>&1)" || return_code="1"
2941 if ! has "$(_python_get_implementation "${PYTHON_ABI}")" Jython PyPy; then
2942 "$(PYTHON)" -O -m py_compile "${files[@]}" &> /dev/null || return_code="1"
2944 _python_clean_compiled_modules "${files[@]}"
2946 eend "${return_code}"
2947 if [[ -n "${stderr}" ]]; then
2948 eerror "Syntax errors / warnings in Python modules for $(python_get_implementation_and_version):" &> /dev/null
2949 while read stderr_line; do
2950 eerror " ${stderr_line}"
2951 done <<< "${stderr}"
2957 if _python_package_supporting_installation_for_multiple_python_abis; then
2958 # Restore previous value of PYTHON_ABI.
2959 if [[ -n "${previous_PYTHON_ABI}" ]]; then
2960 PYTHON_ABI="${previous_PYTHON_ABI}"
2966 if ((${#other_dirs[@]})) || ((${#other_files[@]})); then
2969 ebegin "Compilation and optimization of Python modules placed outside of site-packages directories for $(python_get_implementation_and_version)"
2970 if ((${#other_dirs[@]})); then
2971 stderr+="${stderr:+$'\n'}$("$(PYTHON ${PYTHON_ABI})" -m compileall "${options[@]}" "${other_dirs[@]}" 2>&1)" || return_code="1"
2972 if ! has "$(_python_get_implementation "${PYTHON_ABI}")" Jython PyPy; then
2973 "$(PYTHON ${PYTHON_ABI})" -O -m compileall "${options[@]}" "${other_dirs[@]}" &> /dev/null || return_code="1"
2975 _python_clean_compiled_modules "${other_dirs[@]}"
2977 if ((${#other_files[@]})); then
2978 stderr+="${stderr:+$'\n'}$("$(PYTHON ${PYTHON_ABI})" -m py_compile "${other_files[@]}" 2>&1)" || return_code="1"
2979 if ! has "$(_python_get_implementation "${PYTHON_ABI}")" Jython PyPy; then
2980 "$(PYTHON ${PYTHON_ABI})" -O -m py_compile "${other_files[@]}" &> /dev/null || return_code="1"
2982 _python_clean_compiled_modules "${other_files[@]}"
2984 eend "${return_code}"
2985 if [[ -n "${stderr}" ]]; then
2986 eerror "Syntax errors / warnings in Python modules placed outside of site-packages directories for $(python_get_implementation_and_version):" &> /dev/null
2987 while read stderr_line; do
2988 eerror " ${stderr_line}"
2989 done <<< "${stderr}"
2993 # Deprecated part of python_mod_optimize()
2995 local myroot mydirs=() myfiles=() myopts=() return_code="0"
2997 # strip trailing slash
3000 # respect EROOT and options passed to compileall.py
3015 die "${FUNCNAME}(): Unrecognized option '$1'"
3024 if [[ "$#" -eq 0 ]]; then
3025 die "${FUNCNAME}(): Missing files or directories"
3029 if [[ "$1" =~ ^($|(\.|\.\.|/)($|/)) ]]; then
3030 die "${FUNCNAME}(): Invalid argument '$1'"
3031 elif [[ -d "${myroot}/${1#/}" ]]; then
3032 mydirs+=("${myroot}/${1#/}")
3033 elif [[ -f "${myroot}/${1#/}" ]]; then
3034 myfiles+=("${myroot}/${1#/}")
3035 elif [[ -e "${myroot}/${1#/}" ]]; then
3036 eerror "${FUNCNAME}(): ${myroot}/${1#/} is not a regular file or directory"
3038 eerror "${FUNCNAME}(): ${myroot}/${1#/} does not exist"
3043 # set additional opts
3046 PYTHON_ABI="${PYTHON_ABI:-$(PYTHON --ABI)}"
3048 ebegin "Compilation and optimization of Python modules for $(python_get_implementation) $(python_get_version)"
3049 if ((${#mydirs[@]})); then
3050 "$(PYTHON ${PYTHON_ABI})" "${myroot}$(python_get_libdir)/compileall.py" "${myopts[@]}" "${mydirs[@]}" || return_code="1"
3051 "$(PYTHON ${PYTHON_ABI})" -O "${myroot}$(python_get_libdir)/compileall.py" "${myopts[@]}" "${mydirs[@]}" &> /dev/null || return_code="1"
3052 _python_clean_compiled_modules "${mydirs[@]}"
3055 if ((${#myfiles[@]})); then
3056 "$(PYTHON ${PYTHON_ABI})" "${myroot}$(python_get_libdir)/py_compile.py" "${myfiles[@]}" || return_code="1"
3057 "$(PYTHON ${PYTHON_ABI})" -O "${myroot}$(python_get_libdir)/py_compile.py" "${myfiles[@]}" &> /dev/null || return_code="1"
3058 _python_clean_compiled_modules "${myfiles[@]}"
3061 eend "${return_code}"
3065 # @FUNCTION: python_mod_cleanup
3066 # @USAGE: [--allow-evaluated-non-sitedir-paths] [--] <file|directory> [files|directories]
3068 # Delete orphaned byte-compiled Python modules corresponding to specified Python modules.
3070 # This function can be used only in pkg_postrm() phase.
3071 python_mod_cleanup() {
3072 if [[ "${EBUILD_PHASE}" != "postrm" ]]; then
3073 die "${FUNCNAME}() can be used only in pkg_postrm() phase"
3076 _python_check_python_pkg_setup_execution
3077 _python_initialize_prefix_variables
3079 local allow_evaluated_non_sitedir_paths="0" dir iterated_PYTHON_ABIS PYTHON_ABI="${PYTHON_ABI}" root search_paths=() sitedir
3081 if _python_package_supporting_installation_for_multiple_python_abis; then
3082 if has "${EAPI:-0}" 0 1 2 3 && [[ -z "${PYTHON_ABIS}" ]]; then
3083 die "${FUNCNAME}(): python_pkg_setup() or python_execute_function() not called"
3085 iterated_PYTHON_ABIS="${PYTHON_ABIS}"
3087 if has "${EAPI:-0}" 0 1 2 3; then
3088 iterated_PYTHON_ABIS="${PYTHON_ABI:-$(PYTHON --ABI)}"
3090 iterated_PYTHON_ABIS="${PYTHON_ABI}"
3094 # Strip trailing slash from EROOT.
3099 --allow-evaluated-non-sitedir-paths)
3100 allow_evaluated_non_sitedir_paths="1"
3107 die "${FUNCNAME}(): Unrecognized option '$1'"
3116 if [[ "${allow_evaluated_non_sitedir_paths}" == "1" ]] && ! _python_package_supporting_installation_for_multiple_python_abis; then
3117 die "${FUNCNAME}(): '--allow-evaluated-non-sitedir-paths' option cannot be used in ebuilds of packages not supporting installation for multiple Python ABIs"
3120 if [[ "$#" -eq 0 ]]; then
3121 die "${FUNCNAME}(): Missing files or directories"
3124 if ! has "${EAPI:-0}" 0 1 2 || _python_package_supporting_installation_for_multiple_python_abis || _python_implementation || [[ "${CATEGORY}/${PN}" == "sys-apps/portage" ]]; then
3126 if [[ "$1" =~ ^($|(\.|\.\.|/)($|/)) ]]; then
3127 die "${FUNCNAME}(): Invalid argument '$1'"
3128 elif ! _python_implementation && [[ "$1" =~ ^/usr/lib(32|64)?/python[[:digit:]]+\.[[:digit:]]+ ]]; then
3129 die "${FUNCNAME}(): Paths of directories / files in site-packages directories must be relative to site-packages directories"
3130 elif [[ "$1" =~ ^/ ]]; then
3131 if _python_package_supporting_installation_for_multiple_python_abis; then
3132 if [[ "${allow_evaluated_non_sitedir_paths}" != "1" ]]; then
3133 die "${FUNCNAME}(): Absolute paths cannot be used in ebuilds of packages supporting installation for multiple Python ABIs"
3135 if [[ "$1" != *\$* ]]; then
3136 die "${FUNCNAME}(): '$1' has invalid syntax"
3138 for PYTHON_ABI in ${iterated_PYTHON_ABIS}; do
3139 eval "search_paths+=(\"\${root}$1\")"
3142 search_paths+=("${root}$1")
3145 for PYTHON_ABI in ${iterated_PYTHON_ABIS}; do
3146 search_paths+=("${root}$(python_get_sitedir)/$1")
3152 # Deprecated part of python_mod_cleanup()
3154 search_paths=("${@#/}")
3155 search_paths=("${search_paths[@]/#/${root}/}")
3158 _python_clean_compiled_modules "${search_paths[@]}"
3161 # ================================================================================================
3162 # ===================================== DEPRECATED FUNCTIONS =====================================
3163 # ================================================================================================
3165 fi # _PYTHON_ECLASS_INHERITED