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

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

  ViewVC Help
Powered by ViewVC 1.1.20