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

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

  ViewVC Help
Powered by ViewVC 1.1.20