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

Side by Side Diff: recipe_engine/loader.py

Issue 2909983003: [loader] Make recipe engine support examples/ module subdir (Closed)
Patch Set: 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/recipe_api.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 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 import collections 5 import collections
6 import imp 6 import imp
7 import inspect 7 import inspect
8 import os 8 import os
9 import sys 9 import sys
10 10
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 'chromiuminternal': 'build_internal/chromium', 244 'chromiuminternal': 'build_internal/chromium',
245 } 245 }
246 """ 246 """
247 return { 247 return {
248 local_name: self.universe.load(pkg, name) 248 local_name: self.universe.load(pkg, name)
249 for local_name, (pkg, name) in self.normalize_deps_spec(spec).iteritems() 249 for local_name, (pkg, name) in self.normalize_deps_spec(spec).iteritems()
250 } 250 }
251 251
252 252
253 def find_recipe(self, recipe): 253 def find_recipe(self, recipe):
254 """Finds the given recipe.
255
256 Args:
257 recipe (str) - the name of the recipe as you would specify to
258 `recipes.py run`. This may have the form:
259 recipe, path/to/recipe - a recipe under the `recipes folder`
260 module:tests/recipe - a test recipe under a recipe_module.
261 module:examples/recipe - an example recipe under a recipe_module.
262 module:example - a legacy example example recipe under a recipe_module
263
264 Return (str) - The absolute path to the recipe .py file.
265
266 Raises NoSuchRecipe if this cannot find the recipe.
267 """
268 # If the recipe is specified as "module:recipe", then it is an recipe
269 # contained in a recipe_module as an example, or a test. Look for it in the
270 # modules imported by load_recipe_modules instead of the normal search
271 # paths.
272 #
273 # TODO(martiniss) change "infra/example" to ["infra", "example"],
274 # and handle appropriately, because of windows.
254 if ':' in recipe: 275 if ':' in recipe:
255 module_name, recipe_name = recipe.split(':') 276 module_name, recipe_name = recipe.split(':')
256 module_dir = os.path.join(self.package.module_dir, module_name) 277 module_dir = os.path.join(self.package.module_dir, module_name)
257 if _is_recipe_module_dir(module_dir): 278 if _is_recipe_module_dir(module_dir):
258 if recipe_name.endswith('example'): 279 # TODO(iannucci): remove legacy example.
259 # TODO(martinis) change to example == 'example' ? Technically a bug... 280 if (recipe_name == 'example' or
260 recipe_path = os.path.join(module_dir, 'example.py') 281 recipe_name.startswith(('tests/', 'examples/'))):
261 elif recipe_name.startswith('tests/'): 282 recipe_path = os.path.join(module_dir, recipe_name + '.py')
262 recipe_path = os.path.join(
263 module_dir, 'tests', recipe_name[len('tests/'):] + '.py')
264 else: 283 else:
265 raise NoSuchRecipe(recipe) 284 raise NoSuchRecipe(recipe)
266 else: 285 else:
267 recipe_path = os.path.join(self.package.recipe_dir, recipe)+".py" 286 recipe_path = os.path.join(self.package.recipe_dir, recipe)+".py"
268 287
269 if os.path.exists(recipe_path): 288 if os.path.exists(recipe_path):
270 return recipe_path 289 return recipe_path
271 290
272 raise NoSuchRecipe(recipe) 291 raise NoSuchRecipe(recipe)
273 292
274 def load_recipe(self, recipe, engine=None): 293 def load_recipe(self, recipe, engine=None):
275 """Given name of a recipe, loads and returns it as RecipeScript instance. 294 """Given name of a recipe, loads and returns it as RecipeScript instance.
276 295
277 Args: 296 Args:
278 recipe (str): name of a recipe, can be in form '<module>:<recipe>'. 297 recipe (str): name of a recipe, can be in form '<module>:<recipe>'.
279 engine (RecipeEngine): If not None, resolve requirements with this recipe 298 engine (RecipeEngine): If not None, resolve requirements with this recipe
280 engine. Otherwise, requirements will be unresolved. 299 engine. Otherwise, requirements will be unresolved.
281 300
282 Returns: 301 Returns:
283 RecipeScript instance. 302 RecipeScript instance.
284 303
285 Raises: 304 Raises:
286 NoSuchRecipe: recipe is not found. 305 NoSuchRecipe: recipe is not found.
287 """ 306 """
288 # If the recipe is specified as "module:recipe", then it is an recipe
289 # contained in a recipe_module as an example. Look for it in the modules
290 # imported by load_recipe_modules instead of the normal search paths.
291 # TODO(martiniss) change "infra/example" to ["infra", "example"], and handle
292 # appropriately, because of windows.
293 recipe_path = self.find_recipe(recipe) 307 recipe_path = self.find_recipe(recipe)
294 try: 308 try:
295 script = RecipeScript.from_script_path(recipe, recipe_path, self) 309 script = RecipeScript.from_script_path(recipe, recipe_path, self)
296 except (LoaderError,AssertionError,ImportError) as e: 310 except (LoaderError,AssertionError,ImportError) as e:
297 _amend_exception(e, 'while loading recipe %s' % recipe) 311 _amend_exception(e, 'while loading recipe %s' % recipe)
298 312
299 if engine is not None: 313 if engine is not None:
300 script.globals.update({k: _resolve_requirement(v, engine) 314 script.globals.update({k: _resolve_requirement(v, engine)
301 for k, v in script.globals.iteritems() 315 for k, v in script.globals.iteritems()
302 if isinstance(v, _UnresolvedRequirement)}) 316 if isinstance(v, _UnresolvedRequirement)})
(...skipping 27 matching lines...) Expand all
330 yield file_path 344 yield file_path
331 345
332 path = self.package.recipe_dir 346 path = self.package.recipe_dir
333 for recipe in scan_directory( 347 for recipe in scan_directory(
334 path, lambda f: f.endswith('.py') and f[0] != '_'): 348 path, lambda f: f.endswith('.py') and f[0] != '_'):
335 yield recipe, recipe[len(path)+1:-len('.py')] 349 yield recipe, recipe[len(path)+1:-len('.py')]
336 350
337 for module_name in self.loop_over_recipe_modules(): 351 for module_name in self.loop_over_recipe_modules():
338 module_dir = os.path.join(self.package.module_dir, module_name) 352 module_dir = os.path.join(self.package.module_dir, module_name)
339 353
354 # TODO(iannucci): remove unscoped example.py
340 example_path = os.path.join(module_dir, 'example.py') 355 example_path = os.path.join(module_dir, 'example.py')
341 if os.path.exists(example_path): 356 if os.path.exists(example_path):
342 yield example_path, '%s:example' % module_name 357 yield example_path, '%s:example' % module_name
343 358
344 test_dir = os.path.join(module_dir, 'tests') 359 for subdir_name in ('tests', 'examples'):
345 if os.path.exists(test_dir): 360 subdir = os.path.join(module_dir, subdir_name)
346 for recipe in scan_directory(test_dir, lambda f: f.endswith('.py')): 361 if os.path.exists(subdir):
347 yield recipe, '%s:tests/%s' % ( 362 for recipe in scan_directory(subdir, lambda f: f.endswith('.py')):
348 module_name, recipe[len(test_dir)+1:-len('.py')]) 363 yield recipe, '%s:%s/%s' % (
364 module_name, subdir_name, recipe[len(subdir)+1:-len('.py')])
349 365
350 def loop_over_recipe_modules(self): 366 def loop_over_recipe_modules(self):
351 """Yields the paths to all the modules that this view can see.""" 367 """Yields the paths to all the modules that this view can see."""
352 path = self.package.module_dir 368 path = self.package.module_dir
353 if os.path.isdir(path): 369 if os.path.isdir(path):
354 for item in os.listdir(path): 370 for item in os.listdir(path):
355 subpath = os.path.join(path, item) 371 subpath = os.path.join(path, item)
356 if _is_recipe_module_dir(subpath): 372 if _is_recipe_module_dir(subpath):
357 yield os.path.basename(subpath) 373 yield os.path.basename(subpath)
358 374
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
697 for k,v in toplevel_deps.iteritems(): 713 for k,v in toplevel_deps.iteritems():
698 setattr(api, k, mapper.instantiate(v)) 714 setattr(api, k, mapper.instantiate(v))
699 return api 715 return api
700 716
701 717
702 def _resolve_requirement(req, engine): 718 def _resolve_requirement(req, engine):
703 if req._typ == 'client': 719 if req._typ == 'client':
704 return engine._get_client(req._name) 720 return engine._get_client(req._name)
705 else: 721 else:
706 raise ValueError('Unknown requirement type [%s]' % (req._typ,)) 722 raise ValueError('Unknown requirement type [%s]' % (req._typ,))
OLDNEW
« no previous file with comments | « no previous file | recipe_engine/recipe_api.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698