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

Diff of /eclass/python.eclass

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

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

Legend:
Removed from v.1.40  
changed lines
  Added in v.1.72

  ViewVC Help
Powered by ViewVC 1.1.20