Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(453)

Side by Side Diff: scripts/common/annotator.py

Issue 17635005: Make blink_trybot recipe work on windows (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Contains generating and parsing systems of the Chromium Buildbot Annotator. 6 """Contains generating and parsing systems of the Chromium Buildbot Annotator.
7 7
8 When executed as a script, this reads step name / command pairs from a file and 8 When executed as a script, this reads step name / command pairs from a file and
9 executes those lines while annotating the output. The input is json: 9 executes those lines while annotating the output. The input is json:
10 10
11 [{"name": "step_name", "cmd": ["command", "arg1", "arg2"]}, 11 [{"name": "step_name", "cmd": ["command", "arg1", "arg2"]},
12 {"name": "step_name2", "cmd": ["command2", "arg1"]}] 12 {"name": "step_name2", "cmd": ["command2", "arg1"]}]
13 13
14 """ 14 """
15 15
16 import itertools
16 import json 17 import json
17 import optparse 18 import optparse
18 import os 19 import os
19 import re 20 import re
21 import subprocess
20 import sys 22 import sys
23 import threading
21 import traceback 24 import traceback
22 25
23 from common import chromium_utils
24
25 26
26 def emit(line, stream, flush_before=None): 27 def emit(line, stream, flush_before=None):
27 if flush_before: 28 if flush_before:
28 flush_before.flush() 29 flush_before.flush()
29 print >> stream, '\n' + line 30 print >> stream
31 # WinDOS can only handle 64kb of output to the console at a time, per process.
32 if sys.platform.startswith('win'):
33 lim = 2**15
34 while line:
35 to_print, line = line[:lim], line[lim:]
36 stream.write(to_print)
37 else:
38 print >> stream, line
30 stream.flush() 39 stream.flush()
31 40
32 41
33 class StepCommands(object): 42 class StepCommands(object):
34 """Class holding step commands. Intended to be subclassed.""" 43 """Class holding step commands. Intended to be subclassed."""
35 def __init__(self, stream, flush_before): 44 def __init__(self, stream, flush_before):
36 self.stream = stream 45 self.stream = stream
37 self.flush_before = flush_before 46 self.flush_before = flush_before
38 47
39 def emit(self, line): 48 def emit(self, line):
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 415
407 # For error reporting. 416 # For error reporting.
408 step_dict = locals().copy() 417 step_dict = locals().copy()
409 step_dict.pop('kwargs') 418 step_dict.pop('kwargs')
410 step_dict.pop('stream') 419 step_dict.pop('stream')
411 step_dict.update(kwargs) 420 step_dict.update(kwargs)
412 421
413 for step_name in (seed_steps or []): 422 for step_name in (seed_steps or []):
414 stream.seed_step(step_name) 423 stream.seed_step(step_name)
415 424
416 filter_obj = None
417 if not allow_subannotations:
418 class AnnotationFilter(chromium_utils.RunCommandFilter):
419 # Missing __init__
420 # Method could be a function (but not really since it's an override)
421 # pylint: disable=W0232,R0201
422 def FilterLine(self, line):
423 return line.replace('@@@', '###')
424 filter_obj = AnnotationFilter()
425
426 ret = None 425 ret = None
427 with stream.step(name) as s: 426 with stream.step(name) as s:
428 print_step(step_dict) 427 print_step(step_dict)
429 try: 428 try:
430 ret = chromium_utils.RunCommand(command=cmd, 429 proc = subprocess.Popen(
431 cwd=cwd, 430 cmd,
432 env=_merge_envs(os.environ, env), 431 env=_merge_envs(os.environ, env),
433 filter_obj=filter_obj, 432 cwd=cwd,
434 print_cmd=False) 433 stdout=subprocess.PIPE,
434 stderr=subprocess.PIPE)
435
436 outlock = threading.Lock()
437 def filter_lines(lock, allow_subannotations, inhandle, outhandle):
438 while True:
439 line = inhandle.readline()
440 if not line:
441 break
442 if not allow_subannotations:
443 if line.startswith('@@@'):
444 line = '###'+line[3:]
agable 2013/06/25 15:55:28 This only replaces the leading @@@ with ###, where
iannucci 2013/06/25 21:22:09 I'll do you one better. I changed it to just print
445 lock.acquire()
446 try:
447 outhandle.write(line)
448 outhandle.flush()
449 finally:
450 lock.release()
451
452 outthread = threading.Thread(
453 target=filter_lines,
454 args=(outlock, allow_subannotations, proc.stdout, sys.stdout))
455 errthread = threading.Thread(
456 target=filter_lines,
457 args=(outlock, allow_subannotations, proc.stderr, sys.stderr))
458 outthread.start()
459 errthread.start()
460 proc.wait()
461 outthread.join()
462 errthread.join()
463 ret = proc.returncode
435 except OSError: 464 except OSError:
436 # File wasn't found, error will be reported to stream when the exception 465 # File wasn't found, error will be reported to stream when the exception
437 # crosses the context manager. 466 # crosses the context manager.
438 ret = -1 467 ret = -1
439 raise 468 raise
440 if ret > 0: 469 if ret > 0:
441 stream.step_cursor(stream.current_step) 470 stream.step_cursor(stream.current_step)
442 print 'step returned non-zero exit code: %d' % ret 471 print 'step returned non-zero exit code: %d' % ret
443 s.step_failure() 472 s.step_failure()
444 if followup_fn: 473 if followup_fn:
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 usage = '%s <command list file or - for stdin>' % sys.argv[0] 511 usage = '%s <command list file or - for stdin>' % sys.argv[0]
483 parser = optparse.OptionParser(usage=usage) 512 parser = optparse.OptionParser(usage=usage)
484 _, args = parser.parse_args() 513 _, args = parser.parse_args()
485 if not args: 514 if not args:
486 parser.error('Must specify an input filename.') 515 parser.error('Must specify an input filename.')
487 if len(args) > 1: 516 if len(args) > 1:
488 parser.error('Too many arguments specified.') 517 parser.error('Too many arguments specified.')
489 518
490 steps = [] 519 steps = []
491 520
521 def force_list_str(lst):
522 ret = []
523 for v in lst:
524 if isinstance(v, basestring):
525 v = str(v)
agable 2013/06/25 15:55:28 this isn't very unicode() friendly :(
iannucci 2013/06/25 21:22:09 No, but we shouldn't have unicode in our annotator
526 elif isinstance(v, list):
527 v = force_list_str(v)
528 ret.append(v)
529 return ret
530
531 def force_dict_strs(obj):
532 ret = {}
533 for k, v in obj.iteritems():
534 if isinstance(v, basestring):
535 v = str(v)
536 elif isinstance(v, list):
537 v = force_list_str(v)
538 ret[str(k)] = v
agable 2013/06/25 15:55:28 elif isinstance(v, dict):?
iannucci 2013/06/25 21:22:09 Oops. Fixed.
539 return ret
540
492 if args[0] == '-': 541 if args[0] == '-':
493 steps.extend(json.load(sys.stdin)) 542 steps.extend(json.load(sys.stdin, object_hook=force_dict_strs))
494 else: 543 else:
495 with open(args[0], 'rb') as f: 544 with open(args[0], 'rb') as f:
496 steps.extend(json.load(f)) 545 steps.extend(json.load(f, object_hook=force_dict_strs))
497 546
498 return 1 if run_steps(steps, False)[0] else 0 547 return 1 if run_steps(steps, False)[0] else 0
499 548
500 549
501 if __name__ == '__main__': 550 if __name__ == '__main__':
502 sys.exit(main()) 551 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | scripts/common/unittests/annotator_test.py » ('j') | scripts/slave/recipe_modules/chromium/config.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698