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

Diff of /eclass/python.eclass

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

Revision 1.55 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.55 2009/05/27 22:49:32 betelgeuse 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 PYTHON_ATOM=">=dev-lang/python-${NEED_PYTHON}" 17 PYTHON_ATOM=">=dev-lang/python-${NEED_PYTHON}"
18 DEPEND="${PYTHON_ATOM}" 18 DEPEND="${PYTHON_ATOM}"
19 RDEPEND="${DEPEND}" 19 RDEPEND="${DEPEND}"
20else 20else
21 PYTHON_ATOM="dev-lang/python" 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"
22fi 27fi
23 28
24__python_eclass_test() { 29__python_eclass_test() {
25 __python_version_extract 2.3 30 __python_version_extract 2.3
26 echo -n "2.3 -> PYVER: $PYVER PYVER_MAJOR: $PYVER_MAJOR" 31 echo -n "2.3 -> PYVER: $PYVER PYVER_MAJOR: $PYVER_MAJOR"
60 tmpstr="$(${python} -V 2>&1 )" 65 tmpstr="$(${python} -V 2>&1 )"
61 export PYVER_ALL="${tmpstr#Python }" 66 export PYVER_ALL="${tmpstr#Python }"
62 __python_version_extract $PYVER_ALL 67 __python_version_extract $PYVER_ALL
63} 68}
64 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
65# @ECLASS-VARIABLE: PYTHON_USE_WITH 375# @ECLASS-VARIABLE: PYTHON_USE_WITH
66# @DESCRIPTION: 376# @DESCRIPTION:
67# Set this to a space separated list of use flags 377# Set this to a space separated list of use flags
68# the python slot in use must be built with. 378# the python slot in use must be built with.
69 379
80 390
81# @FUNCTION: python_pkg_setup 391# @FUNCTION: python_pkg_setup
82# @DESCRIPTION: 392# @DESCRIPTION:
83# Makes sure PYTHON_USE_WITH or PYTHON_USE_WITH_OR listed use flags 393# Makes sure PYTHON_USE_WITH or PYTHON_USE_WITH_OR listed use flags
84# are respected. Only exported if one of those variables is set. 394# are respected. Only exported if one of those variables is set.
85if ! has ${EAPI} 0 1 && [[ -n ${PYTHON_USE_WITH} || -n ${PYTHON_USE_WITH_OR} ]]; then 395if ! has ${EAPI:-0} 0 1 && [[ -n ${PYTHON_USE_WITH} || -n ${PYTHON_USE_WITH_OR} ]]; then
86 python_pkg_setup_fail() { 396 python_pkg_setup_fail() {
87 eerror "${1}" 397 eerror "${1}"
88 die "${1}" 398 die "${1}"
89 } 399 }
90 400
134 RDEPEND="${PYTHON_USE_WITH_ATOM}" 444 RDEPEND="${PYTHON_USE_WITH_ATOM}"
135fi 445fi
136 446
137# @FUNCTION: python_disable_pyc 447# @FUNCTION: python_disable_pyc
138# @DESCRIPTION: 448# @DESCRIPTION:
139# Tells python not to automatically recompile modules to .pyc/.pyo 449# Tell Python not to automatically recompile modules to .pyc/.pyo
140# even if the timestamps/version stamps don't match. This is done 450# even if the timestamps/version stamps don't match. This is done
141# to protect sandbox. 451# to protect sandbox.
142#
143# note: supported by >=dev-lang/python-2.2.3-r3 only.
144#
145python_disable_pyc() { 452python_disable_pyc() {
146 export PYTHONDONTWRITEBYTECODE=1 # For 2.6 and above 453 export PYTHONDONTWRITEBYTECODE="1"
147 export PYTHON_DONTCOMPILE=1 # For 2.5 and below
148} 454}
149 455
150# @FUNCTION: python_enable_pyc 456# @FUNCTION: python_enable_pyc
151# @DESCRIPTION: 457# @DESCRIPTION:
152# Tells python to automatically recompile modules to .pyc/.pyo if the 458# Tell Python to automatically recompile modules to .pyc/.pyo if the
153# timestamps/version stamps change 459# timestamps/version stamps have changed.
154python_enable_pyc() { 460python_enable_pyc() {
155 unset PYTHONDONTWRITEBYTECODE 461 unset PYTHONDONTWRITEBYTECODE
156 unset PYTHON_DONTCOMPILE
157} 462}
158 463
159python_disable_pyc 464python_disable_pyc
160 465
161# @FUNCTION: python_need_rebuild 466# @FUNCTION: python_need_rebuild
164python_need_rebuild() { 469python_need_rebuild() {
165 python_version 470 python_version
166 export PYTHON_NEED_REBUILD=${PYVER} 471 export PYTHON_NEED_REBUILD=${PYVER}
167} 472}
168 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
169# @FUNCTION: python_get_libdir 486# @FUNCTION: python_get_libdir
170# @DESCRIPTION: 487# @DESCRIPTION:
171# Run without arguments, returns the python library dir 488# Run without arguments, returns the Python library directory.
172python_get_libdir() { 489python_get_libdir() {
490 if [[ -n "${PYTHON_ABI}" ]]; then
491 echo "/usr/$(get_libdir)/python${PYTHON_ABI}"
492 else
173 python_version 493 python_version
174 echo "/usr/$(get_libdir)/python${PYVER}" 494 echo "/usr/$(get_libdir)/python${PYVER}"
495 fi
175} 496}
176 497
177# @FUNCTION: python_get_sitedir 498# @FUNCTION: python_get_sitedir
178# @DESCRIPTION: 499# @DESCRIPTION:
179# Run without arguments, returns the python site-packages dir 500# Run without arguments, returns the Python site-packages directory.
180python_get_sitedir() { 501python_get_sitedir() {
181 echo "$(python_get_libdir)/site-packages" 502 echo "$(python_get_libdir)/site-packages"
182}
183
184# @FUNCTION: python_makesym
185# @DESCRIPTION:
186# Run without arguments, it will create the /usr/bin/python symlinks
187# to the latest installed version
188python_makesym() {
189 alternatives_auto_makesym "/usr/bin/python" "python[0-9].[0-9]"
190 alternatives_auto_makesym "/usr/bin/python2" "python2.[0-9]"
191} 503}
192 504
193# @FUNCTION: python_tkinter_exists 505# @FUNCTION: python_tkinter_exists
194# @DESCRIPTION: 506# @DESCRIPTION:
195# Run without arguments, checks if python was compiled with Tkinter 507# Run without arguments, checks if python was compiled with Tkinter
203 die "missing tkinter support with installed python" 515 die "missing tkinter support with installed python"
204 fi 516 fi
205} 517}
206 518
207# @FUNCTION: python_mod_exists 519# @FUNCTION: python_mod_exists
208# @USAGE: < module > 520# @USAGE: <module>
209# @DESCRIPTION: 521# @DESCRIPTION:
210# 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
211# python module is installed and loadable. it will return 523# python module is installed and loadable. it will return
212# 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
213# not exist. 525# not exist.
216# if python_mod_exists gtk; then 528# if python_mod_exists gtk; then
217# echo "gtk support enabled" 529# echo "gtk support enabled"
218# fi 530# fi
219python_mod_exists() { 531python_mod_exists() {
220 [[ "$1" ]] || die "${FUNCNAME} requires an argument!" 532 [[ "$1" ]] || die "${FUNCNAME} requires an argument!"
221 python -c "import $1" >/dev/null 2>&1 533 python -c "import $1" &>/dev/null
222} 534}
223 535
224# @FUNCTION: python_mod_compile 536# @FUNCTION: python_mod_compile
225# @USAGE: < file > [more files ...] 537# @USAGE: <file> [more files ...]
226# @DESCRIPTION: 538# @DESCRIPTION:
227# 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.
228# This function should only be run in pkg_postinst() 540# This function should only be run in pkg_postinst()
229# 541#
230# Example: 542# Example:
231# python_mod_compile /usr/lib/python2.3/site-packages/pygoogle.py 543# python_mod_compile /usr/lib/python2.3/site-packages/pygoogle.py
232# 544#
233python_mod_compile() { 545python_mod_compile() {
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
234 local f myroot myfiles=() 550 local f myroot myfiles=()
235 551
236 # Check if phase is pkg_postinst() 552 # Check if phase is pkg_postinst()
237 [[ ${EBUILD_PHASE} != postinst ]] &&\ 553 [[ ${EBUILD_PHASE} != postinst ]] &&\
238 die "${FUNCNAME} should only be run in pkg_postinst()" 554 die "${FUNCNAME} should only be run in pkg_postinst()"
252 [[ -f "${myroot}/${f}" ]] && myfiles+=("${myroot}/${f}") 568 [[ -f "${myroot}/${f}" ]] && myfiles+=("${myroot}/${f}")
253 done 569 done
254 570
255 if ((${#myfiles[@]})); then 571 if ((${#myfiles[@]})); then
256 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[@]}"
257 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
258 else 574 else
259 ewarn "No files to compile!" 575 ewarn "No files to compile!"
260 fi 576 fi
261} 577}
262 578
263# @FUNCTION: python_mod_optimize 579# @FUNCTION: python_mod_optimize
264# @USAGE: [ path ] 580# @USAGE: [options] [directory|file]
265# @DESCRIPTION: 581# @DESCRIPTION:
266# If no arguments supplied, it will recompile all modules under 582# If no arguments supplied, it will recompile not recursively all modules
267# 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).
268# no recursively
269# 584#
270# If supplied with arguments, it will recompile all modules recursively 585# If supplied with arguments, it will recompile all modules recursively
271# in the supplied directory 586# in the supplied directory.
272# This function should only be run in pkg_postinst() 587# This function should only be run in pkg_postinst().
273# 588#
274# Options passed to this function are passed to compileall.py 589# Options passed to this function are passed to compileall.py.
275# 590#
276# Example: 591# Example:
277# python_mod_optimize /usr/share/codegen 592# python_mod_optimize ctypesgencore
278python_mod_optimize() { 593python_mod_optimize() {
279 local myroot mydirs=() myfiles=() myopts=()
280
281 # Check if phase is pkg_postinst() 594 # Check if phase is pkg_postinst().
282 [[ ${EBUILD_PHASE} != postinst ]] &&\ 595 [[ ${EBUILD_PHASE} != "postinst" ]] && die "${FUNCNAME} should only be run in pkg_postinst()"
283 die "${FUNCNAME} should only be run in pkg_postinst()"
284 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
285 # strip trailing slash 694 # strip trailing slash
286 myroot="${ROOT%/}" 695 myroot="${ROOT%/}"
287 696
288 # respect ROOT and options passed to compileall.py 697 # respect ROOT and options passed to compileall.py
289 while (($#)); do 698 while (($#)); do
290 case $1 in 699 case "$1" in
291 -l|-f|-q) 700 -l|-f|-q)
292 myopts+=("$1") 701 myopts+=("$1")
293 ;; 702 ;;
294 -d|-x) 703 -d|-x)
295 myopts+=("$1" "$2") 704 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
296 shift 786 shift
297 ;;
298 -*)
299 ewarn "${FUNCNAME}: Ignoring compile option $1"
300 ;;
301 *)
302 if [[ -d "${myroot}"/$1 ]]; then
303 mydirs+=("${myroot}/$1")
304 elif [[ -f "${myroot}"/$1 ]]; then
305 # Files are passed to python_mod_compile which is ROOT-aware
306 myfiles+=("$1")
307 elif [[ -e "${myroot}/$1" ]]; then
308 ewarn "${myroot}/$1 is not a file or directory!"
309 else
310 ewarn "${myroot}/$1 doesn't exist!"
311 fi
312 ;;
313 esac
314 shift
315 done 787 done
316
317 # allow compiling for older python versions
318 if [ -n "${PYTHON_OVERRIDE_PYVER}" ]; then
319 PYVER=${PYTHON_OVERRIDE_PYVER}
320 else 788 else
321 python_version
322 fi
323
324 # set additional opts
325 myopts+=(-q)
326
327 ebegin "Byte compiling python modules for python-${PYVER} .."
328 if ((${#mydirs[@]})); then
329 python${PYVER} \
330 "${myroot}"/usr/$(get_libdir)/python${PYVER}/compileall.py \
331 "${myopts[@]}" "${mydirs[@]}"
332 python${PYVER} -O \
333 "${myroot}"/usr/$(get_libdir)/python${PYVER}/compileall.py \
334 "${myopts[@]}" "${mydirs[@]}"
335 fi
336
337 if ((${#myfiles[@]})); then
338 python_mod_compile "${myfiles[@]}"
339 fi
340
341 eend $?
342}
343
344# @FUNCTION: python_mod_cleanup
345# @USAGE: [ dir ]
346# @DESCRIPTION:
347# Run with optional arguments, where arguments are directories of
348# python modules. if none given, it will look in /usr/lib/python[0-9].[0-9]
349#
350# It will recursively scan all compiled python modules in the directories
351# and determine if they are orphaned (eg. their corresponding .py is missing.)
352# if they are, then it will remove their corresponding .pyc and .pyo
353#
354# This function should only be run in pkg_postrm()
355python_mod_cleanup() {
356 local SEARCH_PATH=() myroot src_py
357
358 # Check if phase is pkg_postrm()
359 [[ ${EBUILD_PHASE} != postrm ]] &&\
360 die "${FUNCNAME} should only be run in pkg_postrm()"
361
362 # strip trailing slash
363 myroot="${ROOT%/}"
364
365 if (($#)); then
366 SEARCH_PATH=("${@#/}") 789 SEARCH_PATH=("${@#/}")
367 SEARCH_PATH=("${SEARCH_PATH[@]/#/$myroot/}") 790 SEARCH_PATH=("${SEARCH_PATH[@]/#/${root}/}")
791 fi
368 else 792 else
369 SEARCH_PATH=("${myroot}"/usr/lib*/python*/site-packages) 793 SEARCH_PATH=("${root}"/usr/lib*/python*/site-packages)
370 fi 794 fi
371 795
372 for path in "${SEARCH_PATH[@]}"; do 796 for path in "${SEARCH_PATH[@]}"; do
797 [[ ! -d "${path}" ]] && continue
373 einfo "Cleaning orphaned Python bytecode from ${path} .." 798 einfo "Cleaning orphaned Python bytecode from ${path} .."
374 find "${path}" -name '*.py[co]' -print0 | while read -rd ''; do 799 find "${path}" -name '*.py[co]' -print0 | while read -rd ''; do
375 src_py="${REPLY%[co]}" 800 src_py="${REPLY%[co]}"
376 [[ -f "${src_py}" ]] && continue 801 [[ -f "${src_py}" || (! -f "${src_py}c" && ! -f "${src_py}o") ]] && continue
377 einfo "Purging ${src_py}[co]" 802 einfo "Purging ${src_py}[co]"
378 rm -f "${src_py}"[co] 803 rm -f "${src_py}"[co]
379 done 804 done
380 805
381 # attempt to remove directories that maybe empty 806 # Attempt to remove directories that may be empty.
382 find "${path}" -type d | sort -r | while read -r dir; do 807 find "${path}" -type d | sort -r | while read -r dir; do
383 rmdir "${dir}" 2>/dev/null 808 rmdir "${dir}" 2>/dev/null && einfo "Removing empty directory ${dir}"
384 done 809 done
385 done 810 done
386} 811}

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

  ViewVC Help
Powered by ViewVC 1.1.20