Gentoo Archives: gentoo-dev

From: "Michał Górny" <mgorny@g.o>
To: gentoo-dev@l.g.o
Cc: python@g.o, "Michał Górny" <mgorny@g.o>
Subject: [gentoo-dev] [PATCH python-utils-r1] Move python_fix_shebang to python-utils-r1 and rewrite it clean.
Date: Tue, 20 May 2014 18:20:13
Message-Id: 1400609998-17563-1-git-send-email-mgorny@gentoo.org
1 It serves both as public shebang fixing function and replacement of
2 _python_rewrite_shebang internal function. For the sake of having common
3 code and consistent behavior.
4
5 Notes on the 'new' function:
6
7 1. takes a list of files and/or directories to fix. Directories are
8 processed recursively,
9
10 2. files, depending on the shebang:
11
12 a) with shebang matching $EPYTHON (e.g. already having pythonX.Y) are
13 skipped silently (but see 3),
14
15 b) with shebang 'compatible' with $EPYTHON (e.g. python3 -> python3.2,
16 but not python2 -> python3.2) are mangled verbosely,
17
18 c) with shebang 'incompatible' with $EPYTHON (e.g. python3 -> python2.7,
19 python3.2 -> python3.3) raise a fatal error,
20
21 d) with shebang not looking like Python at all are skipped when
22 processing directory recursively and raise a fatal error when are
23 specified directly.
24
25 3. there are two new QA warnings:
26
27 a) when specified file (or all files in the directory) has proper
28 shebang already -- likely attempting double mangling,
29
30 b) when specified directory contains no Python files.
31 ---
32 eclass/python-r1.eclass | 6 +-
33 eclass/python-single-r1.eclass | 44 -----------
34 eclass/python-utils-r1.eclass | 170 +++++++++++++++++++++++------------------
35 3 files changed, 100 insertions(+), 120 deletions(-)
36
37 diff --git a/eclass/python-r1.eclass b/eclass/python-r1.eclass
38 index 0fb188d..876ce7e 100644
39 --- a/eclass/python-r1.eclass
40 +++ b/eclass/python-r1.eclass
41 @@ -783,6 +783,8 @@ python_replicate_script() {
42 debug-print-function ${FUNCNAME} "${@}"
43
44 _python_replicate_script() {
45 + local _PYTHON_FIX_SHEBANG_QUIET=1
46 +
47 if _python_want_python_exec2; then
48 local PYTHON_SCRIPTDIR
49 python_export PYTHON_SCRIPTDIR
50 @@ -792,7 +794,7 @@ python_replicate_script() {
51 doexe "${files[@]}"
52 )
53
54 - _python_rewrite_shebang "${EPYTHON}" \
55 + python_fix_shebang \
56 "${files[@]/*\//${D%/}/${PYTHON_SCRIPTDIR}/}"
57 else
58 local f
59 @@ -800,7 +802,7 @@ python_replicate_script() {
60 cp -p "${f}" "${f}-${EPYTHON}" || die
61 done
62
63 - _python_rewrite_shebang "${EPYTHON}" \
64 + python_fix_shebang \
65 "${files[@]/%/-${EPYTHON}}"
66 fi
67 }
68 diff --git a/eclass/python-single-r1.eclass b/eclass/python-single-r1.eclass
69 index 7ce57c6..2a3a3fc 100644
70 --- a/eclass/python-single-r1.eclass
71 +++ b/eclass/python-single-r1.eclass
72 @@ -261,49 +261,5 @@ python-single-r1_pkg_setup() {
73 python_setup
74 }
75
76 -# @FUNCTION: python_fix_shebang
77 -# @USAGE: <path>...
78 -# @DESCRIPTION:
79 -# Replace the shebang in Python scripts with the current Python
80 -# implementation (EPYTHON). If a directory is passed, works recursively
81 -# on all Python scripts.
82 -#
83 -# Only files having a 'python' shebang will be modified; other files
84 -# will be skipped. If a script has a complete shebang matching
85 -# the chosen interpreter version, it is left unmodified. If a script has
86 -# a complete shebang matching other version, the command dies.
87 -python_fix_shebang() {
88 - debug-print-function ${FUNCNAME} "${@}"
89 -
90 - [[ ${1} ]] || die "${FUNCNAME}: no paths given"
91 - [[ ${EPYTHON} ]] || die "${FUNCNAME}: EPYTHON unset (pkg_setup not called?)"
92 -
93 - local path f
94 - for path; do
95 - while IFS= read -r -d '' f; do
96 - local shebang=$(head -n 1 "${f}")
97 -
98 - case "${shebang}" in
99 - '#!'*${EPYTHON}*)
100 - debug-print "${FUNCNAME}: in file ${f#${D}}"
101 - debug-print "${FUNCNAME}: shebang matches EPYTHON: ${shebang}"
102 - ;;
103 - '#!'*python[23].[0123456789]*|'#!'*pypy-c*|'#!'*jython*)
104 - debug-print "${FUNCNAME}: in file ${f#${D}}"
105 - debug-print "${FUNCNAME}: incorrect specific shebang: ${shebang}"
106 -
107 - die "${f#${D}} has a specific Python shebang not matching EPYTHON"
108 - ;;
109 - '#!'*python*)
110 - debug-print "${FUNCNAME}: in file ${f#${D}}"
111 - debug-print "${FUNCNAME}: rewriting shebang: ${shebang}"
112 -
113 - einfo "Fixing shebang in ${f#${D}}"
114 - _python_rewrite_shebang "${f}"
115 - esac
116 - done < <(find "${path}" -type f -print0)
117 - done
118 -}
119 -
120 _PYTHON_SINGLE_R1=1
121 fi
122 diff --git a/eclass/python-utils-r1.eclass b/eclass/python-utils-r1.eclass
123 index 81d6691..e292760 100644
124 --- a/eclass/python-utils-r1.eclass
125 +++ b/eclass/python-utils-r1.eclass
126 @@ -478,79 +478,6 @@ python_get_scriptdir() {
127 echo "${PYTHON_SCRIPTDIR}"
128 }
129
130 -# @FUNCTION: _python_rewrite_shebang
131 -# @USAGE: [<EPYTHON>] <path>...
132 -# @INTERNAL
133 -# @DESCRIPTION:
134 -# Replaces 'python' executable in the shebang with the executable name
135 -# of the specified interpreter. If no EPYTHON value (implementation) is
136 -# used, the current ${EPYTHON} will be used.
137 -#
138 -# All specified files must start with a 'python' shebang. A file not
139 -# having a matching shebang will be refused. The exact shebang style
140 -# will be preserved in order not to break anything.
141 -#
142 -# Example conversions:
143 -# @CODE
144 -# From: #!/usr/bin/python -R
145 -# To: #!/usr/bin/python2.7 -R
146 -#
147 -# From: #!/usr/bin/env FOO=bar python
148 -# To: #!/usr/bin/env FOO=bar python2.7
149 -# @CODE
150 -_python_rewrite_shebang() {
151 - debug-print-function ${FUNCNAME} "${@}"
152 -
153 - local impl
154 - case "${1}" in
155 - python*|jython*|pypy*)
156 - impl=${1}
157 - shift
158 - ;;
159 - *)
160 - impl=${EPYTHON}
161 - [[ ${impl} ]] || die "${FUNCNAME}: no impl nor EPYTHON"
162 - ;;
163 - esac
164 - debug-print "${FUNCNAME}: implementation: ${impl}"
165 -
166 - local f
167 - for f; do
168 - local from shebang
169 - read -r shebang < "${f}"
170 - shebang=${shebang%$'\r'}
171 - debug-print "${FUNCNAME}: path = ${f}"
172 - debug-print "${FUNCNAME}: shebang = ${shebang}"
173 -
174 - if [[ "${shebang} " == *"${impl} "* ]]; then
175 - # skip files with correct impl
176 - continue
177 - elif [[ "${shebang} " == *'python '* ]]; then
178 - from=python
179 - elif [[ "${shebang} " == *'python2 '* ]]; then
180 - from=python2
181 - elif [[ "${shebang} " == *'python3 '* ]]; then
182 - from=python3
183 - else
184 - eerror "A file does not seem to have a supported shebang:"
185 - eerror " file: ${f}"
186 - eerror " shebang: ${shebang}"
187 - die "${FUNCNAME}: ${f} does not seem to have a valid shebang"
188 - fi
189 -
190 - if { [[ ${from} == python2 ]] && python_is_python3 "${impl}"; } \
191 - || { [[ ${from} == python3 ]] && ! python_is_python3 "${impl}"; } then
192 - eerror "A file does have shebang not supporting requested impl:"
193 - eerror " file: ${f}"
194 - eerror " shebang: ${shebang}"
195 - eerror " impl: ${impl}"
196 - die "${FUNCNAME}: ${f} does have shebang not supporting ${EPYTHON}"
197 - fi
198 -
199 - sed -i -e "1s:${from}:${impl}:" "${f}" || die
200 - done
201 -}
202 -
203 # @FUNCTION: _python_ln_rel
204 # @USAGE: <from> <to>
205 # @INTERNAL
206 @@ -743,7 +670,8 @@ python_newexe() {
207
208 # don't use this at home, just call python_doscript() instead
209 if [[ ${_PYTHON_REWRITE_SHEBANG} ]]; then
210 - _python_rewrite_shebang "${ED%/}/${d}/${newfn}"
211 + local _PYTHON_FIX_SHEBANG_QUIET=1
212 + python_fix_shebang "${ED%/}/${d}/${newfn}"
213 fi
214 }
215
216 @@ -1006,6 +934,100 @@ python_is_python3() {
217 [[ ${impl} == python3* ]]
218 }
219
220 +# @FUNCTION: python_fix_shebang
221 +# @USAGE: <path>...
222 +# @DESCRIPTION:
223 +# Replace the shebang in Python scripts with the current Python
224 +# implementation (EPYTHON). If a directory is passed, works recursively
225 +# on all Python scripts.
226 +#
227 +# Only files having a 'python*' shebang will be modified. Files with
228 +# other shebang will either be skipped when working recursively
229 +# on a directory or treated as error when specified explicitly.
230 +#
231 +# Shebangs matching explicitly current Python version will be left
232 +# unmodified. Shebangs requesting another Python version will be treated
233 +# as fatal error.
234 +python_fix_shebang() {
235 + debug-print-function ${FUNCNAME} "${@}"
236 +
237 + [[ ${1} ]] || die "${FUNCNAME}: no paths given"
238 + [[ ${EPYTHON} ]] || die "${FUNCNAME}: EPYTHON unset (pkg_setup not called?)"
239 +
240 + local path f
241 + for path; do
242 + local any_correct any_fixed is_recursive
243 +
244 + [[ -d ${path} ]] && is_recursive=1
245 +
246 + while IFS= read -r -d '' f; do
247 + local shebang=$(head -n 1 "${f}")
248 + local error
249 +
250 + case "${shebang} " in
251 + '#!'*"${EPYTHON} "*)
252 + debug-print "${FUNCNAME}: in file ${f#${D}}"
253 + debug-print "${FUNCNAME}: shebang matches EPYTHON: ${shebang}"
254 +
255 + # Nothing to do, move along.
256 + any_correct=1
257 + ;;
258 + '#!'*python" "*|'#!'*python[23]" "*)
259 + debug-print "${FUNCNAME}: in file ${f#${D}}"
260 + debug-print "${FUNCNAME}: rewriting shebang: ${shebang}"
261 +
262 + # Note: for internal use.
263 + if [[ ! ${_PYTHON_FIX_SHEBANG_QUIET} ]]; then
264 + einfo "Fixing shebang in ${f#${D}}."
265 + fi
266 +
267 + local from
268 + if [[ "${shebang} " == *'python2 '* ]]; then
269 + from=python2
270 + python_is_python3 "${EPYTHON}" && error=1
271 + elif [[ "${shebang} " == *'python3 '* ]]; then
272 + from=python3
273 + python_is_python3 "${EPYTHON}" || error=1
274 + else
275 + from=python
276 + fi
277 +
278 + if [[ ! ${error} ]]; then
279 + sed -i -e "1s:${from}:${EPYTHON}:" "${f}" || die
280 + any_fixed=1
281 + fi
282 + ;;
283 + '#!'*python[23].[0123456789]" "*|'#!'*pypy" "*|'#!'*jython[23].[0123456789]" "*)
284 + # Explicit mismatch.
285 + error=1
286 + ;;
287 + *)
288 + # Non-Python shebang. Allowed in recursive mode,
289 + # disallowed when specifying file explicitly.
290 + [[ ${is_recursive} ]] || error=1
291 + ;;
292 + esac
293 +
294 + if [[ ${error} ]]; then
295 + eerror "The file has incompatible shebang:"
296 + eerror " file: ${f#${D}}"
297 + eerror " current shebang: ${shebang}"
298 + eerror " requested impl: ${EPYTHON}"
299 + die "${FUNCNAME}: conversion of incompatible shebang requested"
300 + fi
301 + done < <(find "${path}" -type f -print0)
302 +
303 + if [[ ! ${any_fixed} ]]; then
304 + eqawarn "QA warning: ${FUNCNAME}, ${path#${D}} did not match any fixable files."
305 + if [[ ${any_correct} ]]; then
306 + eqawarn "All files have ${EPYTHON} shebang already."
307 + else
308 + eqawarn "There are no Python files in specified directory."
309 + fi
310 + fi
311 + done
312 +}
313 +
314 # @FUNCTION: _python_want_python_exec2
315 # @INTERNAL
316 # @DESCRIPTION:
317 --
318 1.9.3

Replies