Gentoo Archives: gentoo-commits

From: Krzysztof Pawlik <nelchael@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] dev/nelchael:master commit in: eclass/, profiles/desc/
Date: Tue, 28 Feb 2012 20:52:44
Message-Id: 1330259923.3de95e7b7cf8f25749d29b698963d019961d95d8.nelchael@gentoo
1 commit: 3de95e7b7cf8f25749d29b698963d019961d95d8
2 Author: Krzysztof Pawlik <none <AT> none>
3 AuthorDate: Sun Feb 26 12:38:43 2012 +0000
4 Commit: Krzysztof Pawlik <nelchael <AT> gentoo <DOT> org>
5 CommitDate: Sun Feb 26 12:38:43 2012 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=dev/nelchael.git;a=commit;h=3de95e7b
7
8 Add a new Python-distutils eclass for Python, distutils-based packages.
9
10 ---
11 eclass/python-distutils-ng.eclass | 375 +++++++++++++++++++++++++++++++++++++
12 profiles/desc/python_targets.desc | 14 ++
13 2 files changed, 389 insertions(+), 0 deletions(-)
14
15 diff --git a/eclass/python-distutils-ng.eclass b/eclass/python-distutils-ng.eclass
16 new file mode 100644
17 index 0000000..880b525
18 --- /dev/null
19 +++ b/eclass/python-distutils-ng.eclass
20 @@ -0,0 +1,375 @@
21 +# Copyright 1999-2012 Gentoo Foundation
22 +# Distributed under the terms of the GNU General Public License v2
23 +# $Header$
24 +
25 +# @ECLASS: python-distutils-ng
26 +# @MAINTAINER:
27 +# Python herd <python@g.o>
28 +# @AUTHOR:
29 +# Author: Krzysztof Pawlik <nelchael@g.o>
30 +# @BLURB: An eclass for installing Python packages using distutils with proper
31 +# support for multiple Python slots.
32 +# @DESCRIPTION:
33 +# The Python eclass is designed to allow an easier installation of Python
34 +# packages and their incorporation into the Gentoo Linux system.
35 +#
36 +# TODO: Document implementations!
37 +
38 +# @ECLASS-VARIABLE: USE_PYTHON
39 +# @DESCRIPTION:
40 +# This variable contains a space separated list of targets (see above) a package
41 +# is compatible to. It must be set before the `inherit' call. The default is to
42 +# enable all targets.
43 +
44 +if [[ -z "${USE_PYTHON}" ]]; then
45 + # Default: pure python, support all implementations
46 + USE_PYTHON=" python25 python26 python27"
47 + USE_PYTHON+=" python31 python32"
48 + USE_PYTHON+=" jython25"
49 + USE_PYTHON+=" pypy17 pypy18"
50 +fi
51 +
52 +# @ECLASS-VARIABLE: PYTHON_OPTIONAL
53 +# @DESCRIPTION:
54 +# Set the value to "yes" to make the dependency on a Python interpreter
55 +# optional.
56 +
57 +# @ECLASS-VARIABLE: PYTHON_DISABLE_COMPILATION
58 +# @DESCRIPTION:
59 +# Set the value to "yes" to skip compilation and/or optimization of Python
60 +# modules.
61 +
62 +EXPORT_FUNCTIONS src_unpack src_prepare src_configure src_compile src_test src_install
63 +
64 +case "${EAPI}" in
65 + 0|1|2|3)
66 + die "Unsupported EAPI=${EAPI} (too old) for python-distutils-ng.eclass" ;;
67 + 4)
68 + # EAPI=4 needed for REQUIRED_USE
69 + S="${S:-${WORKDIR}/${P}}"
70 + ;;
71 + *)
72 + die "Unsupported EAPI=${EAPI} (unknown) for python-distutils-ng.eclass" ;;
73 +esac
74 +
75 +# @FUNCTION: _python-distutils-ng_generate_depend
76 +# @USAGE: implementation
77 +# @RETURN: Package atom of a Python implementation for *DEPEND.
78 +# @DESCRIPTION:
79 +# This function returns the full package atom of a Python implementation.
80 +#
81 +# `implementation' has to be one of the valid values for USE_PYTHON.
82 +_python-distutils-ng_generate_depend() {
83 + case "${1}" in
84 + python??)
85 + echo "dev-lang/${1::-2}:${1: -2:-1}.${1: -1}" ;;
86 + jython??)
87 + echo "dev-java/${1::-2}:${1: -2:-1}.${1: -1}" ;;
88 + pypy??)
89 + echo "dev-python/${1::-2}:${1: -2:-1}.${1: -1}" ;;
90 + *)
91 + die "Unsupported implementation: ${1}" ;;
92 + esac
93 +}
94 +
95 +# @FUNCTION: _python-distutils-ng_get_binary_for_implementation
96 +# @USAGE: implementation
97 +# @RETURN: Full path to Python binary for given implementation.
98 +# @DESCRIPTION:
99 +# This function returns full path for Python binary for given implementation.
100 +#
101 +# Binary returned by this function should be used instead of simply calling
102 +# `python'.
103 +_python-distutils-ng_get_binary_for_implementation() {
104 + case "${1}" in
105 + python??|jython??)
106 + echo "/usr/bin/${1::-1}.${1: -1}" ;;
107 + pypy??)
108 + echo "TODO" ;;
109 + *)
110 + die "Unsupported implementation: ${1}" ;;
111 + esac
112 +}
113 +
114 +required_use_str=" || (
115 + python_targets_python25 python_targets_python26 python_targets_python27
116 + python_targets_python31 python_targets_python32
117 + python_targets_jython25
118 + python_targets_pypy17 python_targets_pypy18 )"
119 +if [[ "${PYTHON_OPTIONAL}" = "yes" ]]; then
120 + IUSE+="python"
121 + REQUIRED_USE+=" python? ( ${required_use_str} )"
122 +else
123 + REQUIRED_USE+="${required_use_str}"
124 +fi
125 +
126 +for impl in ${USE_PYTHON}; do
127 + IUSE+=" python_targets_${impl} "
128 + local dep_str="python_targets_${impl}? ( $(_python-distutils-ng_generate_depend "${impl}") )"
129 +
130 + if [[ "${PYTHON_OPTIONAL}" = "yes" ]]; then
131 + RDEPEND="${RDEPEND} python? ( ${dep_str} )"
132 + DEPEND="${DEPEND} python? ( ${dep_str} )"
133 + else
134 + RDEPEND="${RDEPEND} ${dep_str}"
135 + DEPEND="${DEPEND} ${dep_str}"
136 + fi
137 +done
138 +
139 +PACKAGE_SPECIFIC_S="${S#${WORKDIR}/}"
140 +
141 +# @FUNCTION: _python-distutils-ng_run_for_impl
142 +# @USAGE: implementation command_to_run
143 +# @DESCRIPTION:
144 +# Run command_to_run using specified Python implementation.
145 +#
146 +# This will run the command_to_run in implementation-specific working directory.
147 +_python-distutils-ng_run_for_impl() {
148 + local impl="${1}"
149 + local command="${2}"
150 +
151 + S="${WORKDIR}/impl_${impl}/${PACKAGE_SPECIFIC_S}"
152 + PYTHON="$(_python-distutils-ng_get_binary_for_implementation "${impl}")"
153 +
154 + einfo "Running ${command} in ${S} for ${impl}"
155 +
156 + pushd "${S}" &> /dev/null
157 + "${command}" "${impl}" "${PYTHON}"
158 + popd &> /dev/null
159 +}
160 +
161 +# @FUNCTION: _python-distutils-ng_run_for_all_impls
162 +# @USAGE: command_to_run
163 +# @DESCRIPTION:
164 +# Run command_to_run for all enabled Python implementations.
165 +#
166 +# See also _python-distutils-ng_run_for_impl
167 +_python-distutils-ng_run_for_all_impls() {
168 + local command="${1}"
169 +
170 + for impl in ${USE_PYTHON}; do
171 + use "python_targets_${impl}" ${USE_PYTHON} || continue
172 + _python-distutils-ng_run_for_impl "${impl}" "${command}"
173 + done
174 +}
175 +
176 +# @FUNCTION: _python-distutils-ng_default_distutils_compile
177 +# @DESCRIPTION:
178 +# Default src_compile for distutils-based packages.
179 +_python-distutils-ng_default_distutils_compile() {
180 + "${PYTHON}" setup.py build || die
181 +}
182 +
183 +# @FUNCTION: _python-distutils-ng_default_distutils_install
184 +# @DESCRIPTION:
185 +# Default src_install for distutils-based packages.
186 +_python-distutils-ng_default_distutils_install() {
187 + "${PYTHON}" setup.py install --no-compile --root="${D}/" || die
188 +}
189 +
190 +# @FUNCTION: _python-distutils-ng_has_compileall
191 +# @USAGE: implementation
192 +# @RETURN: 0 if given implementation has compileall module
193 +# @DESCRIPTION:
194 +# This function is used to decide whenever to compile Python modules for given
195 +# implementation.
196 +_python-distutils-ng_has_compileall() {
197 + case "${1}" in
198 + python??|jython??)
199 + return 0 ;;
200 + *)
201 + return 1 ;;
202 + esac
203 +}
204 +
205 +# @FUNCTION: _python-distutils-ng_has_compileall_opt
206 +# @USAGE: implementation
207 +# @RETURN: 0 if given implementation has compileall module and supports # optimizations
208 +# @DESCRIPTION:
209 +# This function is used to decide whenever to compile and optimize Python
210 +# modules for given implementation.
211 +_python-distutils-ng_has_compileall_opt() {
212 + case "${1}" in
213 + python??)
214 + return 0 ;;
215 + *)
216 + return 1 ;;
217 + esac
218 +}
219 +
220 +# @FUNCTION: python-distutils-ng_doscript
221 +# @USAGE: script_file_name
222 +# @DESCRIPTION:
223 +# Install given script file in /usr/bin/ for all enabled implementations using
224 +# original script name as a base name.
225 +#
226 +# See also python-distutils-ng_newscript
227 +python-distutils-ng_doscript() {
228 + python-distutils-ng_newscript "${1}" "$(basename "${1}")"
229 +}
230 +
231 +# @FUNCTION: python-distutils-ng_newscript
232 +# @USAGE: script_file_name new_file_name
233 +# @DESCRIPTION:
234 +# Install given script file in /usr/bin/ for all enabled implementations using
235 +# new_file_name as a base name.
236 +#
237 +# Each script copy will have the name mangled to "new_file_name-IMPLEMENTATION"
238 +# and new hash-bang line will be inserted to reference specific Python
239 +# interpreter.
240 +#
241 +# There will be also a symlink with name equal to new_file_name that will be a
242 +# symlink to default implementation, which defaults to value of
243 +# PYTHON_DEFAULT_IMPLEMENTATION, if not specified the function will pick default
244 +# implementation: it will the be first enabled from the following list:
245 +# python27, python26, python25, python32, python31, pypy18, pypy17, jython25
246 +python-distutils-ng_newscript() {
247 + [[ -n "${1}" ]] || die "Missing source file name"
248 + [[ -n "${2}" ]] || die "Missing destination file name"
249 + local source_file="${1}"
250 + local destination_file="${2}"
251 + local default_impl="${PYTHON_DEFAULT_IMPLEMENTATION}"
252 +
253 + if [[ -z "${default_impl}" ]]; then
254 + # TODO: Pick default implementation
255 + for impl in python{27,26,25,32,21} pypy{18,17} jython25; do
256 + use "python_targets_${impl}" || continue
257 + default_impl="${impl}"
258 + break;
259 + done
260 + else
261 + use "python_targets_${impl}" || \
262 + die "default implementation ${default_impl} not enabled"
263 + fi
264 +
265 + [[ -n "${default_impl}" ]] || die "Could not select default implementation"
266 +
267 + einfo "Installing ${source_file} for multiple implementations (default: ${default_impl})"
268 + insinto /usr/bin
269 + for impl in ${USE_PYTHON}; do
270 + use "python_targets_${impl}" ${USE_PYTHON} || continue
271 +
272 + newins "${source_file}" "${destination_file}-${impl}"
273 + fperms 755 "/usr/bin/${destination_file}-${impl}"
274 + sed -i \
275 + -e "1i#!$(_python-distutils-ng_get_binary_for_implementation "${impl}")" \
276 + "${D}/usr/bin/${destination_file}-${impl}" || die
277 + done
278 +
279 + dosym "${destination_file}-${default_impl}" "/usr/bin/${destination_file}"
280 +}
281 +
282 +# Phase function: src_unpack
283 +python-distutils-ng_src_unpack() {
284 + [[ "${PYTHON_OPTIONAL}" = "yes" ]] && { use python || return; }
285 +
286 + if type python_unpack &> /dev/null; then
287 + # This should not run anything specific to any single Python
288 + # implementation, keep it generic:
289 + python_unpack_all
290 + else
291 + [[ -n ${A} ]] && unpack ${A}
292 + fi
293 +}
294 +
295 +# Phase function: src_prepare
296 +python-distutils-ng_src_prepare() {
297 + [[ "${PYTHON_OPTIONAL}" = "yes" ]] && { use python || return; }
298 +
299 + # Try to run binary for each implementation:
300 + for impl in ${USE_PYTHON}; do
301 + use "python_targets_${impl}" ${USE_PYTHON} || continue
302 + $(_python-distutils-ng_get_binary_for_implementation "${impl}") \
303 + -c "import sys" || die
304 + done
305 +
306 + # Run prepare shared by all implementations:
307 + if type python_prepare_all &> /dev/null; then
308 + einfo "Running python_prepare_all in ${S} for all"
309 + python_prepare_all
310 + fi
311 +
312 + # Create a copy of S for each implementation:
313 + for impl in ${USE_PYTHON}; do
314 + use "python_targets_${impl}" ${USE_PYTHON} || continue
315 +
316 + einfo "Creating copy for ${impl} in ${WORKDIR}/impl_${impl}"
317 + mkdir -p "${WORKDIR}/impl_${impl}" || die
318 + cp -pr "${S}" "${WORKDIR}/impl_${impl}/${PACKAGE_SPECIFIC_S}" || die
319 + done
320 +
321 + # Run python_prepare for each implementation:
322 + if type python_prepare &> /dev/null; then
323 + _python-distutils-ng_run_for_all_impls python_prepare
324 + fi
325 +}
326 +
327 +# Phase function: src_configure
328 +python-distutils-ng_src_configure() {
329 + [[ "${PYTHON_OPTIONAL}" = "yes" ]] && { use python || return; }
330 +
331 + if type python_configure &> /dev/null; then
332 + _python-distutils-ng_run_for_all_impls python_configure
333 + fi
334 +}
335 +
336 +# Phase function: src_compile
337 +python-distutils-ng_src_compile() {
338 + [[ "${PYTHON_OPTIONAL}" = "yes" ]] && { use python || return; }
339 +
340 + if type python_compile &> /dev/null; then
341 + _python-distutils-ng_run_for_all_impls python_compile
342 + else
343 + _python-distutils-ng_run_for_all_impls \
344 + _python-distutils-ng_default_distutils_compile
345 + fi
346 +}
347 +
348 +# Phase function: src_test
349 +python-distutils-ng_src_test() {
350 + [[ "${PYTHON_OPTIONAL}" = "yes" ]] && { use python || return; }
351 +
352 + if type python_test &> /dev/null; then
353 + _python-distutils-ng_run_for_all_impls python_test
354 + fi
355 +}
356 +
357 +# Phase function: src_install
358 +python-distutils-ng_src_install() {
359 + [[ "${PYTHON_OPTIONAL}" = "yes" ]] && { use python || return; }
360 +
361 + if type python_install &> /dev/null; then
362 + _python-distutils-ng_run_for_all_impls python_install
363 + else
364 + _python-distutils-ng_run_for_all_impls \
365 + _python-distutils-ng_default_distutils_install
366 + fi
367 +
368 + S="${WORKDIR}/${PACKAGE_SPECIFIC_S}"
369 + if type python_install_all &> /dev/null; then
370 + einfo "Running python_install_all in ${S} for all"
371 + python_install_all
372 + fi
373 +
374 + for impl in ${USE_PYTHON}; do
375 + [[ "${PYTHON_DISABLE_COMPILATION}" = "yes" ]] && continue
376 + use "python_targets_${impl}" ${USE_PYTHON} || continue
377 +
378 + PYTHON="$(_python-distutils-ng_get_binary_for_implementation "${impl}")"
379 + for accessible_path in $(${PYTHON} -c 'import sys; print " ".join(sys.path)'); do
380 + [[ -d "${D}/${accessible_path}" ]] || continue
381 +
382 + _python-distutils-ng_has_compileall "${impl}" || continue
383 + ebegin "Compiling ${accessible_path} for ${impl}"
384 + ${PYTHON} \
385 + -m compileall -q -f "${D}/${accessible_path}" || die
386 + eend $?
387 +
388 + _python-distutils-ng_has_compileall_opt "${impl}" || continue
389 + ebegin "Optimizing ${accessible_path} for ${impl}"
390 + PYTHONOPTIMIZE=1 ${PYTHON} \
391 + -m compileall -q -f "${D}/${accessible_path}" || die
392 + eend $?
393 + done;
394 + done
395 +}
396
397 diff --git a/profiles/desc/python_targets.desc b/profiles/desc/python_targets.desc
398 new file mode 100644
399 index 0000000..350fa10
400 --- /dev/null
401 +++ b/profiles/desc/python_targets.desc
402 @@ -0,0 +1,14 @@
403 +# Copyright 2009-2012 Gentoo Foundation.
404 +# Distributed under the terms of the GNU General Public License v2
405 +# $Header$
406 +
407 +# This file contains descriptions of PYTHON_TARGETS USE_EXPAND flags.
408 +
409 +python25 - Build with Python 2.5
410 +python26 - Build with Python 2.6
411 +python27 - Build with Python 2.7
412 +python31 - Build with Python 3.1
413 +python32 - Build with Python 3.2
414 +jython25 - Build with Jythin 2.5
415 +pypy17 - Build with PyPy 1.7
416 +pypy18 - Build with PyPy 1.8