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

Unified Diff: recipe_engine/loader.py

Issue 1421843006: Add simple depends_on API. (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/recipes-py@master
Patch Set: Remove old expectation, move tests to their own folder. Created 5 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « recipe_engine/lint_test.py ('k') | recipe_engine/package.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: recipe_engine/loader.py
diff --git a/recipe_engine/loader.py b/recipe_engine/loader.py
index e8b67258781b23872108043f4f193f2370d3c147..e5adefb7e6825f34afe78752fe4184a51e45728c 100644
--- a/recipe_engine/loader.py
+++ b/recipe_engine/loader.py
@@ -25,7 +25,9 @@ class NoSuchRecipe(Exception):
class RecipeScript(object):
"""Holds dict of an evaluated recipe script."""
- def __init__(self, recipe_dict):
+ def __init__(self, recipe_dict, name):
+ self.name = name
+
# Let each property object know about the property name.
recipe_dict['PROPERTIES'] = {
name: value.bind(name, BoundProperty.RECIPE_PROPERTY, name)
@@ -50,6 +52,8 @@ class RecipeScript(object):
return_schema = getattr(self, 'RETURN_SCHEMA', None)
if return_schema:
+ if not recipe_result:
+ raise ValueError("Recipe %s did not return a value." % self.name)
return recipe_result.as_jsonish(True)
else:
return None
@@ -66,7 +70,10 @@ class RecipeScript(object):
script_vars['LOADED_DEPS'] = universe.deps_from_spec(
script_vars.get('DEPS', []))
- return cls(script_vars)
+
+ # 'a/b/c/my_name.py' -> my_name
+ name = os.path.basename(script_path).split('.')[0]
+ return cls(script_vars, name)
class Dependency(object):
@@ -131,9 +138,14 @@ class PackageDependency(PathDependency):
class RecipeUniverse(object):
- def __init__(self, package_deps):
+ def __init__(self, package_deps, config_file):
self._loaded = {}
self._package_deps = package_deps
+ self._config_file = config_file
+
+ @property
+ def config_file(self):
+ return self._config_file
@property
def module_dirs(self):
@@ -406,6 +418,36 @@ class DependencyMapper(object):
self._instances[mod] = self._instantiator(mod, deps_dict)
return self._instances[mod]
+def _invoke_with_properties(callable_obj, all_props, prop_defs, arg_names,
+ **additional_args):
+ """Internal version of invoke_with_properties.
+
+ The main difference is it gets passed the argument names as `arg_names`.
+ This allows us to reuse this logic elsewhere, without defining a fake function
+ which has arbitrary argument names.
+ """
+ for name, prop in prop_defs.items():
+ if not isinstance(prop, BoundProperty):
+ raise ValueError(
+ "You tried to invoke {} with an unbound Property {} named {}".format(
+ callable, prop, name))
+
+ props = []
+ for arg in arg_names:
+ if arg in additional_args:
+ props.append(additional_args.pop(arg))
+ continue
+
+ if arg not in prop_defs:
+ raise UndefinedPropertyException(
+ "Missing property definition for '{}'.".format(arg))
+
+ prop = prop_defs[arg]
+ props.append(prop.interpret(all_props.get(
+ prop.param_name, PROPERTY_SENTINEL)))
+
+ return callable_obj(*props, **additional_args)
+
def invoke_with_properties(callable_obj, all_props, prop_defs,
**additional_args):
"""
@@ -428,39 +470,21 @@ def invoke_with_properties(callable_obj, all_props, prop_defs,
"""
# Check that we got passed BoundProperties, and not Properties
- for name, prop in prop_defs.items():
- if not isinstance(prop, BoundProperty):
- raise ValueError(
- "You tried to invoke {} with an unbound Property {} named {}".format(
- callable, prop, name))
# To detect when they didn't specify a property that they have as a
# function argument, list the arguments, through inspection,
# and then comparing this list to the provided properties. We use a list
# instead of a dict because getargspec returns a list which we would have to
# convert to a dictionary, and the benefit of the dictionary is pretty small.
- props = []
if inspect.isclass(callable_obj):
arg_names = inspect.getargspec(callable_obj.__init__).args
arg_names.pop(0)
else:
arg_names = inspect.getargspec(callable_obj).args
+ return _invoke_with_properties(callable_obj, all_props, prop_defs, arg_names,
+ **additional_args)
- for arg in arg_names:
- if arg in additional_args:
- props.append(additional_args.pop(arg))
- continue
-
- if arg not in prop_defs:
- raise UndefinedPropertyException(
- "Missing property definition for '{}'.".format(arg))
-
- prop = prop_defs[arg]
- props.append(prop.interpret(all_props.get(
- prop.param_name, PROPERTY_SENTINEL)))
-
- return callable_obj(*props, **additional_args)
def create_recipe_api(toplevel_deps, engine, test_data=DisabledTestData()):
def instantiator(mod, deps):
« no previous file with comments | « recipe_engine/lint_test.py ('k') | recipe_engine/package.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698