Gentoo Archives: gentoo-portage-dev

From: Mike Frysinger <vapier@g.o>
To: gentoo-portage-dev@l.g.o
Subject: [gentoo-portage-dev] [PATCH] runtests: rewrite in python
Date: Sat, 30 May 2015 16:29:23
Message-Id: 1433003354-18413-1-git-send-email-vapier@gentoo.org
1 The bash was getting ugly, and this allows us to add more smarts sanely
2 to the main script.
3 ---
4 DEVELOPING | 2 +-
5 runtests | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 runtests.sh | 109 ------------------------------------------
7 3 files changed, 157 insertions(+), 110 deletions(-)
8 create mode 100755 runtests
9 delete mode 100755 runtests.sh
10
11 diff --git a/DEVELOPING b/DEVELOPING
12 index 0b0bb60..31b5594 100644
13 --- a/DEVELOPING
14 +++ b/DEVELOPING
15 @@ -225,7 +225,7 @@ Second create a git tag for this release:
16 Then create the tarball and run the tests:
17 ./mkrelease.sh --changelog-rev v2.2.7 --tag --runtests 2.2.8
18 Make sure you have all supported python versions installed first
19 -(see PYTHON_SUPPORTED_VERSIONS in runtests.sh).
20 +(see PYTHON_SUPPORTED_VERSIONS in runtests).
21
22 Version bump the ebuild and verify it can re-install itself:
23 emerge portage
24 diff --git a/runtests b/runtests
25 new file mode 100755
26 index 0000000..d1f7b6f
27 --- /dev/null
28 +++ b/runtests
29 @@ -0,0 +1,156 @@
30 +#!/usr/bin/python
31 +# Copyright 2010-2015 Gentoo Foundation
32 +# Distributed under the terms of the GNU General Public License v2
33 +#
34 +# Note: We don't want to import portage modules directly because we do things
35 +# like run the testsuite through multiple versions of python.
36 +
37 +"""Helper script to run portage unittests against different python versions.
38 +
39 +Note: Any additional arguments will be passed down directly to the underlying
40 +unittest runner. This lets you select specific tests to execute.
41 +"""
42 +
43 +from __future__ import print_function
44 +
45 +import argparse
46 +import os
47 +import sys
48 +import subprocess
49 +
50 +
51 +# These are the versions we fully support and require to pass tests.
52 +PYTHON_SUPPORTED_VERSIONS = [
53 + '2.7',
54 + '3.3',
55 + '3.4',
56 +]
57 +# The rest are just "nice to have".
58 +PYTHON_NICE_VERSIONS = [
59 + 'pypy',
60 + '3.5',
61 +]
62 +
63 +EPREFIX = os.environ.get('PORTAGE_OVERRIDE_EPREFIX', '/')
64 +
65 +
66 +class Colors(object):
67 + """Simple object holding color constants."""
68 +
69 + _COLORS_YES = ('y', 'yes', 'true')
70 + _COLORS_NO = ('n', 'no', 'false')
71 +
72 + GOOD = BAD = NORMAL = ''
73 +
74 + def __init__(self, colorize=None):
75 + if colorize is None:
76 + nocolors = os.environ.get('NOCOLOR', 'false')
77 + # Ugh, look away, for here we invert the world!
78 + if nocolors in self._COLORS_YES:
79 + colorize = False
80 + elif nocolors in self._COLORS_NO:
81 + colorize = True
82 + else:
83 + raise ValueError('$NOCOLORS is invalid: %s' % nocolors)
84 + else:
85 + if colorize in self._COLORS_YES:
86 + colorize = True
87 + elif colorize in self._COLORS_NO:
88 + colorize = False
89 + else:
90 + raise ValueError('--colors is invalid: %s' % colorize)
91 +
92 + if colorize:
93 + self.GOOD = '\033[1;32m'
94 + self.BAD = '\033[1;31m'
95 + self.NORMAL = '\033[0m'
96 +
97 +
98 +def get_python_executable(ver):
99 + """Find the right python executable for |ver|"""
100 + if ver == 'pypy':
101 + prog = 'pypy'
102 + else:
103 + prog = 'python' + ver
104 + return os.path.join(EPREFIX, 'usr', 'bin', prog)
105 +
106 +
107 +def get_parser():
108 + """Return a argument parser for this module"""
109 + epilog = """Examples:
110 +List all the available unittests.
111 +$ %(prog)s --list
112 +
113 +Run against specific versions of python.
114 +$ %(prog)s --python-version '2.7 3.3'
115 +
116 +Run just one unittest.
117 +$ %(prog)s pym/portage/tests/xpak/test_decodeint.py
118 +"""
119 + parser = argparse.ArgumentParser(
120 + description=__doc__,
121 + formatter_class=argparse.RawDescriptionHelpFormatter,
122 + epilog=epilog)
123 + parser.add_argument('--color', type=str, default=None,
124 + help='Whether to use colorized output (default is auto)')
125 + parser.add_argument('--python-versions', action='append',
126 + help='Versions of python to test (default is test available)')
127 + return parser
128 +
129 +
130 +def main(argv):
131 + parser = get_parser()
132 + opts, args = parser.parse_known_args(argv)
133 + colors = Colors(colorize=opts.color)
134 +
135 + # Figure out all the versions we want to test.
136 + if opts.python_versions is None:
137 + ignore_missing = True
138 + pyversions = PYTHON_SUPPORTED_VERSIONS + PYTHON_NICE_VERSIONS
139 + else:
140 + ignore_missing = False
141 + pyversions = []
142 + for ver in opts.python_versions:
143 + if ver == 'supported':
144 + pyversions.extend(PYTHON_SUPPORTED_VERSIONS)
145 + else:
146 + pyversions.extend(ver.split())
147 +
148 + # Actually test those versions now.
149 + statuses = []
150 + for ver in pyversions:
151 + prog = get_python_executable(ver)
152 + cmd = [prog, '-b', '-Wd', 'pym/portage/tests/runTests.py'] + args
153 + if os.access(prog, os.X_OK):
154 + print('%sTesting with Python %s...%s' %
155 + (colors.GOOD, ver, colors.NORMAL))
156 + statuses.append(subprocess.call(cmd))
157 + elif not ignore_missing:
158 + print('%sCould not find requested Python %s%s' %
159 + (colors.BAD, ver, colors.NORMAL))
160 + statuses.append(1)
161 + print()
162 +
163 + # Then summarize it all.
164 + print('\nSummary:\n')
165 + width = 10
166 + header = '| %-*s | %s' % (width, 'Version', 'Status')
167 + print('%s\n|%s' % (header, '-' * (len(header) - 1)))
168 + for ver, status in zip(pyversions, statuses):
169 + if status:
170 + color = colors.BAD
171 + msg = 'FAIL'
172 + else:
173 + color = colors.GOOD
174 + msg = 'PASS'
175 + print('| %s%-*s%s | %s%s%s' %
176 + (color, width, ver, colors.NORMAL, color, msg, colors.NORMAL))
177 + exit(sum(statuses))
178 +
179 +
180 +if __name__ == '__main__':
181 + try:
182 + main(sys.argv[1:])
183 + except KeyboardInterrupt:
184 + print('interrupted ...', file=sys.stderr)
185 + exit(1)
186 diff --git a/runtests.sh b/runtests.sh
187 deleted file mode 100755
188 index a7ca101..0000000
189 --- a/runtests.sh
190 +++ /dev/null
191 @@ -1,109 +0,0 @@
192 -#!/bin/bash
193 -# Copyright 2010-2014 Gentoo Foundation
194 -# Distributed under the terms of the GNU General Public License v2
195 -
196 -# These are the versions we care about. The rest are just "nice to have".
197 -PYTHON_SUPPORTED_VERSIONS="2.7 3.3 3.4"
198 -PYTHON_VERSIONS="2.7 pypy 3.3 3.4 3.5"
199 -
200 -# has to be run from portage root dir
201 -cd "${0%/*}" || exit 1
202 -
203 -case "${NOCOLOR:-false}" in
204 - yes|true)
205 - GOOD=
206 - BAD=
207 - NORMAL=
208 - ;;
209 - no|false)
210 - GOOD=$'\e[1;32m'
211 - BAD=$'\e[1;31m'
212 - NORMAL=$'\e[0m'
213 - ;;
214 -esac
215 -
216 -interrupted() {
217 - echo "interrupted." >&2
218 - exit 1
219 -}
220 -
221 -trap interrupted SIGINT
222 -
223 -unused_args=()
224 -IGNORE_MISSING_VERSIONS=true
225 -
226 -while [ $# -gt 0 ] ; do
227 - case "$1" in
228 - --python-versions=*)
229 - PYTHON_VERSIONS=${1#--python-versions=}
230 - IGNORE_MISSING_VERSIONS=false
231 - ;;
232 - --python-versions)
233 - shift
234 - PYTHON_VERSIONS=$1
235 - IGNORE_MISSING_VERSIONS=false
236 - ;;
237 - *)
238 - unused_args[${#unused_args[@]}]=$1
239 - ;;
240 - esac
241 - shift
242 -done
243 -if [[ ${PYTHON_VERSIONS} == "supported" ]] ; then
244 - PYTHON_VERSIONS=${PYTHON_SUPPORTED_VERSIONS}
245 -fi
246 -
247 -set -- "${unused_args[@]}"
248 -
249 -eprefix=${PORTAGE_OVERRIDE_EPREFIX}
250 -exit_status="0"
251 -found_versions=()
252 -status_array=()
253 -for version in ${PYTHON_VERSIONS}; do
254 - if [[ $version = 'pypy' ]] ; then
255 - executable=${eprefix}/usr/bin/pypy
256 - else
257 - executable=${eprefix}/usr/bin/python${version}
258 - fi
259 - if [[ -x "${executable}" ]]; then
260 - echo -e "${GOOD}Testing with Python ${version}...${NORMAL}"
261 - "${executable}" -b -Wd pym/portage/tests/runTests.py "$@"
262 - status=$?
263 - status_array[${#status_array[@]}]=${status}
264 - found_versions[${#found_versions[@]}]=${version}
265 - if [ ${status} -ne 0 ] ; then
266 - echo -e "${BAD}Testing with Python ${version} failed${NORMAL}"
267 - exit_status="1"
268 - fi
269 - echo
270 - elif [[ ${IGNORE_MISSING_VERSIONS} != "true" ]] ; then
271 - echo -e "${BAD}Could not find requested Python ${version}${NORMAL}"
272 - exit_status="1"
273 - fi
274 -done
275 -
276 -if [ ${#status_array[@]} -gt 0 ] ; then
277 - max_len=0
278 - for version in ${found_versions[@]} ; do
279 - [ ${#version} -gt ${max_len} ] && max_len=${#version}
280 - done
281 - (( columns = max_len + 2 ))
282 - (( columns >= 7 )) || columns=7
283 - printf "\nSummary:\n\n"
284 - printf "| %-${columns}s | %s\n|" "Version" "Status"
285 - (( total_cols = columns + 11 ))
286 - eval "printf -- '-%.0s' {1..${total_cols}}"
287 - printf "\n"
288 - row=0
289 - for version in ${found_versions[@]} ; do
290 - if [ ${status_array[${row}]} -eq 0 ] ; then
291 - status="success"
292 - else
293 - status="fail"
294 - fi
295 - printf "| %-${columns}s | %s\n" "${version}" "${status}"
296 - (( row++ ))
297 - done
298 -fi
299 -
300 -exit ${exit_status}
301 --
302 2.4.1

Replies

Subject Author
Re: [gentoo-portage-dev] [PATCH] runtests: rewrite in python Brian Dolbec <dolsen@g.o>