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

Side by Side Diff: recipe_engine/recipe_api.py

Issue 2933473002: [context] Split "env" values and prefixes. (Closed)
Patch Set: plumb pathsep through so we don't assume OS Created 3 years, 6 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 | « no previous file | recipe_engine/step_runner.py » ('j') | recipe_engine/step_runner.py » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « no previous file | recipe_engine/step_runner.py » ('j') | recipe_engine/step_runner.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698