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

Diff of /eclass/python.eclass

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

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

Legend:
Removed from v.1.53  
changed lines
  Added in v.1.75

  ViewVC Help
Powered by ViewVC 1.1.20