/[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.82
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.82 2009/12/23 23:43:42 arfrever Exp $
4 4
5# @ECLASS: python.eclass 5# @ECLASS: python.eclass
6# @MAINTAINER: 6# @MAINTAINER:
7# python@gentoo.org 7# python@gentoo.org
8#
9# original author: Alastair Tse <liquidx@gentoo.org>
10# @BLURB: A Utility Eclass that should be inherited by anything that deals with Python or Python modules. 8# @BLURB: A utility eclass that should be inherited by anything that deals with Python or Python modules.
11# @DESCRIPTION: 9# @DESCRIPTION:
12# Some useful functions for dealing with python. 10# Some useful functions for dealing with Python.
13inherit alternatives multilib
14 11
12inherit multilib
15 13
16if [[ -n "${NEED_PYTHON}" ]] ; then 14if [[ -n "${NEED_PYTHON}" ]]; then
17 DEPEND=">=dev-lang/python-${NEED_PYTHON}" 15 PYTHON_ATOM=">=dev-lang/python-${NEED_PYTHON}"
16 DEPEND="${PYTHON_ATOM}"
18 RDEPEND="${DEPEND}" 17 RDEPEND="${DEPEND}"
18else
19 PYTHON_ATOM="dev-lang/python"
19fi 20fi
21
22DEPEND+=" >=app-admin/eselect-python-20090804
23 >=app-shells/bash-3.2"
20 24
21__python_eclass_test() { 25__python_eclass_test() {
22 __python_version_extract 2.3 26 __python_version_extract 2.3
23 echo -n "2.3 -> PYVER: $PYVER PYVER_MAJOR: $PYVER_MAJOR" 27 echo -n "2.3 -> PYVER: $PYVER PYVER_MAJOR: $PYVER_MAJOR"
24 echo " PYVER_MINOR: $PYVER_MINOR PYVER_MICRO: $PYVER_MICRO" 28 echo " PYVER_MINOR: $PYVER_MINOR PYVER_MICRO: $PYVER_MICRO"
34 __python_version_extract 2.5b3 38 __python_version_extract 2.5b3
35 echo -n "2.5b3 -> PYVER: $PYVER PYVER_MAJOR: $PYVER_MAJOR" 39 echo -n "2.5b3 -> PYVER: $PYVER PYVER_MAJOR: $PYVER_MAJOR"
36 echo " PYVER_MINOR: $PYVER_MINOR PYVER_MICRO: $PYVER_MICRO" 40 echo " PYVER_MINOR: $PYVER_MINOR PYVER_MICRO: $PYVER_MICRO"
37} 41}
38 42
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 43# @FUNCTION: python_version
62# @DESCRIPTION: 44# @DESCRIPTION:
63# Run without arguments and it will export the version of python 45# Run without arguments and it will export the version of python
64# currently in use as $PYVER; sets PYVER/PYVER_MAJOR/PYVER_MINOR 46# currently in use as $PYVER; sets PYVER/PYVER_MAJOR/PYVER_MINOR
65__python_version_extract() { 47__python_version_extract() {
66 verstr=$1 48 local verstr=$1
67 export PYVER_MAJOR=${verstr:0:1} 49 export PYVER_MAJOR=${verstr:0:1}
68 export PYVER_MINOR=${verstr:2:1} 50 export PYVER_MINOR=${verstr:2:1}
69 if [ "${verstr:3}x" = ".x" ]; then 51 if [[ ${verstr:3:1} == . ]]; then
70 export PYVER_MICRO=${verstr:4} 52 export PYVER_MICRO=${verstr:4}
71 fi 53 fi
72 export PYVER="${PYVER_MAJOR}.${PYVER_MINOR}" 54 export PYVER="${PYVER_MAJOR}.${PYVER_MINOR}"
73} 55}
74 56
75python_version() { 57python_version() {
58 [[ -n "${PYVER}" ]] && return 0
76 local tmpstr 59 local tmpstr
77 python=${python:-/usr/bin/python} 60 python=${python:-/usr/bin/python}
78 tmpstr="$(${python} -V 2>&1 )" 61 tmpstr="$(EPYTHON= ${python} -V 2>&1 )"
79 export PYVER_ALL="${tmpstr#Python }" 62 export PYVER_ALL="${tmpstr#Python }"
80 __python_version_extract $PYVER_ALL 63 __python_version_extract $PYVER_ALL
81} 64}
82 65
66# @FUNCTION: PYTHON
67# @USAGE: [-2] [-3] [-A|--only-ABI] [-a|--absolute-path] [-f|--final-ABI] [--] <Python_ABI="${PYTHON_ABI}">
68# @DESCRIPTION:
69# Get Python interpreter filename for specified Python ABI. If Python_ABI argument
70# is ommitted, then PYTHON_ABI environment variable must be set and is used.
71# If -2 option is specified, then active version of Python 2 is used.
72# If -3 option is specified, then active version of Python 3 is used.
73# If --final-ABI option is specified, then final ABI from the list of enabled ABIs is used.
74# -2, -3 and --final-ABI options and Python_ABI argument cannot be specified simultaneously.
75# If --only-ABI option is specified, then only specified Python ABI is printed instead of
76# Python interpreter filename.
77# --only-ABI and --absolute-path options cannot be specified simultaneously.
78PYTHON() {
79 local absolute_path="0" final_ABI="0" only_ABI="0" python2="0" python3="0" slot=
80
81 while (($#)); do
82 case "$1" in
83 -2)
84 python2="1"
85 ;;
86 -3)
87 python3="1"
88 ;;
89 -A|--only-ABI)
90 only_ABI="1"
91 ;;
92 -a|--absolute-path)
93 absolute_path="1"
94 ;;
95 -f|--final-ABI)
96 final_ABI="1"
97 ;;
98 --)
99 break
100 ;;
101 -*)
102 die "${FUNCNAME}(): Unrecognized option '$1'"
103 ;;
104 *)
105 break
106 ;;
107 esac
108 shift
109 done
110
111 if [[ "${only_ABI}" == "1" && "${absolute_path}" == "1" ]]; then
112 die "${FUNCNAME}(): '--only-ABI and '--absolute-path' options cannot be specified simultaneously"
113 fi
114
115 if [[ "$((${python2} + ${python3} + ${final_ABI}))" -gt "1" ]]; then
116 die "${FUNCNAME}(): '-2', '-3' or '--final-ABI' options cannot be specified simultaneously"
117 fi
118
119 if [[ "$#" -eq "0" ]]; then
120 if [[ "${final_ABI}" == "1" ]]; then
121 validate_PYTHON_ABIS
122 slot="${PYTHON_ABIS##* }"
123 elif [[ "${python2}" == "1" ]]; then
124 slot="$(eselect python show --python2)"
125 if [[ -z "${slot}" ]]; then
126 die "${FUNCNAME}(): Active Python 2 interpreter not set"
127 elif [[ "${slot}" != "python2."* ]]; then
128 die "${FUNCNAME}(): Internal error in \`eselect python show --python2\`"
129 fi
130 slot="${slot#python}"
131 elif [[ "${python3}" == "1" ]]; then
132 slot="$(eselect python show --python3)"
133 if [[ -z "${slot}" ]]; then
134 die "${FUNCNAME}(): Active Python 3 interpreter not set"
135 elif [[ "${slot}" != "python3."* ]]; then
136 die "${FUNCNAME}(): Internal error in \`eselect python show --python3\`"
137 fi
138 slot="${slot#python}"
139 elif [[ -n "${PYTHON_ABI}" ]]; then
140 slot="${PYTHON_ABI}"
141 else
142 die "${FUNCNAME}(): Invalid usage"
143 fi
144 elif [[ "$#" -eq "1" ]]; then
145 if [[ "${final_ABI}" == "1" ]]; then
146 die "${FUNCNAME}(): '--final-ABI' option and Python ABI cannot be specified simultaneously"
147 fi
148 if [[ "${python2}" == "1" ]]; then
149 die "${FUNCNAME}(): '-2' option and Python ABI cannot be specified simultaneously"
150 fi
151 if [[ "${python3}" == "1" ]]; then
152 die "${FUNCNAME}(): '-3' option and Python ABI cannot be specified simultaneously"
153 fi
154 slot="$1"
155 else
156 die "${FUNCNAME}(): Invalid usage"
157 fi
158
159 if [[ "${only_ABI}" == "1" ]]; then
160 echo -n "${slot}"
161 return
162 elif [[ "${absolute_path}" == "1" ]]; then
163 echo -n "/usr/bin/python${slot}"
164 else
165 echo -n "python${slot}"
166 fi
167
168 if [[ -n "${ABI}" && "${ABI}" != "${DEFAULT_ABI}" && "${DEFAULT_ABI}" != "default" ]]; then
169 echo -n "-${ABI}"
170 fi
171}
172
173# @FUNCTION: python_set_active_version
174# @USAGE: <Python_ABI|2|3>
175# @DESCRIPTION:
176# Set active version of Python.
177python_set_active_version() {
178 if [[ "$#" -ne "1" ]]; then
179 die "${FUNCNAME}() requires 1 argument"
180 fi
181
182 if [[ "$1" =~ ^[[:digit:]]+\.[[:digit:]]+$ ]]; then
183 if ! has_version "dev-lang/python:$1"; then
184 die "${FUNCNAME}(): 'dev-lang/python:$1' isn't installed"
185 fi
186 export EPYTHON="$(PYTHON "$1")"
187 elif [[ "$1" == "2" ]]; then
188 if ! has_version "=dev-lang/python-2*"; then
189 die "${FUNCNAME}(): '=dev-lang/python-2*' isn't installed"
190 fi
191 export EPYTHON="$(PYTHON -2)"
192 elif [[ "$1" == "3" ]]; then
193 if ! has_version "=dev-lang/python-3*"; then
194 die "${FUNCNAME}(): '=dev-lang/python-3*' isn't installed"
195 fi
196 export EPYTHON="$(PYTHON -3)"
197 else
198 die "${FUNCNAME}(): Unrecognized argument '$1'"
199 fi
200
201 # PYTHON_ABI variable is intended to be used only in ebuilds/eclasses,
202 # so it doesn't need to be exported to subprocesses.
203 PYTHON_ABI="${EPYTHON#python}"
204 PYTHON_ABI="${PYTHON_ABI%%-*}"
205}
206
207unset PYTHON_ABIS
208unset PYTHON_ABIS_SANITY_CHECKS
209
210# @FUNCTION: validate_PYTHON_ABIS
211# @DESCRIPTION:
212# Ensure that PYTHON_ABIS variable has valid value.
213validate_PYTHON_ABIS() {
214 # Ensure that some functions cannot be accidentally successfully used in EAPI <= 2 without setting SUPPORT_PYTHON_ABIS variable.
215 if has "${EAPI:-0}" 0 1 2 && [[ -z "${SUPPORT_PYTHON_ABIS}" ]]; then
216 die "${FUNCNAME}() cannot be used in this EAPI without setting SUPPORT_PYTHON_ABIS variable"
217 fi
218
219 # Ensure that /usr/bin/python and /usr/bin/python-config are valid.
220 if [[ "$(readlink /usr/bin/python)" != "python-wrapper" ]]; then
221 die "'/usr/bin/python' isn't valid symlink"
222 fi
223 if [[ "$(</usr/bin/python-config)" != *"Gentoo python-config wrapper script"* ]]; then
224 die "'/usr/bin/python-config' isn't valid script"
225 fi
226
227 # USE_${ABI_TYPE^^} and RESTRICT_${ABI_TYPE^^}_ABIS variables hopefully will be included in EAPI >= 5.
228 if [[ "$(declare -p PYTHON_ABIS 2> /dev/null)" != "declare -x PYTHON_ABIS="* ]] && has "${EAPI:-0}" 0 1 2 3 4; then
229 local PYTHON_ABI python2_supported_versions python3_supported_versions restricted_ABI support_ABI supported_PYTHON_ABIS=
230 PYTHON_ABI_SUPPORTED_VALUES="2.4 2.5 2.6 2.7 3.0 3.1 3.2"
231 python2_supported_versions="2.4 2.5 2.6 2.7"
232 python3_supported_versions="3.0 3.1 3.2"
233
234 if [[ "$(declare -p USE_PYTHON 2> /dev/null)" == "declare -x USE_PYTHON="* ]]; then
235 local python2_enabled="0" python3_enabled="0"
236
237 if [[ -z "${USE_PYTHON}" ]]; then
238 die "USE_PYTHON variable is empty"
239 fi
240
241 for PYTHON_ABI in ${USE_PYTHON}; do
242 if ! has "${PYTHON_ABI}" ${PYTHON_ABI_SUPPORTED_VALUES}; then
243 die "USE_PYTHON variable contains invalid value '${PYTHON_ABI}'"
244 fi
245
246 if has "${PYTHON_ABI}" ${python2_supported_versions}; then
247 python2_enabled="1"
248 fi
249 if has "${PYTHON_ABI}" ${python3_supported_versions}; then
250 python3_enabled="1"
251 fi
252
253 support_ABI="1"
254 for restricted_ABI in ${RESTRICT_PYTHON_ABIS}; do
255 if [[ "${PYTHON_ABI}" == ${restricted_ABI} ]]; then
256 support_ABI="0"
257 break
258 fi
259 done
260 [[ "${support_ABI}" == "1" ]] && export PYTHON_ABIS+="${PYTHON_ABIS:+ }${PYTHON_ABI}"
261 done
262
263 if [[ -z "${PYTHON_ABIS//[${IFS}]/}" ]]; then
264 die "USE_PYTHON variable doesn't enable any version of Python supported by ${CATEGORY}/${PF}"
265 fi
266
267 if [[ "${python2_enabled}" == "0" ]]; then
268 ewarn "USE_PYTHON variable doesn't enable any version of Python 2. This configuration is unsupported."
269 fi
270 if [[ "${python3_enabled}" == "0" ]]; then
271 ewarn "USE_PYTHON variable doesn't enable any version of Python 3. This configuration is unsupported."
272 fi
273 else
274 local python_version python2_version= python3_version= support_python_major_version
275
276 python_version="$(/usr/bin/python -c 'from sys import version_info; print(".".join([str(x) for x in version_info[:2]]))')"
277
278 if has_version "=dev-lang/python-2*"; then
279 if [[ "$(readlink /usr/bin/python2)" != "python2."* ]]; then
280 die "'/usr/bin/python2' isn't valid symlink"
281 fi
282
283 python2_version="$(/usr/bin/python2 -c 'from sys import version_info; print(".".join([str(x) for x in version_info[:2]]))')"
284
285 for PYTHON_ABI in ${python2_supported_versions}; do
286 support_python_major_version="1"
287 for restricted_ABI in ${RESTRICT_PYTHON_ABIS}; do
288 if [[ "${PYTHON_ABI}" == ${restricted_ABI} ]]; then
289 support_python_major_version="0"
290 fi
291 done
292 [[ "${support_python_major_version}" == "1" ]] && break
293 done
294 if [[ "${support_python_major_version}" == "1" ]]; then
295 for restricted_ABI in ${RESTRICT_PYTHON_ABIS}; do
296 if [[ "${python2_version}" == ${restricted_ABI} ]]; then
297 die "Active version of Python 2 isn't supported by ${CATEGORY}/${PF}"
298 fi
299 done
300 else
301 python2_version=""
302 fi
303 fi
304
305 if has_version "=dev-lang/python-3*"; then
306 if [[ "$(readlink /usr/bin/python3)" != "python3."* ]]; then
307 die "'/usr/bin/python3' isn't valid symlink"
308 fi
309
310 python3_version="$(/usr/bin/python3 -c 'from sys import version_info; print(".".join([str(x) for x in version_info[:2]]))')"
311
312 for PYTHON_ABI in ${python3_supported_versions}; do
313 support_python_major_version="1"
314 for restricted_ABI in ${RESTRICT_PYTHON_ABIS}; do
315 if [[ "${PYTHON_ABI}" == ${restricted_ABI} ]]; then
316 support_python_major_version="0"
317 fi
318 done
319 [[ "${support_python_major_version}" == "1" ]] && break
320 done
321 if [[ "${support_python_major_version}" == "1" ]]; then
322 for restricted_ABI in ${RESTRICT_PYTHON_ABIS}; do
323 if [[ "${python3_version}" == ${restricted_ABI} ]]; then
324 die "Active version of Python 3 isn't supported by ${CATEGORY}/${PF}"
325 fi
326 done
327 else
328 python3_version=""
329 fi
330 fi
331
332 if [[ -n "${python2_version}" && "${python_version}" == "2."* && "${python_version}" != "${python2_version}" ]]; then
333 eerror "Python wrapper is configured incorrectly or /usr/bin/python2 symlink"
334 eerror "is set incorrectly. Use \`eselect python\` to fix configuration."
335 die "Incorrect configuration of Python"
336 fi
337 if [[ -n "${python3_version}" && "${python_version}" == "3."* && "${python_version}" != "${python3_version}" ]]; then
338 eerror "Python wrapper is configured incorrectly or /usr/bin/python3 symlink"
339 eerror "is set incorrectly. Use \`eselect python\` to fix configuration."
340 die "Incorrect configuration of Python"
341 fi
342
343 PYTHON_ABIS="${python2_version} ${python3_version}"
344 PYTHON_ABIS="${PYTHON_ABIS# }"
345 export PYTHON_ABIS="${PYTHON_ABIS% }"
346 fi
347 fi
348
349 if [[ "$(declare -p PYTHON_ABIS_SANITY_CHECKS 2> /dev/null)" != "declare -- PYTHON_ABIS_SANITY_CHECKS="* ]]; then
350 local PYTHON_ABI
351 for PYTHON_ABI in ${PYTHON_ABIS}; do
352 # Ensure that appropriate version of Python is installed.
353 if ! has_version "dev-lang/python:${PYTHON_ABI}"; then
354 die "dev-lang/python:${PYTHON_ABI} isn't installed"
355 fi
356
357 # Ensure that EPYTHON variable is respected.
358 if [[ "$(EPYTHON="$(PYTHON)" python -c 'from sys import version_info; print(".".join([str(x) for x in version_info[:2]]))')" != "${PYTHON_ABI}" ]]; then
359 eerror "python: '$(type -p python)'"
360 eerror "ABI: '${ABI}'"
361 eerror "DEFAULT_ABI: '${DEFAULT_ABI}'"
362 eerror "EPYTHON: '$(PYTHON)'"
363 eerror "PYTHON_ABI: '${PYTHON_ABI}'"
364 eerror "Version of enabled Python: '$(EPYTHON="$(PYTHON)" python -c 'from sys import version_info; print(".".join([str(x) for x in version_info[:2]]))')'"
365 die "'python' doesn't respect EPYTHON variable"
366 fi
367 done
368 PYTHON_ABIS_SANITY_CHECKS="1"
369 fi
370}
371
372# @FUNCTION: python_copy_sources
373# @USAGE: [--no-link] [--] [directory]
374# @DESCRIPTION:
375# Copy unpacked sources of given package for each Python ABI.
376python_copy_sources() {
377 local dir dirs=() no_link="0" PYTHON_ABI
378
379 while (($#)); do
380 case "$1" in
381 --no-link)
382 no_link="1"
383 ;;
384 --)
385 break
386 ;;
387 -*)
388 die "${FUNCNAME}(): Unrecognized option '$1'"
389 ;;
390 *)
391 break
392 ;;
393 esac
394 shift
395 done
396
397 if [[ "$#" -eq "0" ]]; then
398 if [[ "${WORKDIR}" == "${S}" ]]; then
399 die "${FUNCNAME}() cannot be used"
400 fi
401 dirs="${S}"
402 else
403 dirs="$@"
404 fi
405
406 validate_PYTHON_ABIS
407 for PYTHON_ABI in ${PYTHON_ABIS}; do
408 for dir in "${dirs[@]}"; do
409 if [[ "${no_link}" == "1" ]]; then
410 cp -pr "${dir}" "${dir}-${PYTHON_ABI}" > /dev/null || die "Copying of sources failed"
411 else
412 cp -lpr "${dir}" "${dir}-${PYTHON_ABI}" > /dev/null || die "Copying of sources failed"
413 fi
414 done
415 done
416}
417
418# @FUNCTION: python_set_build_dir_symlink
419# @USAGE: [directory="build"]
420# @DESCRIPTION:
421# Create build directory symlink.
422python_set_build_dir_symlink() {
423 local dir="$1"
424
425 [[ -z "${PYTHON_ABI}" ]] && die "PYTHON_ABI variable not set"
426 [[ -z "${dir}" ]] && dir="build"
427
428 # Don't delete preexistent directories.
429 rm -f "${dir}" || die "Deletion of '${dir}' failed"
430 ln -s "${dir}-${PYTHON_ABI}" "${dir}" || die "Creation of '${dir}' directory symlink failed"
431}
432
433# @FUNCTION: python_execute_function
434# @USAGE: [--action-message message] [-d|--default-function] [--failure-message message] [--nonfatal] [-q|--quiet] [-s|--separate-build-dirs] [--source-dir source_directory] [--] <function> [arguments]
435# @DESCRIPTION:
436# Execute specified function for each value of PYTHON_ABIS, optionally passing additional
437# arguments. The specified function can use PYTHON_ABI and BUILDDIR variables.
438python_execute_function() {
439 local action action_message action_message_template= default_function="0" failure_message failure_message_template= function nonfatal="0" previous_directory previous_directory_stack previous_directory_stack_length PYTHON_ABI quiet="0" separate_build_dirs="0" source_dir=
440
441 while (($#)); do
442 case "$1" in
443 --action-message)
444 action_message_template="$2"
445 shift
446 ;;
447 -d|--default-function)
448 default_function="1"
449 ;;
450 --failure-message)
451 failure_message_template="$2"
452 shift
453 ;;
454 --nonfatal)
455 nonfatal="1"
456 ;;
457 -q|--quiet)
458 quiet="1"
459 ;;
460 -s|--separate-build-dirs)
461 separate_build_dirs="1"
462 ;;
463 --source-dir)
464 source_dir="$2"
465 shift
466 ;;
467 --)
468 break
469 ;;
470 -*)
471 die "${FUNCNAME}(): Unrecognized option '$1'"
472 ;;
473 *)
474 break
475 ;;
476 esac
477 shift
478 done
479
480 if [[ -n "${source_dir}" && "${separate_build_dirs}" == 0 ]]; then
481 die "${FUNCNAME}(): '--source-dir' option can be specified only with '--separate-build-dirs' option"
482 fi
483
484 if [[ "${default_function}" == "0" ]]; then
485 if [[ "$#" -eq "0" ]]; then
486 die "${FUNCNAME}(): Missing function name"
487 fi
488 function="$1"
489 shift
490
491 if [[ -z "$(type -t "${function}")" ]]; then
492 die "${FUNCNAME}(): '${function}' function isn't defined"
493 fi
494 else
495 if [[ "$#" -ne "0" ]]; then
496 die "${FUNCNAME}(): '--default-function' option and function name cannot be specified simultaneously"
497 fi
498 if has "${EAPI:-0}" 0 1; then
499 die "${FUNCNAME}(): '--default-function' option cannot be used in this EAPI"
500 fi
501
502 if [[ "${EBUILD_PHASE}" == "configure" ]]; then
503 if has "${EAPI}" 2 3; then
504 python_default_function() {
505 econf
506 }
507 else
508 python_default_function() {
509 nonfatal econf
510 }
511 fi
512 elif [[ "${EBUILD_PHASE}" == "compile" ]]; then
513 python_default_function() {
514 emake
515 }
516 elif [[ "${EBUILD_PHASE}" == "test" ]]; then
517 python_default_function() {
518 if emake -j1 -n check &> /dev/null; then
519 emake -j1 check
520 elif emake -j1 -n test &> /dev/null; then
521 emake -j1 test
522 fi
523 }
524 elif [[ "${EBUILD_PHASE}" == "install" ]]; then
525 python_default_function() {
526 emake DESTDIR="${D}" install
527 }
528 else
529 die "${FUNCNAME}(): '--default-function' option cannot be used in this ebuild phase"
530 fi
531 function="python_default_function"
532 fi
533
534 if [[ "${quiet}" == "0" ]]; then
535 [[ "${EBUILD_PHASE}" == "setup" ]] && action="Setting up"
536 [[ "${EBUILD_PHASE}" == "unpack" ]] && action="Unpacking"
537 [[ "${EBUILD_PHASE}" == "prepare" ]] && action="Preparation"
538 [[ "${EBUILD_PHASE}" == "configure" ]] && action="Configuration"
539 [[ "${EBUILD_PHASE}" == "compile" ]] && action="Building"
540 [[ "${EBUILD_PHASE}" == "test" ]] && action="Testing"
541 [[ "${EBUILD_PHASE}" == "install" ]] && action="Installation"
542 [[ "${EBUILD_PHASE}" == "preinst" ]] && action="Preinstallation"
543 [[ "${EBUILD_PHASE}" == "postinst" ]] && action="Postinstallation"
544 [[ "${EBUILD_PHASE}" == "prerm" ]] && action="Preuninstallation"
545 [[ "${EBUILD_PHASE}" == "postrm" ]] && action="Postuninstallation"
546 fi
547
548 local RED GREEN BLUE NORMAL
549 if [[ "${NOCOLOR:-false}" =~ ^(false|no)$ ]]; then
550 RED=$'\e[1;31m'
551 GREEN=$'\e[1;32m'
552 BLUE=$'\e[1;34m'
553 NORMAL=$'\e[0m'
554 else
555 RED=
556 GREEN=
557 BLUE=
558 NORMAL=
559 fi
560
561 validate_PYTHON_ABIS
562 for PYTHON_ABI in ${PYTHON_ABIS}; do
563 if [[ "${quiet}" == "0" ]]; then
564 if [[ -n "${action_message_template}" ]]; then
565 action_message="$(eval echo -n "${action_message_template}")"
566 else
567 action_message="${action} of ${CATEGORY}/${PF} with Python ${PYTHON_ABI}..."
568 fi
569 echo " ${GREEN}*${NORMAL} ${BLUE}${action_message}${NORMAL}"
570 fi
571
572 if [[ "${separate_build_dirs}" == "1" ]]; then
573 if [[ -n "${source_dir}" ]]; then
574 export BUILDDIR="${S}/${source_dir}-${PYTHON_ABI}"
575 else
576 export BUILDDIR="${S}-${PYTHON_ABI}"
577 fi
578 pushd "${BUILDDIR}" > /dev/null || die "pushd failed"
579 else
580 export BUILDDIR="${S}"
581 fi
582
583 previous_directory="$(pwd)"
584 previous_directory_stack="$(dirs -p)"
585 previous_directory_stack_length="$(dirs -p | wc -l)"
586
587 if ! has "${EAPI}" 0 1 2 3 && has "${PYTHON_ABI}" ${FAILURE_TOLERANT_PYTHON_ABIS}; then
588 EPYTHON="$(PYTHON)" nonfatal "${function}" "$@"
589 else
590 EPYTHON="$(PYTHON)" "${function}" "$@"
591 fi
592
593 if [[ "$?" != "0" ]]; then
594 if [[ -n "${failure_message_template}" ]]; then
595 failure_message="$(eval echo -n "${failure_message_template}")"
596 else
597 failure_message="${action} failed with Python ${PYTHON_ABI} in ${function}() function"
598 fi
599
600 if [[ "${nonfatal}" == "1" ]]; then
601 if [[ "${quiet}" == "0" ]]; then
602 ewarn "${RED}${failure_message}${NORMAL}"
603 fi
604 elif has "${PYTHON_ABI}" ${FAILURE_TOLERANT_PYTHON_ABIS}; then
605 if [[ "${EBUILD_PHASE}" != "test" ]] || ! has test-fail-continue ${FEATURES}; then
606 local enabled_PYTHON_ABIS= other_PYTHON_ABI
607 for other_PYTHON_ABI in ${PYTHON_ABIS}; do
608 [[ "${other_PYTHON_ABI}" != "${PYTHON_ABI}" ]] && enabled_PYTHON_ABIS+="${enabled_PYTHON_ABIS:+ }${other_PYTHON_ABI}"
609 done
610 export PYTHON_ABIS="${enabled_PYTHON_ABIS}"
611 fi
612 if [[ "${quiet}" == "0" ]]; then
613 ewarn "${RED}${failure_message}${NORMAL}"
614 fi
615 if [[ -z "${PYTHON_ABIS}" ]]; then
616 die "${function}() function failed with all enabled versions of Python"
617 fi
618 else
619 die "${failure_message}"
620 fi
621 fi
622
623 # Ensure that directory stack hasn't been decreased.
624 if [[ "$(dirs -p | wc -l)" -lt "${previous_directory_stack_length}" ]]; then
625 die "Directory stack decreased illegally"
626 fi
627
628 # Avoid side effects of earlier returning from the specified function.
629 while [[ "$(dirs -p | wc -l)" -gt "${previous_directory_stack_length}" ]]; do
630 popd > /dev/null || die "popd failed"
631 done
632
633 # Ensure that the bottom part of directory stack hasn't been changed. Restore
634 # previous directory (from before running of the specified function) before
635 # comparison of directory stacks to avoid mismatch of directory stacks after
636 # potential using of 'cd' to change current directory. Restoration of previous
637 # directory allows to safely use 'cd' to change current directory in the
638 # specified function without changing it back to original directory.
639 cd "${previous_directory}"
640 if [[ "$(dirs -p)" != "${previous_directory_stack}" ]]; then
641 die "Directory stack changed illegally"
642 fi
643
644 if [[ "${separate_build_dirs}" == "1" ]]; then
645 popd > /dev/null || die "popd failed"
646 fi
647 unset BUILDDIR
648 done
649
650 if [[ "${default_function}" == "1" ]]; then
651 unset -f python_default_function
652 fi
653}
654
655# @FUNCTION: python_convert_shebangs
656# @USAGE: [-q|--quiet] [-r|--recursive] [-x|--only-executables] [--] <Python_version> <file|directory> [files|directories]
657# @DESCRIPTION:
658# Convert shebangs in specified files. Directories can be specified only with --recursive option.
659python_convert_shebangs() {
660 local argument file files=() only_executables="0" python_version quiet="0" recursive="0"
661
662 while (($#)); do
663 case "$1" in
664 -r|--recursive)
665 recursive="1"
666 ;;
667 -q|--quiet)
668 quiet="1"
669 ;;
670 -x|--only-executables)
671 only_executables="1"
672 ;;
673 --)
674 break
675 ;;
676 -*)
677 die "${FUNCNAME}(): Unrecognized option '$1'"
678 ;;
679 *)
680 break
681 ;;
682 esac
683 shift
684 done
685
686 if [[ "$#" -eq 0 ]]; then
687 die "${FUNCNAME}(): Missing Python version and files or directories"
688 elif [[ "$#" -eq 1 ]]; then
689 die "${FUNCNAME}(): Missing files or directories"
690 fi
691
692 python_version="$1"
693 shift
694
695 for argument in "$@"; do
696 if [[ ! -e "${argument}" ]]; then
697 die "${FUNCNAME}(): '${argument}' doesn't exist"
698 elif [[ -f "${argument}" ]]; then
699 files+=("${argument}")
700 elif [[ -d "${argument}" ]]; then
701 if [[ "${recursive}" == "1" ]]; then
702 if [[ "${only_executables}" == "1" ]]; then
703 files+=($(find "${argument}" -perm /111 -type f))
704 else
705 files+=($(find "${argument}" -type f))
706 fi
707 else
708 die "${FUNCNAME}(): '${argument}' isn't a regular file"
709 fi
710 else
711 die "${FUNCNAME}(): '${argument}' isn't a regular file or a directory"
712 fi
713 done
714
715 for file in "${files[@]}"; do
716 file="${file#./}"
717 [[ "${only_executables}" == "1" && ! -x "${file}" ]] && continue
718
719 if [[ "$(head -n1 "${file}")" =~ ^'#!'.*python ]]; then
720 if [[ "${quiet}" == "0" ]]; then
721 einfo "Converting shebang in '${file}'"
722 fi
723 sed -e "1s/python\([[:digit:]]\+\(\.[[:digit:]]\+\)\?\)\?/python${python_version}/" -i "${file}" || die "Conversion of shebang in '${file}' failed"
724
725 # Delete potential whitespace after "#!".
726 sed -e '1s/\(^#!\)[[:space:]]*/\1/' -i "${file}" || die "sed '${file}' failed"
727 fi
728 done
729}
730
731# @FUNCTION: python_generate_wrapper_scripts
732# @USAGE: [-E|--respect-EPYTHON] [-f|--force] [-q|--quiet] [--] <file> [files]
733# @DESCRIPTION:
734# Generate wrapper scripts. Existing files are overwritten only with --force option.
735# If --respect-EPYTHON option is specified, then generated wrapper scripts will
736# respect EPYTHON variable at run time.
737python_generate_wrapper_scripts() {
738 local eselect_python_option file force="0" quiet="0" PYTHON_ABI python2_enabled="0" python2_supported_versions python3_enabled="0" python3_supported_versions respect_EPYTHON="0"
739 python2_supported_versions="2.4 2.5 2.6 2.7"
740 python3_supported_versions="3.0 3.1 3.2"
741
742 while (($#)); do
743 case "$1" in
744 -E|--respect-EPYTHON)
745 respect_EPYTHON="1"
746 ;;
747 -f|--force)
748 force="1"
749 ;;
750 -q|--quiet)
751 quiet="1"
752 ;;
753 --)
754 break
755 ;;
756 -*)
757 die "${FUNCNAME}(): Unrecognized option '$1'"
758 ;;
759 *)
760 break
761 ;;
762 esac
763 shift
764 done
765
766 if [[ "$#" -eq 0 ]]; then
767 die "${FUNCNAME}(): Missing arguments"
768 fi
769
770 validate_PYTHON_ABIS
771 for PYTHON_ABI in ${python2_supported_versions}; do
772 if has "${PYTHON_ABI}" ${PYTHON_ABIS}; then
773 python2_enabled="1"
774 fi
775 done
776 for PYTHON_ABI in ${python3_supported_versions}; do
777 if has "${PYTHON_ABI}" ${PYTHON_ABIS}; then
778 python3_enabled="1"
779 fi
780 done
781
782 if [[ "${python2_enabled}" == "1" && "${python3_enabled}" == "1" ]]; then
783 eselect_python_option=
784 elif [[ "${python2_enabled}" == "1" && "${python3_enabled}" == "0" ]]; then
785 eselect_python_option="--python2"
786 elif [[ "${python2_enabled}" == "0" && "${python3_enabled}" == "1" ]]; then
787 eselect_python_option="--python3"
788 else
789 die "${FUNCNAME}(): Unsupported environment"
790 fi
791
792 for file in "$@"; do
793 if [[ -f "${file}" && "${force}" == "0" ]]; then
794 die "${FUNCNAME}(): '$1' already exists"
795 fi
796
797 if [[ "${quiet}" == "0" ]]; then
798 einfo "Generating '${file#${D%/}}' wrapper script"
799 fi
800
801 cat << EOF > "${file}"
802#!/usr/bin/env python
803# Gentoo '${file##*/}' wrapper script
804
805import os
806import re
807import subprocess
808import sys
809
810EPYTHON_re = re.compile(r"^python(\d+\.\d+)$")
811
812EOF
813 if [[ "$?" != "0" ]]; then
814 die "${FUNCNAME}(): Generation of '$1' failed"
815 fi
816 if [[ "${respect_EPYTHON}" == "1" ]]; then
817 cat << EOF >> "${file}"
818EPYTHON = os.environ.get("EPYTHON")
819if EPYTHON:
820 EPYTHON_matched = EPYTHON_re.match(EPYTHON)
821 if EPYTHON_matched:
822 PYTHON_ABI = EPYTHON_matched.group(1)
823 else:
824 sys.stderr.write("EPYTHON variable has unrecognized value '%s'\n" % EPYTHON)
825 sys.exit(1)
826else:
827 try:
828 eselect_process = subprocess.Popen(["/usr/bin/eselect", "python", "show"${eselect_python_option:+, $(echo "\"")}${eselect_python_option}${eselect_python_option:+$(echo "\"")}], stdout=subprocess.PIPE)
829 if eselect_process.wait() != 0:
830 raise ValueError
831 except (OSError, ValueError):
832 sys.stderr.write("Execution of 'eselect python show${eselect_python_option:+ }${eselect_python_option}' failed\n")
833 sys.exit(1)
834
835 eselect_output = eselect_process.stdout.read()
836 if not isinstance(eselect_output, str):
837 # Python 3
838 eselect_output = eselect_output.decode()
839
840 EPYTHON_matched = EPYTHON_re.match(eselect_output)
841 if EPYTHON_matched:
842 PYTHON_ABI = EPYTHON_matched.group(1)
843 else:
844 sys.stderr.write("'eselect python show${eselect_python_option:+ }${eselect_python_option}' printed unrecognized value '%s" % eselect_output)
845 sys.exit(1)
846EOF
847 if [[ "$?" != "0" ]]; then
848 die "${FUNCNAME}(): Generation of '$1' failed"
849 fi
850 else
851 cat << EOF >> "${file}"
852try:
853 eselect_process = subprocess.Popen(["/usr/bin/eselect", "python", "show"${eselect_python_option:+, $(echo "\"")}${eselect_python_option}${eselect_python_option:+$(echo "\"")}], stdout=subprocess.PIPE)
854 if eselect_process.wait() != 0:
855 raise ValueError
856except (OSError, ValueError):
857 sys.stderr.write("Execution of 'eselect python show${eselect_python_option:+ }${eselect_python_option}' failed\n")
858 sys.exit(1)
859
860eselect_output = eselect_process.stdout.read()
861if not isinstance(eselect_output, str):
862 # Python 3
863 eselect_output = eselect_output.decode()
864
865EPYTHON_matched = EPYTHON_re.match(eselect_output)
866if EPYTHON_matched:
867 PYTHON_ABI = EPYTHON_matched.group(1)
868else:
869 sys.stderr.write("'eselect python show${eselect_python_option:+ }${eselect_python_option}' printed unrecognized value '%s" % eselect_output)
870 sys.exit(1)
871EOF
872 if [[ "$?" != "0" ]]; then
873 die "${FUNCNAME}(): Generation of '$1' failed"
874 fi
875 fi
876 cat << EOF >> "${file}"
877
878target_executable = "%s-%s" % (sys.argv[0], PYTHON_ABI)
879if not os.path.exists(target_executable):
880 sys.stderr.write("'%s' does not exist\n" % target_executable)
881 sys.exit(1)
882
883os.execv(target_executable, sys.argv)
884EOF
885 if [[ "$?" != "0" ]]; then
886 die "${FUNCNAME}(): Generation of '$1' failed"
887 fi
888 fperms +x "${file#${D%/}}" || die "fperms '${file}' failed"
889 done
890}
891
892# @ECLASS-VARIABLE: PYTHON_USE_WITH
893# @DESCRIPTION:
894# Set this to a space separated list of use flags
895# the python slot in use must be built with.
896
897# @ECLASS-VARIABLE: PYTHON_USE_WITH_OR
898# @DESCRIPTION:
899# Set this to a space separated list of use flags
900# of which one must be turned on for the slot of
901# in use.
902
903# @ECLASS-VARIABLE: PYTHON_USE_WITH_OPT
904# @DESCRIPTION:
905# Set this if you need to make either PYTHON_USE_WITH or
906# PYTHON_USE_WITH_OR atoms conditional under a use flag.
907
908# @FUNCTION: python_pkg_setup
909# @DESCRIPTION:
910# Makes sure PYTHON_USE_WITH or PYTHON_USE_WITH_OR listed use flags
911# are respected. Only exported if one of those variables is set.
912if ! has "${EAPI:-0}" 0 1 && [[ -n ${PYTHON_USE_WITH} || -n ${PYTHON_USE_WITH_OR} ]]; then
913 python_pkg_setup() {
914 python_pkg_setup_fail() {
915 eerror "${1}"
916 die "${1}"
917 }
918
919 [[ ${PYTHON_USE_WITH_OPT} ]] && use !${PYTHON_USE_WITH_OPT} && return
920
921 python_pkg_setup_check_USE_flags() {
922 local pyatom use
923 if [[ -n "${PYTHON_ABI}" ]]; then
924 pyatom="dev-lang/python:${PYTHON_ABI}"
925 else
926 python_version
927 pyatom="dev-lang/python:${PYVER}"
928 fi
929
930 for use in ${PYTHON_USE_WITH}; do
931 if ! has_version "${pyatom}[${use}]"; then
932 python_pkg_setup_fail "Please rebuild ${pyatom} with the following USE flags enabled: ${PYTHON_USE_WITH}"
933 fi
934 done
935
936 for use in ${PYTHON_USE_WITH_OR}; do
937 if has_version "${pyatom}[${use}]"; then
938 return
939 fi
940 done
941
942 if [[ ${PYTHON_USE_WITH_OR} ]]; then
943 python_pkg_setup_fail "Please rebuild ${pyatom} with at least one of the following USE flags enabled: ${PYTHON_USE_WITH_OR}"
944 fi
945 }
946
947 if ! has "${EAPI:-0}" 0 1 2 || [[ -n "${SUPPORT_PYTHON_ABIS}" ]]; then
948 python_execute_function -q python_pkg_setup_check_USE_flags
949 else
950 python_pkg_setup_check_USE_flags
951 fi
952 }
953
954 EXPORT_FUNCTIONS pkg_setup
955
956 if [[ -n "${PYTHON_USE_WITH}" ]]; then
957 PYTHON_USE_WITH_ATOM="${PYTHON_ATOM}[${PYTHON_USE_WITH/ /,}]"
958 elif [[ -n "${PYTHON_USE_WITH_OR}" ]]; then
959 PYTHON_USE_WITH_ATOM="|| ( "
960 for use in ${PYTHON_USE_WITH_OR}; do
961 PYTHON_USE_WITH_ATOM+=" ${PYTHON_ATOM}[${use}]"
962 done
963 unset use
964 PYTHON_USE_WITH_ATOM+=" )"
965 fi
966 if [[ -n "${PYTHON_USE_WITH_OPT}" ]]; then
967 PYTHON_USE_WITH_ATOM="${PYTHON_USE_WITH_OPT}? ( ${PYTHON_USE_WITH_ATOM} )"
968 fi
969 DEPEND+=" ${PYTHON_USE_WITH_ATOM}"
970 RDEPEND+=" ${PYTHON_USE_WITH_ATOM}"
971fi
972
973# @ECLASS-VARIABLE: PYTHON_DEFINE_DEFAULT_FUNCTIONS
974# @DESCRIPTION:
975# Set this to define default functions for the following ebuild phases:
976# src_prepare, src_configure, src_compile, src_test, src_install.
977if ! has "${EAPI:-0}" 0 1 && [[ -n "${PYTHON_DEFINE_DEFAULT_FUNCTIONS}" ]]; then
978 python_src_prepare() {
979 python_copy_sources
980 }
981
982 for python_default_function in src_configure src_compile src_test src_install; do
983 eval "python_${python_default_function}() { python_execute_function -d -s; }"
984 done
985 unset python_default_function
986
987 EXPORT_FUNCTIONS src_prepare src_configure src_compile src_test src_install
988fi
989
990# @FUNCTION: python_disable_pyc
991# @DESCRIPTION:
992# Tell Python not to automatically recompile modules to .pyc/.pyo
993# even if the timestamps/version stamps don't match. This is done
994# to protect sandbox.
995python_disable_pyc() {
996 export PYTHONDONTWRITEBYTECODE="1"
997}
998
83# @FUNCTION: python_makesym 999# @FUNCTION: python_enable_pyc
84# @DESCRIPTION: 1000# @DESCRIPTION:
85# Run without arguments, it will create the /usr/bin/python symlinks 1001# Tell Python to automatically recompile modules to .pyc/.pyo if the
86# to the latest installed version 1002# timestamps/version stamps have changed.
87python_makesym() { 1003python_enable_pyc() {
88 alternatives_auto_makesym "/usr/bin/python" "python[0-9].[0-9]" 1004 unset PYTHONDONTWRITEBYTECODE
89 alternatives_auto_makesym "/usr/bin/python2" "python2.[0-9]" 1005}
1006
1007# @FUNCTION: python_need_rebuild
1008# @DESCRIPTION: Run without arguments, specifies that the package should be
1009# rebuilt after a python upgrade.
1010python_need_rebuild() {
1011 python_version
1012 export PYTHON_NEED_REBUILD=${PYVER}
1013}
1014
1015# @FUNCTION: python_get_includedir
1016# @DESCRIPTION:
1017# Run without arguments, returns the Python include directory.
1018python_get_includedir() {
1019 if [[ -n "${PYTHON_ABI}" ]]; then
1020 echo "/usr/include/python${PYTHON_ABI}"
1021 else
1022 python_version
1023 echo "/usr/include/python${PYVER}"
1024 fi
1025}
1026
1027# @FUNCTION: python_get_libdir
1028# @DESCRIPTION:
1029# Run without arguments, returns the Python library directory.
1030python_get_libdir() {
1031 if [[ -n "${PYTHON_ABI}" ]]; then
1032 echo "/usr/$(get_libdir)/python${PYTHON_ABI}"
1033 else
1034 python_version
1035 echo "/usr/$(get_libdir)/python${PYVER}"
1036 fi
1037}
1038
1039# @FUNCTION: python_get_sitedir
1040# @DESCRIPTION:
1041# Run without arguments, returns the Python site-packages directory.
1042python_get_sitedir() {
1043 echo "$(python_get_libdir)/site-packages"
90} 1044}
91 1045
92# @FUNCTION: python_tkinter_exists 1046# @FUNCTION: python_tkinter_exists
93# @DESCRIPTION: 1047# @DESCRIPTION:
94# Run without arguments, checks if python was compiled with Tkinter 1048# Run without arguments, checks if python was compiled with Tkinter
102 die "missing tkinter support with installed python" 1056 die "missing tkinter support with installed python"
103 fi 1057 fi
104} 1058}
105 1059
106# @FUNCTION: python_mod_exists 1060# @FUNCTION: python_mod_exists
107# @USAGE: < module > 1061# @USAGE: <module>
108# @DESCRIPTION: 1062# @DESCRIPTION:
109# Run with the module name as an argument. it will check if a 1063# Run with the module name as an argument. it will check if a
110# python module is installed and loadable. it will return 1064# python module is installed and loadable. it will return
111# TRUE(0) if the module exists, and FALSE(1) if the module does 1065# TRUE(0) if the module exists, and FALSE(1) if the module does
112# not exist. 1066# not exist.
114# Example: 1068# Example:
115# if python_mod_exists gtk; then 1069# if python_mod_exists gtk; then
116# echo "gtk support enabled" 1070# echo "gtk support enabled"
117# fi 1071# fi
118python_mod_exists() { 1072python_mod_exists() {
119 [ -z "$1" ] && die "${FUNCTION} requires an argument!" 1073 [[ "$1" ]] || die "${FUNCNAME} requires an argument!"
120 if ! python -c "import $1" >/dev/null 2>&1; then 1074 python -c "import $1" &>/dev/null
121 return 1
122 fi
123 return 0
124} 1075}
125 1076
126# @FUNCTION: python_mod_compile 1077# @FUNCTION: python_mod_compile
127# @USAGE: < file > [more files ...] 1078# @USAGE: <file> [more files ...]
128# @DESCRIPTION: 1079# @DESCRIPTION:
129# Given filenames, it will pre-compile the module's .pyc and .pyo. 1080# Given filenames, it will pre-compile the module's .pyc and .pyo.
130# This function should only be run in pkg_postinst() 1081# This function should only be run in pkg_postinst()
131# 1082#
132# Example: 1083# Example:
133# python_mod_compile /usr/lib/python2.3/site-packages/pygoogle.py 1084# python_mod_compile /usr/lib/python2.3/site-packages/pygoogle.py
134# 1085#
135python_mod_compile() { 1086python_mod_compile() {
136 local f myroot 1087 if ! has "${EAPI:-0}" 0 1 2 || [[ -n "${SUPPORT_PYTHON_ABIS}" ]]; then
1088 die "${FUNCNAME}() cannot be used in this EAPI"
1089 fi
1090
1091 local f myroot myfiles=()
137 1092
138 # Check if phase is pkg_postinst() 1093 # Check if phase is pkg_postinst()
139 [[ ${EBUILD_PHASE} != postinst ]] &&\ 1094 [[ ${EBUILD_PHASE} != postinst ]] &&\
140 die "${FUNCNAME} should only be run in pkg_postinst()" 1095 die "${FUNCNAME} should only be run in pkg_postinst()"
141 1096
142 # allow compiling for older python versions
143 if [ -n "${PYTHON_OVERRIDE_PYVER}" ]; then 1097 if [[ -n "${PYTHON_ABI}" ]]; then
144 PYVER=${PYTHON_OVERRIDE_PYVER} 1098 PYVER="${PYTHON_ABI}"
145 else 1099 else
146 python_version 1100 python_version
147 fi 1101 fi
148 1102
149 # strip trailing slash 1103 # strip trailing slash
150 myroot="${ROOT%/}" 1104 myroot="${ROOT%/}"
151 1105
152 # respect ROOT 1106 # respect ROOT
153 for f in $@; do 1107 for f in "$@"; do
154 [ -f "${myroot}/${f}" ] && myfiles="${myfiles} ${myroot}/${f}" 1108 [[ -f "${myroot}/${f}" ]] && myfiles+=("${myroot}/${f}")
155 done 1109 done
156 1110
157 if [ -n "${myfiles}" ]; then 1111 if ((${#myfiles[@]})); then
158 python${PYVER} ${myroot}/usr/$(get_libdir)/python${PYVER}/py_compile.py ${myfiles} 1112 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} 1113 python${PYVER} -O ${myroot}/usr/$(get_libdir)/python${PYVER}/py_compile.py "${myfiles[@]}" &> /dev/null
160 else 1114 else
161 ewarn "No files to compile!" 1115 ewarn "No files to compile!"
162 fi 1116 fi
163} 1117}
164 1118
165# @FUNCTION: python_mod_optimize 1119# @FUNCTION: python_mod_optimize
166# @USAGE: [ path ] 1120# @USAGE: [options] [directory|file]
167# @DESCRIPTION: 1121# @DESCRIPTION:
168# If no arguments supplied, it will recompile all modules under 1122# 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/ ..) 1123# under sys.path (eg. /usr/lib/python2.6, /usr/lib/python2.6/site-packages).
170# no recursively
171# 1124#
172# If supplied with arguments, it will recompile all modules recursively 1125# If supplied with arguments, it will recompile all modules recursively
173# in the supplied directory 1126# in the supplied directory.
174# This function should only be run in pkg_postinst() 1127# This function should only be run in pkg_postinst().
175# 1128#
176# Options passed to this function are passed to compileall.py 1129# Options passed to this function are passed to compileall.py.
177# 1130#
178# Example: 1131# Example:
179# python_mod_optimize /usr/share/codegen 1132# python_mod_optimize ctypesgencore
180python_mod_optimize() { 1133python_mod_optimize() {
181 local mydirs myfiles myroot myopts
182
183 # Check if phase is pkg_postinst() 1134 # Check if phase is pkg_postinst().
184 [[ ${EBUILD_PHASE} != postinst ]] &&\ 1135 [[ ${EBUILD_PHASE} != "postinst" ]] && die "${FUNCNAME} should only be run in pkg_postinst()"
185 die "${FUNCNAME} should only be run in pkg_postinst()"
186 1136
1137 if ! has "${EAPI:-0}" 0 1 2 || [[ -n "${SUPPORT_PYTHON_ABIS}" ]]; then
1138 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=()
1139
1140 # Strip trailing slash from ROOT.
1141 root="${ROOT%/}"
1142
1143 # Respect ROOT and options passed to compileall.py.
1144 while (($#)); do
1145 case "$1" in
1146 -l|-f|-q)
1147 options+=("$1")
1148 ;;
1149 -d|-x)
1150 options+=("$1" "$2")
1151 shift
1152 ;;
1153 -*)
1154 ewarn "${FUNCNAME}: Ignoring compile option $1"
1155 ;;
1156 *)
1157 if [[ "$1" =~ ^/usr/lib(32|64)?/python[[:digit:]]+\.[[:digit:]]+ ]]; then
1158 die "${FUNCNAME} doesn't support absolute paths of directories/files in site-packages directories"
1159 elif [[ "$1" =~ ^/ ]]; then
1160 if [[ -d "${root}/$1" ]]; then
1161 other_dirs+=("${root}/$1")
1162 elif [[ -f "${root}/$1" ]]; then
1163 other_files+=("${root}/$1")
1164 elif [[ -e "${root}/$1" ]]; then
1165 ewarn "'${root}/$1' is not a file or a directory!"
1166 else
1167 ewarn "'${root}/$1' doesn't exist!"
1168 fi
1169 else
1170 for PYTHON_ABI in ${PYTHON_ABIS}; do
1171 if [[ -d "${root}$(python_get_sitedir)/$1" ]]; then
1172 site_packages_dirs+=("$1")
1173 break
1174 elif [[ -f "${root}$(python_get_sitedir)/$1" ]]; then
1175 site_packages_files+=("$1")
1176 break
1177 elif [[ -e "${root}$(python_get_sitedir)/$1" ]]; then
1178 ewarn "'$1' is not a file or a directory!"
1179 else
1180 ewarn "'$1' doesn't exist!"
1181 fi
1182 done
1183 fi
1184 ;;
1185 esac
1186 shift
1187 done
1188
1189 # Set additional options.
1190 options+=("-q")
1191
1192 for PYTHON_ABI in ${PYTHON_ABIS}; do
1193 if ((${#site_packages_dirs[@]})) || ((${#site_packages_files[@]})); then
1194 return_code="0"
1195 ebegin "Compilation and optimization of Python modules for Python ${PYTHON_ABI}"
1196 if ((${#site_packages_dirs[@]})); then
1197 for dir in "${site_packages_dirs[@]}"; do
1198 site_packages_absolute_dirs+=("${root}$(python_get_sitedir)/${dir}")
1199 done
1200 "$(PYTHON)" "${root}$(python_get_libdir)/compileall.py" "${options[@]}" "${site_packages_absolute_dirs[@]}" || return_code="1"
1201 "$(PYTHON)" -O "${root}$(python_get_libdir)/compileall.py" "${options[@]}" "${site_packages_absolute_dirs[@]}" &> /dev/null || return_code="1"
1202 fi
1203 if ((${#site_packages_files[@]})); then
1204 for file in "${site_packages_files[@]}"; do
1205 site_packages_absolute_files+=("${root}$(python_get_sitedir)/${file}")
1206 done
1207 "$(PYTHON)" "${root}$(python_get_libdir)/py_compile.py" "${site_packages_absolute_files[@]}" || return_code="1"
1208 "$(PYTHON)" -O "${root}$(python_get_libdir)/py_compile.py" "${site_packages_absolute_files[@]}" &> /dev/null || return_code="1"
1209 fi
1210 eend "${return_code}"
1211 fi
1212 unset site_packages_absolute_dirs site_packages_absolute_files
1213 done
1214
1215 # Don't use PYTHON_ABI in next calls to python_get_libdir().
1216 unset PYTHON_ABI
1217
1218 if ((${#other_dirs[@]})) || ((${#other_files[@]})); then
1219 return_code="0"
1220 ebegin "Compilation and optimization of Python modules placed outside of site-packages directories for Python ${PYVER}"
1221 if ((${#other_dirs[@]})); then
1222 python${PYVER} "${root}$(python_get_libdir)/compileall.py" "${options[@]}" "${other_dirs[@]}" || return_code="1"
1223 python${PYVER} -O "${root}$(python_get_libdir)/compileall.py" "${options[@]}" "${other_dirs[@]}" &> /dev/null || return_code="1"
1224 fi
1225 if ((${#other_files[@]})); then
1226 python${PYVER} "${root}$(python_get_libdir)/py_compile.py" "${other_files[@]}" || return_code="1"
1227 python${PYVER} -O "${root}$(python_get_libdir)/py_compile.py" "${other_files[@]}" &> /dev/null || return_code="1"
1228 fi
1229 eend "${return_code}"
1230 fi
1231 else
1232 local myroot mydirs=() myfiles=() myopts=() return_code="0"
1233
187 # strip trailing slash 1234 # strip trailing slash
188 myroot="${ROOT%/}" 1235 myroot="${ROOT%/}"
189 1236
190 # respect ROOT and options passed to compileall.py 1237 # respect ROOT and options passed to compileall.py
191 while [ $# -gt 0 ]; do 1238 while (($#)); do
192 case $1 in 1239 case "$1" in
193 -l|-f|-q) 1240 -l|-f|-q)
194 myopts="${myopts} $1" 1241 myopts+=("$1")
195 ;; 1242 ;;
196 -d|-x) 1243 -d|-x)
197 myopts="${myopts} $1 $2" 1244 myopts+=("$1" "$2")
1245 shift
1246 ;;
1247 -*)
1248 ewarn "${FUNCNAME}: Ignoring compile option $1"
1249 ;;
1250 *)
1251 if [[ -d "${myroot}"/$1 ]]; then
1252 mydirs+=("${myroot}/$1")
1253 elif [[ -f "${myroot}"/$1 ]]; then
1254 # Files are passed to python_mod_compile which is ROOT-aware
1255 myfiles+=("$1")
1256 elif [[ -e "${myroot}/$1" ]]; then
1257 ewarn "${myroot}/$1 is not a file or directory!"
1258 else
1259 ewarn "${myroot}/$1 doesn't exist!"
1260 fi
1261 ;;
1262 esac
1263 shift
1264 done
1265
1266 if [[ -n "${PYTHON_ABI}" ]]; then
1267 PYVER="${PYTHON_ABI}"
1268 else
1269 python_version
1270 fi
1271
1272 # set additional opts
1273 myopts+=(-q)
1274
1275 ebegin "Compilation and optimization of Python modules for Python ${PYVER}"
1276 if ((${#mydirs[@]})); then
1277 python${PYVER} \
1278 "${myroot}"/usr/$(get_libdir)/python${PYVER}/compileall.py \
1279 "${myopts[@]}" "${mydirs[@]}" || return_code="1"
1280 python${PYVER} -O \
1281 "${myroot}"/usr/$(get_libdir)/python${PYVER}/compileall.py \
1282 "${myopts[@]}" "${mydirs[@]}" &> /dev/null || return_code="1"
1283 fi
1284
1285 if ((${#myfiles[@]})); then
1286 python_mod_compile "${myfiles[@]}"
1287 fi
1288
1289 eend "${return_code}"
1290 fi
1291}
1292
1293# @FUNCTION: python_mod_cleanup
1294# @USAGE: [directory|file]
1295# @DESCRIPTION:
1296# Run with optional arguments, where arguments are Python modules. If none given,
1297# it will look in /usr/lib/python[0-9].[0-9].
1298#
1299# It will recursively scan all compiled Python modules in the directories and
1300# determine if they are orphaned (i.e. their corresponding .py files are missing.)
1301# If they are, then it will remove their corresponding .pyc and .pyo files.
1302#
1303# This function should only be run in pkg_postrm().
1304python_mod_cleanup() {
1305 local path py_file PYTHON_ABI SEARCH_PATH=() root
1306
1307 # Check if phase is pkg_postrm().
1308 [[ ${EBUILD_PHASE} != "postrm" ]] && die "${FUNCNAME} should only be run in pkg_postrm()"
1309
1310 # Strip trailing slash from ROOT.
1311 root="${ROOT%/}"
1312
1313 if (($#)); then
1314 if ! has "${EAPI:-0}" 0 1 2 || [[ -n "${SUPPORT_PYTHON_ABIS}" ]]; then
1315 while (($#)); do
1316 if [[ "$1" =~ ^/usr/lib(32|64)?/python[[:digit:]]+\.[[:digit:]]+ ]]; then
1317 die "${FUNCNAME} doesn't support absolute paths of directories/files in site-packages directories"
1318 elif [[ "$1" =~ ^/ ]]; then
1319 SEARCH_PATH+=("${root}/${1#/}")
1320 else
1321 for PYTHON_ABI in ${PYTHON_ABIS}; do
1322 SEARCH_PATH+=("${root}$(python_get_sitedir)/$1")
1323 done
1324 fi
198 shift 1325 shift
199 ;;
200 -*)
201 ewarn "${FUNCNAME}: Ignoring compile option $1"
202 ;;
203 *)
204 [ ! -e "${myroot}/${1}" ] && ewarn "${myroot}/${1} doesn't exist!"
205 [ -d "${myroot}/${1#/}" ] && mydirs="${mydirs} ${myroot}/${1#/}"
206 # Files are passed to python_mod_compile which is ROOT-aware
207 [ -f "${myroot}/${1}" ] && myfiles="${myfiles} ${1}"
208 ;;
209 esac
210 shift
211 done 1326 done
212 1327 else
213 # allow compiling for older python versions 1328 SEARCH_PATH=("${@#/}")
214 if [ -n "${PYTHON_OVERRIDE_PYVER}" ]; then 1329 SEARCH_PATH=("${SEARCH_PATH[@]/#/${root}/}")
215 PYVER=${PYTHON_OVERRIDE_PYVER} 1330 fi
216 else 1331 else
217 python_version 1332 local dir sitedir
218 fi 1333 for dir in "${root}"/usr/lib*; do
219 1334 if [[ -d "${dir}" && ! -L "${dir}" ]]; then
220 # set additional opts 1335 for sitedir in "${dir}"/python*/site-packages; do
221 myopts="${myopts} -q"
222
223 ebegin "Byte compiling python modules for python-${PYVER} .."
224 if [ -n "${mydirs}" ]; then 1336 if [[ -d "${sitedir}" ]]; then
225 python${PYVER} \ 1337 SEARCH_PATH+=("${sitedir}")
226 ${myroot}/usr/$(get_libdir)/python${PYVER}/compileall.py \ 1338 fi
227 ${myopts} ${mydirs} 1339 done
228 python${PYVER} -O \
229 ${myroot}/usr/$(get_libdir)/python${PYVER}/compileall.py \
230 ${myopts} ${mydirs}
231 fi 1340 fi
232
233 if [ -n "${myfiles}" ]; then
234 python_mod_compile ${myfiles}
235 fi
236
237 eend $?
238}
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 1341 done
1342 fi
1343
1344 local BLUE CYAN NORMAL
1345 if [[ "${NOCOLOR:-false}" =~ ^(false|no)$ ]]; then
1346 BLUE=$'\e[1;34m'
1347 CYAN=$'\e[1;36m'
1348 NORMAL=$'\e[0m'
265 else 1349 else
266 for path in ${myroot}/usr/lib*/python*/site-packages; do 1350 BLUE=
267 SEARCH_PATH="${SEARCH_PATH} ${path}" 1351 CYAN=
268 done 1352 NORMAL=
269 fi 1353 fi
270 1354
271 for path in ${SEARCH_PATH}; do 1355 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 1356 if [[ -d "${path}" ]]; then
276 einfo "Purging ${src_py}[co]" 1357 find "${path}" -name '*.py[co]' -print0 | while read -rd ''; do
1358 py_file="${REPLY%[co]}"
1359 [[ -f "${py_file}" || (! -f "${py_file}c" && ! -f "${py_file}o") ]] && continue
1360 einfo "${BLUE}<<< ${py_file}[co]${NORMAL}"
277 rm -f ${src_py}[co] 1361 rm -f "${py_file}"[co]
278 fi
279 done 1362 done
1363
280 # attempt to remove directories that maybe empty 1364 # Attempt to delete directories, which may be empty.
281 for dir in $(find ${path} -type d | sort -r); do 1365 find "${path}" -type d | sort -r | while read -r dir; do
282 rmdir ${dir} 2>/dev/null 1366 rmdir "${dir}" 2>/dev/null && einfo "${CYAN}<<< ${dir}${NORMAL}"
283 done 1367 done
1368 elif [[ "${path}" == *.py && ! -f "${path}" && (-f "${path}c" || -f "${path}o") ]]; then
1369 einfo "${BLUE}<<< ${path}[co]${NORMAL}"
1370 rm -f "${path}"[co]
1371 fi
284 done 1372 done
285} 1373}

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

  ViewVC Help
Powered by ViewVC 1.1.20