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

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: Fix presubmit + move polyfill (retry) Created 7 years, 5 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 json 16 import json
17 import optparse 17 import optparse
18 import os 18 import os
19 import re 19 import re
20 import subprocess
20 import sys 21 import sys
22 import threading
21 import traceback 23 import traceback
22 24
23 from common import chromium_utils
24
25 25
26 def emit(line, stream, flush_before=None): 26 def emit(line, stream, flush_before=None):
27 if flush_before: 27 if flush_before:
28 flush_before.flush() 28 flush_before.flush()
29 print >> stream, '\n' + line 29 print >> stream
30 # WinDOS can only handle 64kb of output to the console at a time, per process.
31 if sys.platform.startswith('win'):
32 lim = 2**15
33 while line:
34 to_print, line = line[:lim], line[lim:]
35 stream.write(to_print)
36 else:
37 print >> stream, line
30 stream.flush() 38 stream.flush()
31 39
32 40
33 class StepCommands(object): 41 class StepCommands(object):
34 """Class holding step commands. Intended to be subclassed.""" 42 """Class holding step commands. Intended to be subclassed."""
35 def __init__(self, stream, flush_before): 43 def __init__(self, stream, flush_before):
36 self.stream = stream 44 self.stream = stream
37 self.flush_before = flush_before 45 self.flush_before = flush_before
38 46
39 def emit(self, line): 47 def emit(self, line):
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 414
407 # For error reporting. 415 # For error reporting.
408 step_dict = locals().copy() 416 step_dict = locals().copy()
409 step_dict.pop('kwargs') 417 step_dict.pop('kwargs')
410 step_dict.pop('stream') 418 step_dict.pop('stream')
411 step_dict.update(kwargs) 419 step_dict.update(kwargs)
412 420
413 for step_name in (seed_steps or []): 421 for step_name in (seed_steps or []):
414 stream.seed_step(step_name) 422 stream.seed_step(step_name)
415 423
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 424 ret = None
427 with stream.step(name) as s: 425 with stream.step(name) as s:
428 print_step(step_dict) 426 print_step(step_dict)
429 try: 427 try:
430 ret = chromium_utils.RunCommand(command=cmd, 428 proc = subprocess.Popen(
431 cwd=cwd, 429 cmd,
432 env=_merge_envs(os.environ, env), 430 env=_merge_envs(os.environ, env),
433 filter_obj=filter_obj, 431 cwd=cwd,
434 print_cmd=False) 432 stdout=subprocess.PIPE,
433 stderr=subprocess.PIPE)
434
435 outlock = threading.Lock()
436 def filter_lines(lock, allow_subannotations, inhandle, outhandle):
437 while True:
438 line = inhandle.readline()
439 if not line:
440 break
441 lock.acquire()
442 try:
443 if not allow_subannotations and line.startswith('@@@'):
444 outhandle.write('!')
445 outhandle.write(line)
446 outhandle.flush()
447 finally:
448 lock.release()
449
450 outthread = threading.Thread(
451 target=filter_lines,
452 args=(outlock, allow_subannotations, proc.stdout, sys.stdout))
453 errthread = threading.Thread(
454 target=filter_lines,
455 args=(outlock, allow_subannotations, proc.stderr, sys.stderr))
456 outthread.start()
457 errthread.start()
458 proc.wait()
459 outthread.join()
460 errthread.join()
461 ret = proc.returncode
435 except OSError: 462 except OSError:
436 # File wasn't found, error will be reported to stream when the exception 463 # File wasn't found, error will be reported to stream when the exception
437 # crosses the context manager. 464 # crosses the context manager.
438 ret = -1 465 ret = -1
439 raise 466 raise
440 if ret > 0: 467 if ret > 0:
441 stream.step_cursor(stream.current_step) 468 stream.step_cursor(stream.current_step)
442 print 'step returned non-zero exit code: %d' % ret 469 print 'step returned non-zero exit code: %d' % ret
443 s.step_failure() 470 s.step_failure()
444 if followup_fn: 471 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] 509 usage = '%s <command list file or - for stdin>' % sys.argv[0]
483 parser = optparse.OptionParser(usage=usage) 510 parser = optparse.OptionParser(usage=usage)
484 _, args = parser.parse_args() 511 _, args = parser.parse_args()
485 if not args: 512 if not args:
486 parser.error('Must specify an input filename.') 513 parser.error('Must specify an input filename.')
487 if len(args) > 1: 514 if len(args) > 1:
488 parser.error('Too many arguments specified.') 515 parser.error('Too many arguments specified.')
489 516
490 steps = [] 517 steps = []
491 518
519 def force_list_str(lst):
520 ret = []
521 for v in lst:
522 if isinstance(v, basestring):
523 v = str(v)
524 elif isinstance(v, list):
525 v = force_list_str(v)
526 elif isinstance(v, dict):
527 v = force_dict_strs(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 elif isinstance(v, dict):
539 v = force_dict_strs(v)
540 ret[str(k)] = v
541 return ret
542
492 if args[0] == '-': 543 if args[0] == '-':
493 steps.extend(json.load(sys.stdin)) 544 steps.extend(json.load(sys.stdin, object_hook=force_dict_strs))
494 else: 545 else:
495 with open(args[0], 'rb') as f: 546 with open(args[0], 'rb') as f:
496 steps.extend(json.load(f)) 547 steps.extend(json.load(f, object_hook=force_dict_strs))
497 548
498 return 1 if run_steps(steps, False)[0] else 0 549 return 1 if run_steps(steps, False)[0] else 0
499 550
500 551
501 if __name__ == '__main__': 552 if __name__ == '__main__':
502 sys.exit(main()) 553 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | scripts/common/python26_polyfill.py » ('j') | scripts/slave/recipe_modules/gclient/api.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698