blob: 9bad72a77e98d7e258870de80f88efff84e39715 [file] [log] [blame]
Allen Webbe22eed32020-07-30 09:42:18 -05001# Copyright 1999-2020 Gentoo Authors
Allen Webb7cfd3dc2019-01-28 13:27:13 -08002# Distributed under the terms of the GNU General Public License v2
3
4# @ECLASS: python-utils-r1.eclass
5# @MAINTAINER:
6# Python team <python@gentoo.org>
7# @AUTHOR:
8# Author: Michał Górny <mgorny@gentoo.org>
9# Based on work of: Krzysztof Pawlik <nelchael@gentoo.org>
Craig Hesling34e58412020-01-20 20:34:27 -080010# @SUPPORTED_EAPIS: 5 6 7
Allen Webb7cfd3dc2019-01-28 13:27:13 -080011# @BLURB: Utility functions for packages with Python parts.
12# @DESCRIPTION:
13# A utility eclass providing functions to query Python implementations,
14# install Python modules and scripts.
15#
16# This eclass does not set any metadata variables nor export any phase
17# functions. It can be inherited safely.
18#
Allen Webbe22eed32020-07-30 09:42:18 -050019# For more information, please see the Python Guide:
20# https://dev.gentoo.org/~mgorny/python-guide/
Allen Webb7cfd3dc2019-01-28 13:27:13 -080021
22case "${EAPI:-0}" in
Craig Hesling34e58412020-01-20 20:34:27 -080023 [0-4]) die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}" ;;
24 [5-7]) ;;
25 *) die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" ;;
Allen Webb7cfd3dc2019-01-28 13:27:13 -080026esac
27
28if [[ ${_PYTHON_ECLASS_INHERITED} ]]; then
29 die 'python-r1 suite eclasses can not be used with python.eclass.'
30fi
31
32if [[ ! ${_PYTHON_UTILS_R1} ]]; then
33
Craig Hesling34e58412020-01-20 20:34:27 -080034[[ ${EAPI} == 5 ]] && inherit eutils multilib
Allen Webb7cfd3dc2019-01-28 13:27:13 -080035inherit toolchain-funcs
36
37# @ECLASS-VARIABLE: _PYTHON_ALL_IMPLS
38# @INTERNAL
39# @DESCRIPTION:
40# All supported Python implementations, most preferred last.
41_PYTHON_ALL_IMPLS=(
Craig Hesling34e58412020-01-20 20:34:27 -080042 pypy3
Allen Webb7cfd3dc2019-01-28 13:27:13 -080043 python2_7
Allen Webbe22eed32020-07-30 09:42:18 -050044 python3_6 python3_7 python3_8 python3_9
Allen Webb7cfd3dc2019-01-28 13:27:13 -080045)
46readonly _PYTHON_ALL_IMPLS
47
48# @ECLASS-VARIABLE: PYTHON_COMPAT_NO_STRICT
49# @INTERNAL
50# @DESCRIPTION:
51# Set to a non-empty value in order to make eclass tolerate (ignore)
52# unknown implementations in PYTHON_COMPAT.
53#
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.
59
60# @FUNCTION: _python_impl_supported
61# @USAGE: <impl>
62# @INTERNAL
63# @DESCRIPTION:
64# Check whether the implementation <impl> (PYTHON_COMPAT-form)
65# is still supported.
66#
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} "${@}"
72
73 [[ ${#} -eq 1 ]] || die "${FUNCNAME}: takes exactly 1 argument (impl)."
74
75 local impl=${1}
76
77 # keep in sync with _PYTHON_ALL_IMPLS!
78 # (not using that list because inline patterns shall be faster)
79 case "${impl}" in
Allen Webbe22eed32020-07-30 09:42:18 -050080 python2_7|python3_[6789]|pypy3)
Allen Webb7cfd3dc2019-01-28 13:27:13 -080081 return 0
82 ;;
Craig Hesling34e58412020-01-20 20:34:27 -080083 jython2_7|pypy|pypy1_[89]|pypy2_0|python2_[56]|python3_[12345])
Allen Webb7cfd3dc2019-01-28 13:27:13 -080084 return 1
85 ;;
Allen Webb7cfd3dc2019-01-28 13:27:13 -080086 *)
87 [[ ${PYTHON_COMPAT_NO_STRICT} ]] && return 1
88 die "Invalid implementation in PYTHON_COMPAT: ${impl}"
89 esac
90}
91
92# @FUNCTION: _python_set_impls
93# @INTERNAL
94# @DESCRIPTION:
95# Check PYTHON_COMPAT for well-formedness and validity, then set
96# two global variables:
97#
98# - _PYTHON_SUPPORTED_IMPLS containing valid implementations supported
99# by the ebuild (PYTHON_COMPAT - dead implementations),
100#
101# - and _PYTHON_UNSUPPORTED_IMPLS containing valid implementations that
102# are not supported by the ebuild.
103#
104# Implementations in both variables are ordered using the pre-defined
105# eclass implementation ordering.
106#
107# This function must be called once in global scope by an eclass
108# utilizing PYTHON_COMPAT.
109_python_set_impls() {
110 local i
111
112 if ! declare -p PYTHON_COMPAT &>/dev/null; then
113 die 'PYTHON_COMPAT not declared.'
114 fi
115 if [[ $(declare -p PYTHON_COMPAT) != "declare -a"* ]]; then
116 die 'PYTHON_COMPAT must be an array.'
117 fi
118 for i in "${PYTHON_COMPAT[@]}"; do
119 # trigger validity checks
120 _python_impl_supported "${i}"
121 done
122
123 local supp=() unsupp=()
124
125 for i in "${_PYTHON_ALL_IMPLS[@]}"; do
126 if has "${i}" "${PYTHON_COMPAT[@]}"; then
127 supp+=( "${i}" )
128 else
129 unsupp+=( "${i}" )
130 fi
131 done
132
133 if [[ ! ${supp[@]} ]]; then
134 die "No supported implementation in PYTHON_COMPAT."
135 fi
136
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"
144 fi
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"
150 fi
151 else
152 _PYTHON_SUPPORTED_IMPLS=( "${supp[@]}" )
153 _PYTHON_UNSUPPORTED_IMPLS=( "${unsupp[@]}" )
154 readonly _PYTHON_SUPPORTED_IMPLS _PYTHON_UNSUPPORTED_IMPLS
155 fi
156}
157
158# @FUNCTION: _python_impl_matches
Craig Hesling34e58412020-01-20 20:34:27 -0800159# @USAGE: <impl> [<pattern>...]
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800160# @INTERNAL
161# @DESCRIPTION:
162# Check whether the specified <impl> matches at least one
163# of the patterns following it. Return 0 if it does, 1 otherwise.
Craig Hesling34e58412020-01-20 20:34:27 -0800164# Matches if no patterns are provided.
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800165#
166# <impl> can be in PYTHON_COMPAT or EPYTHON form. The patterns can be
167# either:
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() {
Craig Hesling34e58412020-01-20 20:34:27 -0800172 [[ ${#} -ge 1 ]] || die "${FUNCNAME}: takes at least 1 parameter"
173 [[ ${#} -eq 1 ]] && return 0
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800174
175 local impl=${1} pattern
176 shift
177
178 for pattern; do
179 if [[ ${pattern} == -2 ]]; then
Craig Hesling34e58412020-01-20 20:34:27 -0800180 python_is_python3 "${impl}" || return 0
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800181 elif [[ ${pattern} == -3 ]]; then
Craig Hesling34e58412020-01-20 20:34:27 -0800182 python_is_python3 "${impl}" && return 0
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800183 return
184 # unify value style to allow lax matching
185 elif [[ ${impl/./_} == ${pattern/./_} ]]; then
186 return 0
187 fi
188 done
189
190 return 1
191}
192
193# @ECLASS-VARIABLE: PYTHON
194# @DEFAULT_UNSET
195# @DESCRIPTION:
196# The absolute path to the current Python interpreter.
197#
198# This variable is set automatically in the following contexts:
199#
200# python-r1: Set in functions called by python_foreach_impl() or after
Allen Webbe22eed32020-07-30 09:42:18 -0500201# calling python_setup().
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800202#
203# python-single-r1: Set after calling python-single-r1_pkg_setup().
204#
205# distutils-r1: Set within any of the python sub-phase functions.
206#
207# Example value:
208# @CODE
209# /usr/bin/python2.7
210# @CODE
211
212# @ECLASS-VARIABLE: EPYTHON
213# @DEFAULT_UNSET
214# @DESCRIPTION:
215# The executable name of the current Python interpreter.
216#
217# This variable is set automatically in the following contexts:
218#
219# python-r1: Set in functions called by python_foreach_impl() or after
Allen Webbe22eed32020-07-30 09:42:18 -0500220# calling python_setup().
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800221#
222# python-single-r1: Set after calling python-single-r1_pkg_setup().
223#
224# distutils-r1: Set within any of the python sub-phase functions.
225#
226# Example value:
227# @CODE
228# python2.7
229# @CODE
230
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800231# @FUNCTION: python_export
232# @USAGE: [<impl>] <variables>...
Allen Webbe22eed32020-07-30 09:42:18 -0500233# @INTERNAL
234# @DESCRIPTION:
235# Backwards compatibility function. The relevant API is now considered
236# private, please use python_get* instead.
237python_export() {
238 debug-print-function ${FUNCNAME} "${@}"
239
240 eqawarn "python_export() is part of private eclass API."
241 eqawarn "Please call python_get*() instead."
242
243 _python_export "${@}"
244}
245
246# @FUNCTION: _python_export
247# @USAGE: [<impl>] <variables>...
248# @INTERNAL
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800249# @DESCRIPTION:
250# Set and export the Python implementation-relevant variables passed
251# as parameters.
252#
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}.
257#
258# The variables which can be exported are: PYTHON, EPYTHON,
259# PYTHON_SITEDIR. They are described more completely in the eclass
260# variable documentation.
Allen Webbe22eed32020-07-30 09:42:18 -0500261_python_export() {
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800262 debug-print-function ${FUNCNAME} "${@}"
263
264 local impl var
265
266 case "${1}" in
267 python*|jython*)
268 impl=${1/_/.}
269 shift
270 ;;
271 pypy|pypy3)
272 impl=${1}
273 shift
274 ;;
275 *)
276 impl=${EPYTHON}
277 if [[ -z ${impl} ]]; then
Allen Webbe22eed32020-07-30 09:42:18 -0500278 die "_python_export called without a python implementation and EPYTHON is unset"
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800279 fi
280 ;;
281 esac
282 debug-print "${FUNCNAME}: implementation: ${impl}"
283
284 for var; do
285 case "${var}" in
286 EPYTHON)
287 export EPYTHON=${impl}
288 debug-print "${FUNCNAME}: EPYTHON = ${EPYTHON}"
289 ;;
290 PYTHON)
291 export PYTHON=${EPREFIX}/usr/bin/${impl}
292 debug-print "${FUNCNAME}: PYTHON = ${PYTHON}"
293 ;;
294 PYTHON_SITEDIR)
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}"
302 ;;
303 PYTHON_INCLUDEDIR)
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}"
308
309 # Jython gives a non-existing directory
310 if [[ ! -d ${PYTHON_INCLUDEDIR} ]]; then
311 die "${impl} does not install any header files!"
312 fi
313 ;;
314 PYTHON_LIBPATH)
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}"
319
320 if [[ ! ${PYTHON_LIBPATH} ]]; then
321 die "${impl} lacks a (usable) dynamic library"
322 fi
323 ;;
324 PYTHON_CFLAGS)
325 local val
326
327 case "${impl}" in
328 python*)
329 # python-2.7, python-3.2, etc.
330 val=$($(tc-getPKG_CONFIG) --cflags ${impl/n/n-}) || die
331 ;;
332 *)
333 die "${impl}: obtaining ${var} not supported"
334 ;;
335 esac
336
337 export PYTHON_CFLAGS=${val}
338 debug-print "${FUNCNAME}: PYTHON_CFLAGS = ${PYTHON_CFLAGS}"
339 ;;
340 PYTHON_LIBS)
341 local val
342
343 case "${impl}" in
Allen Webbe22eed32020-07-30 09:42:18 -0500344 python2*|python3.6|python3.7*)
345 # python* up to 3.7
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800346 val=$($(tc-getPKG_CONFIG) --libs ${impl/n/n-}) || die
347 ;;
Allen Webbe22eed32020-07-30 09:42:18 -0500348 python*)
349 # python3.8+
350 val=$($(tc-getPKG_CONFIG) --libs ${impl/n/n-}-embed) || die
351 ;;
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800352 *)
353 die "${impl}: obtaining ${var} not supported"
354 ;;
355 esac
356
357 export PYTHON_LIBS=${val}
358 debug-print "${FUNCNAME}: PYTHON_LIBS = ${PYTHON_LIBS}"
359 ;;
360 PYTHON_CONFIG)
361 local flags val
362
363 case "${impl}" in
364 python*)
365 [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
366 flags=$("${PYTHON}" -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS") or "")') || die
367 val=${PYTHON}${flags}-config
368 ;;
369 *)
370 die "${impl}: obtaining ${var} not supported"
371 ;;
372 esac
373
374 export PYTHON_CONFIG=${val}
375 debug-print "${FUNCNAME}: PYTHON_CONFIG = ${PYTHON_CONFIG}"
376 ;;
377 PYTHON_PKG_DEP)
378 local d
379 case ${impl} in
380 python2.7)
381 PYTHON_PKG_DEP='>=dev-lang/python-2.7.5-r2:2.7';;
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800382 python*)
383 PYTHON_PKG_DEP="dev-lang/python:${impl#python}";;
384 pypy)
Allen Webbe22eed32020-07-30 09:42:18 -0500385 PYTHON_PKG_DEP='>=dev-python/pypy-7.3.0:0=';;
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800386 pypy3)
Allen Webbe22eed32020-07-30 09:42:18 -0500387 PYTHON_PKG_DEP='>=dev-python/pypy3-7.3.0:0=';;
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800388 *)
389 die "Invalid implementation: ${impl}"
390 esac
391
392 # use-dep
393 if [[ ${PYTHON_REQ_USE} ]]; then
394 PYTHON_PKG_DEP+=[${PYTHON_REQ_USE}]
395 fi
396
397 export PYTHON_PKG_DEP
398 debug-print "${FUNCNAME}: PYTHON_PKG_DEP = ${PYTHON_PKG_DEP}"
399 ;;
400 PYTHON_SCRIPTDIR)
401 local dir
402 export PYTHON_SCRIPTDIR=${EPREFIX}/usr/lib/python-exec/${impl}
403 debug-print "${FUNCNAME}: PYTHON_SCRIPTDIR = ${PYTHON_SCRIPTDIR}"
404 ;;
405 *)
Allen Webbe22eed32020-07-30 09:42:18 -0500406 die "_python_export: unknown variable ${var}"
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800407 esac
408 done
409}
410
411# @FUNCTION: python_get_sitedir
412# @USAGE: [<impl>]
413# @DESCRIPTION:
414# Obtain and print the 'site-packages' path for the given
415# implementation. If no implementation is provided, ${EPYTHON} will
416# be used.
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800417python_get_sitedir() {
418 debug-print-function ${FUNCNAME} "${@}"
419
Allen Webbe22eed32020-07-30 09:42:18 -0500420 _python_export "${@}" PYTHON_SITEDIR
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800421 echo "${PYTHON_SITEDIR}"
422}
423
424# @FUNCTION: python_get_includedir
425# @USAGE: [<impl>]
426# @DESCRIPTION:
427# Obtain and print the include path for the given implementation. If no
428# implementation is provided, ${EPYTHON} will be used.
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800429python_get_includedir() {
430 debug-print-function ${FUNCNAME} "${@}"
431
Allen Webbe22eed32020-07-30 09:42:18 -0500432 _python_export "${@}" PYTHON_INCLUDEDIR
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800433 echo "${PYTHON_INCLUDEDIR}"
434}
435
436# @FUNCTION: python_get_library_path
437# @USAGE: [<impl>]
438# @DESCRIPTION:
439# Obtain and print the Python library path for the given implementation.
440# If no implementation is provided, ${EPYTHON} will be used.
441#
442# Please note that this function can be used with CPython only. Use
443# in another implementation will result in a fatal failure.
444python_get_library_path() {
445 debug-print-function ${FUNCNAME} "${@}"
446
Allen Webbe22eed32020-07-30 09:42:18 -0500447 _python_export "${@}" PYTHON_LIBPATH
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800448 echo "${PYTHON_LIBPATH}"
449}
450
451# @FUNCTION: python_get_CFLAGS
452# @USAGE: [<impl>]
453# @DESCRIPTION:
454# Obtain and print the compiler flags for building against Python,
455# for the given implementation. If no implementation is provided,
456# ${EPYTHON} will be used.
457#
458# Please note that this function can be used with CPython only.
459# It requires Python and pkg-config installed, and therefore proper
460# build-time dependencies need be added to the ebuild.
461python_get_CFLAGS() {
462 debug-print-function ${FUNCNAME} "${@}"
463
Allen Webbe22eed32020-07-30 09:42:18 -0500464 _python_export "${@}" PYTHON_CFLAGS
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800465 echo "${PYTHON_CFLAGS}"
466}
467
468# @FUNCTION: python_get_LIBS
469# @USAGE: [<impl>]
470# @DESCRIPTION:
471# Obtain and print the compiler flags for linking against Python,
472# for the given implementation. If no implementation is provided,
473# ${EPYTHON} will be used.
474#
475# Please note that this function can be used with CPython only.
476# It requires Python and pkg-config installed, and therefore proper
477# build-time dependencies need be added to the ebuild.
478python_get_LIBS() {
479 debug-print-function ${FUNCNAME} "${@}"
480
Allen Webbe22eed32020-07-30 09:42:18 -0500481 _python_export "${@}" PYTHON_LIBS
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800482 echo "${PYTHON_LIBS}"
483}
484
485# @FUNCTION: python_get_PYTHON_CONFIG
486# @USAGE: [<impl>]
487# @DESCRIPTION:
488# Obtain and print the PYTHON_CONFIG location for the given
489# implementation. If no implementation is provided, ${EPYTHON} will be
490# used.
491#
492# Please note that this function can be used with CPython only.
493# It requires Python installed, and therefore proper build-time
494# dependencies need be added to the ebuild.
495python_get_PYTHON_CONFIG() {
496 debug-print-function ${FUNCNAME} "${@}"
497
Allen Webbe22eed32020-07-30 09:42:18 -0500498 _python_export "${@}" PYTHON_CONFIG
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800499 echo "${PYTHON_CONFIG}"
500}
501
502# @FUNCTION: python_get_scriptdir
503# @USAGE: [<impl>]
504# @DESCRIPTION:
505# Obtain and print the script install path for the given
506# implementation. If no implementation is provided, ${EPYTHON} will
507# be used.
508python_get_scriptdir() {
509 debug-print-function ${FUNCNAME} "${@}"
510
Allen Webbe22eed32020-07-30 09:42:18 -0500511 _python_export "${@}" PYTHON_SCRIPTDIR
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800512 echo "${PYTHON_SCRIPTDIR}"
513}
514
515# @FUNCTION: _python_ln_rel
516# @USAGE: <from> <to>
517# @INTERNAL
518# @DESCRIPTION:
519# Create a relative symlink.
520_python_ln_rel() {
521 debug-print-function ${FUNCNAME} "${@}"
522
523 local target=${1}
524 local symname=${2}
525
526 local tgpath=${target%/*}/
527 local sympath=${symname%/*}/
528 local rel_target=
529
530 while [[ ${sympath} ]]; do
531 local tgseg= symseg=
532
533 while [[ ! ${tgseg} && ${tgpath} ]]; do
534 tgseg=${tgpath%%/*}
535 tgpath=${tgpath#${tgseg}/}
536 done
537
538 while [[ ! ${symseg} && ${sympath} ]]; do
539 symseg=${sympath%%/*}
540 sympath=${sympath#${symseg}/}
541 done
542
543 if [[ ${tgseg} != ${symseg} ]]; then
544 rel_target=../${rel_target}${tgseg:+${tgseg}/}
545 fi
546 done
547 rel_target+=${tgpath}${target##*/}
548
549 debug-print "${FUNCNAME}: ${symname} -> ${target}"
550 debug-print "${FUNCNAME}: rel_target = ${rel_target}"
551
552 ln -fs "${rel_target}" "${symname}"
553}
554
555# @FUNCTION: python_optimize
556# @USAGE: [<directory>...]
557# @DESCRIPTION:
558# Compile and optimize Python modules in specified directories (absolute
559# paths). If no directories are provided, the default system paths
560# are used (prepended with ${D}).
561python_optimize() {
562 debug-print-function ${FUNCNAME} "${@}"
563
564 if [[ ${EBUILD_PHASE} == pre* || ${EBUILD_PHASE} == post* ]]; then
565 eerror "The new Python eclasses expect the compiled Python files to"
566 eerror "be controlled by the Package Manager. For this reason,"
567 eerror "the python_optimize function can be used only during src_* phases"
568 eerror "(src_install most commonly) and not during pkg_* phases."
569 echo
570 die "python_optimize is not to be used in pre/post* phases"
571 fi
572
573 [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
574
575 local PYTHON=${PYTHON}
Allen Webbe22eed32020-07-30 09:42:18 -0500576 [[ ${PYTHON} ]] || _python_export PYTHON
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800577
578 # default to sys.path
579 if [[ ${#} -eq 0 ]]; then
580 local f
581 while IFS= read -r -d '' f; do
582 # 1) accept only absolute paths
583 # (i.e. skip '', '.' or anything like that)
584 # 2) skip paths which do not exist
585 # (python2.6 complains about them verbosely)
586
587 if [[ ${f} == /* && -d ${D%/}${f} ]]; then
588 set -- "${D%/}${f}" "${@}"
589 fi
Craig Hesling34e58412020-01-20 20:34:27 -0800590 done < <("${PYTHON}" -c 'import sys; print("".join(x + "\0" for x in sys.path))' || die)
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800591
592 debug-print "${FUNCNAME}: using sys.path: ${*/%/;}"
593 fi
594
595 local d
596 for d; do
597 # make sure to get a nice path without //
598 local instpath=${d#${D%/}}
599 instpath=/${instpath##/}
600
601 case "${EPYTHON}" in
602 python2.7|python3.[34])
603 "${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
604 "${PYTHON}" -OO -m compileall -q -f -d "${instpath}" "${d}"
605 ;;
606 python*|pypy3)
607 # both levels of optimization are separate since 3.5
608 "${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
609 "${PYTHON}" -O -m compileall -q -f -d "${instpath}" "${d}"
610 "${PYTHON}" -OO -m compileall -q -f -d "${instpath}" "${d}"
611 ;;
612 *)
613 "${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
614 ;;
615 esac
616 done
617}
618
619# @FUNCTION: python_scriptinto
620# @USAGE: <new-path>
621# @DESCRIPTION:
622# Set the directory to which files passed to python_doexe(),
623# python_doscript(), python_newexe() and python_newscript()
624# are going to be installed. The new value needs to be relative
625# to the installation root (${ED}).
626#
627# If not set explicitly, the directory defaults to /usr/bin.
628#
629# Example:
630# @CODE
631# src_install() {
632# python_scriptinto /usr/sbin
633# python_foreach_impl python_doscript foo
634# }
635# @CODE
636python_scriptinto() {
637 debug-print-function ${FUNCNAME} "${@}"
638
639 python_scriptroot=${1}
640}
641
642# @FUNCTION: python_doexe
643# @USAGE: <files>...
644# @DESCRIPTION:
645# Install the given executables into the executable install directory,
646# for the current Python implementation (${EPYTHON}).
647#
648# The executable will be wrapped properly for the Python implementation,
649# though no shebang mangling will be performed.
650python_doexe() {
651 debug-print-function ${FUNCNAME} "${@}"
652
653 local f
654 for f; do
655 python_newexe "${f}" "${f##*/}"
656 done
657}
658
659# @FUNCTION: python_newexe
660# @USAGE: <path> <new-name>
661# @DESCRIPTION:
662# Install the given executable into the executable install directory,
663# for the current Python implementation (${EPYTHON}).
664#
665# The executable will be wrapped properly for the Python implementation,
666# though no shebang mangling will be performed. It will be renamed
667# to <new-name>.
668python_newexe() {
669 debug-print-function ${FUNCNAME} "${@}"
670
671 [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
672 [[ ${#} -eq 2 ]] || die "Usage: ${FUNCNAME} <path> <new-name>"
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800673
674 local wrapd=${python_scriptroot:-/usr/bin}
675
676 local f=${1}
677 local newfn=${2}
678
Allen Webbe22eed32020-07-30 09:42:18 -0500679 local scriptdir=$(python_get_scriptdir)
680 local d=${scriptdir#${EPREFIX}}
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800681
682 (
683 dodir "${wrapd}"
684 exeopts -m 0755
685 exeinto "${d}"
686 newexe "${f}" "${newfn}" || return ${?}
687 )
688
689 # install the wrapper
690 _python_ln_rel "${ED%/}"/usr/lib/python-exec/python-exec2 \
691 "${ED%/}/${wrapd}/${newfn}" || die
692
693 # don't use this at home, just call python_doscript() instead
694 if [[ ${_PYTHON_REWRITE_SHEBANG} ]]; then
695 python_fix_shebang -q "${ED%/}/${d}/${newfn}"
696 fi
697}
698
699# @FUNCTION: python_doscript
700# @USAGE: <files>...
701# @DESCRIPTION:
702# Install the given scripts into the executable install directory,
703# for the current Python implementation (${EPYTHON}).
704#
705# All specified files must start with a 'python' shebang. The shebang
706# will be converted, and the files will be wrapped properly
707# for the Python implementation.
708#
709# Example:
710# @CODE
711# src_install() {
712# python_foreach_impl python_doscript ${PN}
713# }
714# @CODE
715python_doscript() {
716 debug-print-function ${FUNCNAME} "${@}"
717
718 local _PYTHON_REWRITE_SHEBANG=1
719 python_doexe "${@}"
720}
721
722# @FUNCTION: python_newscript
723# @USAGE: <path> <new-name>
724# @DESCRIPTION:
725# Install the given script into the executable install directory
726# for the current Python implementation (${EPYTHON}), and name it
727# <new-name>.
728#
729# The file must start with a 'python' shebang. The shebang will be
730# converted, and the file will be wrapped properly for the Python
731# implementation. It will be renamed to <new-name>.
732#
733# Example:
734# @CODE
735# src_install() {
736# python_foreach_impl python_newscript foo.py foo
737# }
738# @CODE
739python_newscript() {
740 debug-print-function ${FUNCNAME} "${@}"
741
742 local _PYTHON_REWRITE_SHEBANG=1
743 python_newexe "${@}"
744}
745
746# @FUNCTION: python_moduleinto
747# @USAGE: <new-path>
748# @DESCRIPTION:
749# Set the Python module install directory for python_domodule().
750# The <new-path> can either be an absolute target system path (in which
751# case it needs to start with a slash, and ${ED} will be prepended to
752# it) or relative to the implementation's site-packages directory
753# (then it must not start with a slash). The relative path can be
754# specified either using the Python package notation (separated by dots)
755# or the directory notation (using slashes).
756#
757# When not set explicitly, the modules are installed to the top
758# site-packages directory.
759#
760# In the relative case, the exact path is determined directly
761# by each python_doscript/python_newscript function. Therefore,
762# python_moduleinto can be safely called before establishing the Python
763# interpreter and/or a single call can be used to set the path correctly
764# for multiple implementations, as can be seen in the following example.
765#
766# Example:
767# @CODE
768# src_install() {
769# python_moduleinto bar
770# # installs ${PYTHON_SITEDIR}/bar/baz.py
771# python_foreach_impl python_domodule baz.py
772# }
773# @CODE
774python_moduleinto() {
775 debug-print-function ${FUNCNAME} "${@}"
776
777 python_moduleroot=${1}
778}
779
780# @FUNCTION: python_domodule
781# @USAGE: <files>...
782# @DESCRIPTION:
783# Install the given modules (or packages) into the current Python module
784# installation directory. The list can mention both modules (files)
785# and packages (directories). All listed files will be installed
786# for all enabled implementations, and compiled afterwards.
787#
788# Example:
789# @CODE
790# src_install() {
791# # (${PN} being a directory)
792# python_foreach_impl python_domodule ${PN}
793# }
794# @CODE
795python_domodule() {
796 debug-print-function ${FUNCNAME} "${@}"
797
798 [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800799
800 local d
801 if [[ ${python_moduleroot} == /* ]]; then
802 # absolute path
803 d=${python_moduleroot}
804 else
805 # relative to site-packages
Allen Webbe22eed32020-07-30 09:42:18 -0500806 local sitedir=$(python_get_sitedir)
807 d=${sitedir#${EPREFIX}}/${python_moduleroot//.//}
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800808 fi
809
810 (
811 insopts -m 0644
812 insinto "${d}"
813 doins -r "${@}" || return ${?}
814 )
815
816 python_optimize "${ED%/}/${d}"
817}
818
819# @FUNCTION: python_doheader
820# @USAGE: <files>...
821# @DESCRIPTION:
822# Install the given headers into the implementation-specific include
823# directory. This function is unconditionally recursive, i.e. you can
824# pass directories instead of files.
825#
826# Example:
827# @CODE
828# src_install() {
829# python_foreach_impl python_doheader foo.h bar.h
830# }
831# @CODE
832python_doheader() {
833 debug-print-function ${FUNCNAME} "${@}"
834
835 [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800836
Allen Webbe22eed32020-07-30 09:42:18 -0500837 local includedir=$(python_get_includedir)
838 local d=${includedir#${EPREFIX}}
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800839
840 (
841 insopts -m 0644
842 insinto "${d}"
843 doins -r "${@}" || return ${?}
844 )
845}
846
847# @FUNCTION: python_wrapper_setup
848# @USAGE: [<path> [<impl>]]
849# @DESCRIPTION:
Allen Webbe22eed32020-07-30 09:42:18 -0500850# Backwards compatibility function. The relevant API is now considered
851# private, please use python_setup instead.
852python_wrapper_setup() {
853 debug-print-function ${FUNCNAME} "${@}"
854
855 eqawarn "python_wrapper_setup() is part of private eclass API."
856 eqawarn "Please call python_setup() instead."
857
858 _python_wrapper_setup "${@}"
859}
860
861# @FUNCTION: _python_wrapper_setup
862# @USAGE: [<path> [<impl>]]
863# @INTERNAL
864# @DESCRIPTION:
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800865# Create proper 'python' executable and pkg-config wrappers
866# (if available) in the directory named by <path>. Set up PATH
867# and PKG_CONFIG_PATH appropriately. <path> defaults to ${T}/${EPYTHON}.
868#
869# The wrappers will be created for implementation named by <impl>,
870# or for one named by ${EPYTHON} if no <impl> passed.
871#
872# If the named directory contains a python symlink already, it will
873# be assumed to contain proper wrappers already and only environment
874# setup will be done. If wrapper update is requested, the directory
875# shall be removed first.
Allen Webbe22eed32020-07-30 09:42:18 -0500876_python_wrapper_setup() {
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800877 debug-print-function ${FUNCNAME} "${@}"
878
879 local workdir=${1:-${T}/${EPYTHON}}
880 local impl=${2:-${EPYTHON}}
881
882 [[ ${workdir} ]] || die "${FUNCNAME}: no workdir specified."
883 [[ ${impl} ]] || die "${FUNCNAME}: no impl nor EPYTHON specified."
884
885 if [[ ! -x ${workdir}/bin/python ]]; then
886 _python_check_dead_variables
887
888 mkdir -p "${workdir}"/{bin,pkgconfig} || die
889
890 # Clean up, in case we were supposed to do a cheap update.
891 rm -f "${workdir}"/bin/python{,2,3}{,-config} || die
892 rm -f "${workdir}"/bin/2to3 || die
Allen Webbe22eed32020-07-30 09:42:18 -0500893 rm -f "${workdir}"/pkgconfig/python{2,3}{,-embed}.pc || die
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800894
895 local EPYTHON PYTHON
Allen Webbe22eed32020-07-30 09:42:18 -0500896 _python_export "${impl}" EPYTHON PYTHON
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800897
898 local pyver pyother
899 if python_is_python3; then
900 pyver=3
901 pyother=2
902 else
903 pyver=2
904 pyother=3
905 fi
906
907 # Python interpreter
908 # note: we don't use symlinks because python likes to do some
909 # symlink reading magic that breaks stuff
910 # https://bugs.gentoo.org/show_bug.cgi?id=555752
911 cat > "${workdir}/bin/python" <<-_EOF_ || die
912 #!/bin/sh
913 exec "${PYTHON}" "\${@}"
914 _EOF_
915 cp "${workdir}/bin/python" "${workdir}/bin/python${pyver}" || die
916 chmod +x "${workdir}/bin/python" "${workdir}/bin/python${pyver}" || die
917
918 local nonsupp=( "python${pyother}" "python${pyother}-config" )
919
920 # CPython-specific
921 if [[ ${EPYTHON} == python* ]]; then
922 cat > "${workdir}/bin/python-config" <<-_EOF_ || die
923 #!/bin/sh
924 exec "${PYTHON}-config" "\${@}"
925 _EOF_
926 cp "${workdir}/bin/python-config" \
927 "${workdir}/bin/python${pyver}-config" || die
928 chmod +x "${workdir}/bin/python-config" \
929 "${workdir}/bin/python${pyver}-config" || die
930
931 # Python 2.6+.
932 ln -s "${PYTHON/python/2to3-}" "${workdir}"/bin/2to3 || die
933
934 # Python 2.7+.
935 ln -s "${EPREFIX}"/usr/$(get_libdir)/pkgconfig/${EPYTHON/n/n-}.pc \
Allen Webbe22eed32020-07-30 09:42:18 -0500936 "${workdir}"/pkgconfig/python${pyver}.pc || die
937
938 # Python 3.8+.
939 if [[ ${EPYTHON} != python[23].[67] ]]; then
940 ln -s "${EPREFIX}"/usr/$(get_libdir)/pkgconfig/${EPYTHON/n/n-}-embed.pc \
941 "${workdir}"/pkgconfig/python${pyver}-embed.pc || die
942 fi
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800943 else
944 nonsupp+=( 2to3 python-config "python${pyver}-config" )
945 fi
946
947 local x
948 for x in "${nonsupp[@]}"; do
949 cat >"${workdir}"/bin/${x} <<-_EOF_ || die
950 #!/bin/sh
951 echo "${ECLASS}: ${FUNCNAME}: ${x} is not supported by ${EPYTHON} (PYTHON_COMPAT)" >&2
952 exit 127
953 _EOF_
954 chmod +x "${workdir}"/bin/${x} || die
955 done
956 fi
957
958 # Now, set the environment.
959 # But note that ${workdir} may be shared with something else,
960 # and thus already on top of PATH.
961 if [[ ${PATH##:*} != ${workdir}/bin ]]; then
962 PATH=${workdir}/bin${PATH:+:${PATH}}
963 fi
964 if [[ ${PKG_CONFIG_PATH##:*} != ${workdir}/pkgconfig ]]; then
965 PKG_CONFIG_PATH=${workdir}/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}
966 fi
967 export PATH PKG_CONFIG_PATH
968}
969
970# @FUNCTION: python_is_python3
971# @USAGE: [<impl>]
972# @DESCRIPTION:
973# Check whether <impl> (or ${EPYTHON}) is a Python3k variant
974# (i.e. uses syntax and stdlib of Python 3.*).
975#
976# Returns 0 (true) if it is, 1 (false) otherwise.
977python_is_python3() {
978 local impl=${1:-${EPYTHON}}
979 [[ ${impl} ]] || die "python_is_python3: no impl nor EPYTHON"
980
981 [[ ${impl} == python3* || ${impl} == pypy3 ]]
982}
983
984# @FUNCTION: python_is_installed
985# @USAGE: [<impl>]
986# @DESCRIPTION:
987# Check whether the interpreter for <impl> (or ${EPYTHON}) is installed.
988# Uses has_version with a proper dependency string.
989#
990# Returns 0 (true) if it is, 1 (false) otherwise.
991python_is_installed() {
992 local impl=${1:-${EPYTHON}}
993 [[ ${impl} ]] || die "${FUNCNAME}: no impl nor EPYTHON"
994 local hasv_args=()
995
Craig Hesling34e58412020-01-20 20:34:27 -0800996 case ${EAPI} in
Allen Webb7cfd3dc2019-01-28 13:27:13 -0800997 5|6)
998 hasv_args+=( --host-root )
999 ;;
1000 *)
1001 hasv_args+=( -b )
1002 ;;
1003 esac
1004
Allen Webbe22eed32020-07-30 09:42:18 -05001005 local PYTHON_PKG_DEP
1006 _python_export "${impl}" PYTHON_PKG_DEP
1007 has_version "${hasv_args[@]}" "${PYTHON_PKG_DEP}"
Allen Webb7cfd3dc2019-01-28 13:27:13 -08001008}
1009
1010# @FUNCTION: python_fix_shebang
1011# @USAGE: [-f|--force] [-q|--quiet] <path>...
1012# @DESCRIPTION:
1013# Replace the shebang in Python scripts with the current Python
1014# implementation (EPYTHON). If a directory is passed, works recursively
1015# on all Python scripts.
1016#
1017# Only files having a 'python*' shebang will be modified. Files with
1018# other shebang will either be skipped when working recursively
1019# on a directory or treated as error when specified explicitly.
1020#
1021# Shebangs matching explicitly current Python version will be left
1022# unmodified. Shebangs requesting another Python version will be treated
1023# as fatal error, unless --force is given.
1024#
1025# --force causes the function to replace even shebangs that require
1026# incompatible Python version. --quiet causes the function not to list
1027# modified files verbosely.
1028python_fix_shebang() {
1029 debug-print-function ${FUNCNAME} "${@}"
1030
1031 [[ ${EPYTHON} ]] || die "${FUNCNAME}: EPYTHON unset (pkg_setup not called?)"
1032
1033 local force quiet
1034 while [[ ${@} ]]; do
1035 case "${1}" in
1036 -f|--force) force=1; shift;;
1037 -q|--quiet) quiet=1; shift;;
1038 --) shift; break;;
1039 *) break;;
1040 esac
1041 done
1042
1043 [[ ${1} ]] || die "${FUNCNAME}: no paths given"
1044
1045 local path f
1046 for path; do
1047 local any_correct any_fixed is_recursive
1048
1049 [[ -d ${path} ]] && is_recursive=1
1050
1051 while IFS= read -r -d '' f; do
1052 local shebang i
1053 local error= from=
1054
1055 # note: we can't ||die here since read will fail if file
1056 # has no newline characters
1057 IFS= read -r shebang <"${f}"
1058
1059 # First, check if it's shebang at all...
1060 if [[ ${shebang} == '#!'* ]]; then
1061 local split_shebang=()
1062 read -r -a split_shebang <<<${shebang} || die
1063
1064 # Match left-to-right in a loop, to avoid matching random
1065 # repetitions like 'python2.7 python2'.
1066 for i in "${split_shebang[@]}"; do
1067 case "${i}" in
1068 *"${EPYTHON}")
1069 debug-print "${FUNCNAME}: in file ${f#${D%/}}"
1070 debug-print "${FUNCNAME}: shebang matches EPYTHON: ${shebang}"
1071
1072 # Nothing to do, move along.
1073 any_correct=1
1074 from=${EPYTHON}
1075 break
1076 ;;
1077 *python|*python[23])
1078 debug-print "${FUNCNAME}: in file ${f#${D%/}}"
1079 debug-print "${FUNCNAME}: rewriting shebang: ${shebang}"
1080
1081 if [[ ${i} == *python2 ]]; then
1082 from=python2
1083 if [[ ! ${force} ]]; then
1084 python_is_python3 "${EPYTHON}" && error=1
1085 fi
1086 elif [[ ${i} == *python3 ]]; then
1087 from=python3
1088 if [[ ! ${force} ]]; then
1089 python_is_python3 "${EPYTHON}" || error=1
1090 fi
1091 else
1092 from=python
1093 fi
1094 break
1095 ;;
1096 *python[23].[0123456789]|*pypy|*pypy3|*jython[23].[0123456789])
1097 # Explicit mismatch.
1098 if [[ ! ${force} ]]; then
1099 error=1
1100 else
1101 case "${i}" in
1102 *python[23].[0123456789])
1103 from="python[23].[0123456789]";;
1104 *pypy)
1105 from="pypy";;
1106 *pypy3)
1107 from="pypy3";;
1108 *jython[23].[0123456789])
1109 from="jython[23].[0123456789]";;
1110 *)
1111 die "${FUNCNAME}: internal error in 2nd pattern match";;
1112 esac
1113 fi
1114 break
1115 ;;
1116 esac
1117 done
1118 fi
1119
1120 if [[ ! ${error} && ! ${from} ]]; then
1121 # Non-Python shebang. Allowed in recursive mode,
1122 # disallowed when specifying file explicitly.
1123 [[ ${is_recursive} ]] && continue
1124 error=1
1125 fi
1126
1127 if [[ ! ${quiet} ]]; then
1128 einfo "Fixing shebang in ${f#${D%/}}."
1129 fi
1130
1131 if [[ ! ${error} ]]; then
1132 # We either want to match ${from} followed by space
1133 # or at end-of-string.
1134 if [[ ${shebang} == *${from}" "* ]]; then
1135 sed -i -e "1s:${from} :${EPYTHON} :" "${f}" || die
1136 else
1137 sed -i -e "1s:${from}$:${EPYTHON}:" "${f}" || die
1138 fi
1139 any_fixed=1
1140 else
1141 eerror "The file has incompatible shebang:"
1142 eerror " file: ${f#${D%/}}"
1143 eerror " current shebang: ${shebang}"
1144 eerror " requested impl: ${EPYTHON}"
1145 die "${FUNCNAME}: conversion of incompatible shebang requested"
1146 fi
1147 done < <(find -H "${path}" -type f -print0 || die)
1148
1149 if [[ ! ${any_fixed} ]]; then
1150 local cmd=eerror
Craig Hesling34e58412020-01-20 20:34:27 -08001151 [[ ${EAPI} == 5 ]] && cmd=eqawarn
Allen Webb7cfd3dc2019-01-28 13:27:13 -08001152
1153 "${cmd}" "QA warning: ${FUNCNAME}, ${path#${D%/}} did not match any fixable files."
1154 if [[ ${any_correct} ]]; then
1155 "${cmd}" "All files have ${EPYTHON} shebang already."
1156 else
1157 "${cmd}" "There are no Python files in specified directory."
1158 fi
1159
1160 [[ ${cmd} == eerror ]] && die "${FUNCNAME} did not match any fixable files (QA warning fatal in EAPI ${EAPI})"
1161 fi
1162 done
1163}
1164
1165# @FUNCTION: _python_check_locale_sanity
1166# @USAGE: <locale>
1167# @RETURN: 0 if sane, 1 otherwise
Allen Webbe22eed32020-07-30 09:42:18 -05001168# @INTERNAL
Allen Webb7cfd3dc2019-01-28 13:27:13 -08001169# @DESCRIPTION:
1170# Check whether the specified locale sanely maps between lowercase
1171# and uppercase ASCII characters.
1172_python_check_locale_sanity() {
1173 local -x LC_ALL=${1}
1174 local IFS=
1175
1176 local lc=( {a..z} )
1177 local uc=( {A..Z} )
1178 local input="${lc[*]}${uc[*]}"
1179
1180 local output=$(tr '[:lower:][:upper:]' '[:upper:][:lower:]' <<<"${input}")
1181 [[ ${output} == "${uc[*]}${lc[*]}" ]]
1182}
1183
1184# @FUNCTION: python_export_utf8_locale
1185# @RETURN: 0 on success, 1 on failure.
1186# @DESCRIPTION:
1187# Attempts to export a usable UTF-8 locale in the LC_CTYPE variable. Does
1188# nothing if LC_ALL is defined, or if the current locale uses a UTF-8 charmap.
1189# This may be used to work around the quirky open() behavior of python3.
1190python_export_utf8_locale() {
1191 debug-print-function ${FUNCNAME} "${@}"
1192
1193 # If the locale program isn't available, just return.
1194 type locale >/dev/null || return 0
1195
1196 if [[ $(locale charmap) != UTF-8 ]]; then
1197 # Try English first, then everything else.
1198 local lang locales="C.UTF-8 en_US.UTF-8 en_GB.UTF-8 $(locale -a)"
1199
1200 for lang in ${locales}; do
1201 if [[ $(LC_ALL=${lang} locale charmap 2>/dev/null) == UTF-8 ]]; then
1202 if _python_check_locale_sanity "${lang}"; then
1203 export LC_CTYPE=${lang}
1204 if [[ -n ${LC_ALL} ]]; then
1205 export LC_NUMERIC=${LC_ALL}
1206 export LC_TIME=${LC_ALL}
1207 export LC_COLLATE=${LC_ALL}
1208 export LC_MONETARY=${LC_ALL}
1209 export LC_MESSAGES=${LC_ALL}
1210 export LC_PAPER=${LC_ALL}
1211 export LC_NAME=${LC_ALL}
1212 export LC_ADDRESS=${LC_ALL}
1213 export LC_TELEPHONE=${LC_ALL}
1214 export LC_MEASUREMENT=${LC_ALL}
1215 export LC_IDENTIFICATION=${LC_ALL}
1216 export LC_ALL=
1217 fi
1218 return 0
1219 fi
1220 fi
1221 done
1222
1223 ewarn "Could not find a UTF-8 locale. This may trigger build failures in"
1224 ewarn "some python packages. Please ensure that a UTF-8 locale is listed in"
1225 ewarn "/etc/locale.gen and run locale-gen."
1226 return 1
1227 fi
1228
1229 return 0
1230}
1231
Craig Hesling34e58412020-01-20 20:34:27 -08001232# @FUNCTION: build_sphinx
1233# @USAGE: <directory>
1234# @DESCRIPTION:
1235# Build HTML documentation using dev-python/sphinx in the specified
1236# <directory>. Takes care of disabling Intersphinx and appending
1237# to HTML_DOCS.
1238#
1239# If <directory> is relative to the current directory, care needs
1240# to be taken to run einstalldocs from the same directory
1241# (usually ${S}).
1242build_sphinx() {
1243 debug-print-function ${FUNCNAME} "${@}"
1244 [[ ${#} -eq 1 ]] || die "${FUNCNAME} takes 1 arg: <directory>"
1245
1246 local dir=${1}
1247
1248 sed -i -e 's:^intersphinx_mapping:disabled_&:' \
1249 "${dir}"/conf.py || die
1250 # not all packages include the Makefile in pypi tarball
1251 sphinx-build -b html -d "${dir}"/_build/doctrees "${dir}" \
1252 "${dir}"/_build/html || die
1253
1254 HTML_DOCS+=( "${dir}/_build/html/." )
1255}
1256
Allen Webb7cfd3dc2019-01-28 13:27:13 -08001257# -- python.eclass functions --
1258
1259_python_check_dead_variables() {
1260 local v
1261
1262 for v in PYTHON_DEPEND PYTHON_USE_WITH{,_OR,_OPT} {RESTRICT,SUPPORT}_PYTHON_ABIS
1263 do
1264 if [[ ${!v} ]]; then
1265 die "${v} is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Ebuild_head"
1266 fi
1267 done
1268
1269 for v in PYTHON_{CPPFLAGS,CFLAGS,CXXFLAGS,LDFLAGS}
1270 do
1271 if [[ ${!v} ]]; then
1272 die "${v} is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#PYTHON_CFLAGS"
1273 fi
1274 done
1275
1276 for v in PYTHON_TESTS_RESTRICTED_ABIS PYTHON_EXPORT_PHASE_FUNCTIONS \
1277 PYTHON_VERSIONED_{SCRIPTS,EXECUTABLES} PYTHON_NONVERSIONED_EXECUTABLES
1278 do
1279 if [[ ${!v} ]]; then
1280 die "${v} is invalid for python-r1 suite"
1281 fi
1282 done
1283
1284 for v in DISTUTILS_USE_SEPARATE_SOURCE_DIRECTORIES DISTUTILS_SETUP_FILES \
1285 DISTUTILS_GLOBAL_OPTIONS DISTUTILS_SRC_TEST PYTHON_MODNAME
1286 do
1287 if [[ ${!v} ]]; then
1288 die "${v} is invalid for distutils-r1, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#${v}"
1289 fi
1290 done
1291
1292 if [[ ${DISTUTILS_DISABLE_TEST_DEPENDENCY} ]]; then
1293 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 fi
1295
1296 # python.eclass::progress
1297 for v in PYTHON_BDEPEND PYTHON_MULTIPLE_ABIS PYTHON_ABI_TYPE \
1298 PYTHON_RESTRICTED_ABIS PYTHON_TESTS_FAILURES_TOLERANT_ABIS \
1299 PYTHON_CFFI_MODULES_GENERATION_COMMANDS
1300 do
1301 if [[ ${!v} ]]; then
1302 die "${v} is invalid for python-r1 suite"
1303 fi
1304 done
1305}
1306
1307python_pkg_setup() {
1308 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}
1310
1311python_convert_shebangs() {
1312 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}
1314
1315python_clean_py-compile_files() {
1316 die "${FUNCNAME}() is invalid for python-r1 suite"
1317}
1318
1319python_clean_installation_image() {
1320 die "${FUNCNAME}() is invalid for python-r1 suite"
1321}
1322
1323python_execute_function() {
1324 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}
1326
1327python_generate_wrapper_scripts() {
1328 die "${FUNCNAME}() is invalid for python-r1 suite"
1329}
1330
1331python_merge_intermediate_installation_images() {
1332 die "${FUNCNAME}() is invalid for python-r1 suite"
1333}
1334
1335python_set_active_version() {
1336 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}
1338
1339python_need_rebuild() {
1340 die "${FUNCNAME}() is invalid for python-r1 suite"
1341}
1342
1343PYTHON() {
1344 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}
1346
1347python_get_implementation() {
1348 die "${FUNCNAME}() is invalid for python-r1 suite"
1349}
1350
1351python_get_implementational_package() {
1352 die "${FUNCNAME}() is invalid for python-r1 suite"
1353}
1354
1355python_get_libdir() {
1356 die "${FUNCNAME}() is invalid for python-r1 suite"
1357}
1358
1359python_get_library() {
1360 die "${FUNCNAME}() is invalid for python-r1 suite"
1361}
1362
1363python_get_version() {
1364 die "${FUNCNAME}() is invalid for python-r1 suite"
1365}
1366
1367python_get_implementation_and_version() {
1368 die "${FUNCNAME}() is invalid for python-r1 suite"
1369}
1370
1371python_execute_nosetests() {
1372 die "${FUNCNAME}() is invalid for python-r1 suite"
1373}
1374
1375python_execute_py.test() {
1376 die "${FUNCNAME}() is invalid for python-r1 suite"
1377}
1378
1379python_execute_trial() {
1380 die "${FUNCNAME}() is invalid for python-r1 suite"
1381}
1382
1383python_enable_pyc() {
1384 die "${FUNCNAME}() is invalid for python-r1 suite"
1385}
1386
1387python_disable_pyc() {
1388 die "${FUNCNAME}() is invalid for python-r1 suite"
1389}
1390
1391python_mod_optimize() {
1392 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}
1394
1395python_mod_cleanup() {
1396 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}
1398
1399# python.eclass::progress
1400
1401python_abi_depend() {
1402 die "${FUNCNAME}() is invalid for python-r1 suite"
1403}
1404
1405python_install_executables() {
1406 die "${FUNCNAME}() is invalid for python-r1 suite"
1407}
1408
1409python_get_extension_module_suffix() {
1410 die "${FUNCNAME}() is invalid for python-r1 suite"
1411}
1412
1413python_byte-compile_modules() {
1414 die "${FUNCNAME}() is invalid for python-r1 suite"
1415}
1416
1417python_clean_byte-compiled_modules() {
1418 die "${FUNCNAME}() is invalid for python-r1 suite"
1419}
1420
1421python_generate_cffi_modules() {
1422 die "${FUNCNAME}() is invalid for python-r1 suite"
1423}
1424
1425_PYTHON_UTILS_R1=1
1426fi