Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2016 The LUCI Authors. All rights reserved. | 1 # Copyright 2016 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 from __future__ import absolute_import | 5 from __future__ import absolute_import |
| 6 import bisect | 6 import bisect |
| 7 import collections | 7 import collections |
| 8 import contextlib | 8 import contextlib |
| 9 import copy | 9 import copy |
| 10 import json | 10 import json |
| 11 import keyword | 11 import keyword |
| 12 import os | |
| 12 import re | 13 import re |
| 13 import types | 14 import types |
| 14 | 15 |
| 15 from functools import wraps | 16 from functools import wraps |
| 16 | 17 |
| 17 from .recipe_test_api import DisabledTestData, ModuleTestData | 18 from .recipe_test_api import DisabledTestData, ModuleTestData |
| 18 from .config import Single | 19 from .config import Single |
| 19 | 20 |
| 20 from .util import ModuleInjectionSite | 21 from .util import ModuleInjectionSite |
| 21 | 22 |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 250 ) | 251 ) |
| 251 | 252 |
| 252 def _render_to_dict(self): | 253 def _render_to_dict(self): |
| 253 d = dict((k, v) for k, v in self._asdict().iteritems() if v) | 254 d = dict((k, v) for k, v in self._asdict().iteritems() if v) |
| 254 if d['critical']: | 255 if d['critical']: |
| 255 d.pop('critical') | 256 d.pop('critical') |
| 256 return d | 257 return d |
| 257 | 258 |
| 258 | 259 |
| 259 _StepConfig = collections.namedtuple('_StepConfig', | 260 _StepConfig = collections.namedtuple('_StepConfig', |
| 260 ('name', 'base_name', 'cmd', 'cwd', 'env', 'allow_subannotations', | 261 ('name', 'base_name', 'cmd', 'cwd', 'env_prefixes', 'env', 'pathsep', |
|
iannucci
2017/06/12 19:58:39
pathsep is necessary for simulations I guess?
dnj
2017/06/13 19:31:21
Yeah, for accuracy I think we should use whatever
| |
| 261 'trigger_specs', 'timeout', 'infra_step', 'stdout', 'stderr', 'stdin', | 262 'allow_subannotations', 'trigger_specs', 'timeout', 'infra_step', 'stdout', |
| 262 'ok_ret', 'step_test_data', 'nest_level')) | 263 'stderr', 'stdin', 'ok_ret', 'step_test_data', 'nest_level')) |
| 263 | 264 |
| 264 class StepConfig(_StepConfig): | 265 class StepConfig(_StepConfig): |
| 265 """ | 266 """ |
| 266 StepConfig is the representation of a raw step as the recipe_engine sees it. | 267 StepConfig is the representation of a raw step as the recipe_engine sees it. |
| 267 You should use the standard 'step' recipe module, which will construct and | 268 You should use the standard 'step' recipe module, which will construct and |
| 268 pass this data to the engine for you, instead. The only reason why you would | 269 pass this data to the engine for you, instead. The only reason why you would |
| 269 need to worry about this object is if you're modifying the step module itself. | 270 need to worry about this object is if you're modifying the step module itself. |
| 270 | 271 |
| 271 The optional "env" parameter provides optional overrides for environment | 272 The optional "env" parameter provides optional overrides for environment |
| 272 variables. Each value is % formatted with the entire existing os.environ. A | 273 variables. Each value is % formatted with the entire existing os.environ. A |
| 273 value of `None` will remove that envvar from the environ. e.g. | 274 value of `None` will remove that envvar from the environ. e.g. |
| 274 | 275 |
| 275 { | 276 { |
| 276 "envvar": "%(envvar)s;%(envvar2)s;extra", | 277 "envvar": "%(envvar)s;%(envvar2)s;extra", |
| 277 "delete_this": None, | 278 "delete_this": None, |
| 278 "static_value": "something", | 279 "static_value": "something", |
| 279 } | 280 } |
| 281 | |
| 282 The optional "env_prefix" parameter contains values that, if specified, will | |
| 283 transform an environment variable into a "pathsep"-delimited sequence of | |
| 284 items: | |
| 285 - If an environment variable is also specified for this key, it will be | |
| 286 appended as the last element: <prefix0>:...:<prefixN>:ENV | |
| 287 - If no enviornment variable is specified, the current environment's value | |
| 288 will be appended, unless it's empty: <prefix0>:...:<prefixN>[:ENV]? | |
| 289 - If an enviornment variable with a value of None (delete) is specified, | |
| 290 nothing will be appeneded: <prefix0>:...:<prefixN> | |
|
iannucci
2017/06/12 19:58:40
"There is currently no way to remove prefix paths;
dnj
2017/06/13 19:31:21
Done.
| |
| 280 """ | 291 """ |
| 281 | 292 |
| 282 _RENDER_WHITELIST=frozenset(( | 293 _RENDER_WHITELIST=frozenset(( |
| 283 'cmd', | 294 'cmd', |
| 284 )) | 295 )) |
| 285 | 296 |
| 286 _RENDER_BLACKLIST=frozenset(( | 297 _RENDER_BLACKLIST=frozenset(( |
| 287 'base_name', | 298 'base_name', |
| 288 'nest_level', | 299 'nest_level', |
| 289 'ok_ret', | 300 'ok_ret', |
| 301 'pathsep', | |
| 290 'step_test_data', | 302 'step_test_data', |
| 291 )) | 303 )) |
| 292 | 304 |
| 293 @classmethod | 305 @classmethod |
| 294 def create(cls, name, base_name=None, cmd=None, cwd=None, env=None, | 306 def create(cls, name, base_name=None, cmd=None, cwd=None, env_prefixes=None, |
| 295 allow_subannotations=None, trigger_specs=None, timeout=None, | 307 pathsep=None, env=None, allow_subannotations=None, |
| 296 infra_step=None, stdout=None, stderr=None, stdin=None, | 308 trigger_specs=None, timeout=None, infra_step=None, stdout=None, |
| 297 ok_ret=None, step_test_data=None, step_nest_level=None): | 309 stderr=None, stdin=None, ok_ret=None, step_test_data=None, |
| 310 step_nest_level=None): | |
| 298 """ | 311 """ |
| 299 Initializes a new StepConfig step API dictionary. | 312 Initializes a new StepConfig step API dictionary. |
| 300 | 313 |
| 301 Args: | 314 Args: |
| 302 name (str): name of the step, will appear in buildbots waterfall | 315 name (str): name of the step, will appear in buildbots waterfall |
| 303 base_name (str): the base name of the step. If the step has a derived | 316 base_name (str): the base name of the step. If the step has a derived |
| 304 name (e.g., nested may be concatenated with its parent), this is the | 317 name (e.g., nested may be concatenated with its parent), this is the |
| 305 name component of just this step. If None, this will be set to "name". | 318 name component of just this step. If None, this will be set to "name". |
| 306 cmd: command to run. Acceptable types: str, Path, Placeholder, or None. | 319 cmd: command to run. Acceptable types: str, Path, Placeholder, or None. |
| 307 cwd (str or None): absolute path to working directory for the command | 320 cwd (str or None): absolute path to working directory for the command |
| 321 env_prefixes (dict): environment prefix variables, described above. | |
| 308 env (dict): overrides for environment variables, described above. | 322 env (dict): overrides for environment variables, described above. |
| 323 pathsep (str): the path separator string. | |
| 309 allow_subannotations (bool): if True, lets the step emit its own | 324 allow_subannotations (bool): if True, lets the step emit its own |
| 310 annotations. NOTE: Enabling this can cause some buggy behavior. Please | 325 annotations. NOTE: Enabling this can cause some buggy behavior. Please |
| 311 strongly consider using step_result.presentation instead. If you have | 326 strongly consider using step_result.presentation instead. If you have |
| 312 questions, please contact infra-dev@chromium.org. | 327 questions, please contact infra-dev@chromium.org. |
| 313 trigger_specs: a list of trigger specifications, see also _trigger_builds. | 328 trigger_specs: a list of trigger specifications, see also _trigger_builds. |
| 314 timeout: if not None, a datetime.timedelta for the step timeout. | 329 timeout: if not None, a datetime.timedelta for the step timeout. |
| 315 infra_step: if True, this is an infrastructure step. Failures will raise | 330 infra_step: if True, this is an infrastructure step. Failures will raise |
| 316 InfraFailure instead of StepFailure. | 331 InfraFailure instead of StepFailure. |
| 317 stdout: Placeholder to put step stdout into. If used, stdout won't appear | 332 stdout: Placeholder to put step stdout into. If used, stdout won't appear |
| 318 in annotator's stdout (and |allow_subannotations| is ignored). | 333 in annotator's stdout (and |allow_subannotations| is ignored). |
| 319 stderr: Placeholder to put step stderr into. If used, stderr won't appear | 334 stderr: Placeholder to put step stderr into. If used, stderr won't appear |
| 320 in annotator's stderr. | 335 in annotator's stderr. |
| 321 stdin: Placeholder to read step stdin from. | 336 stdin: Placeholder to read step stdin from. |
| 322 ok_ret (iter): set of return codes allowed. If the step process returns | 337 ok_ret (iter): set of return codes allowed. If the step process returns |
| 323 something not on this list, it will raise a StepFailure (or | 338 something not on this list, it will raise a StepFailure (or |
| 324 InfraFailure if infra_step is True). If omitted, {0} will be used. | 339 InfraFailure if infra_step is True). If omitted, {0} will be used. |
| 325 step_test_data (func -> recipe_test_api.StepTestData): A factory which | 340 step_test_data (func -> recipe_test_api.StepTestData): A factory which |
| 326 returns a StepTestData object that will be used as the default test | 341 returns a StepTestData object that will be used as the default test |
| 327 data for this step. The recipe author can override/augment this object | 342 data for this step. The recipe author can override/augment this object |
| 328 in the GenTests function. | 343 in the GenTests function. |
| 329 step_nest_level (int): the step's nesting level. | 344 step_nest_level (int): the step's nesting level. |
| 330 """ | 345 """ |
| 331 return cls( | 346 return cls( |
| 332 name=name, | 347 name=name, |
| 333 base_name=(base_name or name), | 348 base_name=(base_name or name), |
| 334 cmd=cmd, | 349 cmd=cmd, |
| 335 cwd=cwd, | 350 cwd=cwd, |
| 336 env=env, | 351 env_prefixes={k: tuple(v) for k, v in (env_prefixes or {}).iteritems()}, |
| 352 env=env or {}, | |
| 353 pathsep=(pathsep or os.pathsep), | |
|
iannucci
2017/06/12 19:58:39
this should just be required... os.pathsep might a
dnj
2017/06/13 19:31:20
Yeah, but "StepConfig" is called in a lot of place
| |
| 337 allow_subannotations=bool(allow_subannotations), | 354 allow_subannotations=bool(allow_subannotations), |
| 338 trigger_specs=[TriggerSpec._create(**trig) | 355 trigger_specs=[TriggerSpec._create(**trig) |
| 339 for trig in (trigger_specs or ())], | 356 for trig in (trigger_specs or ())], |
| 340 timeout=timeout, | 357 timeout=timeout, |
| 341 infra_step=bool(infra_step), | 358 infra_step=bool(infra_step), |
| 342 stdout=stdout, | 359 stdout=stdout, |
| 343 stderr=stderr, | 360 stderr=stderr, |
| 344 stdin=stdin, | 361 stdin=stdin, |
| 345 ok_ret=frozenset(ok_ret or (0,)), | 362 ok_ret=frozenset(ok_ret or (0,)), |
| 346 step_test_data=step_test_data, | 363 step_test_data=step_test_data, |
| 347 nest_level=int(step_nest_level or 0), | 364 nest_level=int(step_nest_level or 0), |
| 348 ) | 365 ) |
| 349 | 366 |
| 350 def render_to_dict(self): | 367 def render_to_dict(self): |
| 351 self = self._replace( | 368 self = self._replace( |
| 369 env_prefixes={k: list(v) for k, v in self.env_prefixes.iteritems()}, | |
|
iannucci
2017/06/12 19:58:40
map(str, v)?
dnj
2017/06/13 19:31:20
I don't think that'd work. We need this here b/c c
| |
| 352 trigger_specs=[trig._render_to_dict() | 370 trigger_specs=[trig._render_to_dict() |
| 353 for trig in (self.trigger_specs or ())], | 371 for trig in (self.trigger_specs or ())], |
| 354 ) | 372 ) |
| 355 return dict((k, v) for k, v in self._asdict().iteritems() | 373 return dict((k, v) for k, v in self._asdict().iteritems() |
| 356 if (v or k in self._RENDER_WHITELIST) | 374 if (v or k in self._RENDER_WHITELIST) |
| 357 and k not in self._RENDER_BLACKLIST) | 375 and k not in self._RENDER_BLACKLIST) |
| 358 | 376 |
| 359 | 377 |
| 360 class StepFailure(Exception): | 378 class StepFailure(Exception): |
| 361 """ | 379 """ |
| (...skipping 713 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1075 def bind(self, name, property_type, full_decl_name): | 1093 def bind(self, name, property_type, full_decl_name): |
| 1076 """ | 1094 """ |
| 1077 Gets the BoundProperty version of this Property. Requires a name. | 1095 Gets the BoundProperty version of this Property. Requires a name. |
| 1078 """ | 1096 """ |
| 1079 return BoundProperty( | 1097 return BoundProperty( |
| 1080 self._default, self.help, self.kind, name, property_type, full_decl_name, | 1098 self._default, self.help, self.kind, name, property_type, full_decl_name, |
| 1081 self.param_name) | 1099 self.param_name) |
| 1082 | 1100 |
| 1083 class UndefinedPropertyException(TypeError): | 1101 class UndefinedPropertyException(TypeError): |
| 1084 pass | 1102 pass |
| OLD | NEW |