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

Side by Side Diff: recipe_engine/recipe_api.py

Issue 2933473002: [context] Split "env" values and prefixes. (Closed)
Patch Set: comments 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 from .util import ModuleInjectionSite, Placeholder 20 from .util import ModuleInjectionSite, Placeholder
20 21
21 22
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 return copy.deepcopy(self._engine.properties) 167 return copy.deepcopy(self._engine.properties)
167 168
168 169
169 class StepClient(object): 170 class StepClient(object):
170 """A recipe engine client representing step running and introspection.""" 171 """A recipe engine client representing step running and introspection."""
171 172
172 IDENT = 'step' 173 IDENT = 'step'
173 174
174 175
175 class StepConfig(collections.namedtuple('_StepConfig', ( 176 class StepConfig(collections.namedtuple('_StepConfig', (
176 'name', 'base_name', 'cmd', 'cwd', 'env', 'allow_subannotations', 177 'name', 'base_name', 'cmd', 'cwd', 'env', 'env_prefixes', 'pathsep',
177 'trigger_specs', 'timeout', 'infra_step', 'stdout', 'stderr', 'stdin', 178 'allow_subannotations', 'trigger_specs', 'timeout', 'infra_step',
178 'ok_ret', 'step_test_data', 'nest_level'))): 179 'stdout', 'stderr', 'stdin', 'ok_ret', 'step_test_data', 'nest_level'))):
179 180
180 """ 181 """
181 StepConfig is the representation of a raw step as the recipe_engine sees it. 182 StepConfig is the representation of a raw step as the recipe_engine sees it.
182 You should use the standard 'step' recipe module, which will construct and 183 You should use the standard 'step' recipe module, which will construct and
183 pass this data to the engine for you, instead. The only reason why you would 184 pass this data to the engine for you, instead. The only reason why you would
184 need to worry about this object is if you're modifying the step module 185 need to worry about this object is if you're modifying the step module
185 itself. 186 itself.
186 187
187 Fields: 188 Fields:
188 name (str): name of the step, will appear in buildbots waterfall 189 name (str): name of the step, will appear in buildbots waterfall
189 base_name (str): the base name of the step. If the step has a derived 190 base_name (str): the base name of the step. If the step has a derived
190 name (e.g., nested may be concatenated with its parent), this is the 191 name (e.g., nested may be concatenated with its parent), this is the
191 name component of just this step. If None, this will be set to "name". 192 name component of just this step. If None, this will be set to "name".
192 cmd: command to run. Acceptable types: str, Path, Placeholder, or None. 193 cmd: command to run. Acceptable types: str, Path, Placeholder, or None.
193 cwd (str or None): absolute path to working directory for the command 194 cwd (str or None): absolute path to working directory for the command
194 env (dict): overrides for environment variables, described above. 195 env (dict): overrides for environment variables, described above.
196 env_prefixes (dict): environment prefix variables, described above.
197 pathsep (str): system path enviornment variable separator.
195 allow_subannotations (bool): if True, lets the step emit its own 198 allow_subannotations (bool): if True, lets the step emit its own
196 annotations. NOTE: Enabling this can cause some buggy behavior. Please 199 annotations. NOTE: Enabling this can cause some buggy behavior. Please
197 strongly consider using step_result.presentation instead. If you have 200 strongly consider using step_result.presentation instead. If you have
198 questions, please contact infra-dev@chromium.org. 201 questions, please contact infra-dev@chromium.org.
199 trigger_specs: a list of trigger specifications, see also _trigger_builds. 202 trigger_specs: a list of trigger specifications, see also _trigger_builds.
200 timeout: if not None, a datetime.timedelta for the step timeout. 203 timeout: if not None, a datetime.timedelta for the step timeout.
201 infra_step: if True, this is an infrastructure step. Failures will raise 204 infra_step: if True, this is an infrastructure step. Failures will raise
202 InfraFailure instead of StepFailure. 205 InfraFailure instead of StepFailure.
203 stdout: Placeholder to put step stdout into. If used, stdout won't appear 206 stdout: Placeholder to put step stdout into. If used, stdout won't appear
204 in annotator's stdout (and |allow_subannotations| is ignored). 207 in annotator's stdout (and |allow_subannotations| is ignored).
(...skipping 11 matching lines...) Expand all
216 219
217 The optional "env" parameter provides optional overrides for environment 220 The optional "env" parameter provides optional overrides for environment
218 variables. Each value is % formatted with the entire existing os.environ. A 221 variables. Each value is % formatted with the entire existing os.environ. A
219 value of `None` will remove that envvar from the environ. e.g. 222 value of `None` will remove that envvar from the environ. e.g.
220 223
221 { 224 {
222 "envvar": "%(envvar)s;%(envvar2)s;extra", 225 "envvar": "%(envvar)s;%(envvar2)s;extra",
223 "delete_this": None, 226 "delete_this": None,
224 "static_value": "something", 227 "static_value": "something",
225 } 228 }
229
230 The optional "env_prefixes" parameter contains values that, if specified,
231 will transform an environment variable into a "pathsep"-delimited sequence
232 of items:
233 - If an environment variable is also specified for this key, it will be
234 appended as the last element: <prefix0>:...:<prefixN>:ENV
235 - If no enviornment variable is specified, the current environment's value
236 will be appended, unless it's empty: <prefix0>:...:<prefixN>[:ENV]?
237 - If an enviornment variable with a value of None (delete) is specified,
238 nothing will be appeneded: <prefix0>:...:<prefixN>
239
240 There is currently no way to remove prefix paths; once they're there,
241 they're there for good. If you think you need to remove paths from the
242 prefix lists, please talk to infra-dev@chromium.org.
226 """ 243 """
227 244
228 _RENDER_WHITELIST=frozenset(( 245 _RENDER_WHITELIST=frozenset((
229 'cmd', 246 'cmd',
230 )) 247 ))
231 248
232 _RENDER_BLACKLIST=frozenset(( 249 _RENDER_BLACKLIST=frozenset((
233 'base_name', 250 'base_name',
234 'nest_level', 251 'nest_level',
235 'ok_ret', 252 'ok_ret',
253 'pathsep',
236 'step_test_data', 254 'step_test_data',
237 )) 255 ))
238 256
239 def __new__(cls, **kwargs): 257 def __new__(cls, **kwargs):
240 for field in cls._fields: 258 for field in cls._fields:
241 kwargs.setdefault(field, None) 259 kwargs.setdefault(field, None)
242 sc = super(StepClient.StepConfig, cls).__new__(cls, **kwargs) 260 sc = super(StepClient.StepConfig, cls).__new__(cls, **kwargs)
243 261
244 return sc._replace( 262 return sc._replace(
245 cmd=[(x if isinstance(x, Placeholder) else str(x)) 263 cmd=[(x if isinstance(x, Placeholder) else str(x))
246 for x in (sc.cmd or ())], 264 for x in (sc.cmd or ())],
247 cwd=(str(sc.cwd) if sc.cwd else (None)), 265 cwd=(str(sc.cwd) if sc.cwd else (None)),
266 env=sc.env or {},
267 env_prefixes={k: tuple(str(x) for x in v)
268 for k, v in (sc.env_prefixes or {}).iteritems()},
269 pathsep=sc.pathsep or os.pathsep,
248 base_name=sc.base_name or sc.name, 270 base_name=sc.base_name or sc.name,
249 allow_subannotations=bool(sc.allow_subannotations), 271 allow_subannotations=bool(sc.allow_subannotations),
250 trigger_specs=sc.trigger_specs or (), 272 trigger_specs=sc.trigger_specs or (),
251 infra_step=bool(sc.infra_step), 273 infra_step=bool(sc.infra_step),
252 ok_ret=frozenset(sc.ok_ret or (0,)), 274 ok_ret=frozenset(sc.ok_ret or (0,)),
253 nest_level=int(sc.nest_level or 0), 275 nest_level=int(sc.nest_level or 0),
254 ) 276 )
255 277
256 def render_to_dict(self): 278 def render_to_dict(self):
257 sc = self._replace( 279 sc = self._replace(
280 env_prefixes={k: list(v) for k, v in self.env_prefixes.iteritems()},
258 trigger_specs=[trig._render_to_dict() 281 trigger_specs=[trig._render_to_dict()
259 for trig in (self.trigger_specs or ())], 282 for trig in (self.trigger_specs or ())],
260 ) 283 )
261 return dict((k, v) for k, v in sc._asdict().iteritems() 284 return dict((k, v) for k, v in sc._asdict().iteritems()
262 if (v or k in sc._RENDER_WHITELIST) 285 if (v or k in sc._RENDER_WHITELIST)
263 and k not in sc._RENDER_BLACKLIST) 286 and k not in sc._RENDER_BLACKLIST)
264 287
265 288
266 class TriggerSpec(collections.namedtuple('_TriggerSpec', ( 289 class TriggerSpec(collections.namedtuple('_TriggerSpec', (
267 'bucket', 'builder_name', 'properties', 'buildbot_changes', 'tags', 290 'bucket', 'builder_name', 'properties', 'buildbot_changes', 'tags',
(...skipping 787 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 def bind(self, name, property_type, full_decl_name): 1078 def bind(self, name, property_type, full_decl_name):
1056 """ 1079 """
1057 Gets the BoundProperty version of this Property. Requires a name. 1080 Gets the BoundProperty version of this Property. Requires a name.
1058 """ 1081 """
1059 return BoundProperty( 1082 return BoundProperty(
1060 self._default, self.help, self.kind, name, property_type, full_decl_name, 1083 self._default, self.help, self.kind, name, property_type, full_decl_name,
1061 self.param_name) 1084 self.param_name)
1062 1085
1063 class UndefinedPropertyException(TypeError): 1086 class UndefinedPropertyException(TypeError):
1064 pass 1087 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