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

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

  ViewVC Help
Powered by ViewVC 1.1.20