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

Diff of /eclass/python.eclass

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.20