Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Contains the parsing system of the Chromium Buildbot Annotator.""" | 5 """Contains the parsing system of the Chromium Buildbot Annotator.""" |
| 6 | 6 |
| 7 import os | 7 import os |
| 8 import sys | 8 import sys |
| 9 import time | |
| 9 import traceback | 10 import traceback |
| 10 | 11 |
| 11 # These are maps of annotation key -> number of expected arguments. | 12 # These are maps of annotation key -> number of expected arguments. |
| 12 STEP_ANNOTATIONS = { | 13 STEP_ANNOTATIONS = { |
| 13 'SET_BUILD_PROPERTY': 2, | 14 'SET_BUILD_PROPERTY': 2, |
| 14 'STEP_CLEAR': 0, | 15 'STEP_CLEAR': 0, |
| 15 'STEP_EXCEPTION': 0, | 16 'STEP_EXCEPTION': 0, |
| 16 'STEP_FAILURE': 0, | 17 'STEP_FAILURE': 0, |
| 17 'STEP_LINK': 2, | 18 'STEP_LINK': 2, |
| 18 'STEP_LOG_END': 1, | 19 'STEP_LOG_END': 1, |
| 19 'STEP_LOG_END_PERF': 2, | 20 'STEP_LOG_END_PERF': 2, |
| 20 'STEP_LOG_LINE': 2, | 21 'STEP_LOG_LINE': 2, |
| 21 'STEP_SUMMARY_CLEAR': 0, | 22 'STEP_SUMMARY_CLEAR': 0, |
| 22 'STEP_SUMMARY_TEXT': 1, | 23 'STEP_SUMMARY_TEXT': 1, |
| 23 'STEP_TEXT': 1, | 24 'STEP_TEXT': 1, |
| 24 'STEP_TRIGGER': 1, | 25 'STEP_TRIGGER': 1, |
| 25 'STEP_WARNINGS': 0, | 26 'STEP_WARNINGS': 0, |
| 26 'STEP_NEST_LEVEL': 1, | 27 'STEP_NEST_LEVEL': 1, |
| 27 } | 28 } |
| 28 | 29 |
| 29 CONTROL_ANNOTATIONS = { | 30 CONTROL_ANNOTATIONS = { |
| 30 'STEP_CLOSED': 0, | 31 'STEP_CLOSED': 0, |
| 31 'STEP_STARTED': 0, | 32 'STEP_STARTED': 0, |
| 32 } | 33 } |
| 33 | 34 |
| 34 STREAM_ANNOTATIONS = { | 35 STREAM_ANNOTATIONS = { |
| 36 # CURRENT_TIMESTAMP has one parameter, Unix timestamp, which specifies | |
| 37 # current time. The following annotation MUST be emitted immediately, | |
| 38 # however there is no requirement for the annotation after the next one | |
| 39 # to be emitted immediately. Annotation parsers must treat CURRENT_TIMESTAMP | |
| 40 # annotation as a decorator for the next annotation only, not for all | |
| 41 # following annotations until next CURRENT_TIMESTAMP. | |
| 42 'CURRENT_TIMESTAMP': 1, | |
| 35 'HALT_ON_FAILURE': 0, | 43 'HALT_ON_FAILURE': 0, |
| 36 'HONOR_ZERO_RETURN_CODE': 0, | 44 'HONOR_ZERO_RETURN_CODE': 0, |
| 37 'SEED_STEP': 1, | 45 'SEED_STEP': 1, |
| 38 'SEED_STEP_TEXT': 2, | 46 'SEED_STEP_TEXT': 2, |
| 39 'STEP_CURSOR': 1, | 47 'STEP_CURSOR': 1, |
| 40 } | 48 } |
| 41 | 49 |
| 42 DEPRECATED_ANNOTATIONS = { | 50 DEPRECATED_ANNOTATIONS = { |
| 43 'BUILD_STEP': 1, | 51 'BUILD_STEP': 1, |
| 44 } | 52 } |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 190 | 198 |
| 191 class StructuredAnnotationStep(StepCommands, StepControlCommands): | 199 class StructuredAnnotationStep(StepCommands, StepControlCommands): |
| 192 """Helper class to provide context for a step.""" | 200 """Helper class to provide context for a step.""" |
| 193 | 201 |
| 194 def __init__(self, annotation_stream, *args, **kwargs): | 202 def __init__(self, annotation_stream, *args, **kwargs): |
| 195 self.annotation_stream = annotation_stream | 203 self.annotation_stream = annotation_stream |
| 196 super(StructuredAnnotationStep, self).__init__(*args, **kwargs) | 204 super(StructuredAnnotationStep, self).__init__(*args, **kwargs) |
| 197 self.control = StepControlCommands(self.stream, self.flush_before) | 205 self.control = StepControlCommands(self.stream, self.flush_before) |
| 198 self.emitted_logs = set() | 206 self.emitted_logs = set() |
| 199 | 207 |
| 200 | |
| 201 def __enter__(self): | 208 def __enter__(self): |
| 202 return self.step_started() | 209 return self.step_started() |
| 203 | 210 |
| 204 def step_started(self): | 211 def step_started(self): |
| 212 self.annotation_stream.emit_current_timestamp() | |
| 205 self.control.step_started() | 213 self.control.step_started() |
| 206 return self | 214 return self |
| 207 | 215 |
| 208 def __exit__(self, exc_type, exc_value, tb): | 216 def __exit__(self, exc_type, exc_value, tb): |
| 209 self.annotation_stream.step_cursor(self.annotation_stream.current_step) | 217 self.annotation_stream.step_cursor(self.annotation_stream.current_step) |
| 210 #TODO(martinis) combine this and step_ended | 218 #TODO(martinis) combine this and step_ended |
| 211 if exc_type: | 219 if exc_type: |
| 212 self.step_exception_occured(exc_type, exc_value, tb) | 220 self.step_exception_occured(exc_type, exc_value, tb) |
| 213 | 221 |
| 222 self.annotation_stream.emit_current_timestamp() | |
| 214 self.control.step_closed() | 223 self.control.step_closed() |
| 215 self.annotation_stream.current_step = '' | 224 self.annotation_stream.current_step = '' |
| 216 return not exc_type | 225 return not exc_type |
| 217 | 226 |
| 218 def step_exception_occured(self, exc_type, exc_value, tb): | 227 def step_exception_occured(self, exc_type, exc_value, tb): |
| 219 trace = traceback.format_exception(exc_type, exc_value, tb) | 228 trace = traceback.format_exception(exc_type, exc_value, tb) |
| 220 trace_lines = ''.join(trace).split('\n') | 229 trace_lines = ''.join(trace).split('\n') |
| 221 self.write_log_lines('exception', filter(None, trace_lines)) | 230 self.write_log_lines('exception', filter(None, trace_lines)) |
| 222 self.step_exception() | 231 self.step_exception() |
| 223 | 232 |
| 224 def step_ended(self): | 233 def step_ended(self): |
| 225 self.annotation_stream.step_cursor(self.annotation_stream.current_step) | 234 self.annotation_stream.step_cursor(self.annotation_stream.current_step) |
| 235 self.annotation_stream.emit_current_timestamp() | |
| 226 self.control.step_closed() | 236 self.control.step_closed() |
| 227 self.annotation_stream.current_step = '' | 237 self.annotation_stream.current_step = '' |
| 228 | 238 |
| 229 return True | 239 return True |
| 230 | 240 |
| 231 | 241 |
| 232 class StructuredAnnotationStream(AnnotationPrinter): | 242 class StructuredAnnotationStream(AnnotationPrinter): |
| 233 """Provides an interface to handle an annotated build. | 243 """Provides an interface to handle an annotated build. |
| 234 | 244 |
| 235 StructuredAnnotationStream handles most of the step setup and closure calls | 245 StructuredAnnotationStream handles most of the step setup and closure calls |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 246 s.step_failure() | 256 s.step_failure() |
| 247 with stream.step('test') as s: | 257 with stream.step('test') as s: |
| 248 # do something | 258 # do something |
| 249 if warnings: | 259 if warnings: |
| 250 s.step_warnings() | 260 s.step_warnings() |
| 251 """ | 261 """ |
| 252 ANNOTATIONS = STREAM_ANNOTATIONS | 262 ANNOTATIONS = STREAM_ANNOTATIONS |
| 253 | 263 |
| 254 def __init__(self, stream=sys.stdout, | 264 def __init__(self, stream=sys.stdout, |
| 255 flush_before=sys.stderr, | 265 flush_before=sys.stderr, |
| 256 seed_steps=None): # pylint: disable=W0613 | 266 seed_steps=None, # pylint: disable=W0613 |
| 267 time_fn=None): | |
| 257 super(StructuredAnnotationStream, self).__init__(stream=stream, | 268 super(StructuredAnnotationStream, self).__init__(stream=stream, |
| 258 flush_before=flush_before) | 269 flush_before=flush_before) |
| 259 self.current_step = '' | 270 self.current_step = '' |
| 271 self.time_fn = time_fn or time.time | |
| 272 | |
| 273 def emit_current_timestamp(self): | |
| 274 self.current_timestamp(self.time_fn()) | |
|
nodir
2016/06/08 17:42:23
current_timestamp method is generated dynamically
| |
| 260 | 275 |
| 261 def step(self, name): | 276 def step(self, name): |
| 262 """Provide a context with which to execute a step.""" | 277 """Provide a context with which to execute a step.""" |
| 263 if self.current_step: | 278 if self.current_step: |
| 264 raise Exception('Can\'t start step %s while in step %s.' % ( | 279 raise Exception('Can\'t start step %s while in step %s.' % ( |
| 265 name, self.current_step)) | 280 name, self.current_step)) |
| 266 | 281 |
| 267 self.seed_step(name) | 282 self.seed_step(name) |
| 268 self.step_cursor(name) | 283 self.step_cursor(name) |
| 269 self.current_step = name | 284 self.current_step = name |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 339 # This prevents functions from showing up as: | 354 # This prevents functions from showing up as: |
| 340 # '<function foo at 0x7f523ec7a410>' | 355 # '<function foo at 0x7f523ec7a410>' |
| 341 # which is tricky to test. | 356 # which is tricky to test. |
| 342 value = value.__name__+'(...)' | 357 value = value.__name__+'(...)' |
| 343 step_info_lines.append(' %s: %s' % (key, value)) | 358 step_info_lines.append(' %s: %s' % (key, value)) |
| 344 step_info_lines.append('full environment:') | 359 step_info_lines.append('full environment:') |
| 345 for key, value in sorted(env.items()): | 360 for key, value in sorted(env.items()): |
| 346 step_info_lines.append(' %s: %s' % (key, value)) | 361 step_info_lines.append(' %s: %s' % (key, value)) |
| 347 step_info_lines.append('') | 362 step_info_lines.append('') |
| 348 stream.emit('\n'.join(step_info_lines)) | 363 stream.emit('\n'.join(step_info_lines)) |
| OLD | NEW |