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 |