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

Diff of /eclass/python.eclass

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

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

Legend:
Removed from v.1.45  
changed lines
  Added in v.1.84

  ViewVC Help
Powered by ViewVC 1.1.20