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

Contents of /eclass/python-distutils-ng.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (show annotations) (download)
Mon Mar 26 18:27:58 2012 UTC (2 years, 9 months ago) by nelchael
Branch: MAIN
Changes since 1.3: +7 -5 lines
Small fixes: use +=, cleanup used variables, white space.

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

  ViewVC Help
Powered by ViewVC 1.1.20