1 # Copyright 1999-2020 Gentoo Authors
2 # Distributed under the terms of the GNU General Public License v2
4 # @ECLASS: python-utils-r1.eclass
6 # Python team <python@gentoo.org>
8 # Author: Michał Górny <mgorny@gentoo.org>
9 # Based on work of: Krzysztof Pawlik <nelchael@gentoo.org>
10 # @SUPPORTED_EAPIS: 5 6 7
11 # @BLURB: Utility functions for packages with Python parts.
13 # A utility eclass providing functions to query Python implementations,
14 # install Python modules and scripts.
16 # This eclass does not set any metadata variables nor export any phase
17 # functions. It can be inherited safely.
19 # For more information, please see the Python Guide:
20 # https://dev.gentoo.org/~mgorny/python-guide/
23 [0-4]) die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}" ;;
25 *) die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" ;;
28 if [[ ${_PYTHON_ECLASS_INHERITED} ]]; then
29 die 'python-r1 suite eclasses can not be used with python.eclass.'
32 if [[ ! ${_PYTHON_UTILS_R1} ]]; then
34 [[ ${EAPI} == 5 ]] && inherit eutils multilib
35 inherit toolchain-funcs
37 # @ECLASS-VARIABLE: _PYTHON_ALL_IMPLS
40 # All supported Python implementations, most preferred last.
44 python3_6 python3_7 python3_8
46 readonly _PYTHON_ALL_IMPLS
48 # @ECLASS-VARIABLE: PYTHON_COMPAT_NO_STRICT
51 # Set to a non-empty value in order to make eclass tolerate (ignore)
52 # unknown implementations in PYTHON_COMPAT.
54 # This is intended to be set by the user when using ebuilds that may
55 # have unknown (newer) implementations in PYTHON_COMPAT. The assumption
56 # is that the ebuilds are intended to be used within multiple contexts
57 # which can involve revisions of this eclass that support a different
58 # set of Python implementations.
60 # @FUNCTION: _python_impl_supported
64 # Check whether the implementation <impl> (PYTHON_COMPAT-form)
67 # Returns 0 if the implementation is valid and supported. If it is
68 # unsupported, returns 1 -- and the caller should ignore the entry.
69 # If it is invalid, dies with an appopriate error messages.
70 _python_impl_supported() {
71 debug-print-function ${FUNCNAME} "${@}"
73 [[ ${#} -eq 1 ]] || die "${FUNCNAME}: takes exactly 1 argument (impl)."
77 # keep in sync with _PYTHON_ALL_IMPLS!
78 # (not using that list because inline patterns shall be faster)
80 python2_7|python3_[678]|pypy3)
83 jython2_7|pypy|pypy1_[89]|pypy2_0|python2_[56]|python3_[12345])
87 [[ ${PYTHON_COMPAT_NO_STRICT} ]] && return 1
88 die "Invalid implementation in PYTHON_COMPAT: ${impl}"
92 # @FUNCTION: _python_set_impls
95 # Check PYTHON_COMPAT for well-formedness and validity, then set
96 # two global variables:
98 # - _PYTHON_SUPPORTED_IMPLS containing valid implementations supported
99 # by the ebuild (PYTHON_COMPAT - dead implementations),
101 # - and _PYTHON_UNSUPPORTED_IMPLS containing valid implementations that
102 # are not supported by the ebuild.
104 # Implementations in both variables are ordered using the pre-defined
105 # eclass implementation ordering.
107 # This function must be called once in global scope by an eclass
108 # utilizing PYTHON_COMPAT.
109 _python_set_impls() {
112 if ! declare -p PYTHON_COMPAT &>/dev/null; then
113 die 'PYTHON_COMPAT not declared.'
115 if [[ $(declare -p PYTHON_COMPAT) != "declare -a"* ]]; then
116 die 'PYTHON_COMPAT must be an array.'
118 for i in "${PYTHON_COMPAT[@]}"; do
119 # trigger validity checks
120 _python_impl_supported "${i}"
123 local supp=() unsupp=()
125 for i in "${_PYTHON_ALL_IMPLS[@]}"; do
126 if has "${i}" "${PYTHON_COMPAT[@]}"; then
133 if [[ ! ${supp[@]} ]]; then
134 die "No supported implementation in PYTHON_COMPAT."
137 if [[ ${_PYTHON_SUPPORTED_IMPLS[@]} ]]; then
138 # set once already, verify integrity
139 if [[ ${_PYTHON_SUPPORTED_IMPLS[@]} != ${supp[@]} ]]; then
140 eerror "Supported impls (PYTHON_COMPAT) changed between inherits!"
141 eerror "Before: ${_PYTHON_SUPPORTED_IMPLS[*]}"
142 eerror "Now : ${supp[*]}"
143 die "_PYTHON_SUPPORTED_IMPLS integrity check failed"
145 if [[ ${_PYTHON_UNSUPPORTED_IMPLS[@]} != ${unsupp[@]} ]]; then
146 eerror "Unsupported impls changed between inherits!"
147 eerror "Before: ${_PYTHON_UNSUPPORTED_IMPLS[*]}"
148 eerror "Now : ${unsupp[*]}"
149 die "_PYTHON_UNSUPPORTED_IMPLS integrity check failed"
152 _PYTHON_SUPPORTED_IMPLS=( "${supp[@]}" )
153 _PYTHON_UNSUPPORTED_IMPLS=( "${unsupp[@]}" )
154 readonly _PYTHON_SUPPORTED_IMPLS _PYTHON_UNSUPPORTED_IMPLS
158 # @FUNCTION: _python_impl_matches
159 # @USAGE: <impl> [<pattern>...]
162 # Check whether the specified <impl> matches at least one
163 # of the patterns following it. Return 0 if it does, 1 otherwise.
164 # Matches if no patterns are provided.
166 # <impl> can be in PYTHON_COMPAT or EPYTHON form. The patterns can be
168 # a) fnmatch-style patterns, e.g. 'python2*', 'pypy'...
169 # b) '-2' to indicate all Python 2 variants (= !python_is_python3)
170 # c) '-3' to indicate all Python 3 variants (= python_is_python3)
171 _python_impl_matches() {
172 [[ ${#} -ge 1 ]] || die "${FUNCNAME}: takes at least 1 parameter"
173 [[ ${#} -eq 1 ]] && return 0
175 local impl=${1} pattern
179 if [[ ${pattern} == -2 ]]; then
180 python_is_python3 "${impl}" || return 0
181 elif [[ ${pattern} == -3 ]]; then
182 python_is_python3 "${impl}" && return 0
184 # unify value style to allow lax matching
185 elif [[ ${impl/./_} == ${pattern/./_} ]]; then
193 # @ECLASS-VARIABLE: PYTHON
196 # The absolute path to the current Python interpreter.
198 # This variable is set automatically in the following contexts:
200 # python-r1: Set in functions called by python_foreach_impl() or after
201 # calling python_setup().
203 # python-single-r1: Set after calling python-single-r1_pkg_setup().
205 # distutils-r1: Set within any of the python sub-phase functions.
212 # @ECLASS-VARIABLE: EPYTHON
215 # The executable name of the current Python interpreter.
217 # This variable is set automatically in the following contexts:
219 # python-r1: Set in functions called by python_foreach_impl() or after
220 # calling python_setup().
222 # python-single-r1: Set after calling python-single-r1_pkg_setup().
224 # distutils-r1: Set within any of the python sub-phase functions.
231 # @FUNCTION: python_export
232 # @USAGE: [<impl>] <variables>...
235 # Backwards compatibility function. The relevant API is now considered
236 # private, please use python_get* instead.
238 debug-print-function ${FUNCNAME} "${@}"
240 eqawarn "python_export() is part of private eclass API."
241 eqawarn "Please call python_get*() instead."
243 _python_export "${@}"
246 # @FUNCTION: _python_export
247 # @USAGE: [<impl>] <variables>...
250 # Set and export the Python implementation-relevant variables passed
253 # The optional first parameter may specify the requested Python
254 # implementation (either as PYTHON_TARGETS value, e.g. python2_7,
255 # or an EPYTHON one, e.g. python2.7). If no implementation passed,
256 # the current one will be obtained from ${EPYTHON}.
258 # The variables which can be exported are: PYTHON, EPYTHON,
259 # PYTHON_SITEDIR. They are described more completely in the eclass
260 # variable documentation.
262 debug-print-function ${FUNCNAME} "${@}"
277 if [[ -z ${impl} ]]; then
278 die "_python_export called without a python implementation and EPYTHON is unset"
282 debug-print "${FUNCNAME}: implementation: ${impl}"
287 export EPYTHON=${impl}
288 debug-print "${FUNCNAME}: EPYTHON = ${EPYTHON}"
291 export PYTHON=${EPREFIX}/usr/bin/${impl}
292 debug-print "${FUNCNAME}: PYTHON = ${PYTHON}"
295 [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
296 # sysconfig can't be used because:
297 # 1) pypy doesn't give site-packages but stdlib
298 # 2) jython gives paths with wrong case
299 PYTHON_SITEDIR=$("${PYTHON}" -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_lib())') || die
300 export PYTHON_SITEDIR
301 debug-print "${FUNCNAME}: PYTHON_SITEDIR = ${PYTHON_SITEDIR}"
304 [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
305 PYTHON_INCLUDEDIR=$("${PYTHON}" -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_inc())') || die
306 export PYTHON_INCLUDEDIR
307 debug-print "${FUNCNAME}: PYTHON_INCLUDEDIR = ${PYTHON_INCLUDEDIR}"
309 # Jython gives a non-existing directory
310 if [[ ! -d ${PYTHON_INCLUDEDIR} ]]; then
311 die "${impl} does not install any header files!"
315 [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
316 PYTHON_LIBPATH=$("${PYTHON}" -c 'import os.path, sysconfig; print(os.path.join(sysconfig.get_config_var("LIBDIR"), sysconfig.get_config_var("LDLIBRARY")) if sysconfig.get_config_var("LDLIBRARY") else "")') || die
317 export PYTHON_LIBPATH
318 debug-print "${FUNCNAME}: PYTHON_LIBPATH = ${PYTHON_LIBPATH}"
320 if [[ ! ${PYTHON_LIBPATH} ]]; then
321 die "${impl} lacks a (usable) dynamic library"
329 # python-2.7, python-3.2, etc.
330 val=$($(tc-getPKG_CONFIG) --cflags ${impl/n/n-}) || die
333 die "${impl}: obtaining ${var} not supported"
337 export PYTHON_CFLAGS=${val}
338 debug-print "${FUNCNAME}: PYTHON_CFLAGS = ${PYTHON_CFLAGS}"
345 # python-2.7, python-3.2, etc.
346 val=$($(tc-getPKG_CONFIG) --libs ${impl/n/n-}) || die
349 die "${impl}: obtaining ${var} not supported"
353 export PYTHON_LIBS=${val}
354 debug-print "${FUNCNAME}: PYTHON_LIBS = ${PYTHON_LIBS}"
361 [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
362 flags=$("${PYTHON}" -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS") or "")') || die
363 val=${PYTHON}${flags}-config
366 die "${impl}: obtaining ${var} not supported"
370 export PYTHON_CONFIG=${val}
371 debug-print "${FUNCNAME}: PYTHON_CONFIG = ${PYTHON_CONFIG}"
377 PYTHON_PKG_DEP='>=dev-lang/python-2.7.17-r1:2.7';;
379 PYTHON_PKG_DEP=">=dev-lang/python-3.6.10:3.6";;
381 PYTHON_PKG_DEP=">=dev-lang/python-3.7.7-r1:3.7";;
383 PYTHON_PKG_DEP=">=dev-lang/python-3.8.2:3.8";;
385 PYTHON_PKG_DEP='>=dev-python/pypy3-7.3.0:0=';;
387 die "Invalid implementation: ${impl}"
391 if [[ ${PYTHON_REQ_USE} ]]; then
392 PYTHON_PKG_DEP+=[${PYTHON_REQ_USE}]
395 export PYTHON_PKG_DEP
396 debug-print "${FUNCNAME}: PYTHON_PKG_DEP = ${PYTHON_PKG_DEP}"
400 export PYTHON_SCRIPTDIR=${EPREFIX}/usr/lib/python-exec/${impl}
401 debug-print "${FUNCNAME}: PYTHON_SCRIPTDIR = ${PYTHON_SCRIPTDIR}"
404 die "_python_export: unknown variable ${var}"
409 # @FUNCTION: python_get_sitedir
412 # Obtain and print the 'site-packages' path for the given
413 # implementation. If no implementation is provided, ${EPYTHON} will
415 python_get_sitedir() {
416 debug-print-function ${FUNCNAME} "${@}"
418 _python_export "${@}" PYTHON_SITEDIR
419 echo "${PYTHON_SITEDIR}"
422 # @FUNCTION: python_get_includedir
425 # Obtain and print the include path for the given implementation. If no
426 # implementation is provided, ${EPYTHON} will be used.
427 python_get_includedir() {
428 debug-print-function ${FUNCNAME} "${@}"
430 _python_export "${@}" PYTHON_INCLUDEDIR
431 echo "${PYTHON_INCLUDEDIR}"
434 # @FUNCTION: python_get_library_path
437 # Obtain and print the Python library path for the given implementation.
438 # If no implementation is provided, ${EPYTHON} will be used.
440 # Please note that this function can be used with CPython only. Use
441 # in another implementation will result in a fatal failure.
442 python_get_library_path() {
443 debug-print-function ${FUNCNAME} "${@}"
445 _python_export "${@}" PYTHON_LIBPATH
446 echo "${PYTHON_LIBPATH}"
449 # @FUNCTION: python_get_CFLAGS
452 # Obtain and print the compiler flags for building against Python,
453 # for the given implementation. If no implementation is provided,
454 # ${EPYTHON} will be used.
456 # Please note that this function can be used with CPython only.
457 # It requires Python and pkg-config installed, and therefore proper
458 # build-time dependencies need be added to the ebuild.
459 python_get_CFLAGS() {
460 debug-print-function ${FUNCNAME} "${@}"
462 _python_export "${@}" PYTHON_CFLAGS
463 echo "${PYTHON_CFLAGS}"
466 # @FUNCTION: python_get_LIBS
469 # Obtain and print the compiler flags for linking against Python,
470 # for the given implementation. If no implementation is provided,
471 # ${EPYTHON} will be used.
473 # Please note that this function can be used with CPython only.
474 # It requires Python and pkg-config installed, and therefore proper
475 # build-time dependencies need be added to the ebuild.
477 debug-print-function ${FUNCNAME} "${@}"
479 _python_export "${@}" PYTHON_LIBS
480 echo "${PYTHON_LIBS}"
483 # @FUNCTION: python_get_PYTHON_CONFIG
486 # Obtain and print the PYTHON_CONFIG location for the given
487 # implementation. If no implementation is provided, ${EPYTHON} will be
490 # Please note that this function can be used with CPython only.
491 # It requires Python installed, and therefore proper build-time
492 # dependencies need be added to the ebuild.
493 python_get_PYTHON_CONFIG() {
494 debug-print-function ${FUNCNAME} "${@}"
496 _python_export "${@}" PYTHON_CONFIG
497 echo "${PYTHON_CONFIG}"
500 # @FUNCTION: python_get_scriptdir
503 # Obtain and print the script install path for the given
504 # implementation. If no implementation is provided, ${EPYTHON} will
506 python_get_scriptdir() {
507 debug-print-function ${FUNCNAME} "${@}"
509 _python_export "${@}" PYTHON_SCRIPTDIR
510 echo "${PYTHON_SCRIPTDIR}"
513 # @FUNCTION: _python_ln_rel
514 # @USAGE: <from> <to>
517 # Create a relative symlink.
519 debug-print-function ${FUNCNAME} "${@}"
524 local tgpath=${target%/*}/
525 local sympath=${symname%/*}/
528 while [[ ${sympath} ]]; do
531 while [[ ! ${tgseg} && ${tgpath} ]]; do
533 tgpath=${tgpath#${tgseg}/}
536 while [[ ! ${symseg} && ${sympath} ]]; do
537 symseg=${sympath%%/*}
538 sympath=${sympath#${symseg}/}
541 if [[ ${tgseg} != ${symseg} ]]; then
542 rel_target=../${rel_target}${tgseg:+${tgseg}/}
545 rel_target+=${tgpath}${target##*/}
547 debug-print "${FUNCNAME}: ${symname} -> ${target}"
548 debug-print "${FUNCNAME}: rel_target = ${rel_target}"
550 ln -fs "${rel_target}" "${symname}"
553 # @FUNCTION: python_optimize
554 # @USAGE: [<directory>...]
556 # Compile and optimize Python modules in specified directories (absolute
557 # paths). If no directories are provided, the default system paths
558 # are used (prepended with ${D}).
560 debug-print-function ${FUNCNAME} "${@}"
562 if [[ ${EBUILD_PHASE} == pre* || ${EBUILD_PHASE} == post* ]]; then
563 eerror "The new Python eclasses expect the compiled Python files to"
564 eerror "be controlled by the Package Manager. For this reason,"
565 eerror "the python_optimize function can be used only during src_* phases"
566 eerror "(src_install most commonly) and not during pkg_* phases."
568 die "python_optimize is not to be used in pre/post* phases"
571 [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
573 local PYTHON=${PYTHON}
574 [[ ${PYTHON} ]] || _python_export PYTHON
576 # default to sys.path
577 if [[ ${#} -eq 0 ]]; then
579 while IFS= read -r -d '' f; do
580 # 1) accept only absolute paths
581 # (i.e. skip '', '.' or anything like that)
582 # 2) skip paths which do not exist
583 # (python2.6 complains about them verbosely)
585 if [[ ${f} == /* && -d ${D%/}${f} ]]; then
586 set -- "${D%/}${f}" "${@}"
588 done < <("${PYTHON}" -c 'import sys; print("".join(x + "\0" for x in sys.path))' || die)
590 debug-print "${FUNCNAME}: using sys.path: ${*/%/;}"
595 # make sure to get a nice path without //
596 local instpath=${d#${D%/}}
597 instpath=/${instpath##/}
600 python2.7|python3.[34])
601 "${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
602 "${PYTHON}" -OO -m compileall -q -f -d "${instpath}" "${d}"
605 # both levels of optimization are separate since 3.5
606 "${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
607 "${PYTHON}" -O -m compileall -q -f -d "${instpath}" "${d}"
608 "${PYTHON}" -OO -m compileall -q -f -d "${instpath}" "${d}"
611 "${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
617 # @FUNCTION: python_scriptinto
620 # Set the directory to which files passed to python_doexe(),
621 # python_doscript(), python_newexe() and python_newscript()
622 # are going to be installed. The new value needs to be relative
623 # to the installation root (${ED}).
625 # If not set explicitly, the directory defaults to /usr/bin.
630 # python_scriptinto /usr/sbin
631 # python_foreach_impl python_doscript foo
634 python_scriptinto() {
635 debug-print-function ${FUNCNAME} "${@}"
637 python_scriptroot=${1}
640 # @FUNCTION: python_doexe
643 # Install the given executables into the executable install directory,
644 # for the current Python implementation (${EPYTHON}).
646 # The executable will be wrapped properly for the Python implementation,
647 # though no shebang mangling will be performed.
649 debug-print-function ${FUNCNAME} "${@}"
653 python_newexe "${f}" "${f##*/}"
657 # @FUNCTION: python_newexe
658 # @USAGE: <path> <new-name>
660 # Install the given executable into the executable install directory,
661 # for the current Python implementation (${EPYTHON}).
663 # The executable will be wrapped properly for the Python implementation,
664 # though no shebang mangling will be performed. It will be renamed
667 debug-print-function ${FUNCNAME} "${@}"
669 [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
670 [[ ${#} -eq 2 ]] || die "Usage: ${FUNCNAME} <path> <new-name>"
672 local wrapd=${python_scriptroot:-/usr/bin}
677 local scriptdir=$(python_get_scriptdir)
678 local d=${scriptdir#${EPREFIX}}
684 newexe "${f}" "${newfn}" || return ${?}
687 # install the wrapper
688 _python_ln_rel "${ED%/}"/usr/lib/python-exec/python-exec2 \
689 "${ED%/}/${wrapd}/${newfn}" || die
691 # don't use this at home, just call python_doscript() instead
692 if [[ ${_PYTHON_REWRITE_SHEBANG} ]]; then
693 python_fix_shebang -q "${ED%/}/${d}/${newfn}"
697 # @FUNCTION: python_doscript
700 # Install the given scripts into the executable install directory,
701 # for the current Python implementation (${EPYTHON}).
703 # All specified files must start with a 'python' shebang. The shebang
704 # will be converted, and the files will be wrapped properly
705 # for the Python implementation.
710 # python_foreach_impl python_doscript ${PN}
714 debug-print-function ${FUNCNAME} "${@}"
716 local _PYTHON_REWRITE_SHEBANG=1
720 # @FUNCTION: python_newscript
721 # @USAGE: <path> <new-name>
723 # Install the given script into the executable install directory
724 # for the current Python implementation (${EPYTHON}), and name it
727 # The file must start with a 'python' shebang. The shebang will be
728 # converted, and the file will be wrapped properly for the Python
729 # implementation. It will be renamed to <new-name>.
734 # python_foreach_impl python_newscript foo.py foo
738 debug-print-function ${FUNCNAME} "${@}"
740 local _PYTHON_REWRITE_SHEBANG=1
744 # @FUNCTION: python_moduleinto
747 # Set the Python module install directory for python_domodule().
748 # The <new-path> can either be an absolute target system path (in which
749 # case it needs to start with a slash, and ${ED} will be prepended to
750 # it) or relative to the implementation's site-packages directory
751 # (then it must not start with a slash). The relative path can be
752 # specified either using the Python package notation (separated by dots)
753 # or the directory notation (using slashes).
755 # When not set explicitly, the modules are installed to the top
756 # site-packages directory.
758 # In the relative case, the exact path is determined directly
759 # by each python_doscript/python_newscript function. Therefore,
760 # python_moduleinto can be safely called before establishing the Python
761 # interpreter and/or a single call can be used to set the path correctly
762 # for multiple implementations, as can be seen in the following example.
767 # python_moduleinto bar
768 # # installs ${PYTHON_SITEDIR}/bar/baz.py
769 # python_foreach_impl python_domodule baz.py
772 python_moduleinto() {
773 debug-print-function ${FUNCNAME} "${@}"
775 python_moduleroot=${1}
778 # @FUNCTION: python_domodule
781 # Install the given modules (or packages) into the current Python module
782 # installation directory. The list can mention both modules (files)
783 # and packages (directories). All listed files will be installed
784 # for all enabled implementations, and compiled afterwards.
789 # # (${PN} being a directory)
790 # python_foreach_impl python_domodule ${PN}
794 debug-print-function ${FUNCNAME} "${@}"
796 [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
799 if [[ ${python_moduleroot} == /* ]]; then
801 d=${python_moduleroot}
803 # relative to site-packages
804 local sitedir=$(python_get_sitedir)
805 d=${sitedir#${EPREFIX}}/${python_moduleroot//.//}
811 doins -r "${@}" || return ${?}
814 python_optimize "${ED%/}/${d}"
817 # @FUNCTION: python_doheader
820 # Install the given headers into the implementation-specific include
821 # directory. This function is unconditionally recursive, i.e. you can
822 # pass directories instead of files.
827 # python_foreach_impl python_doheader foo.h bar.h
831 debug-print-function ${FUNCNAME} "${@}"
833 [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
835 local includedir=$(python_get_includedir)
836 local d=${includedir#${EPREFIX}}
841 doins -r "${@}" || return ${?}
845 # @FUNCTION: python_wrapper_setup
846 # @USAGE: [<path> [<impl>]]
848 # Backwards compatibility function. The relevant API is now considered
849 # private, please use python_setup instead.
850 python_wrapper_setup() {
851 debug-print-function ${FUNCNAME} "${@}"
853 eqawarn "python_wrapper_setup() is part of private eclass API."
854 eqawarn "Please call python_setup() instead."
856 _python_wrapper_setup "${@}"
859 # @FUNCTION: _python_wrapper_setup
860 # @USAGE: [<path> [<impl>]]
863 # Create proper 'python' executable and pkg-config wrappers
864 # (if available) in the directory named by <path>. Set up PATH
865 # and PKG_CONFIG_PATH appropriately. <path> defaults to ${T}/${EPYTHON}.
867 # The wrappers will be created for implementation named by <impl>,
868 # or for one named by ${EPYTHON} if no <impl> passed.
870 # If the named directory contains a python symlink already, it will
871 # be assumed to contain proper wrappers already and only environment
872 # setup will be done. If wrapper update is requested, the directory
873 # shall be removed first.
874 _python_wrapper_setup() {
875 debug-print-function ${FUNCNAME} "${@}"
877 local workdir=${1:-${T}/${EPYTHON}}
878 local impl=${2:-${EPYTHON}}
880 [[ ${workdir} ]] || die "${FUNCNAME}: no workdir specified."
881 [[ ${impl} ]] || die "${FUNCNAME}: no impl nor EPYTHON specified."
883 if [[ ! -x ${workdir}/bin/python ]]; then
884 _python_check_dead_variables
886 mkdir -p "${workdir}"/{bin,pkgconfig} || die
888 # Clean up, in case we were supposed to do a cheap update.
889 rm -f "${workdir}"/bin/python{,2,3}{,-config} || die
890 rm -f "${workdir}"/bin/2to3 || die
891 rm -f "${workdir}"/pkgconfig/python{2,3}{,-embed}.pc || die
894 _python_export "${impl}" EPYTHON PYTHON
897 if python_is_python3; then
906 # note: we don't use symlinks because python likes to do some
907 # symlink reading magic that breaks stuff
908 # https://bugs.gentoo.org/show_bug.cgi?id=555752
909 cat > "${workdir}/bin/python" <<-_EOF_ || die
911 exec "${PYTHON}" "\${@}"
913 cp "${workdir}/bin/python" "${workdir}/bin/python${pyver}" || die
914 chmod +x "${workdir}/bin/python" "${workdir}/bin/python${pyver}" || die
916 local nonsupp=( "python${pyother}" "python${pyother}-config" )
919 if [[ ${EPYTHON} == python* ]]; then
920 cat > "${workdir}/bin/python-config" <<-_EOF_ || die
922 exec "${PYTHON}-config" "\${@}"
924 cp "${workdir}/bin/python-config" \
925 "${workdir}/bin/python${pyver}-config" || die
926 chmod +x "${workdir}/bin/python-config" \
927 "${workdir}/bin/python${pyver}-config" || die
930 ln -s "${PYTHON/python/2to3-}" "${workdir}"/bin/2to3 || die
933 ln -s "${EPREFIX}"/usr/$(get_libdir)/pkgconfig/${EPYTHON/n/n-}.pc \
934 "${workdir}"/pkgconfig/python${pyver}.pc || die
937 if [[ ${EPYTHON} != python[23].[67] ]]; then
938 ln -s "${EPREFIX}"/usr/$(get_libdir)/pkgconfig/${EPYTHON/n/n-}-embed.pc \
939 "${workdir}"/pkgconfig/python${pyver}-embed.pc || die
942 nonsupp+=( 2to3 python-config "python${pyver}-config" )
946 for x in "${nonsupp[@]}"; do
947 cat >"${workdir}"/bin/${x} <<-_EOF_ || die
949 echo "${ECLASS}: ${FUNCNAME}: ${x} is not supported by ${EPYTHON} (PYTHON_COMPAT)" >&2
952 chmod +x "${workdir}"/bin/${x} || die
956 # Now, set the environment.
957 # But note that ${workdir} may be shared with something else,
958 # and thus already on top of PATH.
959 if [[ ${PATH##:*} != ${workdir}/bin ]]; then
960 PATH=${workdir}/bin${PATH:+:${PATH}}
962 if [[ ${PKG_CONFIG_PATH##:*} != ${workdir}/pkgconfig ]]; then
963 PKG_CONFIG_PATH=${workdir}/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}
965 export PATH PKG_CONFIG_PATH
968 # @FUNCTION: python_is_python3
971 # Check whether <impl> (or ${EPYTHON}) is a Python3k variant
972 # (i.e. uses syntax and stdlib of Python 3.*).
974 # Returns 0 (true) if it is, 1 (false) otherwise.
975 python_is_python3() {
976 local impl=${1:-${EPYTHON}}
977 [[ ${impl} ]] || die "python_is_python3: no impl nor EPYTHON"
979 [[ ${impl} == python3* || ${impl} == pypy3 ]]
982 # @FUNCTION: python_is_installed
985 # Check whether the interpreter for <impl> (or ${EPYTHON}) is installed.
986 # Uses has_version with a proper dependency string.
988 # Returns 0 (true) if it is, 1 (false) otherwise.
989 python_is_installed() {
990 local impl=${1:-${EPYTHON}}
991 [[ ${impl} ]] || die "${FUNCNAME}: no impl nor EPYTHON"
996 hasv_args+=( --host-root )
1003 local PYTHON_PKG_DEP
1004 _python_export "${impl}" PYTHON_PKG_DEP
1005 has_version "${hasv_args[@]}" "${PYTHON_PKG_DEP}"
1008 # @FUNCTION: python_fix_shebang
1009 # @USAGE: [-f|--force] [-q|--quiet] <path>...
1011 # Replace the shebang in Python scripts with the current Python
1012 # implementation (EPYTHON). If a directory is passed, works recursively
1013 # on all Python scripts.
1015 # Only files having a 'python*' shebang will be modified. Files with
1016 # other shebang will either be skipped when working recursively
1017 # on a directory or treated as error when specified explicitly.
1019 # Shebangs matching explicitly current Python version will be left
1020 # unmodified. Shebangs requesting another Python version will be treated
1021 # as fatal error, unless --force is given.
1023 # --force causes the function to replace even shebangs that require
1024 # incompatible Python version. --quiet causes the function not to list
1025 # modified files verbosely.
1026 python_fix_shebang() {
1027 debug-print-function ${FUNCNAME} "${@}"
1029 [[ ${EPYTHON} ]] || die "${FUNCNAME}: EPYTHON unset (pkg_setup not called?)"
1032 while [[ ${@} ]]; do
1034 -f|--force) force=1; shift;;
1035 -q|--quiet) quiet=1; shift;;
1041 [[ ${1} ]] || die "${FUNCNAME}: no paths given"
1045 local any_correct any_fixed is_recursive
1047 [[ -d ${path} ]] && is_recursive=1
1049 while IFS= read -r -d '' f; do
1053 # note: we can't ||die here since read will fail if file
1054 # has no newline characters
1055 IFS= read -r shebang <"${f}"
1057 # First, check if it's shebang at all...
1058 if [[ ${shebang} == '#!'* ]]; then
1059 local split_shebang=()
1060 read -r -a split_shebang <<<${shebang} || die
1062 # Match left-to-right in a loop, to avoid matching random
1063 # repetitions like 'python2.7 python2'.
1064 for i in "${split_shebang[@]}"; do
1067 debug-print "${FUNCNAME}: in file ${f#${D%/}}"
1068 debug-print "${FUNCNAME}: shebang matches EPYTHON: ${shebang}"
1070 # Nothing to do, move along.
1075 *python|*python[23])
1076 debug-print "${FUNCNAME}: in file ${f#${D%/}}"
1077 debug-print "${FUNCNAME}: rewriting shebang: ${shebang}"
1079 if [[ ${i} == *python2 ]]; then
1081 if [[ ! ${force} ]]; then
1082 python_is_python3 "${EPYTHON}" && error=1
1084 elif [[ ${i} == *python3 ]]; then
1086 if [[ ! ${force} ]]; then
1087 python_is_python3 "${EPYTHON}" || error=1
1094 *python[23].[0123456789]|*pypy|*pypy3|*jython[23].[0123456789])
1095 # Explicit mismatch.
1096 if [[ ! ${force} ]]; then
1100 *python[23].[0123456789])
1101 from="python[23].[0123456789]";;
1106 *jython[23].[0123456789])
1107 from="jython[23].[0123456789]";;
1109 die "${FUNCNAME}: internal error in 2nd pattern match";;
1118 if [[ ! ${error} && ! ${from} ]]; then
1119 # Non-Python shebang. Allowed in recursive mode,
1120 # disallowed when specifying file explicitly.
1121 [[ ${is_recursive} ]] && continue
1125 if [[ ! ${quiet} ]]; then
1126 einfo "Fixing shebang in ${f#${D%/}}."
1129 if [[ ! ${error} ]]; then
1130 # We either want to match ${from} followed by space
1131 # or at end-of-string.
1132 if [[ ${shebang} == *${from}" "* ]]; then
1133 sed -i -e "1s:${from} :${EPYTHON} :" "${f}" || die
1135 sed -i -e "1s:${from}$:${EPYTHON}:" "${f}" || die
1139 eerror "The file has incompatible shebang:"
1140 eerror " file: ${f#${D%/}}"
1141 eerror " current shebang: ${shebang}"
1142 eerror " requested impl: ${EPYTHON}"
1143 die "${FUNCNAME}: conversion of incompatible shebang requested"
1145 done < <(find -H "${path}" -type f -print0 || die)
1147 if [[ ! ${any_fixed} ]]; then
1149 [[ ${EAPI} == 5 ]] && cmd=eqawarn
1151 "${cmd}" "QA warning: ${FUNCNAME}, ${path#${D%/}} did not match any fixable files."
1152 if [[ ${any_correct} ]]; then
1153 "${cmd}" "All files have ${EPYTHON} shebang already."
1155 "${cmd}" "There are no Python files in specified directory."
1158 [[ ${cmd} == eerror ]] && die "${FUNCNAME} did not match any fixable files (QA warning fatal in EAPI ${EAPI})"
1163 # @FUNCTION: _python_check_locale_sanity
1166 # @RETURN: 0 if sane, 1 otherwise
1168 # Check whether the specified locale sanely maps between lowercase
1169 # and uppercase ASCII characters.
1170 _python_check_locale_sanity() {
1171 local -x LC_ALL=${1}
1176 local input="${lc[*]}${uc[*]}"
1178 local output=$(tr '[:lower:][:upper:]' '[:upper:][:lower:]' <<<"${input}")
1179 [[ ${output} == "${uc[*]}${lc[*]}" ]]
1182 # @FUNCTION: python_export_utf8_locale
1183 # @RETURN: 0 on success, 1 on failure.
1185 # Attempts to export a usable UTF-8 locale in the LC_CTYPE variable. Does
1186 # nothing if LC_ALL is defined, or if the current locale uses a UTF-8 charmap.
1187 # This may be used to work around the quirky open() behavior of python3.
1188 python_export_utf8_locale() {
1189 debug-print-function ${FUNCNAME} "${@}"
1191 # If the locale program isn't available, just return.
1192 type locale >/dev/null || return 0
1194 if [[ $(locale charmap) != UTF-8 ]]; then
1195 # Try English first, then everything else.
1196 local lang locales="C.UTF-8 en_US.UTF-8 en_GB.UTF-8 $(locale -a)"
1198 for lang in ${locales}; do
1199 if [[ $(LC_ALL=${lang} locale charmap 2>/dev/null) == UTF-8 ]]; then
1200 if _python_check_locale_sanity "${lang}"; then
1201 export LC_CTYPE=${lang}
1202 if [[ -n ${LC_ALL} ]]; then
1203 export LC_NUMERIC=${LC_ALL}
1204 export LC_TIME=${LC_ALL}
1205 export LC_COLLATE=${LC_ALL}
1206 export LC_MONETARY=${LC_ALL}
1207 export LC_MESSAGES=${LC_ALL}
1208 export LC_PAPER=${LC_ALL}
1209 export LC_NAME=${LC_ALL}
1210 export LC_ADDRESS=${LC_ALL}
1211 export LC_TELEPHONE=${LC_ALL}
1212 export LC_MEASUREMENT=${LC_ALL}
1213 export LC_IDENTIFICATION=${LC_ALL}
1221 ewarn "Could not find a UTF-8 locale. This may trigger build failures in"
1222 ewarn "some python packages. Please ensure that a UTF-8 locale is listed in"
1223 ewarn "/etc/locale.gen and run locale-gen."
1230 # @FUNCTION: build_sphinx
1231 # @USAGE: <directory>
1233 # Build HTML documentation using dev-python/sphinx in the specified
1234 # <directory>. Takes care of disabling Intersphinx and appending
1237 # If <directory> is relative to the current directory, care needs
1238 # to be taken to run einstalldocs from the same directory
1241 debug-print-function ${FUNCNAME} "${@}"
1242 [[ ${#} -eq 1 ]] || die "${FUNCNAME} takes 1 arg: <directory>"
1246 sed -i -e 's:^intersphinx_mapping:disabled_&:' \
1247 "${dir}"/conf.py || die
1248 # not all packages include the Makefile in pypi tarball
1249 sphinx-build -b html -d "${dir}"/_build/doctrees "${dir}" \
1250 "${dir}"/_build/html || die
1252 HTML_DOCS+=( "${dir}/_build/html/." )
1255 # -- python.eclass functions --
1257 _python_check_dead_variables() {
1260 for v in PYTHON_DEPEND PYTHON_USE_WITH{,_OR,_OPT} {RESTRICT,SUPPORT}_PYTHON_ABIS
1262 if [[ ${!v} ]]; then
1263 die "${v} is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Ebuild_head"
1267 for v in PYTHON_{CPPFLAGS,CFLAGS,CXXFLAGS,LDFLAGS}
1269 if [[ ${!v} ]]; then
1270 die "${v} is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#PYTHON_CFLAGS"
1274 for v in PYTHON_TESTS_RESTRICTED_ABIS PYTHON_EXPORT_PHASE_FUNCTIONS \
1275 PYTHON_VERSIONED_{SCRIPTS,EXECUTABLES} PYTHON_NONVERSIONED_EXECUTABLES
1277 if [[ ${!v} ]]; then
1278 die "${v} is invalid for python-r1 suite"
1282 for v in DISTUTILS_USE_SEPARATE_SOURCE_DIRECTORIES DISTUTILS_SETUP_FILES \
1283 DISTUTILS_GLOBAL_OPTIONS DISTUTILS_SRC_TEST PYTHON_MODNAME
1285 if [[ ${!v} ]]; then
1286 die "${v} is invalid for distutils-r1, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#${v}"
1290 if [[ ${DISTUTILS_DISABLE_TEST_DEPENDENCY} ]]; then
1291 die "${v} is invalid for distutils-r1, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#DISTUTILS_SRC_TEST"
1294 # python.eclass::progress
1295 for v in PYTHON_BDEPEND PYTHON_MULTIPLE_ABIS PYTHON_ABI_TYPE \
1296 PYTHON_RESTRICTED_ABIS PYTHON_TESTS_FAILURES_TOLERANT_ABIS \
1297 PYTHON_CFFI_MODULES_GENERATION_COMMANDS
1299 if [[ ${!v} ]]; then
1300 die "${v} is invalid for python-r1 suite"
1305 python_pkg_setup() {
1306 die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#pkg_setup"
1309 python_convert_shebangs() {
1310 die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#python_convert_shebangs"
1313 python_clean_py-compile_files() {
1314 die "${FUNCNAME}() is invalid for python-r1 suite"
1317 python_clean_installation_image() {
1318 die "${FUNCNAME}() is invalid for python-r1 suite"
1321 python_execute_function() {
1322 die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#python_execute_function"
1325 python_generate_wrapper_scripts() {
1326 die "${FUNCNAME}() is invalid for python-r1 suite"
1329 python_merge_intermediate_installation_images() {
1330 die "${FUNCNAME}() is invalid for python-r1 suite"
1333 python_set_active_version() {
1334 die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#pkg_setup"
1337 python_need_rebuild() {
1338 die "${FUNCNAME}() is invalid for python-r1 suite"
1342 die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#.24.28PYTHON.29.2C_.24.7BEPYTHON.7D"
1345 python_get_implementation() {
1346 die "${FUNCNAME}() is invalid for python-r1 suite"
1349 python_get_implementational_package() {
1350 die "${FUNCNAME}() is invalid for python-r1 suite"
1353 python_get_libdir() {
1354 die "${FUNCNAME}() is invalid for python-r1 suite"
1357 python_get_library() {
1358 die "${FUNCNAME}() is invalid for python-r1 suite"
1361 python_get_version() {
1362 die "${FUNCNAME}() is invalid for python-r1 suite"
1365 python_get_implementation_and_version() {
1366 die "${FUNCNAME}() is invalid for python-r1 suite"
1369 python_execute_nosetests() {
1370 die "${FUNCNAME}() is invalid for python-r1 suite"
1373 python_execute_py.test() {
1374 die "${FUNCNAME}() is invalid for python-r1 suite"
1377 python_execute_trial() {
1378 die "${FUNCNAME}() is invalid for python-r1 suite"
1381 python_enable_pyc() {
1382 die "${FUNCNAME}() is invalid for python-r1 suite"
1385 python_disable_pyc() {
1386 die "${FUNCNAME}() is invalid for python-r1 suite"
1389 python_mod_optimize() {
1390 die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Python_byte-code_compilation"
1393 python_mod_cleanup() {
1394 die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Python_byte-code_compilation"
1397 # python.eclass::progress
1399 python_abi_depend() {
1400 die "${FUNCNAME}() is invalid for python-r1 suite"
1403 python_install_executables() {
1404 die "${FUNCNAME}() is invalid for python-r1 suite"
1407 python_get_extension_module_suffix() {
1408 die "${FUNCNAME}() is invalid for python-r1 suite"
1411 python_byte-compile_modules() {
1412 die "${FUNCNAME}() is invalid for python-r1 suite"
1415 python_clean_byte-compiled_modules() {
1416 die "${FUNCNAME}() is invalid for python-r1 suite"
1419 python_generate_cffi_modules() {
1420 die "${FUNCNAME}() is invalid for python-r1 suite"