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

Side by Side Diff: recipe_engine/step_runner.py

Issue 1785543004: Split Placeholder into InputPlaceholder and OutputPlaceholder. (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/recipes-py@master
Patch Set: Fix nits. 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 413 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 self._test_data.step_data.keys(), 424 self._test_data.step_data.keys(),
425 self._test_data.expected_exception)) 425 self._test_data.expected_exception))
426 426
427 @property 427 @property
428 def steps_ran(self): 428 def steps_ran(self):
429 return self._step_history.values() 429 return self._step_history.values()
430 430
431 431
432 # Result of 'render_step'. 432 # Result of 'render_step'.
433 Placeholders = collections.namedtuple( 433 Placeholders = collections.namedtuple(
434 'Placeholders', ['cmd', 'stdout', 'stderr', 'stdin']) 434 'Placeholders', ['inputs_cmd', 'outputs_cmd', 'stdout', 'stderr', 'stdin'])
435 435
436 436
437 def render_step(step, step_test): 437 def render_step(step, step_test):
438 """Renders a step so that it can be fed to annotator.py. 438 """Renders a step so that it can be fed to annotator.py.
439 439
440 Args: 440 Args:
441 step: The step to render. 441 step: The step to render.
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 placeholders = 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 new_cmd = [] 453 new_cmd = []
453 for item in step.get('cmd', []): 454 for item in step.get('cmd', []):
454 if isinstance(item, util.Placeholder): 455 if isinstance(item, util.Placeholder):
455 module_name, placeholder_name = item.name_pieces 456 module_name, placeholder_name = item.name_pieces
456 tdata = step_test.pop_placeholder(item.name_pieces) 457 if isinstance(item, util.InputPlaceholder):
458 tdata = step_test.pop_input_placeholder(item.name_pieces)
iannucci 2016/03/12 03:36:12 not needed: inputs are never mocked
stgao 2016/03/22 05:56:43 Reverted to the old approach. We still need a def
459 input_phs[module_name][placeholder_name].append((item, tdata))
460 else:
461 assert isinstance(item, util.OutputPlaceholder), (
462 'Not an OutputPlaceholder: %r' % item)
463 tdata = step_test.pop_output_placeholder(item.name_pieces)
464 output_phs[module_name][placeholder_name].append((item, tdata))
457 new_cmd.extend(item.render(tdata)) 465 new_cmd.extend(item.render(tdata))
458 placeholders[module_name][placeholder_name].append((item, tdata))
459 else: 466 else:
460 new_cmd.append(item) 467 new_cmd.append(item)
461 rendered_step['cmd'] = new_cmd 468 rendered_step['cmd'] = new_cmd
462 469
463 # Process 'stdout', 'stderr' and 'stdin' placeholders, if given. 470 # Process 'stdout', 'stderr' and 'stdin' placeholders, if given.
464 stdio_placeholders = {} 471 stdio_placeholders = {}
465 for key in ('stdout', 'stderr', 'stdin'): 472 for key in ('stdout', 'stderr', 'stdin'):
466 placeholder = step.get(key) 473 placeholder = step.get(key)
467 tdata = None 474 tdata = None
468 if placeholder: 475 if placeholder:
469 assert isinstance(placeholder, util.Placeholder), key 476 if key == 'stdin':
477 assert isinstance(placeholder, util.InputPlaceholder), key
478 else:
479 assert isinstance(placeholder, util.OutputPlaceholder), key
470 tdata = getattr(step_test, key) 480 tdata = getattr(step_test, key)
471 placeholder.render(tdata) 481 placeholder.render(tdata)
472 assert placeholder.backing_file 482 assert placeholder.backing_file
473 rendered_step[key] = placeholder.backing_file 483 rendered_step[key] = placeholder.backing_file
474 stdio_placeholders[key] = (placeholder, tdata) 484 stdio_placeholders[key] = (placeholder, tdata)
475 485
476 return rendered_step, Placeholders(cmd=placeholders, **stdio_placeholders) 486 return rendered_step, Placeholders(
487 inputs_cmd=input_phs, outputs_cmd=output_phs, **stdio_placeholders)
477 488
478 489
479 def construct_step_result(step, retcode, placeholders): 490 def construct_step_result(step, retcode, placeholders):
480 """Constructs a StepData step result from step return data. 491 """Constructs a StepData step result from step return data.
481 492
482 The main purpose of this function is to add placeholder results into the 493 The main purpose of this function is to add output placeholder results into
483 step result where placeholders appeared in the input step. 494 the step result where output placeholders appeared in the input step.
495 Also give input placeholders the chance to do the clean-up if needed.
484 """ 496 """
485 497
486 step_result = types.StepData(step, retcode) 498 step_result = types.StepData(step, retcode)
487 499
488 class BlankObject(object): 500 class BlankObject(object):
489 pass 501 pass
490 502
491 # Placeholders inside step |cmd|. 503 # Input placeholders inside step |cmd|.
492 for module_name, pholders in placeholders.cmd.iteritems(): 504 for _, pholders in placeholders.inputs_cmd.iteritems():
505 for _, items in pholders.iteritems():
506 for ph, td in items:
507 ph.result(step_result.presentation, td)
508
509 # Output placeholders inside step |cmd|.
510 for module_name, pholders in placeholders.outputs_cmd.iteritems():
493 assert not hasattr(step_result, module_name) 511 assert not hasattr(step_result, module_name)
494 o = BlankObject() 512 o = BlankObject()
495 setattr(step_result, module_name, o) 513 setattr(step_result, module_name, o)
496 514
497 for placeholder_name, items in pholders.iteritems(): 515 for placeholder_name, items in pholders.iteritems():
498 lst = [ph.result(step_result.presentation, td) for ph, td in items] 516 lst = [ph.result(step_result.presentation, td) for ph, td in items]
499 setattr(o, placeholder_name+"_all", lst) 517 setattr(o, placeholder_name+"_all", lst)
500 setattr(o, placeholder_name, lst[0]) 518 setattr(o, placeholder_name, lst[0])
501 519
502 # Placeholders that are used with IO redirection. 520 # Placeholders that are used with IO redirection.
503 for key in ('stdout', 'stderr', 'stdin'): 521 for key in ('stdout', 'stderr', 'stdin'):
504 assert not hasattr(step_result, key) 522 assert not hasattr(step_result, key)
505 ph, td = getattr(placeholders, key) 523 ph, td = getattr(placeholders, key)
506 result = ph.result(step_result.presentation, td) if ph else None 524 result = ph.result(step_result.presentation, td) if ph else None
507 setattr(step_result, key, result) 525 if key != 'stdin':
iannucci 2016/03/12 03:36:12 this looks wrong to me...? Not sure what this is s
stgao 2016/03/22 05:56:43 Reverted. However, I thought we don't want to inc
526 setattr(step_result, key, result)
508 527
509 return step_result 528 return step_result
510 529
511 530
512 def _merge_envs(original, override): 531 def _merge_envs(original, override):
513 """Merges two environments. 532 """Merges two environments.
514 533
515 Returns a new environment dict with entries from |override| overwriting 534 Returns a new environment dict with entries from |override| overwriting
516 corresponding entries in |original|. Keys whose value is None will completely 535 corresponding entries in |original|. Keys whose value is None will completely
517 remove the environment variable. Values can contain %(KEY)s strings, which 536 remove the environment variable. Values can contain %(KEY)s strings, which
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 supplied command, and only uses the |env| kwarg for modifying the environment 577 supplied command, and only uses the |env| kwarg for modifying the environment
559 of the child process. 578 of the child process.
560 """ 579 """
561 saved_path = os.environ['PATH'] 580 saved_path = os.environ['PATH']
562 try: 581 try:
563 if path is not None: 582 if path is not None:
564 os.environ['PATH'] = path 583 os.environ['PATH'] = path
565 yield 584 yield
566 finally: 585 finally:
567 os.environ['PATH'] = saved_path 586 os.environ['PATH'] = saved_path
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698