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

Diff of /eclass/python.eclass

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

Revision 1.39 Revision 1.71
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.39 2008/05/29 21:19:19 hawking Exp $ 3# $Header: /var/cvsroot/gentoo-x86/eclass/python.eclass,v 1.71 2009/09/09 04:16:58 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" 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 if ! has "${EAPI}" 0 1 2 && has "${PYTHON_ABI}" ${FAILURE_TOLERANT_PYTHON_ABIS}; then
387 EPYTHON="$(PYTHON)" nonfatal "${function}" "$@"
388 else
389 EPYTHON="$(PYTHON)" "${function}" "$@"
390 fi
391
392 if [[ "$?" != "0" ]]; then
393 if [[ -n "${failure_message_template}" ]]; then
394 failure_message="$(eval echo -n "${failure_message_template}")"
395 else
396 failure_message="${action} failed with Python ${PYTHON_ABI} in ${function}() function"
397 fi
398
399 if [[ "${nonfatal}" == "1" ]]; then
400 if [[ "${quiet}" == "0" ]]; then
401 ewarn "${RED}${failure_message}${NORMAL}"
402 fi
403 elif has "${PYTHON_ABI}" ${FAILURE_TOLERANT_PYTHON_ABIS}; then
404 if [[ "${EBUILD_PHASE}" != "test" ]] || ! has test-fail-continue ${FEATURES}; then
405 local ABI enabled_PYTHON_ABIS=
406 for ABI in ${PYTHON_ABIS}; do
407 [[ "${ABI}" != "${PYTHON_ABI}" ]] && enabled_PYTHON_ABIS+=" ${ABI}"
408 done
409 export PYTHON_ABIS="${enabled_PYTHON_ABIS# }"
410 fi
411 if [[ "${quiet}" == "0" ]]; then
412 ewarn "${RED}${failure_message}${NORMAL}"
413 fi
414 if [[ -z "${PYTHON_ABIS}" ]]; then
415 die "${function}() function failed with all enabled versions of Python"
416 fi
417 else
418 die "${failure_message}"
419 fi
420 fi
421
422 if [[ "${separate_build_dirs}" == "1" ]]; then
423 popd > /dev/null || die "popd failed"
424 fi
425 unset BUILDDIR
426 done
427
428 if [[ "${default_function}" == "1" ]]; then
429 unset -f python_default_function
430 fi
431}
432
433
434# @ECLASS-VARIABLE: PYTHON_USE_WITH
435# @DESCRIPTION:
436# Set this to a space separated list of use flags
437# the python slot in use must be built with.
438
439# @ECLASS-VARIABLE: PYTHON_USE_WITH_OR
440# @DESCRIPTION:
441# Set this to a space separated list of use flags
442# of which one must be turned on for the slot of
443# in use.
444
445# @ECLASS-VARIABLE: PYTHON_USE_WITH_OPT
446# @DESCRIPTION:
447# Set this if you need to make either PYTHON_USE_WITH or
448# PYTHON_USE_WITH_OR atoms conditional under a use flag.
449
450# @FUNCTION: python_pkg_setup
451# @DESCRIPTION:
452# Makes sure PYTHON_USE_WITH or PYTHON_USE_WITH_OR listed use flags
453# are respected. Only exported if one of those variables is set.
454if ! has "${EAPI:-0}" 0 1 && [[ -n ${PYTHON_USE_WITH} || -n ${PYTHON_USE_WITH_OR} ]]; then
455 python_pkg_setup_fail() {
456 eerror "${1}"
457 die "${1}"
458 }
459
460 python_pkg_setup() {
461 [[ ${PYTHON_USE_WITH_OPT} ]] && use !${PYTHON_USE_WITH_OPT} && return
462
463 python_version
464 local failed
465 local pyatom="dev-lang/python:${PYVER}"
466
467 for use in ${PYTHON_USE_WITH}; do
468 if ! has_version "${pyatom}[${use}]"; then
469 python_pkg_setup_fail \
470 "Please rebuild ${pyatom} with use flags: ${PYTHON_USE_WITH}"
471 fi
472 done
473
474 for use in ${PYTHON_USE_WITH_OR}; do
475 if has_version "${pyatom}[${use}]"; then
476 return
477 fi
478 done
479
480 if [[ ${PYTHON_USE_WITH_OR} ]]; then
481 python_pkg_setup_fail \
482 "Please rebuild ${pyatom} with one of: ${PYTHON_USE_WITH_OR}"
483 fi
484 }
485
486 EXPORT_FUNCTIONS pkg_setup
487
488 if [[ ${PYTHON_USE_WITH} ]]; then
489 PYTHON_USE_WITH_ATOM="${PYTHON_ATOM}[${PYTHON_USE_WITH/ /,}]"
490 elif [[ ${PYTHON_USE_WITH_OR} ]]; then
491 PYTHON_USE_WITH_ATOM="|| ( "
492 for use in ${PYTHON_USE_WITH_OR}; do
493 PYTHON_USE_WITH_ATOM="
494 ${PYTHON_USE_WITH_ATOM}
495 ${PYTHON_ATOM}[${use}]"
496 done
497 PYTHON_USE_WITH_ATOM="${PYTHON_USE_WITH_ATOM} )"
498 fi
499 if [[ ${PYTHON_USE_WITH_OPT} ]]; then
500 PYTHON_USE_WITH_ATOM="${PYTHON_USE_WITH_OPT}? ( ${PYTHON_USE_WITH_ATOM} )"
501 fi
502 DEPEND="${PYTHON_USE_WITH_ATOM}"
503 RDEPEND="${PYTHON_USE_WITH_ATOM}"
504fi
505
506# @ECLASS-VARIABLE: PYTHON_DEFINE_DEFAULT_FUNCTIONS
507# @DESCRIPTION:
508# Set this to define default functions for the following ebuild phases:
509# src_prepare, src_configure, src_compile, src_test, src_install.
510if ! has "${EAPI:-0}" 0 1 && [[ -n "${PYTHON_DEFINE_DEFAULT_FUNCTIONS}" ]]; then
511 python_src_prepare() {
512 python_copy_sources
513 }
514
515 for python_default_function in src_configure src_compile src_test src_install; do
516 eval "python_${python_default_function}() { python_execute_function -d -s; }"
517 done
518 unset python_default_function
519
520 EXPORT_FUNCTIONS src_prepare src_configure src_compile src_test src_install
521fi
522
523# @FUNCTION: python_disable_pyc
524# @DESCRIPTION:
525# Tell Python not to automatically recompile modules to .pyc/.pyo
526# even if the timestamps/version stamps don't match. This is done
527# to protect sandbox.
528python_disable_pyc() {
529 export PYTHONDONTWRITEBYTECODE="1"
530}
531
83# @FUNCTION: python_makesym 532# @FUNCTION: python_enable_pyc
84# @DESCRIPTION: 533# @DESCRIPTION:
85# Run without arguments, it will create the /usr/bin/python symlinks 534# Tell Python to automatically recompile modules to .pyc/.pyo if the
86# to the latest installed version 535# timestamps/version stamps have changed.
87python_makesym() { 536python_enable_pyc() {
88 alternatives_auto_makesym "/usr/bin/python" "python[0-9].[0-9]" 537 unset PYTHONDONTWRITEBYTECODE
89 alternatives_auto_makesym "/usr/bin/python2" "python2.[0-9]" 538}
539
540python_disable_pyc
541
542# @FUNCTION: python_need_rebuild
543# @DESCRIPTION: Run without arguments, specifies that the package should be
544# rebuilt after a python upgrade.
545python_need_rebuild() {
546 python_version
547 export PYTHON_NEED_REBUILD=${PYVER}
548}
549
550# @FUNCTION: python_get_includedir
551# @DESCRIPTION:
552# Run without arguments, returns the Python include directory.
553python_get_includedir() {
554 if [[ -n "${PYTHON_ABI}" ]]; then
555 echo "/usr/include/python${PYTHON_ABI}"
556 else
557 python_version
558 echo "/usr/include/python${PYVER}"
559 fi
560}
561
562# @FUNCTION: python_get_libdir
563# @DESCRIPTION:
564# Run without arguments, returns the Python library directory.
565python_get_libdir() {
566 if [[ -n "${PYTHON_ABI}" ]]; then
567 echo "/usr/$(get_libdir)/python${PYTHON_ABI}"
568 else
569 python_version
570 echo "/usr/$(get_libdir)/python${PYVER}"
571 fi
572}
573
574# @FUNCTION: python_get_sitedir
575# @DESCRIPTION:
576# Run without arguments, returns the Python site-packages directory.
577python_get_sitedir() {
578 echo "$(python_get_libdir)/site-packages"
90} 579}
91 580
92# @FUNCTION: python_tkinter_exists 581# @FUNCTION: python_tkinter_exists
93# @DESCRIPTION: 582# @DESCRIPTION:
94# Run without arguments, checks if python was compiled with Tkinter 583# Run without arguments, checks if python was compiled with Tkinter
102 die "missing tkinter support with installed python" 591 die "missing tkinter support with installed python"
103 fi 592 fi
104} 593}
105 594
106# @FUNCTION: python_mod_exists 595# @FUNCTION: python_mod_exists
107# @USAGE: < module > 596# @USAGE: <module>
108# @DESCRIPTION: 597# @DESCRIPTION:
109# Run with the module name as an argument. it will check if a 598# Run with the module name as an argument. it will check if a
110# python module is installed and loadable. it will return 599# python module is installed and loadable. it will return
111# TRUE(0) if the module exists, and FALSE(1) if the module does 600# TRUE(0) if the module exists, and FALSE(1) if the module does
112# not exist. 601# not exist.
114# Example: 603# Example:
115# if python_mod_exists gtk; then 604# if python_mod_exists gtk; then
116# echo "gtk support enabled" 605# echo "gtk support enabled"
117# fi 606# fi
118python_mod_exists() { 607python_mod_exists() {
119 [ -z "$1" ] && die "${FUNCTION} requires an argument!" 608 [[ "$1" ]] || die "${FUNCNAME} requires an argument!"
120 if ! python -c "import $1" >/dev/null 2>&1; then 609 python -c "import $1" &>/dev/null
121 return 1
122 fi
123 return 0
124} 610}
125 611
126# @FUNCTION: python_mod_compile 612# @FUNCTION: python_mod_compile
127# @USAGE: < file > [more files ...] 613# @USAGE: <file> [more files ...]
128# @DESCRIPTION: 614# @DESCRIPTION:
129# Given filenames, it will pre-compile the module's .pyc and .pyo. 615# Given filenames, it will pre-compile the module's .pyc and .pyo.
130# This function should only be run in pkg_postinst() 616# This function should only be run in pkg_postinst()
131# 617#
132# Example: 618# Example:
133# python_mod_compile /usr/lib/python2.3/site-packages/pygoogle.py 619# python_mod_compile /usr/lib/python2.3/site-packages/pygoogle.py
134# 620#
135python_mod_compile() { 621python_mod_compile() {
136 local f myroot 622 if ! has "${EAPI:-0}" 0 1 2 || [[ -n "${SUPPORT_PYTHON_ABIS}" ]]; then
623 die "${FUNCNAME}() cannot be used in this EAPI"
624 fi
625
626 local f myroot myfiles=()
137 627
138 # Check if phase is pkg_postinst() 628 # Check if phase is pkg_postinst()
139 [[ ${EBUILD_PHASE} != postinst ]] &&\ 629 [[ ${EBUILD_PHASE} != postinst ]] &&\
140 die "${FUNCNAME} should only be run in pkg_postinst()" 630 die "${FUNCNAME} should only be run in pkg_postinst()"
141 631
142 # allow compiling for older python versions 632 # allow compiling for older python versions
143 if [ -n "${PYTHON_OVERRIDE_PYVER}" ]; then 633 if [[ "${PYTHON_OVERRIDE_PYVER}" ]]; then
144 PYVER=${PYTHON_OVERRIDE_PYVER} 634 PYVER=${PYTHON_OVERRIDE_PYVER}
145 else 635 else
146 python_version 636 python_version
147 fi 637 fi
148 638
149 # strip trailing slash 639 # strip trailing slash
150 myroot="${ROOT%/}" 640 myroot="${ROOT%/}"
151 641
152 # respect ROOT 642 # respect ROOT
153 for f in $@; do 643 for f in "$@"; do
154 [ -f "${myroot}/${f}" ] && myfiles="${myfiles} ${myroot}/${f}" 644 [[ -f "${myroot}/${f}" ]] && myfiles+=("${myroot}/${f}")
155 done 645 done
156 646
157 if [ -n "${myfiles}" ]; then 647 if ((${#myfiles[@]})); then
158 python${PYVER} ${myroot}/usr/$(get_libdir)/python${PYVER}/py_compile.py ${myfiles} 648 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} 649 python${PYVER} -O ${myroot}/usr/$(get_libdir)/python${PYVER}/py_compile.py "${myfiles[@]}" &> /dev/null
160 else 650 else
161 ewarn "No files to compile!" 651 ewarn "No files to compile!"
162 fi 652 fi
163} 653}
164 654
165# @FUNCTION: python_mod_optimize 655# @FUNCTION: python_mod_optimize
166# @USAGE: [ path ] 656# @USAGE: [options] [directory|file]
167# @DESCRIPTION: 657# @DESCRIPTION:
168# If no arguments supplied, it will recompile all modules under 658# 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/ ..) 659# under sys.path (eg. /usr/lib/python2.6, /usr/lib/python2.6/site-packages).
170# no recursively
171# 660#
172# If supplied with arguments, it will recompile all modules recursively 661# If supplied with arguments, it will recompile all modules recursively
173# in the supplied directory 662# in the supplied directory.
174# This function should only be run in pkg_postinst() 663# This function should only be run in pkg_postinst().
175# 664#
176# Options passed to this function are passed to compileall.py 665# Options passed to this function are passed to compileall.py.
177# 666#
178# Example: 667# Example:
179# python_mod_optimize /usr/share/codegen 668# python_mod_optimize ctypesgencore
180python_mod_optimize() { 669python_mod_optimize() {
181 local mydirs myfiles myroot myopts path
182
183 # Check if phase is pkg_postinst() 670 # Check if phase is pkg_postinst().
184 [[ ${EBUILD_PHASE} != postinst ]] &&\ 671 [[ ${EBUILD_PHASE} != "postinst" ]] && die "${FUNCNAME} should only be run in pkg_postinst()"
185 die "${FUNCNAME} should only be run in pkg_postinst()"
186 672
673 if ! has "${EAPI:-0}" 0 1 2 || [[ -n "${SUPPORT_PYTHON_ABIS}" ]]; then
674 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=()
675
676 # Strip trailing slash from ROOT.
677 root="${ROOT%/}"
678
679 # Respect ROOT and options passed to compileall.py.
680 while (($#)); do
681 case "$1" in
682 -l|-f|-q)
683 options+=("$1")
684 ;;
685 -d|-x)
686 options+=("$1" "$2")
687 shift
688 ;;
689 -*)
690 ewarn "${FUNCNAME}: Ignoring compile option $1"
691 ;;
692 *)
693 if [[ "$1" =~ ^/usr/lib(32|64)?/python[[:digit:]]+\.[[:digit:]]+ ]]; then
694 die "${FUNCNAME} doesn't support absolute paths of directories/files in site-packages directories"
695 elif [[ "$1" =~ ^/ ]]; then
696 if [[ -d "${root}/$1" ]]; then
697 other_dirs+=("${root}/$1")
698 elif [[ -f "${root}/$1" ]]; then
699 other_files+=("${root}/$1")
700 elif [[ -e "${root}/$1" ]]; then
701 ewarn "'${root}/$1' is not a file or a directory!"
702 else
703 ewarn "'${root}/$1' doesn't exist!"
704 fi
705 else
706 for PYTHON_ABI in ${PYTHON_ABIS}; do
707 if [[ -d "${root}$(python_get_sitedir)/$1" ]]; then
708 site_packages_dirs+=("$1")
709 break
710 elif [[ -f "${root}$(python_get_sitedir)/$1" ]]; then
711 site_packages_files+=("$1")
712 break
713 elif [[ -e "${root}$(python_get_sitedir)/$1" ]]; then
714 ewarn "'$1' is not a file or a directory!"
715 else
716 ewarn "'$1' doesn't exist!"
717 fi
718 done
719 fi
720 ;;
721 esac
722 shift
723 done
724
725 # Set additional options.
726 options+=("-q")
727
728 for PYTHON_ABI in ${PYTHON_ABIS}; do
729 if ((${#site_packages_dirs[@]})) || ((${#site_packages_files[@]})); then
730 return_code="0"
731 ebegin "Compilation and optimization of Python modules for Python ${PYTHON_ABI}"
732 if ((${#site_packages_dirs[@]})); then
733 for dir in "${site_packages_dirs[@]}"; do
734 site_packages_absolute_dirs+=("${root}$(python_get_sitedir)/${dir}")
735 done
736 "$(PYTHON)" "${root}$(python_get_libdir)/compileall.py" "${options[@]}" "${site_packages_absolute_dirs[@]}" || return_code="1"
737 "$(PYTHON)" -O "${root}$(python_get_libdir)/compileall.py" "${options[@]}" "${site_packages_absolute_dirs[@]}" &> /dev/null || return_code="1"
738 fi
739 if ((${#site_packages_files[@]})); then
740 for file in "${site_packages_files[@]}"; do
741 site_packages_absolute_files+=("${root}$(python_get_sitedir)/${file}")
742 done
743 "$(PYTHON)" "${root}$(python_get_libdir)/py_compile.py" "${site_packages_absolute_files[@]}" || return_code="1"
744 "$(PYTHON)" -O "${root}$(python_get_libdir)/py_compile.py" "${site_packages_absolute_files[@]}" &> /dev/null || return_code="1"
745 fi
746 eend "${return_code}"
747 fi
748 unset site_packages_absolute_dirs site_packages_absolute_files
749 done
750
751 # Don't use PYTHON_ABI in next calls to python_get_libdir().
752 unset PYTHON_ABI
753
754 if ((${#other_dirs[@]})) || ((${#other_files[@]})); then
755 return_code="0"
756 ebegin "Compilation and optimization of Python modules placed outside of site-packages directories for Python ${PYVER}..."
757 if ((${#other_dirs[@]})); then
758 python${PYVER} "${root}$(python_get_libdir)/compileall.py" "${options[@]}" "${other_dirs[@]}" || return_code="1"
759 python${PYVER} -O "${root}$(python_get_libdir)/compileall.py" "${options[@]}" "${other_dirs[@]}" &> /dev/null || return_code="1"
760 fi
761 if ((${#other_files[@]})); then
762 python${PYVER} "${root}$(python_get_libdir)/py_compile.py" "${other_files[@]}" || return_code="1"
763 python${PYVER} -O "${root}$(python_get_libdir)/py_compile.py" "${other_files[@]}" &> /dev/null || return_code="1"
764 fi
765 eend "${return_code}"
766 fi
767 else
768 local myroot mydirs=() myfiles=() myopts=() return_code="0"
769
187 # strip trailing slash 770 # strip trailing slash
188 myroot="${ROOT%/}" 771 myroot="${ROOT%/}"
189 772
190 # respect ROOT and options passed to compileall.py 773 # respect ROOT and options passed to compileall.py
191 while [ $# -gt 0 ]; do 774 while (($#)); do
192 case $1 in 775 case "$1" in
193 -l|-f|-q) 776 -l|-f|-q)
194 myopts="${myopts} $1" 777 myopts+=("$1")
195 ;; 778 ;;
196 -d|-x) 779 -d|-x)
197 # -x takes regexp as argument so quoting is necessary. 780 myopts+=("$1" "$2")
198 myopts="${myopts} $1 \"$2\"" 781 shift
782 ;;
783 -*)
784 ewarn "${FUNCNAME}: Ignoring compile option $1"
785 ;;
786 *)
787 if [[ -d "${myroot}"/$1 ]]; then
788 mydirs+=("${myroot}/$1")
789 elif [[ -f "${myroot}"/$1 ]]; then
790 # Files are passed to python_mod_compile which is ROOT-aware
791 myfiles+=("$1")
792 elif [[ -e "${myroot}/$1" ]]; then
793 ewarn "${myroot}/$1 is not a file or directory!"
794 else
795 ewarn "${myroot}/$1 doesn't exist!"
796 fi
797 ;;
798 esac
799 shift
800 done
801
802 # allow compiling for older python versions
803 if [ -n "${PYTHON_OVERRIDE_PYVER}" ]; then
804 PYVER=${PYTHON_OVERRIDE_PYVER}
805 else
806 python_version
807 fi
808
809 # set additional opts
810 myopts+=(-q)
811
812 ebegin "Byte compiling python modules for python-${PYVER} .."
813 if ((${#mydirs[@]})); then
814 python${PYVER} \
815 "${myroot}"/usr/$(get_libdir)/python${PYVER}/compileall.py \
816 "${myopts[@]}" "${mydirs[@]}" || return_code="1"
817 python${PYVER} -O \
818 "${myroot}"/usr/$(get_libdir)/python${PYVER}/compileall.py \
819 "${myopts[@]}" "${mydirs[@]}" &> /dev/null || return_code="1"
820 fi
821
822 if ((${#myfiles[@]})); then
823 python_mod_compile "${myfiles[@]}"
824 fi
825
826 eend "${return_code}"
827 fi
828}
829
830# @FUNCTION: python_mod_cleanup
831# @USAGE: [directory]
832# @DESCRIPTION:
833# Run with optional arguments, where arguments are directories of
834# python modules. If none given, it will look in /usr/lib/python[0-9].[0-9].
835#
836# It will recursively scan all compiled Python modules in the directories and
837# determine if they are orphaned (i.e. their corresponding .py files are missing.)
838# If they are, then it will remove their corresponding .pyc and .pyo files.
839#
840# This function should only be run in pkg_postrm().
841python_mod_cleanup() {
842 local PYTHON_ABI SEARCH_PATH=() root src_py
843
844 # Check if phase is pkg_postrm().
845 [[ ${EBUILD_PHASE} != "postrm" ]] && die "${FUNCNAME} should only be run in pkg_postrm()"
846
847 # Strip trailing slash from ROOT.
848 root="${ROOT%/}"
849
850 if (($#)); then
851 if ! has "${EAPI:-0}" 0 1 2 || [[ -n "${SUPPORT_PYTHON_ABIS}" ]]; then
852 while (($#)); do
853 if [[ "$1" =~ ^/usr/lib(32|64)?/python[[:digit:]]+\.[[:digit:]]+ ]]; then
854 die "${FUNCNAME} doesn't support absolute paths of directories/files in site-packages directories"
855 elif [[ "$1" =~ ^/ ]]; then
856 SEARCH_PATH+=("${root}/${1#/}")
857 else
858 for PYTHON_ABI in ${PYTHON_ABIS}; do
859 SEARCH_PATH+=("${root}$(python_get_sitedir)/$1")
860 done
861 fi
199 shift 862 shift
200 ;;
201 -*)
202 ewarn "${FUNCNAME}: Ignoring compile option $1"
203 ;;
204 *)
205 for path in $@; do
206 [ ! -e "${myroot}/${path}" ] && ewarn "${myroot}/${path} doesn't exist!"
207 [ -d "${myroot}/${path#/}" ] && mydirs="${mydirs} ${myroot}/${path#/}"
208 # Files are passed to python_mod_compile which is ROOT-aware
209 [ -f "${myroot}/${path}" ] && myfiles="${myfiles} ${path}"
210 done 863 done
211 ;;
212 esac
213 shift
214 done
215
216 # allow compiling for older python versions
217 if [ -n "${PYTHON_OVERRIDE_PYVER}" ]; then
218 PYVER=${PYTHON_OVERRIDE_PYVER}
219 else 864 else
220 python_version 865 SEARCH_PATH=("${@#/}")
866 SEARCH_PATH=("${SEARCH_PATH[@]/#/${root}/}")
221 fi 867 fi
222
223 # set opts
224 if [ "${PYVER}" = "2.2" ]; then
225 compileopts=""
226 else 868 else
227 compileopts="-q" 869 SEARCH_PATH=("${root}"/usr/lib*/python*/site-packages)
228 fi 870 fi
229 871
230 ebegin "Byte compiling python modules for python-${PYVER} .." 872 for path in "${SEARCH_PATH[@]}"; do
231 if [ -n "${mydirs}" ]; then 873 [[ ! -d "${path}" ]] && continue
232 python${PYVER} \ 874 einfo "Cleaning orphaned Python bytecode from ${path} .."
233 ${myroot}/usr/$(get_libdir)/python${PYVER}/compileall.py \ 875 find "${path}" -name '*.py[co]' -print0 | while read -rd ''; do
234 ${compileopts} ${myopts} ${mydirs} 876 src_py="${REPLY%[co]}"
235 python${PYVER} -O \ 877 [[ -f "${src_py}" || (! -f "${src_py}c" && ! -f "${src_py}o") ]] && continue
236 ${myroot}/usr/$(get_libdir)/python${PYVER}/compileall.py \ 878 einfo "Purging ${src_py}[co]"
237 ${compileopts} ${myopts} ${mydirs} 879 rm -f "${src_py}"[co]
238 fi
239
240 if [ -n "${myfiles}" ]; then
241 python_mod_compile ${myfiles}
242 fi
243
244 eend $?
245}
246
247# @FUNCTION: python_mod_cleanup
248# @USAGE: [ dir ]
249# @DESCRIPTION:
250# Run with optional arguments, where arguments are directories of
251# python modules. if none given, it will look in /usr/lib/python[0-9].[0-9]
252#
253# It will recursively scan all compiled python modules in the directories
254# and determine if they are orphaned (eg. their corresponding .py is missing.)
255# if they are, then it will remove their corresponding .pyc and .pyo
256#
257# This function should only be run in pkg_postrm()
258python_mod_cleanup() {
259 local SEARCH_PATH myroot
260
261 # Check if phase is pkg_postrm()
262 [[ ${EBUILD_PHASE} != postrm ]] &&\
263 die "${FUNCNAME} should only be run in pkg_postrm()"
264
265 # strip trailing slash
266 myroot="${ROOT%/}"
267
268 if [ $# -gt 0 ]; then
269 for path in $@; do
270 SEARCH_PATH="${SEARCH_PATH} ${myroot}/${path#/}"
271 done 880 done
272 else
273 for path in ${myroot}/usr/lib*/python*/site-packages; do
274 SEARCH_PATH="${SEARCH_PATH} ${path}"
275 done
276 fi
277 881
278 for path in ${SEARCH_PATH}; do
279 einfo "Cleaning orphaned Python bytecode from ${path} .."
280 for obj in $(find ${path} -name '*.py[co]'); do
281 src_py="${obj%[co]}"
282 if [ ! -f "${src_py}" ]; then
283 einfo "Purging ${src_py}[co]"
284 rm -f ${src_py}[co]
285 fi
286 done
287 # attempt to remove directories that maybe empty 882 # Attempt to remove directories that may be empty.
288 for dir in $(find ${path} -type d | sort -r); do 883 find "${path}" -type d | sort -r | while read -r dir; do
289 rmdir ${dir} 2>/dev/null 884 rmdir "${dir}" 2>/dev/null && einfo "Removing empty directory ${dir}"
290 done 885 done
291 done 886 done
292} 887}

Legend:
Removed from v.1.39  
changed lines
  Added in v.1.71

  ViewVC Help
Powered by ViewVC 1.1.20