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

Diff of /eclass/python.eclass

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

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

Legend:
Removed from v.1.41  
changed lines
  Added in v.1.65

  ViewVC Help
Powered by ViewVC 1.1.20