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

Contents of /eclass/python.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.81 - (show annotations) (download)
Sun Nov 22 16:45:54 2009 UTC (5 years ago) by arfrever
Branch: MAIN
Changes since 1.80: +16 -4 lines
Support --source-dir option of python_execute_function().

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

  ViewVC Help
Powered by ViewVC 1.1.20