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

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: Simplify InputPlaceholder.cleanup 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
« no previous file with comments | « recipe_engine/recipe_test_api.py ('k') | recipe_engine/util.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 tdata = step_test.pop_placeholder(item.name_pieces)
457 new_cmd.extend(item.render(tdata)) 458 new_cmd.extend(item.render(tdata))
458 placeholders[module_name][placeholder_name].append((item, tdata)) 459 if isinstance(item, util.InputPlaceholder):
460 input_phs[module_name][placeholder_name].append((item, tdata))
461 else:
462 assert isinstance(item, util.OutputPlaceholder), (
463 'Not an OutputPlaceholder: %r' % item)
464 output_phs[module_name][placeholder_name].append((item, tdata))
459 else: 465 else:
460 new_cmd.append(item) 466 new_cmd.append(item)
461 rendered_step['cmd'] = new_cmd 467 rendered_step['cmd'] = new_cmd
462 468
463 # Process 'stdout', 'stderr' and 'stdin' placeholders, if given. 469 # Process 'stdout', 'stderr' and 'stdin' placeholders, if given.
464 stdio_placeholders = {} 470 stdio_placeholders = {}
465 for key in ('stdout', 'stderr', 'stdin'): 471 for key in ('stdout', 'stderr', 'stdin'):
466 placeholder = step.get(key) 472 placeholder = step.get(key)
467 tdata = None 473 tdata = None
468 if placeholder: 474 if placeholder:
469 assert isinstance(placeholder, util.Placeholder), key 475 if key == 'stdin':
476 assert isinstance(placeholder, util.InputPlaceholder), (
477 '%s(%r) should be an InputPlaceholder.' % (key, placeholder))
478 else:
479 assert isinstance(placeholder, util.OutputPlaceholder), (
480 '%s(%r) should be an OutputPlaceholder.' % (key, placeholder))
470 tdata = getattr(step_test, key) 481 tdata = getattr(step_test, key)
471 placeholder.render(tdata) 482 placeholder.render(tdata)
472 assert placeholder.backing_file 483 assert placeholder.backing_file
473 rendered_step[key] = placeholder.backing_file 484 rendered_step[key] = placeholder.backing_file
474 stdio_placeholders[key] = (placeholder, tdata) 485 stdio_placeholders[key] = (placeholder, tdata)
475 486
476 return rendered_step, Placeholders(cmd=placeholders, **stdio_placeholders) 487 return rendered_step, Placeholders(
488 inputs_cmd=input_phs, outputs_cmd=output_phs, **stdio_placeholders)
477 489
478 490
479 def construct_step_result(step, retcode, placeholders): 491 def construct_step_result(step, retcode, placeholders):
480 """Constructs a StepData step result from step return data. 492 """Constructs a StepData step result from step return data.
481 493
482 The main purpose of this function is to add placeholder results into the 494 The main purpose of this function is to add output placeholder results into
483 step result where placeholders appeared in the input step. 495 the step result where output placeholders appeared in the input step.
496 Also give input placeholders the chance to do the clean-up if needed.
484 """ 497 """
485 498
486 step_result = types.StepData(step, retcode) 499 step_result = types.StepData(step, retcode)
487 500
488 class BlankObject(object): 501 class BlankObject(object):
489 pass 502 pass
490 503
491 # Placeholders inside step |cmd|. 504 # Input placeholders inside step |cmd|.
492 for module_name, pholders in placeholders.cmd.iteritems(): 505 for _, pholders in placeholders.inputs_cmd.iteritems():
506 for _, items in pholders.iteritems():
507 for ph, td in items:
508 ph.cleanup(td.enabled)
509
510 # Output placeholders inside step |cmd|.
511 for module_name, pholders in placeholders.outputs_cmd.iteritems():
493 assert not hasattr(step_result, module_name) 512 assert not hasattr(step_result, module_name)
494 o = BlankObject() 513 o = BlankObject()
495 setattr(step_result, module_name, o) 514 setattr(step_result, module_name, o)
496 515
497 for placeholder_name, items in pholders.iteritems(): 516 for placeholder_name, items in pholders.iteritems():
498 lst = [ph.result(step_result.presentation, td) for ph, td in items] 517 lst = [ph.result(step_result.presentation, td) for ph, td in items]
499 setattr(o, placeholder_name+"_all", lst) 518 setattr(o, placeholder_name+"_all", lst)
500 setattr(o, placeholder_name, lst[0]) 519 setattr(o, placeholder_name, lst[0])
501 520
502 # Placeholders that are used with IO redirection. 521 # Placeholders that are used with IO redirection.
503 for key in ('stdout', 'stderr', 'stdin'): 522 for key in ('stdout', 'stderr', 'stdin'):
504 assert not hasattr(step_result, key) 523 assert not hasattr(step_result, key)
505 ph, td = getattr(placeholders, key) 524 ph, td = getattr(placeholders, key)
506 result = ph.result(step_result.presentation, td) if ph else None 525 if ph:
507 setattr(step_result, key, result) 526 if isinstance(ph, util.OutputPlaceholder):
527 setattr(step_result, key, ph.result(step_result.presentation, td))
528 else:
529 assert isinstance(ph, util.InputPlaceholder), (
530 '%s(%r) should be an InputPlaceholder.' % (key, ph))
531 ph.cleanup(td.enabled)
508 532
509 return step_result 533 return step_result
510 534
511 535
512 def _merge_envs(original, override): 536 def _merge_envs(original, override):
513 """Merges two environments. 537 """Merges two environments.
514 538
515 Returns a new environment dict with entries from |override| overwriting 539 Returns a new environment dict with entries from |override| overwriting
516 corresponding entries in |original|. Keys whose value is None will completely 540 corresponding entries in |original|. Keys whose value is None will completely
517 remove the environment variable. Values can contain %(KEY)s strings, which 541 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 582 supplied command, and only uses the |env| kwarg for modifying the environment
559 of the child process. 583 of the child process.
560 """ 584 """
561 saved_path = os.environ['PATH'] 585 saved_path = os.environ['PATH']
562 try: 586 try:
563 if path is not None: 587 if path is not None:
564 os.environ['PATH'] = path 588 os.environ['PATH'] = path
565 yield 589 yield
566 finally: 590 finally:
567 os.environ['PATH'] = saved_path 591 os.environ['PATH'] = saved_path
OLDNEW
« no previous file with comments | « recipe_engine/recipe_test_api.py ('k') | recipe_engine/util.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698