OLD | NEW |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 | 2 |
3 ''' | 3 ''' |
4 Copyright 2012 Google Inc. | 4 Copyright 2012 Google Inc. |
5 | 5 |
6 Use of this source code is governed by a BSD-style license that can be | 6 Use of this source code is governed by a BSD-style license that can be |
7 found in the LICENSE file. | 7 found in the LICENSE file. |
8 ''' | 8 ''' |
9 | 9 |
10 ''' | 10 ''' |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
98 # them to display later on. | 98 # them to display later on. |
99 class ExceptionHandler(object): | 99 class ExceptionHandler(object): |
100 | 100 |
101 # params: | 101 # params: |
102 # keep_going_on_failure: if False, report failures and quit right away; | 102 # keep_going_on_failure: if False, report failures and quit right away; |
103 # if True, collect failures until | 103 # if True, collect failures until |
104 # ReportAllFailures() is called | 104 # ReportAllFailures() is called |
105 def __init__(self, keep_going_on_failure=False): | 105 def __init__(self, keep_going_on_failure=False): |
106 self._keep_going_on_failure = keep_going_on_failure | 106 self._keep_going_on_failure = keep_going_on_failure |
107 self._failures_encountered = [] | 107 self._failures_encountered = [] |
108 self._exiting = False | |
109 | |
110 # Exit the program with the given status value. | |
111 def _Exit(self, status=1): | |
112 self._exiting = True | |
113 sys.exit(status) | |
114 | 108 |
115 # We have encountered an exception; either collect the info and keep going, | 109 # We have encountered an exception; either collect the info and keep going, |
116 # or exit the program right away. | 110 # or exit the program right away. |
rmistry
2013/09/03 17:09:35
Make this a method level comment.
epoger
2013/09/03 18:01:33
Done throughout ExceptionHandler object.
| |
117 def RaiseExceptionOrContinue(self, e): | 111 def RaiseExceptionOrContinue(self): |
118 # If we are already quitting the program, propagate any exceptions | 112 # Get traceback information about the most recently raised exception. |
119 # so that the proper exit status will be communicated to the shell. | 113 exc_info = sys.exc_info() |
120 if self._exiting: | |
121 raise e | |
122 | 114 |
123 if self._keep_going_on_failure: | 115 if self._keep_going_on_failure: |
124 print >> sys.stderr, 'WARNING: swallowing exception %s' % e | 116 # I don't understand why we need to log [exc_info[1]] instead of just |
125 self._failures_encountered.append(e) | 117 # exc_info[1] , but for some reason the former preserves more information. |
rmistry
2013/09/03 17:09:35
Thats because exc_info[1] is like calling str(exc_
epoger
2013/09/03 18:01:33
Works as you describe... thanks! Done.
| |
118 print >> sys.stderr, 'WARNING: swallowing exception %s' % [exc_info[1]] | |
119 self._failures_encountered.append(exc_info) | |
126 else: | 120 else: |
127 print >> sys.stderr, e | |
128 print >> sys.stderr, ( | 121 print >> sys.stderr, ( |
129 'Halting at first exception; to keep going, re-run ' + | 122 'Halting at first exception; to keep going, re-run ' + |
130 'with the --keep-going-on-failure option set.') | 123 'with the --keep-going-on-failure option set.') |
131 self._Exit() | 124 raise exc_info[1], None, exc_info[2] |
epoger
2013/09/03 16:54:38
Patchset 5: While I was at it, improved error repo
| |
132 | 125 |
133 def ReportAllFailures(self): | 126 def ReportAllFailures(self): |
134 if self._failures_encountered: | 127 if self._failures_encountered: |
135 print >> sys.stderr, ('Encountered %d failures (see above).' % | 128 print >> sys.stderr, ('Encountered %d failures (see above).' % |
136 len(self._failures_encountered)) | 129 len(self._failures_encountered)) |
137 self._Exit() | 130 sys.exit(1) |
138 | 131 |
139 | 132 |
140 # Object that rebaselines a JSON expectations file (not individual image files). | 133 # Object that rebaselines a JSON expectations file (not individual image files). |
141 class JsonRebaseliner(object): | 134 class JsonRebaseliner(object): |
142 | 135 |
143 # params: | 136 # params: |
144 # expectations_root: root directory of all expectations JSON files | 137 # expectations_root: root directory of all expectations JSON files |
145 # expectations_input_filename: filename (under expectations_root) of JSON | 138 # expectations_input_filename: filename (under expectations_root) of JSON |
146 # expectations file to read; typically | 139 # expectations file to read; typically |
147 # "expected-results.json" | 140 # "expected-results.json" |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
253 gm_json.JSONKEY_ACTUALRESULTS_SUCCEEDED] | 246 gm_json.JSONKEY_ACTUALRESULTS_SUCCEEDED] |
254 if self._add_new: | 247 if self._add_new: |
255 sections.append(gm_json.JSONKEY_ACTUALRESULTS_NOCOMPARISON) | 248 sections.append(gm_json.JSONKEY_ACTUALRESULTS_NOCOMPARISON) |
256 results_to_update = self._GetActualResults(json_url=actuals_url, | 249 results_to_update = self._GetActualResults(json_url=actuals_url, |
257 sections=sections) | 250 sections=sections) |
258 | 251 |
259 # Read in current expectations. | 252 # Read in current expectations. |
260 expectations_input_filepath = os.path.join( | 253 expectations_input_filepath = os.path.join( |
261 self._expectations_root, builder, self._expectations_input_filename) | 254 self._expectations_root, builder, self._expectations_input_filename) |
262 expectations_dict = gm_json.LoadFromFile(expectations_input_filepath) | 255 expectations_dict = gm_json.LoadFromFile(expectations_input_filepath) |
263 expected_results = expectations_dict[gm_json.JSONKEY_EXPECTEDRESULTS] | 256 expected_results = expectations_dict.get(gm_json.JSONKEY_EXPECTEDRESULTS) |
257 if not expected_results: | |
epoger
2013/09/03 16:54:38
Patchset 5: properly handle the case where there a
| |
258 expected_results = {} | |
rmistry
2013/09/03 17:09:35
I think you should be able to get rid of this line
epoger
2013/09/03 18:01:33
Done, but we still need to set expectations_dict[g
rmistry
2013/09/03 18:17:18
Lets go with what you prefer, not a big deal eithe
epoger
2013/09/03 18:23:07
Went back to my old way, then. :-)
| |
259 expectations_dict[gm_json.JSONKEY_EXPECTEDRESULTS] = expected_results | |
264 | 260 |
265 # Update the expectations in memory, skipping any tests/configs that | 261 # Update the expectations in memory, skipping any tests/configs that |
266 # the caller asked to exclude. | 262 # the caller asked to exclude. |
267 skipped_images = [] | 263 skipped_images = [] |
268 if results_to_update: | 264 if results_to_update: |
269 for (image_name, image_results) in results_to_update.iteritems(): | 265 for (image_name, image_results) in results_to_update.iteritems(): |
270 (test, config) = self._image_filename_re.match(image_name).groups() | 266 (test, config) = self._image_filename_re.match(image_name).groups() |
271 if self._tests: | 267 if self._tests: |
272 if test not in self._tests: | 268 if test not in self._tests: |
273 skipped_images.append(image_name) | 269 skipped_images.append(image_name) |
(...skipping 23 matching lines...) Expand all Loading... | |
297 parser = argparse.ArgumentParser() | 293 parser = argparse.ArgumentParser() |
298 parser.add_argument('--actuals-base-url', | 294 parser.add_argument('--actuals-base-url', |
299 help='base URL from which to read files containing JSON ' + | 295 help='base URL from which to read files containing JSON ' + |
300 'summaries of actual GM results; defaults to %(default)s', | 296 'summaries of actual GM results; defaults to %(default)s', |
301 default='http://skia-autogen.googlecode.com/svn/gm-actual') | 297 default='http://skia-autogen.googlecode.com/svn/gm-actual') |
302 parser.add_argument('--actuals-filename', | 298 parser.add_argument('--actuals-filename', |
303 help='filename (within builder-specific subdirectories ' + | 299 help='filename (within builder-specific subdirectories ' + |
304 'of ACTUALS_BASE_URL) to read a summary of results from; ' + | 300 'of ACTUALS_BASE_URL) to read a summary of results from; ' + |
305 'defaults to %(default)s', | 301 'defaults to %(default)s', |
306 default='actual-results.json') | 302 default='actual-results.json') |
307 # TODO(epoger): Add test that exercises --add-new argument. | |
308 parser.add_argument('--add-new', action='store_true', | 303 parser.add_argument('--add-new', action='store_true', |
309 help='in addition to the standard behavior of ' + | 304 help='in addition to the standard behavior of ' + |
310 'updating expectations for failing tests, add ' + | 305 'updating expectations for failing tests, add ' + |
311 'expectations for tests which don\'t have expectations ' + | 306 'expectations for tests which don\'t have expectations ' + |
312 'yet.') | 307 'yet.') |
313 parser.add_argument('--builders', metavar='BUILDER', nargs='+', | 308 parser.add_argument('--builders', metavar='BUILDER', nargs='+', |
314 help='which platforms to rebaseline; ' + | 309 help='which platforms to rebaseline; ' + |
315 'if unspecified, rebaseline all platforms, same as ' + | 310 'if unspecified, rebaseline all platforms, same as ' + |
316 '"--builders %s"' % ' '.join(sorted(TEST_BUILDERS))) | 311 '"--builders %s"' % ' '.join(sorted(TEST_BUILDERS))) |
317 # TODO(epoger): Add test that exercises --configs argument. | 312 # TODO(epoger): Add test that exercises --configs argument. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
370 expectations_input_filename=args.expectations_filename, | 365 expectations_input_filename=args.expectations_filename, |
371 expectations_output_filename=(args.expectations_filename_output or | 366 expectations_output_filename=(args.expectations_filename_output or |
372 args.expectations_filename), | 367 args.expectations_filename), |
373 tests=args.tests, configs=args.configs, | 368 tests=args.tests, configs=args.configs, |
374 actuals_base_url=args.actuals_base_url, | 369 actuals_base_url=args.actuals_base_url, |
375 actuals_filename=args.actuals_filename, | 370 actuals_filename=args.actuals_filename, |
376 exception_handler=exception_handler, | 371 exception_handler=exception_handler, |
377 add_new=args.add_new) | 372 add_new=args.add_new) |
378 try: | 373 try: |
379 rebaseliner.RebaselineSubdir(builder=builder) | 374 rebaseliner.RebaselineSubdir(builder=builder) |
380 except BaseException as e: | 375 except BaseException: |
381 exception_handler.RaiseExceptionOrContinue(e) | 376 exception_handler.RaiseExceptionOrContinue() |
382 else: | 377 else: |
383 exception_handler.RaiseExceptionOrContinue(_InternalException( | 378 try: |
384 'expectations_json_file %s not found' % expectations_json_file)) | 379 raise _InternalException('expectations_json_file %s not found' % |
380 expectations_json_file) | |
381 except BaseException: | |
rmistry
2013/09/03 17:09:35
Why is this catching BaseException instead of Exce
epoger
2013/09/03 18:01:33
I don't think it really matters. Got rid of the e
rmistry
2013/09/03 18:17:18
I think it does slightly matter because 'except Ba
| |
382 exception_handler.RaiseExceptionOrContinue() | |
385 | 383 |
386 exception_handler.ReportAllFailures() | 384 exception_handler.ReportAllFailures() |
OLD | NEW |