Chromium Code Reviews| Index: recipe_engine/step_runner.py |
| diff --git a/recipe_engine/step_runner.py b/recipe_engine/step_runner.py |
| index dcfb0b384086c2b626e7d149c45b2c0507945e63..c7d5c4be1c7dc1cee9033e0d47c29674092bfb57 100644 |
| --- a/recipe_engine/step_runner.py |
| +++ b/recipe_engine/step_runner.py |
| @@ -449,19 +449,26 @@ def render_step(step, step_test): |
| # Process 'cmd', rendering placeholders there. |
| input_phs = collections.defaultdict(lambda: collections.defaultdict(list)) |
| - output_phs = collections.defaultdict(lambda: collections.defaultdict(list)) |
| + output_phs = collections.defaultdict( |
| + lambda: collections.defaultdict(collections.OrderedDict)) |
| new_cmd = [] |
| for item in step.get('cmd', []): |
| if isinstance(item, util.Placeholder): |
| - module_name, placeholder_name = item.name_pieces |
| - tdata = step_test.pop_placeholder(item.name_pieces) |
| + module_name, placeholder_name = item.namespaces |
| + tdata = step_test.pop_placeholder( |
| + module_name, placeholder_name, item.name) |
| new_cmd.extend(item.render(tdata)) |
| if isinstance(item, util.InputPlaceholder): |
| input_phs[module_name][placeholder_name].append((item, tdata)) |
| else: |
| assert isinstance(item, util.OutputPlaceholder), ( |
| 'Not an OutputPlaceholder: %r' % item) |
| - output_phs[module_name][placeholder_name].append((item, tdata)) |
| + # 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.
|
| + assert item.name not in output_phs[module_name][placeholder_name], ( |
| + 'Step "%s" has multiple output placeholders of %s.%s. Please ' |
| + 'specify explicit and different names for them.' % ( |
| + step['name'], module_name, placeholder_name)) |
| + output_phs[module_name][placeholder_name][item.name] = (item, tdata) |
| else: |
| new_cmd.append(item) |
| rendered_step['cmd'] = new_cmd |
| @@ -511,17 +518,29 @@ def construct_step_result(step, retcode, placeholders): |
| o = BlankObject() |
| setattr(step_result, module_name, o) |
| - for placeholder_name, items in pholders.iteritems(): |
| - lst = [ph.result(step_result.presentation, td) for ph, td in items] |
| - setattr(o, placeholder_name+"_all", lst) |
| - setattr(o, placeholder_name, lst[0]) |
| + for placeholder_name, instances in pholders.iteritems(): |
| + named_results = {} |
| + default_result = None |
| + for _, (ph, td) in instances.iteritems(): |
| + result = ph.result(step_result.presentation, td) |
| + if ph.name is None: |
| + default_result = result |
| + else: |
| + named_results[ph.name] = result |
| + setattr(o, placeholder_name + "s", named_results) |
| + |
| + if default_result is None and len(named_results) == 1: |
| + # Only 1 output placeholder with an explicit name. |
| + default_result = named_results.values()[0] |
| + 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
|
| # Placeholders that are used with IO redirection. |
| for key in ('stdout', 'stderr', 'stdin'): |
| assert not hasattr(step_result, key) |
| ph, td = getattr(placeholders, key) |
| result = ph.result(step_result.presentation, td) if ph else None |
| - setattr(step_result, key, result) |
| + if key != 'stdin': |
| + setattr(step_result, key, result) |
| return step_result |