/[gentoo-x86]/eclass/python.eclass
Gentoo

Diff of /eclass/python.eclass

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.41 Revision 1.74
1# Copyright 1999-2008 Gentoo Foundation 1# Copyright 1999-2009 Gentoo Foundation
2# Distributed under the terms of the GNU General Public License v2 2# Distributed under the terms of the GNU General Public License v2
3# $Header: /var/cvsroot/gentoo-x86/eclass/python.eclass,v 1.41 2008/05/30 09:58:28 hawking Exp $ 3# $Header: /var/cvsroot/gentoo-x86/eclass/python.eclass,v 1.74 2009/10/02 02:02:24 arfrever Exp $
4 4
5# @ECLASS: python.eclass 5# @ECLASS: python.eclass
6# @MAINTAINER: 6# @MAINTAINER:
7# python@gentoo.org 7# python@gentoo.org
8#
9# original author: Alastair Tse <liquidx@gentoo.org>
10# @BLURB: A Utility Eclass that should be inherited by anything that deals with Python or Python modules. 8# @BLURB: A utility eclass that should be inherited by anything that deals with Python or Python modules.
11# @DESCRIPTION: 9# @DESCRIPTION:
12# Some useful functions for dealing with python. 10# Some useful functions for dealing with Python.
13inherit alternatives multilib
14 11
12inherit multilib
15 13
16if [[ -n "${NEED_PYTHON}" ]] ; then 14if [[ -n "${NEED_PYTHON}" ]] ; then
17 DEPEND=">=dev-lang/python-${NEED_PYTHON}" 15 PYTHON_ATOM=">=dev-lang/python-${NEED_PYTHON}"
16 DEPEND="${PYTHON_ATOM}"
18 RDEPEND="${DEPEND}" 17 RDEPEND="${DEPEND}"
18else
19 PYTHON_ATOM="dev-lang/python"
19fi 20fi
21
22DEPEND+=" >=app-admin/eselect-python-20090804
23 >=app-shells/bash-3.2"
20 24
21__python_eclass_test() { 25__python_eclass_test() {
22 __python_version_extract 2.3 26 __python_version_extract 2.3
23 echo -n "2.3 -> PYVER: $PYVER PYVER_MAJOR: $PYVER_MAJOR" 27 echo -n "2.3 -> PYVER: $PYVER PYVER_MAJOR: $PYVER_MAJOR"
24 echo " PYVER_MINOR: $PYVER_MINOR PYVER_MICRO: $PYVER_MICRO" 28 echo " PYVER_MINOR: $PYVER_MINOR PYVER_MICRO: $PYVER_MICRO"
34 __python_version_extract 2.5b3 38 __python_version_extract 2.5b3
35 echo -n "2.5b3 -> PYVER: $PYVER PYVER_MAJOR: $PYVER_MAJOR" 39 echo -n "2.5b3 -> PYVER: $PYVER PYVER_MAJOR: $PYVER_MAJOR"
36 echo " PYVER_MINOR: $PYVER_MINOR PYVER_MICRO: $PYVER_MICRO" 40 echo " PYVER_MINOR: $PYVER_MINOR PYVER_MICRO: $PYVER_MICRO"
37} 41}
38 42
39# @FUNCTION: python_disable_pyc
40# @DESCRIPTION:
41# Tells python not to automatically recompile modules to .pyc/.pyo
42# even if the timestamps/version stamps don't match. This is done
43# to protect sandbox.
44#
45# note: supported by >=dev-lang/python-2.2.3-r3 only.
46#
47python_disable_pyc() {
48 export PYTHON_DONTCOMPILE=1
49}
50
51# @FUNCTION: python_enable_pyc
52# @DESCRIPTION:
53# Tells python to automatically recompile modules to .pyc/.pyo if the
54# timestamps/version stamps change
55python_enable_pyc() {
56 unset PYTHON_DONTCOMPILE
57}
58
59python_disable_pyc
60
61# @FUNCTION: python_version 43# @FUNCTION: python_version
62# @DESCRIPTION: 44# @DESCRIPTION:
63# Run without arguments and it will export the version of python 45# Run without arguments and it will export the version of python
64# currently in use as $PYVER; sets PYVER/PYVER_MAJOR/PYVER_MINOR 46# currently in use as $PYVER; sets PYVER/PYVER_MAJOR/PYVER_MINOR
65__python_version_extract() { 47__python_version_extract() {
66 verstr=$1 48 local verstr=$1
67 export PYVER_MAJOR=${verstr:0:1} 49 export PYVER_MAJOR=${verstr:0:1}
68 export PYVER_MINOR=${verstr:2:1} 50 export PYVER_MINOR=${verstr:2:1}
69 if [ "${verstr:3}x" = ".x" ]; then 51 if [[ ${verstr:3:1} == . ]]; then
70 export PYVER_MICRO=${verstr:4} 52 export PYVER_MICRO=${verstr:4}
71 fi 53 fi
72 export PYVER="${PYVER_MAJOR}.${PYVER_MINOR}" 54 export PYVER="${PYVER_MAJOR}.${PYVER_MINOR}"
73} 55}
74 56
75python_version() { 57python_version() {
58 [[ -n "${PYVER}" ]] && return 0
76 local tmpstr 59 local tmpstr
77 python=${python:-/usr/bin/python} 60 python=${python:-/usr/bin/python}
78 tmpstr="$(${python} -V 2>&1 )" 61 tmpstr="$(${python} -V 2>&1 )"
79 export PYVER_ALL="${tmpstr#Python }" 62 export PYVER_ALL="${tmpstr#Python }"
80 __python_version_extract $PYVER_ALL 63 __python_version_extract $PYVER_ALL
81} 64}
82 65
66# @FUNCTION: PYTHON
67# @USAGE: [-a|--absolute-path] [--] <Python_ABI="${PYTHON_ABI}">
68# @DESCRIPTION:
69# Get Python interpreter filename for specified Python ABI. If Python_ABI argument
70# is ommitted, then PYTHON_ABI environment variable must be set and is used.
71PYTHON() {
72 local absolute_path="0" slot=
73
74 while (($#)); do
75 case "$1" in
76 -a|--absolute-path)
77 absolute_path="1"
78 ;;
79 --)
80 break
81 ;;
82 -*)
83 die "${FUNCNAME}(): Unrecognized option $1"
84 ;;
85 *)
86 break
87 ;;
88 esac
89 shift
90 done
91
92 if [[ "$#" -eq "0" ]]; then
93 if [[ -n "${PYTHON_ABI}" ]]; then
94 slot="${PYTHON_ABI}"
95 else
96 die "${FUNCNAME}(): Invalid usage"
97 fi
98 elif [[ "$#" -eq "1" ]]; then
99 slot="$1"
100 else
101 die "${FUNCNAME}(): Invalid usage"
102 fi
103
104 if [[ "${absolute_path}" == "1" ]]; then
105 echo -n "/usr/bin/python${slot}"
106 else
107 echo -n "python${slot}"
108 fi
109}
110
111# @FUNCTION: validate_PYTHON_ABIS
112# @DESCRIPTION:
113# Make sure PYTHON_ABIS variable has valid value.
114validate_PYTHON_ABIS() {
115 # Ensure that some functions cannot be accidentally successfully used in EAPI <= 2 without setting SUPPORT_PYTHON_ABIS variable.
116 if has "${EAPI:-0}" 0 1 2 && [[ -z "${SUPPORT_PYTHON_ABIS}" ]]; then
117 die "${FUNCNAME}() cannot be used in this EAPI without setting SUPPORT_PYTHON_ABIS variable"
118 fi
119
120 # Ensure that /usr/bin/python and /usr/bin/python-config are valid.
121 if [[ "$(readlink /usr/bin/python)" != "python-wrapper" ]]; then
122 die "'/usr/bin/python' isn't valid symlink"
123 fi
124 if [[ "$(</usr/bin/python-config)" != *"Gentoo python-config wrapper script"* ]]; then
125 die "'/usr/bin/python-config' isn't valid script"
126 fi
127
128 # USE_${ABI_TYPE^^} and RESTRICT_${ABI_TYPE^^}_ABIS variables hopefully will be included in EAPI >= 4.
129 if [[ "$(declare -p PYTHON_ABIS 2> /dev/null)" != "declare -x PYTHON_ABIS="* ]] && has "${EAPI:-0}" 0 1 2 3; then
130 local ABI restricted_ABI support_ABI supported_PYTHON_ABIS=
131 PYTHON_ABI_SUPPORTED_VALUES="2.4 2.5 2.6 2.7 3.0 3.1 3.2"
132
133 if [[ "$(declare -p USE_PYTHON 2> /dev/null)" == "declare -x USE_PYTHON="* ]]; then
134 if [[ -z "${USE_PYTHON}" ]]; then
135 die "USE_PYTHON variable is empty"
136 fi
137
138 for ABI in ${USE_PYTHON}; do
139 if ! has "${ABI}" ${PYTHON_ABI_SUPPORTED_VALUES}; then
140 die "USE_PYTHON variable contains invalid value '${ABI}'"
141 fi
142 support_ABI="1"
143 for restricted_ABI in ${RESTRICT_PYTHON_ABIS}; do
144 if python -c "from fnmatch import fnmatch; exit(not fnmatch('${ABI}', '${restricted_ABI}'))"; then
145 support_ABI="0"
146 break
147 fi
148 done
149 [[ "${support_ABI}" == "1" ]] && supported_PYTHON_ABIS+=" ${ABI}"
150 done
151 export PYTHON_ABIS="${supported_PYTHON_ABIS# }"
152
153 if [[ -z "${PYTHON_ABIS//[${IFS}]/}" ]]; then
154 die "USE_PYTHON variable doesn't enable any version of Python supported by ${CATEGORY}/${PF}"
155 fi
156 else
157 local ABI python2_version= python2_supported_versions python3_version= python3_supported_versions restricted_ABI support_python_major_version
158
159 if has_version "=dev-lang/python-2*"; then
160 if [[ "$(readlink /usr/bin/python2)" != "python2."* ]]; then
161 die "'/usr/bin/python2' isn't valid symlink"
162 fi
163
164 python2_version="$(/usr/bin/python2 -c 'from sys import version_info; print(".".join([str(x) for x in version_info[:2]]))')"
165 python2_supported_versions="2.4 2.5 2.6 2.7"
166
167 for ABI in ${python2_supported_versions}; do
168 support_python_major_version="1"
169 for restricted_ABI in ${RESTRICT_PYTHON_ABIS}; do
170 if python -c "from fnmatch import fnmatch; exit(not fnmatch('${ABI}', '${restricted_ABI}'))"; then
171 support_python_major_version="0"
172 fi
173 done
174 [[ "${support_python_major_version}" == "1" ]] && break
175 done
176 if [[ "${support_python_major_version}" == "1" ]]; then
177 for restricted_ABI in ${RESTRICT_PYTHON_ABIS}; do
178 if python -c "from fnmatch import fnmatch; exit(not fnmatch('${python2_version}', '${restricted_ABI}'))"; then
179 die "Active version of Python 2 isn't supported by ${CATEGORY}/${PF}"
180 fi
181 done
182 else
183 python2_version=""
184 fi
185 fi
186
187 if has_version "=dev-lang/python-3*"; then
188 if [[ "$(readlink /usr/bin/python3)" != "python3."* ]]; then
189 die "'/usr/bin/python3' isn't valid symlink"
190 fi
191
192 python3_version="$(/usr/bin/python3 -c 'from sys import version_info; print(".".join([str(x) for x in version_info[:2]]))')"
193 python3_supported_versions="3.0 3.1 3.2"
194
195 for ABI in ${python3_supported_versions}; do
196 support_python_major_version="1"
197 for restricted_ABI in ${RESTRICT_PYTHON_ABIS}; do
198 if python -c "from fnmatch import fnmatch; exit(not fnmatch('${ABI}', '${restricted_ABI}'))"; then
199 support_python_major_version="0"
200 fi
201 done
202 [[ "${support_python_major_version}" == "1" ]] && break
203 done
204 if [[ "${support_python_major_version}" == "1" ]]; then
205 for restricted_ABI in ${RESTRICT_PYTHON_ABIS}; do
206 if python -c "from fnmatch import fnmatch; exit(not fnmatch('${python3_version}', '${restricted_ABI}'))"; then
207 die "Active version of Python 3 isn't supported by ${CATEGORY}/${PF}"
208 fi
209 done
210 else
211 python3_version=""
212 fi
213 fi
214
215 PYTHON_ABIS="${python2_version} ${python3_version}"
216 PYTHON_ABIS="${PYTHON_ABIS# }"
217 export PYTHON_ABIS="${PYTHON_ABIS% }"
218 fi
219 fi
220
221 local PYTHON_ABI
222 for PYTHON_ABI in ${PYTHON_ABIS}; do
223 # Ensure that appropriate Python version is installed.
224 if ! has_version "dev-lang/python:${PYTHON_ABI}"; then
225 die "dev-lang/python:${PYTHON_ABI} isn't installed"
226 fi
227
228 # Ensure that EPYTHON variable is respected.
229 if [[ "$(EPYTHON="$(PYTHON)" python -c 'from sys import version_info; print(".".join([str(x) for x in version_info[:2]]))')" != "${PYTHON_ABI}" ]]; then
230 die "'python' doesn't respect EPYTHON variable"
231 fi
232 done
233}
234
235# @FUNCTION: python_copy_sources
236# @USAGE: [--no-link] [--] [directory]
237# @DESCRIPTION:
238# Copy unpacked sources of given package for each Python ABI.
239python_copy_sources() {
240 local dir dirs=() no_link="0" PYTHON_ABI
241
242 while (($#)); do
243 case "$1" in
244 --no-link)
245 no_link="1"
246 ;;
247 --)
248 break
249 ;;
250 -*)
251 die "${FUNCNAME}(): Unrecognized option '$1'"
252 ;;
253 *)
254 break
255 ;;
256 esac
257 shift
258 done
259
260 if [[ "$#" -eq "0" ]]; then
261 if [[ "${WORKDIR}" == "${S}" ]]; then
262 die "${FUNCNAME}() cannot be used"
263 fi
264 dirs="${S}"
265 else
266 dirs="$@"
267 fi
268
269 validate_PYTHON_ABIS
270 for PYTHON_ABI in ${PYTHON_ABIS}; do
271 for dir in "${dirs[@]}"; do
272 if [[ "${no_link}" == "1" ]]; then
273 cp -pr "${dir}" "${dir}-${PYTHON_ABI}" > /dev/null || die "Copying of sources failed"
274 else
275 cp -lpr "${dir}" "${dir}-${PYTHON_ABI}" > /dev/null || die "Copying of sources failed"
276 fi
277 done
278 done
279}
280
281# @FUNCTION: python_set_build_dir_symlink
282# @USAGE: [directory="build"]
283# @DESCRIPTION:
284# Create build directory symlink.
285python_set_build_dir_symlink() {
286 local dir="$1"
287
288 [[ -z "${PYTHON_ABI}" ]] && die "PYTHON_ABI variable not set"
289 [[ -z "${dir}" ]] && dir="build"
290
291 # Don't delete preexistent directories.
292 rm -f "${dir}" || die "Deletion of '${dir}' failed"
293 ln -s "${dir}-${PYTHON_ABI}" "${dir}" || die "Creation of '${dir}' directory symlink failed"
294}
295
296# @FUNCTION: python_execute_function
297# @USAGE: [--action-message message] [-d|--default-function] [--failure-message message] [--nonfatal] [-q|--quiet] [-s|--separate-build-dirs] [--] <function> [arguments]
298# @DESCRIPTION:
299# Execute specified function for each value of PYTHON_ABIS, optionally passing additional
300# arguments. The specified function can use PYTHON_ABI and BUILDDIR variables.
301python_execute_function() {
302 local action action_message action_message_template= default_function="0" failure_message failure_message_template= function nonfatal="0" previous_directory previous_directory_stack previous_directory_stack_length PYTHON_ABI quiet="0" separate_build_dirs="0"
303
304 while (($#)); do
305 case "$1" in
306 --action-message)
307 action_message_template="$2"
308 shift
309 ;;
310 -d|--default-function)
311 default_function="1"
312 ;;
313 --failure-message)
314 failure_message_template="$2"
315 shift
316 ;;
317 --nonfatal)
318 nonfatal="1"
319 ;;
320 -q|--quiet)
321 quiet="1"
322 ;;
323 -s|--separate-build-dirs)
324 separate_build_dirs="1"
325 ;;
326 --)
327 break
328 ;;
329 -*)
330 die "${FUNCNAME}(): Unrecognized option '$1'"
331 ;;
332 *)
333 break
334 ;;
335 esac
336 shift
337 done
338
339 if [[ "${default_function}" == "0" ]]; then
340 if [[ "$#" -eq "0" ]]; then
341 die "${FUNCNAME}(): Missing function name"
342 fi
343 function="$1"
344 shift
345
346 if [[ -z "$(type -t "${function}")" ]]; then
347 die "${FUNCNAME}(): '${function}' function isn't defined"
348 fi
349 else
350 if [[ "$#" -ne "0" ]]; then
351 die "${FUNCNAME}(): '--default-function' option and function name cannot be specified simultaneously"
352 fi
353 if has "${EAPI:-0}" 0 1; then
354 die "${FUNCNAME}(): '--default-function' option cannot be used in this EAPI"
355 fi
356
357 if [[ "${EBUILD_PHASE}" == "configure" ]]; then
358 if has "${EAPI}" 2; then
359 python_default_function() {
360 econf
361 }
362 else
363 python_default_function() {
364 nonfatal econf
365 }
366 fi
367 elif [[ "${EBUILD_PHASE}" == "compile" ]]; then
368 python_default_function() {
369 emake
370 }
371 elif [[ "${EBUILD_PHASE}" == "test" ]]; then
372 python_default_function() {
373 if emake -j1 -n check &> /dev/null; then
374 emake -j1 check
375 elif emake -j1 -n test &> /dev/null; then
376 emake -j1 test
377 fi
378 }
379 elif [[ "${EBUILD_PHASE}" == "install" ]]; then
380 python_default_function() {
381 emake DESTDIR="${D}" install
382 }
383 else
384 die "${FUNCNAME}(): --default-function option cannot be used in this ebuild phase"
385 fi
386 function="python_default_function"
387 fi
388
389 if [[ "${quiet}" == "0" ]]; then
390 [[ "${EBUILD_PHASE}" == "setup" ]] && action="Setting up"
391 [[ "${EBUILD_PHASE}" == "unpack" ]] && action="Unpacking"
392 [[ "${EBUILD_PHASE}" == "prepare" ]] && action="Preparation"
393 [[ "${EBUILD_PHASE}" == "configure" ]] && action="Configuration"
394 [[ "${EBUILD_PHASE}" == "compile" ]] && action="Building"
395 [[ "${EBUILD_PHASE}" == "test" ]] && action="Testing"
396 [[ "${EBUILD_PHASE}" == "install" ]] && action="Installation"
397 [[ "${EBUILD_PHASE}" == "preinst" ]] && action="Preinstallation"
398 [[ "${EBUILD_PHASE}" == "postinst" ]] && action="Postinstallation"
399 [[ "${EBUILD_PHASE}" == "prerm" ]] && action="Preuninstallation"
400 [[ "${EBUILD_PHASE}" == "postrm" ]] && action="Postuninstallation"
401 fi
402
403 local RED GREEN BLUE NORMAL
404 if [[ "${NOCOLOR:-false}" =~ ^(false|no)$ ]]; then
405 RED=$'\e[1;31m'
406 GREEN=$'\e[1;32m'
407 BLUE=$'\e[1;34m'
408 NORMAL=$'\e[0m'
409 else
410 RED=
411 GREEN=
412 BLUE=
413 NORMAL=
414 fi
415
416 validate_PYTHON_ABIS
417 for PYTHON_ABI in ${PYTHON_ABIS}; do
418 if [[ "${quiet}" == "0" ]]; then
419 if [[ -n "${action_message_template}" ]]; then
420 action_message="$(eval echo -n "${action_message_template}")"
421 else
422 action_message="${action} of ${CATEGORY}/${PF} with Python ${PYTHON_ABI}..."
423 fi
424 echo " ${GREEN}*${NORMAL} ${BLUE}${action_message}${NORMAL}"
425 fi
426
427 if [[ "${separate_build_dirs}" == "1" ]]; then
428 export BUILDDIR="${S}-${PYTHON_ABI}"
429 pushd "${BUILDDIR}" > /dev/null || die "pushd failed"
430 else
431 export BUILDDIR="${S}"
432 fi
433
434 previous_directory="$(pwd)"
435 previous_directory_stack="$(dirs -p)"
436 previous_directory_stack_length="$(dirs -p | wc -l)"
437
438 if ! has "${EAPI}" 0 1 2 && has "${PYTHON_ABI}" ${FAILURE_TOLERANT_PYTHON_ABIS}; then
439 EPYTHON="$(PYTHON)" nonfatal "${function}" "$@"
440 else
441 EPYTHON="$(PYTHON)" "${function}" "$@"
442 fi
443
444 if [[ "$?" != "0" ]]; then
445 if [[ -n "${failure_message_template}" ]]; then
446 failure_message="$(eval echo -n "${failure_message_template}")"
447 else
448 failure_message="${action} failed with Python ${PYTHON_ABI} in ${function}() function"
449 fi
450
451 if [[ "${nonfatal}" == "1" ]]; then
452 if [[ "${quiet}" == "0" ]]; then
453 ewarn "${RED}${failure_message}${NORMAL}"
454 fi
455 elif has "${PYTHON_ABI}" ${FAILURE_TOLERANT_PYTHON_ABIS}; then
456 if [[ "${EBUILD_PHASE}" != "test" ]] || ! has test-fail-continue ${FEATURES}; then
457 local ABI enabled_PYTHON_ABIS=
458 for ABI in ${PYTHON_ABIS}; do
459 [[ "${ABI}" != "${PYTHON_ABI}" ]] && enabled_PYTHON_ABIS+=" ${ABI}"
460 done
461 export PYTHON_ABIS="${enabled_PYTHON_ABIS# }"
462 fi
463 if [[ "${quiet}" == "0" ]]; then
464 ewarn "${RED}${failure_message}${NORMAL}"
465 fi
466 if [[ -z "${PYTHON_ABIS}" ]]; then
467 die "${function}() function failed with all enabled versions of Python"
468 fi
469 else
470 die "${failure_message}"
471 fi
472 fi
473
474 # Ensure that directory stack hasn't been decreased.
475 if [[ "$(dirs -p | wc -l)" -lt "${previous_directory_stack_length}" ]]; then
476 die "Directory stack decreased illegally"
477 fi
478
479 # Avoid side effects of earlier returning from the specified function.
480 while [[ "$(dirs -p | wc -l)" -gt "${previous_directory_stack_length}" ]]; do
481 popd > /dev/null || die "popd failed"
482 done
483
484 # Ensure that the bottom part of directory stack hasn't been changed. Restore
485 # previous directory (from before running of the specified function) before
486 # comparison of directory stacks to avoid mismatch of directory stacks after
487 # potential using of 'cd' to change current directory. Restoration of previous
488 # directory allows to safely use 'cd' to change current directory in the
489 # specified function without changing it back to original directory.
490 cd "${previous_directory}"
491 if [[ "$(dirs -p)" != "${previous_directory_stack}" ]]; then
492 die "Directory stack changed illegally"
493 fi
494
495 if [[ "${separate_build_dirs}" == "1" ]]; then
496 popd > /dev/null || die "popd failed"
497 fi
498 unset BUILDDIR
499 done
500
501 if [[ "${default_function}" == "1" ]]; then
502 unset -f python_default_function
503 fi
504}
505
506
507# @ECLASS-VARIABLE: PYTHON_USE_WITH
508# @DESCRIPTION:
509# Set this to a space separated list of use flags
510# the python slot in use must be built with.
511
512# @ECLASS-VARIABLE: PYTHON_USE_WITH_OR
513# @DESCRIPTION:
514# Set this to a space separated list of use flags
515# of which one must be turned on for the slot of
516# in use.
517
518# @ECLASS-VARIABLE: PYTHON_USE_WITH_OPT
519# @DESCRIPTION:
520# Set this if you need to make either PYTHON_USE_WITH or
521# PYTHON_USE_WITH_OR atoms conditional under a use flag.
522
523# @FUNCTION: python_pkg_setup
524# @DESCRIPTION:
525# Makes sure PYTHON_USE_WITH or PYTHON_USE_WITH_OR listed use flags
526# are respected. Only exported if one of those variables is set.
527if ! has "${EAPI:-0}" 0 1 && [[ -n ${PYTHON_USE_WITH} || -n ${PYTHON_USE_WITH_OR} ]]; then
528 python_pkg_setup() {
529 python_pkg_setup_fail() {
530 eerror "${1}"
531 die "${1}"
532 }
533
534 [[ ${PYTHON_USE_WITH_OPT} ]] && use !${PYTHON_USE_WITH_OPT} && return
535
536 python_pkg_setup_check_USE_flags() {
537 local pyatom use
538 if [[ -n "${PYTHON_ABI}" ]]; then
539 pyatom="dev-lang/python:${PYTHON_ABI}"
540 else
541 python_version
542 pyatom="dev-lang/python:${PYVER}"
543 fi
544
545 for use in ${PYTHON_USE_WITH}; do
546 if ! has_version "${pyatom}[${use}]"; then
547 python_pkg_setup_fail "Please rebuild ${pyatom} with the following USE flags enabled: ${PYTHON_USE_WITH}"
548 fi
549 done
550
551 for use in ${PYTHON_USE_WITH_OR}; do
552 if has_version "${pyatom}[${use}]"; then
553 return
554 fi
555 done
556
557 if [[ ${PYTHON_USE_WITH_OR} ]]; then
558 python_pkg_setup_fail "Please rebuild ${pyatom} with at least one of the following USE flags enabled: ${PYTHON_USE_WITH_OR}"
559 fi
560 }
561
562 if ! has "${EAPI:-0}" 0 1 2 || [[ -n "${SUPPORT_PYTHON_ABIS}" ]]; then
563 python_execute_function -q python_pkg_setup_check_USE_flags
564 else
565 python_pkg_setup_check_USE_flags
566 fi
567 }
568
569 EXPORT_FUNCTIONS pkg_setup
570
571 if [[ -n "${PYTHON_USE_WITH}" ]]; then
572 PYTHON_USE_WITH_ATOM="${PYTHON_ATOM}[${PYTHON_USE_WITH/ /,}]"
573 elif [[ -n "${PYTHON_USE_WITH_OR}" ]]; then
574 PYTHON_USE_WITH_ATOM="|| ( "
575 for use in ${PYTHON_USE_WITH_OR}; do
576 PYTHON_USE_WITH_ATOM+=" ${PYTHON_ATOM}[${use}]"
577 done
578 unset use
579 PYTHON_USE_WITH_ATOM+=" )"
580 fi
581 if [[ -n "${PYTHON_USE_WITH_OPT}" ]]; then
582 PYTHON_USE_WITH_ATOM="${PYTHON_USE_WITH_OPT}? ( ${PYTHON_USE_WITH_ATOM} )"
583 fi
584 DEPEND+=" ${PYTHON_USE_WITH_ATOM}"
585 RDEPEND+=" ${PYTHON_USE_WITH_ATOM}"
586fi
587
588# @ECLASS-VARIABLE: PYTHON_DEFINE_DEFAULT_FUNCTIONS
589# @DESCRIPTION:
590# Set this to define default functions for the following ebuild phases:
591# src_prepare, src_configure, src_compile, src_test, src_install.
592if ! has "${EAPI:-0}" 0 1 && [[ -n "${PYTHON_DEFINE_DEFAULT_FUNCTIONS}" ]]; then
593 python_src_prepare() {
594 python_copy_sources
595 }
596
597 for python_default_function in src_configure src_compile src_test src_install; do
598 eval "python_${python_default_function}() { python_execute_function -d -s; }"
599 done
600 unset python_default_function
601
602 EXPORT_FUNCTIONS src_prepare src_configure src_compile src_test src_install
603fi
604
605# @FUNCTION: python_disable_pyc
606# @DESCRIPTION:
607# Tell Python not to automatically recompile modules to .pyc/.pyo
608# even if the timestamps/version stamps don't match. This is done
609# to protect sandbox.
610python_disable_pyc() {
611 export PYTHONDONTWRITEBYTECODE="1"
612}
613
83# @FUNCTION: python_makesym 614# @FUNCTION: python_enable_pyc
84# @DESCRIPTION: 615# @DESCRIPTION:
85# Run without arguments, it will create the /usr/bin/python symlinks 616# Tell Python to automatically recompile modules to .pyc/.pyo if the
86# to the latest installed version 617# timestamps/version stamps have changed.
87python_makesym() { 618python_enable_pyc() {
88 alternatives_auto_makesym "/usr/bin/python" "python[0-9].[0-9]" 619 unset PYTHONDONTWRITEBYTECODE
89 alternatives_auto_makesym "/usr/bin/python2" "python2.[0-9]" 620}
621
622python_disable_pyc
623
624# @FUNCTION: python_need_rebuild
625# @DESCRIPTION: Run without arguments, specifies that the package should be
626# rebuilt after a python upgrade.
627python_need_rebuild() {
628 python_version
629 export PYTHON_NEED_REBUILD=${PYVER}
630}
631
632# @FUNCTION: python_get_includedir
633# @DESCRIPTION:
634# Run without arguments, returns the Python include directory.
635python_get_includedir() {
636 if [[ -n "${PYTHON_ABI}" ]]; then
637 echo "/usr/include/python${PYTHON_ABI}"
638 else
639 python_version
640 echo "/usr/include/python${PYVER}"
641 fi
642}
643
644# @FUNCTION: python_get_libdir
645# @DESCRIPTION:
646# Run without arguments, returns the Python library directory.
647python_get_libdir() {
648 if [[ -n "${PYTHON_ABI}" ]]; then
649 echo "/usr/$(get_libdir)/python${PYTHON_ABI}"
650 else
651 python_version
652 echo "/usr/$(get_libdir)/python${PYVER}"
653 fi
654}
655
656# @FUNCTION: python_get_sitedir
657# @DESCRIPTION:
658# Run without arguments, returns the Python site-packages directory.
659python_get_sitedir() {
660 echo "$(python_get_libdir)/site-packages"
90} 661}
91 662
92# @FUNCTION: python_tkinter_exists 663# @FUNCTION: python_tkinter_exists
93# @DESCRIPTION: 664# @DESCRIPTION:
94# Run without arguments, checks if python was compiled with Tkinter 665# Run without arguments, checks if python was compiled with Tkinter
102 die "missing tkinter support with installed python" 673 die "missing tkinter support with installed python"
103 fi 674 fi
104} 675}
105 676
106# @FUNCTION: python_mod_exists 677# @FUNCTION: python_mod_exists
107# @USAGE: < module > 678# @USAGE: <module>
108# @DESCRIPTION: 679# @DESCRIPTION:
109# Run with the module name as an argument. it will check if a 680# Run with the module name as an argument. it will check if a
110# python module is installed and loadable. it will return 681# python module is installed and loadable. it will return
111# TRUE(0) if the module exists, and FALSE(1) if the module does 682# TRUE(0) if the module exists, and FALSE(1) if the module does
112# not exist. 683# not exist.
114# Example: 685# Example:
115# if python_mod_exists gtk; then 686# if python_mod_exists gtk; then
116# echo "gtk support enabled" 687# echo "gtk support enabled"
117# fi 688# fi
118python_mod_exists() { 689python_mod_exists() {
119 [ -z "$1" ] && die "${FUNCTION} requires an argument!" 690 [[ "$1" ]] || die "${FUNCNAME} requires an argument!"
120 if ! python -c "import $1" >/dev/null 2>&1; then 691 python -c "import $1" &>/dev/null
121 return 1
122 fi
123 return 0
124} 692}
125 693
126# @FUNCTION: python_mod_compile 694# @FUNCTION: python_mod_compile
127# @USAGE: < file > [more files ...] 695# @USAGE: <file> [more files ...]
128# @DESCRIPTION: 696# @DESCRIPTION:
129# Given filenames, it will pre-compile the module's .pyc and .pyo. 697# Given filenames, it will pre-compile the module's .pyc and .pyo.
130# This function should only be run in pkg_postinst() 698# This function should only be run in pkg_postinst()
131# 699#
132# Example: 700# Example:
133# python_mod_compile /usr/lib/python2.3/site-packages/pygoogle.py 701# python_mod_compile /usr/lib/python2.3/site-packages/pygoogle.py
134# 702#
135python_mod_compile() { 703python_mod_compile() {
136 local f myroot 704 if ! has "${EAPI:-0}" 0 1 2 || [[ -n "${SUPPORT_PYTHON_ABIS}" ]]; then
705 die "${FUNCNAME}() cannot be used in this EAPI"
706 fi
707
708 local f myroot myfiles=()
137 709
138 # Check if phase is pkg_postinst() 710 # Check if phase is pkg_postinst()
139 [[ ${EBUILD_PHASE} != postinst ]] &&\ 711 [[ ${EBUILD_PHASE} != postinst ]] &&\
140 die "${FUNCNAME} should only be run in pkg_postinst()" 712 die "${FUNCNAME} should only be run in pkg_postinst()"
141 713
142 # allow compiling for older python versions 714 # allow compiling for older python versions
143 if [ -n "${PYTHON_OVERRIDE_PYVER}" ]; then 715 if [[ "${PYTHON_OVERRIDE_PYVER}" ]]; then
144 PYVER=${PYTHON_OVERRIDE_PYVER} 716 PYVER=${PYTHON_OVERRIDE_PYVER}
145 else 717 else
146 python_version 718 python_version
147 fi 719 fi
148 720
149 # strip trailing slash 721 # strip trailing slash
150 myroot="${ROOT%/}" 722 myroot="${ROOT%/}"
151 723
152 # respect ROOT 724 # respect ROOT
153 for f in $@; do 725 for f in "$@"; do
154 [ -f "${myroot}/${f}" ] && myfiles="${myfiles} ${myroot}/${f}" 726 [[ -f "${myroot}/${f}" ]] && myfiles+=("${myroot}/${f}")
155 done 727 done
156 728
157 if [ -n "${myfiles}" ]; then 729 if ((${#myfiles[@]})); then
158 python${PYVER} ${myroot}/usr/$(get_libdir)/python${PYVER}/py_compile.py ${myfiles} 730 python${PYVER} ${myroot}/usr/$(get_libdir)/python${PYVER}/py_compile.py "${myfiles[@]}"
159 python${PYVER} -O ${myroot}/usr/$(get_libdir)/python${PYVER}/py_compile.py ${myfiles} 731 python${PYVER} -O ${myroot}/usr/$(get_libdir)/python${PYVER}/py_compile.py "${myfiles[@]}" &> /dev/null
160 else 732 else
161 ewarn "No files to compile!" 733 ewarn "No files to compile!"
162 fi 734 fi
163} 735}
164 736
165# @FUNCTION: python_mod_optimize 737# @FUNCTION: python_mod_optimize
166# @USAGE: [ path ] 738# @USAGE: [options] [directory|file]
167# @DESCRIPTION: 739# @DESCRIPTION:
168# If no arguments supplied, it will recompile all modules under 740# If no arguments supplied, it will recompile not recursively all modules
169# sys.path (eg. /usr/lib/python2.3, /usr/lib/python2.3/site-packages/ ..) 741# under sys.path (eg. /usr/lib/python2.6, /usr/lib/python2.6/site-packages).
170# no recursively
171# 742#
172# If supplied with arguments, it will recompile all modules recursively 743# If supplied with arguments, it will recompile all modules recursively
173# in the supplied directory 744# in the supplied directory.
174# This function should only be run in pkg_postinst() 745# This function should only be run in pkg_postinst().
175# 746#
176# Options passed to this function are passed to compileall.py 747# Options passed to this function are passed to compileall.py.
177# 748#
178# Example: 749# Example:
179# python_mod_optimize /usr/share/codegen 750# python_mod_optimize ctypesgencore
180python_mod_optimize() { 751python_mod_optimize() {
181 local mydirs myfiles myroot myopts
182
183 # Check if phase is pkg_postinst() 752 # Check if phase is pkg_postinst().
184 [[ ${EBUILD_PHASE} != postinst ]] &&\ 753 [[ ${EBUILD_PHASE} != "postinst" ]] && die "${FUNCNAME} should only be run in pkg_postinst()"
185 die "${FUNCNAME} should only be run in pkg_postinst()"
186 754
755 if ! has "${EAPI:-0}" 0 1 2 || [[ -n "${SUPPORT_PYTHON_ABIS}" ]]; then
756 local dir file options=() other_dirs=() other_files=() PYTHON_ABI return_code root site_packages_absolute_dirs=() site_packages_dirs=() site_packages_absolute_files=() site_packages_files=()
757
758 # Strip trailing slash from ROOT.
759 root="${ROOT%/}"
760
761 # Respect ROOT and options passed to compileall.py.
762 while (($#)); do
763 case "$1" in
764 -l|-f|-q)
765 options+=("$1")
766 ;;
767 -d|-x)
768 options+=("$1" "$2")
769 shift
770 ;;
771 -*)
772 ewarn "${FUNCNAME}: Ignoring compile option $1"
773 ;;
774 *)
775 if [[ "$1" =~ ^/usr/lib(32|64)?/python[[:digit:]]+\.[[:digit:]]+ ]]; then
776 die "${FUNCNAME} doesn't support absolute paths of directories/files in site-packages directories"
777 elif [[ "$1" =~ ^/ ]]; then
778 if [[ -d "${root}/$1" ]]; then
779 other_dirs+=("${root}/$1")
780 elif [[ -f "${root}/$1" ]]; then
781 other_files+=("${root}/$1")
782 elif [[ -e "${root}/$1" ]]; then
783 ewarn "'${root}/$1' is not a file or a directory!"
784 else
785 ewarn "'${root}/$1' doesn't exist!"
786 fi
787 else
788 for PYTHON_ABI in ${PYTHON_ABIS}; do
789 if [[ -d "${root}$(python_get_sitedir)/$1" ]]; then
790 site_packages_dirs+=("$1")
791 break
792 elif [[ -f "${root}$(python_get_sitedir)/$1" ]]; then
793 site_packages_files+=("$1")
794 break
795 elif [[ -e "${root}$(python_get_sitedir)/$1" ]]; then
796 ewarn "'$1' is not a file or a directory!"
797 else
798 ewarn "'$1' doesn't exist!"
799 fi
800 done
801 fi
802 ;;
803 esac
804 shift
805 done
806
807 # Set additional options.
808 options+=("-q")
809
810 for PYTHON_ABI in ${PYTHON_ABIS}; do
811 if ((${#site_packages_dirs[@]})) || ((${#site_packages_files[@]})); then
812 return_code="0"
813 ebegin "Compilation and optimization of Python modules for Python ${PYTHON_ABI}"
814 if ((${#site_packages_dirs[@]})); then
815 for dir in "${site_packages_dirs[@]}"; do
816 site_packages_absolute_dirs+=("${root}$(python_get_sitedir)/${dir}")
817 done
818 "$(PYTHON)" "${root}$(python_get_libdir)/compileall.py" "${options[@]}" "${site_packages_absolute_dirs[@]}" || return_code="1"
819 "$(PYTHON)" -O "${root}$(python_get_libdir)/compileall.py" "${options[@]}" "${site_packages_absolute_dirs[@]}" &> /dev/null || return_code="1"
820 fi
821 if ((${#site_packages_files[@]})); then
822 for file in "${site_packages_files[@]}"; do
823 site_packages_absolute_files+=("${root}$(python_get_sitedir)/${file}")
824 done
825 "$(PYTHON)" "${root}$(python_get_libdir)/py_compile.py" "${site_packages_absolute_files[@]}" || return_code="1"
826 "$(PYTHON)" -O "${root}$(python_get_libdir)/py_compile.py" "${site_packages_absolute_files[@]}" &> /dev/null || return_code="1"
827 fi
828 eend "${return_code}"
829 fi
830 unset site_packages_absolute_dirs site_packages_absolute_files
831 done
832
833 # Don't use PYTHON_ABI in next calls to python_get_libdir().
834 unset PYTHON_ABI
835
836 if ((${#other_dirs[@]})) || ((${#other_files[@]})); then
837 return_code="0"
838 ebegin "Compilation and optimization of Python modules placed outside of site-packages directories for Python ${PYVER}..."
839 if ((${#other_dirs[@]})); then
840 python${PYVER} "${root}$(python_get_libdir)/compileall.py" "${options[@]}" "${other_dirs[@]}" || return_code="1"
841 python${PYVER} -O "${root}$(python_get_libdir)/compileall.py" "${options[@]}" "${other_dirs[@]}" &> /dev/null || return_code="1"
842 fi
843 if ((${#other_files[@]})); then
844 python${PYVER} "${root}$(python_get_libdir)/py_compile.py" "${other_files[@]}" || return_code="1"
845 python${PYVER} -O "${root}$(python_get_libdir)/py_compile.py" "${other_files[@]}" &> /dev/null || return_code="1"
846 fi
847 eend "${return_code}"
848 fi
849 else
850 local myroot mydirs=() myfiles=() myopts=() return_code="0"
851
187 # strip trailing slash 852 # strip trailing slash
188 myroot="${ROOT%/}" 853 myroot="${ROOT%/}"
189 854
190 # respect ROOT and options passed to compileall.py 855 # respect ROOT and options passed to compileall.py
191 while [ $# -gt 0 ]; do 856 while (($#)); do
192 case $1 in 857 case "$1" in
193 -l|-f|-q) 858 -l|-f|-q)
194 myopts="${myopts} $1" 859 myopts+=("$1")
195 ;; 860 ;;
196 -d|-x) 861 -d|-x)
197 myopts="${myopts} $1 $2" 862 myopts+=("$1" "$2")
863 shift
864 ;;
865 -*)
866 ewarn "${FUNCNAME}: Ignoring compile option $1"
867 ;;
868 *)
869 if [[ -d "${myroot}"/$1 ]]; then
870 mydirs+=("${myroot}/$1")
871 elif [[ -f "${myroot}"/$1 ]]; then
872 # Files are passed to python_mod_compile which is ROOT-aware
873 myfiles+=("$1")
874 elif [[ -e "${myroot}/$1" ]]; then
875 ewarn "${myroot}/$1 is not a file or directory!"
876 else
877 ewarn "${myroot}/$1 doesn't exist!"
878 fi
879 ;;
880 esac
881 shift
882 done
883
884 # allow compiling for older python versions
885 if [ -n "${PYTHON_OVERRIDE_PYVER}" ]; then
886 PYVER=${PYTHON_OVERRIDE_PYVER}
887 else
888 python_version
889 fi
890
891 # set additional opts
892 myopts+=(-q)
893
894 ebegin "Byte compiling python modules for python-${PYVER} .."
895 if ((${#mydirs[@]})); then
896 python${PYVER} \
897 "${myroot}"/usr/$(get_libdir)/python${PYVER}/compileall.py \
898 "${myopts[@]}" "${mydirs[@]}" || return_code="1"
899 python${PYVER} -O \
900 "${myroot}"/usr/$(get_libdir)/python${PYVER}/compileall.py \
901 "${myopts[@]}" "${mydirs[@]}" &> /dev/null || return_code="1"
902 fi
903
904 if ((${#myfiles[@]})); then
905 python_mod_compile "${myfiles[@]}"
906 fi
907
908 eend "${return_code}"
909 fi
910}
911
912# @FUNCTION: python_mod_cleanup
913# @USAGE: [directory]
914# @DESCRIPTION:
915# Run with optional arguments, where arguments are directories of
916# python modules. If none given, it will look in /usr/lib/python[0-9].[0-9].
917#
918# It will recursively scan all compiled Python modules in the directories and
919# determine if they are orphaned (i.e. their corresponding .py files are missing.)
920# If they are, then it will remove their corresponding .pyc and .pyo files.
921#
922# This function should only be run in pkg_postrm().
923python_mod_cleanup() {
924 local PYTHON_ABI SEARCH_PATH=() root src_py
925
926 # Check if phase is pkg_postrm().
927 [[ ${EBUILD_PHASE} != "postrm" ]] && die "${FUNCNAME} should only be run in pkg_postrm()"
928
929 # Strip trailing slash from ROOT.
930 root="${ROOT%/}"
931
932 if (($#)); then
933 if ! has "${EAPI:-0}" 0 1 2 || [[ -n "${SUPPORT_PYTHON_ABIS}" ]]; then
934 while (($#)); do
935 if [[ "$1" =~ ^/usr/lib(32|64)?/python[[:digit:]]+\.[[:digit:]]+ ]]; then
936 die "${FUNCNAME} doesn't support absolute paths of directories/files in site-packages directories"
937 elif [[ "$1" =~ ^/ ]]; then
938 SEARCH_PATH+=("${root}/${1#/}")
939 else
940 for PYTHON_ABI in ${PYTHON_ABIS}; do
941 SEARCH_PATH+=("${root}$(python_get_sitedir)/$1")
942 done
943 fi
198 shift 944 shift
199 ;;
200 -*)
201 ewarn "${FUNCNAME}: Ignoring compile option $1"
202 ;;
203 *)
204 [ ! -e "${myroot}/${1}" ] && ewarn "${myroot}/${1} doesn't exist!"
205 [ -d "${myroot}/${1#/}" ] && mydirs="${mydirs} ${myroot}/${1#/}"
206 # Files are passed to python_mod_compile which is ROOT-aware
207 [ -f "${myroot}/${1}" ] && myfiles="${myfiles} ${1}"
208 ;;
209 esac
210 shift
211 done 945 done
212
213 # allow compiling for older python versions
214 if [ -n "${PYTHON_OVERRIDE_PYVER}" ]; then
215 PYVER=${PYTHON_OVERRIDE_PYVER}
216 else 946 else
217 python_version 947 SEARCH_PATH=("${@#/}")
948 SEARCH_PATH=("${SEARCH_PATH[@]/#/${root}/}")
218 fi 949 fi
219 950 else
220 # set additional opts 951 SEARCH_PATH=("${root}"/usr/lib*/python*/site-packages)
221 myopts="${myopts} -q"
222
223 ebegin "Byte compiling python modules for python-${PYVER} .."
224 if [ -n "${mydirs}" ]; then
225 python${PYVER} \
226 ${myroot}/usr/$(get_libdir)/python${PYVER}/compileall.py \
227 ${myopts} ${mydirs}
228 python${PYVER} -O \
229 ${myroot}/usr/$(get_libdir)/python${PYVER}/compileall.py \
230 ${myopts} ${mydirs}
231 fi 952 fi
232 953
233 if [ -n "${myfiles}" ]; then 954 for path in "${SEARCH_PATH[@]}"; do
234 python_mod_compile ${myfiles} 955 [[ ! -d "${path}" ]] && continue
235 fi 956 einfo "Cleaning orphaned Python bytecode from ${path} .."
236 957 find "${path}" -name '*.py[co]' -print0 | while read -rd ''; do
237 eend $? 958 src_py="${REPLY%[co]}"
238} 959 [[ -f "${src_py}" || (! -f "${src_py}c" && ! -f "${src_py}o") ]] && continue
239 960 einfo "Purging ${src_py}[co]"
240# @FUNCTION: python_mod_cleanup 961 rm -f "${src_py}"[co]
241# @USAGE: [ dir ]
242# @DESCRIPTION:
243# Run with optional arguments, where arguments are directories of
244# python modules. if none given, it will look in /usr/lib/python[0-9].[0-9]
245#
246# It will recursively scan all compiled python modules in the directories
247# and determine if they are orphaned (eg. their corresponding .py is missing.)
248# if they are, then it will remove their corresponding .pyc and .pyo
249#
250# This function should only be run in pkg_postrm()
251python_mod_cleanup() {
252 local SEARCH_PATH myroot
253
254 # Check if phase is pkg_postrm()
255 [[ ${EBUILD_PHASE} != postrm ]] &&\
256 die "${FUNCNAME} should only be run in pkg_postrm()"
257
258 # strip trailing slash
259 myroot="${ROOT%/}"
260
261 if [ $# -gt 0 ]; then
262 for path in $@; do
263 SEARCH_PATH="${SEARCH_PATH} ${myroot}/${path#/}"
264 done 962 done
265 else
266 for path in ${myroot}/usr/lib*/python*/site-packages; do
267 SEARCH_PATH="${SEARCH_PATH} ${path}"
268 done
269 fi
270 963
271 for path in ${SEARCH_PATH}; do
272 einfo "Cleaning orphaned Python bytecode from ${path} .."
273 for obj in $(find ${path} -name '*.py[co]'); do
274 src_py="${obj%[co]}"
275 if [ ! -f "${src_py}" ]; then
276 einfo "Purging ${src_py}[co]"
277 rm -f ${src_py}[co]
278 fi
279 done
280 # attempt to remove directories that maybe empty 964 # Attempt to remove directories that may be empty.
281 for dir in $(find ${path} -type d | sort -r); do 965 find "${path}" -type d | sort -r | while read -r dir; do
282 rmdir ${dir} 2>/dev/null 966 rmdir "${dir}" 2>/dev/null && einfo "Removing empty directory ${dir}"
283 done 967 done
284 done 968 done
285} 969}

Legend:
Removed from v.1.41  
changed lines
  Added in v.1.74

  ViewVC Help
Powered by ViewVC 1.1.20