1 |
commit: 576b06627578c9846b2b265085c13509692ea49f |
2 |
Author: Sam James <sam <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sat Apr 10 07:08:52 2021 +0000 |
4 |
Commit: Sam James <sam <AT> gentoo <DOT> org> |
5 |
CommitDate: Sat Apr 10 07:08:52 2021 +0000 |
6 |
URL: https://gitweb.gentoo.org/repo/proj/prefix.git/commit/?id=576b0662 |
7 |
|
8 |
python-utils-r1.eclass: sync with ::gentoo |
9 |
|
10 |
Signed-off-by: Sam James <sam <AT> gentoo.org> |
11 |
|
12 |
eclass/python-utils-r1.eclass | 304 +++++++++++------------------------------- |
13 |
1 file changed, 81 insertions(+), 223 deletions(-) |
14 |
|
15 |
diff --git a/eclass/python-utils-r1.eclass b/eclass/python-utils-r1.eclass |
16 |
index 1b1f6b4d4b..88b258a7f6 100644 |
17 |
--- a/eclass/python-utils-r1.eclass |
18 |
+++ b/eclass/python-utils-r1.eclass |
19 |
@@ -1,4 +1,4 @@ |
20 |
-# Copyright 1999-2020 Gentoo Authors |
21 |
+# Copyright 1999-2021 Gentoo Authors |
22 |
# Distributed under the terms of the GNU General Public License v2 |
23 |
|
24 |
# @ECLASS: python-utils-r1.eclass |
25 |
@@ -7,7 +7,7 @@ |
26 |
# @AUTHOR: |
27 |
# Author: Michał Górny <mgorny@g.o> |
28 |
# Based on work of: Krzysztof Pawlik <nelchael@g.o> |
29 |
-# @SUPPORTED_EAPIS: 5 6 7 |
30 |
+# @SUPPORTED_EAPIS: 6 7 |
31 |
# @BLURB: Utility functions for packages with Python parts. |
32 |
# @DESCRIPTION: |
33 |
# A utility eclass providing functions to query Python implementations, |
34 |
@@ -19,9 +19,12 @@ |
35 |
# For more information, please see the Python Guide: |
36 |
# https://dev.gentoo.org/~mgorny/python-guide/ |
37 |
|
38 |
+# NOTE: When dropping support for EAPIs here, we need to update |
39 |
+# metadata/install-qa-check.d/60python-pyc |
40 |
+# See bug #704286, bug #781878 |
41 |
case "${EAPI:-0}" in |
42 |
- [0-4]) die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}" ;; |
43 |
- [5-7]) ;; |
44 |
+ [0-5]) die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}" ;; |
45 |
+ [6-7]) ;; |
46 |
*) die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" ;; |
47 |
esac |
48 |
|
49 |
@@ -31,7 +34,6 @@ fi |
50 |
|
51 |
if [[ ! ${_PYTHON_UTILS_R1} ]]; then |
52 |
|
53 |
-[[ ${EAPI} == 5 ]] && inherit eutils multilib |
54 |
inherit toolchain-funcs |
55 |
|
56 |
# @ECLASS-VARIABLE: _PYTHON_ALL_IMPLS |
57 |
@@ -40,8 +42,7 @@ inherit toolchain-funcs |
58 |
# All supported Python implementations, most preferred last. |
59 |
_PYTHON_ALL_IMPLS=( |
60 |
pypy3 |
61 |
- python2_7 |
62 |
- python3_6 python3_7 python3_8 python3_9 |
63 |
+ python3_7 python3_8 python3_9 |
64 |
) |
65 |
readonly _PYTHON_ALL_IMPLS |
66 |
|
67 |
@@ -52,8 +53,8 @@ readonly _PYTHON_ALL_IMPLS |
68 |
_PYTHON_HISTORICAL_IMPLS=( |
69 |
jython2_7 |
70 |
pypy pypy1_{8,9} pypy2_0 |
71 |
- python2_{5,6} |
72 |
- python3_{1,2,3,4,5} |
73 |
+ python2_{5..7} |
74 |
+ python3_{1..6} |
75 |
) |
76 |
readonly _PYTHON_HISTORICAL_IMPLS |
77 |
|
78 |
@@ -69,38 +70,6 @@ readonly _PYTHON_HISTORICAL_IMPLS |
79 |
# which can involve revisions of this eclass that support a different |
80 |
# set of Python implementations. |
81 |
|
82 |
-# @FUNCTION: _python_impl_supported |
83 |
-# @USAGE: <impl> |
84 |
-# @INTERNAL |
85 |
-# @DESCRIPTION: |
86 |
-# Check whether the implementation <impl> (PYTHON_COMPAT-form) |
87 |
-# is still supported. |
88 |
-# |
89 |
-# Returns 0 if the implementation is valid and supported. If it is |
90 |
-# unsupported, returns 1 -- and the caller should ignore the entry. |
91 |
-# If it is invalid, dies with an appopriate error messages. |
92 |
-_python_impl_supported() { |
93 |
- debug-print-function ${FUNCNAME} "${@}" |
94 |
- |
95 |
- [[ ${#} -eq 1 ]] || die "${FUNCNAME}: takes exactly 1 argument (impl)." |
96 |
- |
97 |
- local impl=${1} |
98 |
- |
99 |
- # keep in sync with _PYTHON_ALL_IMPLS! |
100 |
- # (not using that list because inline patterns shall be faster) |
101 |
- case "${impl}" in |
102 |
- python2_7|python3_[6789]|pypy3) |
103 |
- return 0 |
104 |
- ;; |
105 |
- jython2_7|pypy|pypy1_[89]|pypy2_0|python2_[56]|python3_[12345]) |
106 |
- return 1 |
107 |
- ;; |
108 |
- *) |
109 |
- [[ ${PYTHON_COMPAT_NO_STRICT} ]] && return 1 |
110 |
- die "Invalid implementation in PYTHON_COMPAT: ${impl}" |
111 |
- esac |
112 |
-} |
113 |
- |
114 |
# @FUNCTION: _python_verify_patterns |
115 |
# @USAGE: <pattern>... |
116 |
# @INTERNAL |
117 |
@@ -149,10 +118,26 @@ _python_set_impls() { |
118 |
if [[ $(declare -p PYTHON_COMPAT) != "declare -a"* ]]; then |
119 |
die 'PYTHON_COMPAT must be an array.' |
120 |
fi |
121 |
- for i in "${PYTHON_COMPAT[@]}"; do |
122 |
- # trigger validity checks |
123 |
- _python_impl_supported "${i}" |
124 |
- done |
125 |
+ if [[ ! ${PYTHON_COMPAT_NO_STRICT} ]]; then |
126 |
+ for i in "${PYTHON_COMPAT[@]}"; do |
127 |
+ # check for incorrect implementations |
128 |
+ # we're using pattern matching as an optimization |
129 |
+ # please keep them in sync with _PYTHON_ALL_IMPLS |
130 |
+ # and _PYTHON_HISTORICAL_IMPLS |
131 |
+ case ${i} in |
132 |
+ jython2_7|pypy|pypy1_[89]|pypy2_0|pypy3|python2_[5-7]|python3_[1-9]) |
133 |
+ ;; |
134 |
+ *) |
135 |
+ if has "${i}" "${_PYTHON_ALL_IMPLS[@]}" \ |
136 |
+ "${_PYTHON_HISTORICAL_IMPLS[@]}" |
137 |
+ then |
138 |
+ die "Mis-synced patterns in _python_set_impls: missing ${i}" |
139 |
+ else |
140 |
+ die "Invalid implementation in PYTHON_COMPAT: ${i}" |
141 |
+ fi |
142 |
+ esac |
143 |
+ done |
144 |
+ fi |
145 |
|
146 |
local supp=() unsupp=() |
147 |
|
148 |
@@ -165,7 +150,13 @@ _python_set_impls() { |
149 |
done |
150 |
|
151 |
if [[ ! ${supp[@]} ]]; then |
152 |
- die "No supported implementation in PYTHON_COMPAT." |
153 |
+ # special-case python2_7 for python-any-r1 |
154 |
+ if [[ ${_PYTHON_ALLOW_PY27} ]] && has python2_7 "${PYTHON_COMPAT[@]}" |
155 |
+ then |
156 |
+ supp+=( python2_7 ) |
157 |
+ else |
158 |
+ die "No supported implementation in PYTHON_COMPAT." |
159 |
+ fi |
160 |
fi |
161 |
|
162 |
if [[ ${_PYTHON_SUPPORTED_IMPLS[@]} ]]; then |
163 |
@@ -636,6 +627,7 @@ python_optimize() { |
164 |
|
165 |
local PYTHON=${PYTHON} |
166 |
[[ ${PYTHON} ]] || _python_export PYTHON |
167 |
+ [[ -x ${PYTHON} ]] || die "PYTHON (${PYTHON}) is not executable" |
168 |
|
169 |
# default to sys.path |
170 |
if [[ ${#} -eq 0 ]]; then |
171 |
@@ -950,8 +942,6 @@ _python_wrapper_setup() { |
172 |
[[ ${impl} ]] || die "${FUNCNAME}: no impl nor EPYTHON specified." |
173 |
|
174 |
if [[ ! -x ${workdir}/bin/python ]]; then |
175 |
- _python_check_dead_variables |
176 |
- |
177 |
mkdir -p "${workdir}"/{bin,pkgconfig} || die |
178 |
|
179 |
# Clean up, in case we were supposed to do a cheap update. |
180 |
@@ -1058,16 +1048,8 @@ python_is_python3() { |
181 |
python_is_installed() { |
182 |
local impl=${1:-${EPYTHON}} |
183 |
[[ ${impl} ]] || die "${FUNCNAME}: no impl nor EPYTHON" |
184 |
- local hasv_args=() |
185 |
- |
186 |
- case ${EAPI} in |
187 |
- 5|6) |
188 |
- hasv_args+=( --host-root ) |
189 |
- ;; |
190 |
- *) |
191 |
- hasv_args+=( -b ) |
192 |
- ;; |
193 |
- esac |
194 |
+ local hasv_args=( -b ) |
195 |
+ [[ ${EAPI} == 6 ]] && hasv_args=( --host-root ) |
196 |
|
197 |
local PYTHON_PKG_DEP |
198 |
_python_export "${impl}" PYTHON_PKG_DEP |
199 |
@@ -1214,17 +1196,14 @@ python_fix_shebang() { |
200 |
done < <(find -H "${path}" -type f -print0 || die) |
201 |
|
202 |
if [[ ! ${any_fixed} ]]; then |
203 |
- local cmd=eerror |
204 |
- [[ ${EAPI} == 5 ]] && cmd=eqawarn |
205 |
- |
206 |
- "${cmd}" "QA warning: ${FUNCNAME}, ${path#${D%/}} did not match any fixable files." |
207 |
+ eerror "QA error: ${FUNCNAME}, ${path#${D%/}} did not match any fixable files." |
208 |
if [[ ${any_correct} ]]; then |
209 |
- "${cmd}" "All files have ${EPYTHON} shebang already." |
210 |
+ eerror "All files have ${EPYTHON} shebang already." |
211 |
else |
212 |
- "${cmd}" "There are no Python files in specified directory." |
213 |
+ eerror "There are no Python files in specified directory." |
214 |
fi |
215 |
|
216 |
- [[ ${cmd} == eerror ]] && die "${FUNCNAME} did not match any fixable files (QA warning fatal in EAPI ${EAPI})" |
217 |
+ die "${FUNCNAME} did not match any fixable files" |
218 |
fi |
219 |
done |
220 |
} |
221 |
@@ -1321,172 +1300,51 @@ build_sphinx() { |
222 |
HTML_DOCS+=( "${dir}/_build/html/." ) |
223 |
} |
224 |
|
225 |
-# -- python.eclass functions -- |
226 |
- |
227 |
-_python_check_dead_variables() { |
228 |
- local v |
229 |
- |
230 |
- for v in PYTHON_DEPEND PYTHON_USE_WITH{,_OR,_OPT} {RESTRICT,SUPPORT}_PYTHON_ABIS |
231 |
- do |
232 |
- if [[ ${!v} ]]; then |
233 |
- die "${v} is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Ebuild_head" |
234 |
- fi |
235 |
- done |
236 |
- |
237 |
- for v in PYTHON_{CPPFLAGS,CFLAGS,CXXFLAGS,LDFLAGS} |
238 |
- do |
239 |
- if [[ ${!v} ]]; then |
240 |
- die "${v} is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#PYTHON_CFLAGS" |
241 |
- fi |
242 |
- done |
243 |
- |
244 |
- for v in PYTHON_TESTS_RESTRICTED_ABIS PYTHON_EXPORT_PHASE_FUNCTIONS \ |
245 |
- PYTHON_VERSIONED_{SCRIPTS,EXECUTABLES} PYTHON_NONVERSIONED_EXECUTABLES |
246 |
- do |
247 |
- if [[ ${!v} ]]; then |
248 |
- die "${v} is invalid for python-r1 suite" |
249 |
- fi |
250 |
- done |
251 |
- |
252 |
- for v in DISTUTILS_USE_SEPARATE_SOURCE_DIRECTORIES DISTUTILS_SETUP_FILES \ |
253 |
- DISTUTILS_GLOBAL_OPTIONS DISTUTILS_SRC_TEST PYTHON_MODNAME |
254 |
- do |
255 |
- if [[ ${!v} ]]; then |
256 |
- die "${v} is invalid for distutils-r1, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#${v}" |
257 |
- fi |
258 |
- done |
259 |
- |
260 |
- if [[ ${DISTUTILS_DISABLE_TEST_DEPENDENCY} ]]; then |
261 |
- die "${v} is invalid for distutils-r1, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#DISTUTILS_SRC_TEST" |
262 |
- fi |
263 |
- |
264 |
- # python.eclass::progress |
265 |
- for v in PYTHON_BDEPEND PYTHON_MULTIPLE_ABIS PYTHON_ABI_TYPE \ |
266 |
- PYTHON_RESTRICTED_ABIS PYTHON_TESTS_FAILURES_TOLERANT_ABIS \ |
267 |
- PYTHON_CFFI_MODULES_GENERATION_COMMANDS |
268 |
- do |
269 |
- if [[ ${!v} ]]; then |
270 |
- die "${v} is invalid for python-r1 suite" |
271 |
- fi |
272 |
- done |
273 |
-} |
274 |
- |
275 |
-python_pkg_setup() { |
276 |
- die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#pkg_setup" |
277 |
-} |
278 |
- |
279 |
-python_convert_shebangs() { |
280 |
- die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#python_convert_shebangs" |
281 |
-} |
282 |
- |
283 |
-python_clean_py-compile_files() { |
284 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
285 |
-} |
286 |
- |
287 |
-python_clean_installation_image() { |
288 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
289 |
-} |
290 |
- |
291 |
-python_execute_function() { |
292 |
- die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#python_execute_function" |
293 |
-} |
294 |
- |
295 |
-python_generate_wrapper_scripts() { |
296 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
297 |
-} |
298 |
- |
299 |
-python_merge_intermediate_installation_images() { |
300 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
301 |
-} |
302 |
- |
303 |
-python_set_active_version() { |
304 |
- die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#pkg_setup" |
305 |
-} |
306 |
- |
307 |
-python_need_rebuild() { |
308 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
309 |
-} |
310 |
- |
311 |
-PYTHON() { |
312 |
- die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#.24.28PYTHON.29.2C_.24.7BEPYTHON.7D" |
313 |
-} |
314 |
- |
315 |
-python_get_implementation() { |
316 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
317 |
-} |
318 |
- |
319 |
-python_get_implementational_package() { |
320 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
321 |
-} |
322 |
- |
323 |
-python_get_libdir() { |
324 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
325 |
-} |
326 |
- |
327 |
-python_get_library() { |
328 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
329 |
-} |
330 |
- |
331 |
-python_get_version() { |
332 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
333 |
-} |
334 |
- |
335 |
-python_get_implementation_and_version() { |
336 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
337 |
-} |
338 |
- |
339 |
-python_execute_nosetests() { |
340 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
341 |
-} |
342 |
- |
343 |
-python_execute_py.test() { |
344 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
345 |
-} |
346 |
- |
347 |
-python_execute_trial() { |
348 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
349 |
-} |
350 |
- |
351 |
-python_enable_pyc() { |
352 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
353 |
-} |
354 |
- |
355 |
-python_disable_pyc() { |
356 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
357 |
-} |
358 |
- |
359 |
-python_mod_optimize() { |
360 |
- die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Python_byte-code_compilation" |
361 |
-} |
362 |
- |
363 |
-python_mod_cleanup() { |
364 |
- die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Python_byte-code_compilation" |
365 |
-} |
366 |
+# @FUNCTION: epytest |
367 |
+# @USAGE: [<args>...] |
368 |
+# @DESCRIPTION: |
369 |
+# Run pytest, passing the standard set of pytest options, followed |
370 |
+# by user-specified options. |
371 |
+# |
372 |
+# This command dies on failure and respects nonfatal. |
373 |
+epytest() { |
374 |
+ debug-print-function ${FUNCNAME} "${@}" |
375 |
|
376 |
-# python.eclass::progress |
377 |
+ [[ -n ${EPYTHON} ]] || die "EPYTHON unset, invalid call context" |
378 |
|
379 |
-python_abi_depend() { |
380 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
381 |
-} |
382 |
+ local args=( |
383 |
+ # verbose progress reporting and tracebacks |
384 |
+ -vv |
385 |
+ # list all non-passed tests in the summary for convenience |
386 |
+ # (includes failures, skips, xfails...) |
387 |
+ -ra |
388 |
+ # print local variables in tracebacks, useful for debugging |
389 |
+ -l |
390 |
+ ) |
391 |
+ set -- "${EPYTHON}" -m pytest "${args[@]}" "${@}" |
392 |
|
393 |
-python_install_executables() { |
394 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
395 |
+ echo "${@}" >&2 |
396 |
+ "${@}" || die -n "pytest failed with ${EPYTHON}" |
397 |
+ return ${?} |
398 |
} |
399 |
|
400 |
-python_get_extension_module_suffix() { |
401 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
402 |
-} |
403 |
+# @FUNCTION: eunittest |
404 |
+# @USAGE: [<args>...] |
405 |
+# @DESCRIPTION: |
406 |
+# Run unit tests using dev-python/unittest-or-fail, passing the standard |
407 |
+# set of options, followed by user-specified options. |
408 |
+# |
409 |
+# This command dies on failure and respects nonfatal. |
410 |
+eunittest() { |
411 |
+ debug-print-function ${FUNCNAME} "${@}" |
412 |
|
413 |
-python_byte-compile_modules() { |
414 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
415 |
-} |
416 |
+ [[ -n ${EPYTHON} ]] || die "EPYTHON unset, invalid call context" |
417 |
|
418 |
-python_clean_byte-compiled_modules() { |
419 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
420 |
-} |
421 |
+ set -- "${EPYTHON}" -m unittest_or_fail discover -v "${@}" |
422 |
|
423 |
-python_generate_cffi_modules() { |
424 |
- die "${FUNCNAME}() is invalid for python-r1 suite" |
425 |
+ echo "${@}" >&2 |
426 |
+ "${@}" || die -n "Tests failed with ${EPYTHON}" |
427 |
+ return ${?} |
428 |
} |
429 |
|
430 |
_PYTHON_UTILS_R1=1 |