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

Side by Side Diff: recipe_engine/step_runner.py

Issue 1773273003: Make output placeholders like json.output index-able by name. (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/recipes-py@master
Patch Set: Address comments. Created 4 years, 9 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
OLDNEW
1 # Copyright (c) 2013-2015 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2013-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 import cStringIO 5 import cStringIO
6 import collections 6 import collections
7 import contextlib 7 import contextlib
8 import datetime 8 import datetime
9 import json 9 import json
10 import os 10 import os
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 step_test: The test data json dictionary for this step, if any. 442 step_test: The test data json dictionary for this step, if any.
443 Passed through unaltered to each placeholder. 443 Passed through unaltered to each placeholder.
444 444
445 Returns the rendered step and a Placeholders object representing any 445 Returns the rendered step and a Placeholders object representing any
446 placeholder instances that were found while rendering. 446 placeholder instances that were found while rendering.
447 """ 447 """
448 rendered_step = dict(step) 448 rendered_step = dict(step)
449 449
450 # Process 'cmd', rendering placeholders there. 450 # Process 'cmd', rendering placeholders there.
451 input_phs = collections.defaultdict(lambda: collections.defaultdict(list)) 451 input_phs = collections.defaultdict(lambda: collections.defaultdict(list))
452 output_phs = collections.defaultdict(lambda: collections.defaultdict(list)) 452 output_phs = collections.defaultdict(
453 lambda: collections.defaultdict(collections.OrderedDict))
453 new_cmd = [] 454 new_cmd = []
454 for item in step.get('cmd', []): 455 for item in step.get('cmd', []):
455 if isinstance(item, util.Placeholder): 456 if isinstance(item, util.Placeholder):
456 module_name, placeholder_name = item.name_pieces 457 module_name, placeholder_name = item.namespaces
457 tdata = step_test.pop_placeholder(item.name_pieces) 458 tdata = step_test.pop_placeholder(
459 module_name, placeholder_name, item.name)
458 new_cmd.extend(item.render(tdata)) 460 new_cmd.extend(item.render(tdata))
459 if isinstance(item, util.InputPlaceholder): 461 if isinstance(item, util.InputPlaceholder):
460 input_phs[module_name][placeholder_name].append((item, tdata)) 462 input_phs[module_name][placeholder_name].append((item, tdata))
461 else: 463 else:
462 assert isinstance(item, util.OutputPlaceholder), ( 464 assert isinstance(item, util.OutputPlaceholder), (
463 'Not an OutputPlaceholder: %r' % item) 465 'Not an OutputPlaceholder: %r' % item)
464 output_phs[module_name][placeholder_name].append((item, tdata)) 466 # This assert also ensures at most one placeholder has the default name.
iannucci 2016/03/22 22:54:24 well, it also asserts (correctly) that you don't h
stgao 2016/03/22 23:40:25 Yes. Updated.
467 assert item.name not in output_phs[module_name][placeholder_name], (
468 'Step "%s" has multiple output placeholders of %s.%s. Please '
469 'specify explicit and different names for them.' % (
470 step['name'], module_name, placeholder_name))
471 output_phs[module_name][placeholder_name][item.name] = (item, tdata)
465 else: 472 else:
466 new_cmd.append(item) 473 new_cmd.append(item)
467 rendered_step['cmd'] = new_cmd 474 rendered_step['cmd'] = new_cmd
468 475
469 # Process 'stdout', 'stderr' and 'stdin' placeholders, if given. 476 # Process 'stdout', 'stderr' and 'stdin' placeholders, if given.
470 stdio_placeholders = {} 477 stdio_placeholders = {}
471 for key in ('stdout', 'stderr', 'stdin'): 478 for key in ('stdout', 'stderr', 'stdin'):
472 placeholder = step.get(key) 479 placeholder = step.get(key)
473 tdata = None 480 tdata = None
474 if placeholder: 481 if placeholder:
(...skipping 29 matching lines...) Expand all
504 for _, items in pholders.iteritems(): 511 for _, items in pholders.iteritems():
505 for ph, td in items: 512 for ph, td in items:
506 ph.result(step_result.presentation, td) 513 ph.result(step_result.presentation, td)
507 514
508 # Output placeholders inside step |cmd|. 515 # Output placeholders inside step |cmd|.
509 for module_name, pholders in placeholders.outputs_cmd.iteritems(): 516 for module_name, pholders in placeholders.outputs_cmd.iteritems():
510 assert not hasattr(step_result, module_name) 517 assert not hasattr(step_result, module_name)
511 o = BlankObject() 518 o = BlankObject()
512 setattr(step_result, module_name, o) 519 setattr(step_result, module_name, o)
513 520
514 for placeholder_name, items in pholders.iteritems(): 521 for placeholder_name, instances in pholders.iteritems():
515 lst = [ph.result(step_result.presentation, td) for ph, td in items] 522 named_results = {}
516 setattr(o, placeholder_name+"_all", lst) 523 default_result = None
517 setattr(o, placeholder_name, lst[0]) 524 for _, (ph, td) in instances.iteritems():
525 result = ph.result(step_result.presentation, td)
526 if ph.name is None:
527 default_result = result
528 else:
529 named_results[ph.name] = result
530 setattr(o, placeholder_name + "s", named_results)
531
532 if default_result is None and len(named_results) == 1:
533 # Only 1 output placeholder with an explicit name.
534 default_result = named_results.values()[0]
535 setattr(o, placeholder_name, default_result)
iannucci 2016/03/22 22:54:24 what if there's two placeholders with names, and n
stgao 2016/03/22 23:40:25 Then the default output is set to None, per our di
518 536
519 # Placeholders that are used with IO redirection. 537 # Placeholders that are used with IO redirection.
520 for key in ('stdout', 'stderr', 'stdin'): 538 for key in ('stdout', 'stderr', 'stdin'):
521 assert not hasattr(step_result, key) 539 assert not hasattr(step_result, key)
522 ph, td = getattr(placeholders, key) 540 ph, td = getattr(placeholders, key)
523 result = ph.result(step_result.presentation, td) if ph else None 541 result = ph.result(step_result.presentation, td) if ph else None
524 setattr(step_result, key, result) 542 if key != 'stdin':
543 setattr(step_result, key, result)
525 544
526 return step_result 545 return step_result
527 546
528 547
529 def _merge_envs(original, override): 548 def _merge_envs(original, override):
530 """Merges two environments. 549 """Merges two environments.
531 550
532 Returns a new environment dict with entries from |override| overwriting 551 Returns a new environment dict with entries from |override| overwriting
533 corresponding entries in |original|. Keys whose value is None will completely 552 corresponding entries in |original|. Keys whose value is None will completely
534 remove the environment variable. Values can contain %(KEY)s strings, which 553 remove the environment variable. Values can contain %(KEY)s strings, which
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 supplied command, and only uses the |env| kwarg for modifying the environment 594 supplied command, and only uses the |env| kwarg for modifying the environment
576 of the child process. 595 of the child process.
577 """ 596 """
578 saved_path = os.environ['PATH'] 597 saved_path = os.environ['PATH']
579 try: 598 try:
580 if path is not None: 599 if path is not None:
581 os.environ['PATH'] = path 600 os.environ['PATH'] = path
582 yield 601 yield
583 finally: 602 finally:
584 os.environ['PATH'] = saved_path 603 os.environ['PATH'] = saved_path
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698