| OLD | NEW |
| 1 # Copyright 2013 The LUCI Authors. All rights reserved. | 1 # Copyright 2013 The LUCI Authors. All rights reserved. |
| 2 # Use of this source code is governed under the Apache License, Version 2.0 | 2 # Use of this source code is governed under the Apache License, Version 2.0 |
| 3 # that can be found in the LICENSE file. | 3 # that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import contextlib | 5 import contextlib |
| 6 import datetime | 6 import datetime |
| 7 | 7 |
| 8 from recipe_engine import recipe_api | 8 from recipe_engine import recipe_api |
| 9 | 9 |
| 10 | 10 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 new_step_text = result.json.output['step_text'] | 70 new_step_text = result.json.output['step_text'] |
| 71 api.step.active_result.presentation.step_text = new_step_text | 71 api.step.active_result.presentation.step_text = new_step_text |
| 72 """ | 72 """ |
| 73 return self.step_client.previous_step_result() | 73 return self.step_client.previous_step_result() |
| 74 | 74 |
| 75 @property | 75 @property |
| 76 def context(self): | 76 def context(self): |
| 77 """ See recipe_api.py for docs. """ | 77 """ See recipe_api.py for docs. """ |
| 78 return recipe_api.context | 78 return recipe_api.context |
| 79 | 79 |
| 80 def get_context(self): |
| 81 return recipe_api._STEP_CONTEXT |
| 82 |
| 80 @contextlib.contextmanager | 83 @contextlib.contextmanager |
| 81 def nest(self, name): | 84 def nest(self, name): |
| 82 """Nest is the high-level interface to annotated hierarchical steps. | 85 """Nest is the high-level interface to annotated hierarchical steps. |
| 83 | 86 |
| 84 Calling | 87 Calling |
| 85 | 88 |
| 86 with api.step.nest(<name>): | 89 with api.step.nest(<name>): |
| 87 ... | 90 ... |
| 88 | 91 |
| 89 will generate a dummy step and implicitly create a new context (as | 92 will generate a dummy step and implicitly create a new context (as |
| 90 above); the dummy step will govern annotation emission, while the implicit | 93 above); the dummy step will govern annotation emission, while the implicit |
| 91 context will propagate the dummy step's name to subordinate steps. | 94 context will propagate the dummy step's name to subordinate steps. |
| 92 """ | 95 """ |
| 93 step_result = self(name, []) | 96 step_result = self(name, []) |
| 94 context_dict = {'name': name, 'nest_level': 1} | 97 context_dict = {'name': name, 'nest_level': 1} |
| 95 with self.context(context_dict): | 98 with self.context(context_dict): |
| 96 yield step_result | 99 yield step_result |
| 97 | 100 |
| 98 @property | 101 @property |
| 99 def defer_results(self): | 102 def defer_results(self): |
| 100 """ See recipe_api.py for docs. """ | 103 """ See recipe_api.py for docs. """ |
| 101 return recipe_api.defer_results | 104 return recipe_api.defer_results |
| 102 | 105 |
| 103 def __call__(self, name, cmd, ok_ret=None, infra_step=False, wrapper=(), | 106 def __call__(self, name, cmd, ok_ret=None, infra_step=False, wrapper=(), |
| 104 timeout=None, cwd=None, env=None, allow_subannotations=None, | 107 timeout=None, env=None, allow_subannotations=None, |
| 105 trigger_specs=None, stdout=None, stderr=None, stdin=None, | 108 trigger_specs=None, stdout=None, stderr=None, stdin=None, |
| 106 step_test_data=None): | 109 step_test_data=None): |
| 107 """Returns a step dictionary which is compatible with annotator.py. | 110 """Returns a step dictionary which is compatible with annotator.py. |
| 108 | 111 |
| 109 Args: | 112 Args: |
| 110 name (string): The name of this step. | 113 name (string): The name of this step. |
| 111 cmd (list of strings): in the style of subprocess.Popen or None to create | 114 cmd (list of strings): in the style of subprocess.Popen or None to create |
| 112 a no-op fake step. | 115 a no-op fake step. |
| 113 ok_ret (tuple or set of ints, str): allowed return codes. Any unexpected | 116 ok_ret (tuple or set of ints, str): allowed return codes. Any unexpected |
| 114 return codes will cause an exception to be thrown. If you pass in the | 117 return codes will cause an exception to be thrown. If you pass in the |
| (...skipping 19 matching lines...) Expand all Loading... |
| 134 stdin: Placeholder to read step stdin from. | 137 stdin: Placeholder to read step stdin from. |
| 135 step_test_data (func -> recipe_test_api.StepTestData): A factory which | 138 step_test_data (func -> recipe_test_api.StepTestData): A factory which |
| 136 returns a StepTestData object that will be used as the default test | 139 returns a StepTestData object that will be used as the default test |
| 137 data for this step. The recipe author can override/augment this object | 140 data for this step. The recipe author can override/augment this object |
| 138 in the GenTests function. | 141 in the GenTests function. |
| 139 | 142 |
| 140 Returns: | 143 Returns: |
| 141 Opaque step object produced and understood by recipe engine. | 144 Opaque step object produced and understood by recipe engine. |
| 142 """ | 145 """ |
| 143 kwargs = {} | 146 kwargs = {} |
| 144 if cwd: | |
| 145 kwargs['cwd'] = cwd | |
| 146 if env: | 147 if env: |
| 147 kwargs['env'] = env | 148 kwargs['env'] = env |
| 148 if allow_subannotations is not None: | 149 if allow_subannotations is not None: |
| 149 kwargs['allow_subannotations'] = allow_subannotations | 150 kwargs['allow_subannotations'] = allow_subannotations |
| 150 if trigger_specs: | 151 if trigger_specs: |
| 151 kwargs['trigger_specs'] = trigger_specs | 152 kwargs['trigger_specs'] = trigger_specs |
| 152 if stdout: | 153 if stdout: |
| 153 kwargs['stdout'] = stdout | 154 kwargs['stdout'] = stdout |
| 154 if stderr: | 155 if stderr: |
| 155 kwargs['stderr'] = stderr | 156 kwargs['stderr'] = stderr |
| 156 if stdin: | 157 if stdin: |
| 157 kwargs['stdin'] = stdin | 158 kwargs['stdin'] = stdin |
| 158 if step_test_data: | 159 if step_test_data: |
| 159 kwargs['step_test_data'] = step_test_data | 160 kwargs['step_test_data'] = step_test_data |
| 160 assert cmd is None or isinstance(cmd, list) | 161 assert cmd is None or isinstance(cmd, list) |
| 161 if not ok_ret: | 162 if not ok_ret: |
| 162 ok_ret = {0} | 163 ok_ret = {0} |
| 163 if ok_ret in ('any', 'all'): | 164 if ok_ret in ('any', 'all'): |
| 164 ok_ret = set(range(-256, 256)) | 165 ok_ret = set(range(-256, 256)) |
| 165 | 166 |
| 166 if cmd is not None: | 167 if cmd is not None: |
| 167 command = list(wrapper) | 168 command = list(wrapper) |
| 168 command += cmd | 169 command += cmd |
| 169 kwargs['cmd'] = command | 170 kwargs['cmd'] = command |
| 170 | 171 |
| 171 kwargs['timeout'] = timeout | 172 kwargs['timeout'] = timeout |
| 172 kwargs['ok_ret'] = ok_ret | 173 kwargs['ok_ret'] = ok_ret |
| 173 | 174 |
| 174 # Obtain information from composite step parent. | 175 # Obtain information from composite step parent. |
| 175 compositor = recipe_api._STEP_CONTEXT | 176 compositor = self.get_context() |
| 176 | 177 |
| 177 # Calculate our full step name. If a step already has that name, add an | 178 # Calculate our full step name. If a step already has that name, add an |
| 178 # index to the end of it. | 179 # index to the end of it. |
| 179 # | 180 # |
| 180 # Note that another step could exist with that index already added to it | 181 # Note that another step could exist with that index already added to it |
| 181 # by the user. If this happens, we'll continue appending indexes until we | 182 # by the user. If this happens, we'll continue appending indexes until we |
| 182 # have a unique step name. | 183 # have a unique step name. |
| 183 while True: | 184 while True: |
| 184 full_name = compositor.get_with_context('name', name) | 185 full_name = compositor.get_with_context('name', name) |
| 185 if full_name not in self._seen_steps: | 186 if full_name not in self._seen_steps: |
| (...skipping 14 matching lines...) Expand all Loading... |
| 200 kwargs['base_name'] = name | 201 kwargs['base_name'] = name |
| 201 | 202 |
| 202 schema = self.make_config() | 203 schema = self.make_config() |
| 203 schema.set_val(kwargs) | 204 schema.set_val(kwargs) |
| 204 return self.run_from_dict(schema.as_jsonish()) | 205 return self.run_from_dict(schema.as_jsonish()) |
| 205 | 206 |
| 206 # TODO(martiniss) delete, and make generator_script use **kwargs on step() | 207 # TODO(martiniss) delete, and make generator_script use **kwargs on step() |
| 207 @recipe_api.composite_step | 208 @recipe_api.composite_step |
| 208 def run_from_dict(self, dct): | 209 def run_from_dict(self, dct): |
| 209 return self.step_client.run_step(dct) | 210 return self.step_client.run_step(dct) |
| OLD | NEW |