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

Unified Diff: recipe_engine/loader.py

Issue 2798053003: introduce recipe_exception in result.proto (Closed)
Patch Set: Created 3 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | recipe_engine/result.proto » ('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 f7df5739924f230e6fb963d0fc7db7f662ac9d31..65ee1518316bf24867d8ac01d9fb5181ae09404d 100644
--- a/recipe_engine/loader.py
+++ b/recipe_engine/loader.py
@@ -3,6 +3,7 @@
# that can be found in the LICENSE file.
import collections
+import functools
import imp
import inspect
import os
@@ -18,7 +19,10 @@ from .recipe_api import RecipeApiPlain, RecipeScriptApi
from .recipe_api import _UnresolvedRequirement
from .recipe_api import BoundProperty
from .recipe_api import UndefinedPropertyException, PROPERTY_SENTINEL
+from .recipe_api import StepFailure
from .recipe_test_api import RecipeTestApi, DisabledTestData
+from .types import StepDataAttributeError
+import subprocess42
class LoaderError(Exception):
@@ -31,6 +35,14 @@ class NoSuchRecipe(LoaderError):
super(NoSuchRecipe, self).__init__('No such recipe: %s' % recipe)
+class RecipeException(Exception):
+ """Raised when an unhandeled exception is raised in a recipe."""
+ def __init__(self, inner_exception, traceback):
+ self.inner_exception = inner_exception
+ self.traceback = traceback
+ super(RecipeException, self).__init__(inner_exception.message)
+
+
class RecipeScript(object):
"""Holds dict of an evaluated recipe script."""
@@ -76,9 +88,29 @@ class RecipeScript(object):
"""
Run this recipe, with the given api and property arguments.
Check the return value, if we have a RETURN_SCHEMA.
+
+ Raises:
+ RecipeException if an unhandled exception happened in the recipe.
+ TypeError if recipe did not return an expected result.
"""
+
+ orig_run_steps = self.run_steps
+
+ def run_steps(*args, **kwargs):
+ try:
+ return orig_run_steps(*args, **kwargs)
+ except (
+ StepFailure,
+ StepDataAttributeError,
+ subprocess42.TimeoutExpired):
+ raise
+ except Exception as ex:
+ raise RecipeException(ex, sys.exc_info()[2])
+
recipe_result = invoke_with_properties(
- self.run_steps, properties, self.PROPERTIES, api=api)
+ run_steps, properties, self.PROPERTIES,
+ inspectable_obj=orig_run_steps,
+ api=api)
if self.RETURN_SCHEMA:
if not recipe_result:
@@ -546,7 +578,7 @@ def _invoke_with_properties(callable_obj, all_props, prop_defs, arg_names,
def invoke_with_properties(callable_obj, all_props, prop_defs,
- **additional_args):
+ inspectable_obj=None, **additional_args):
"""
Invokes callable with filtered, type-checked properties.
@@ -558,6 +590,8 @@ def invoke_with_properties(callable_obj, all_props, prop_defs,
defined in the system.
prop_defs: A dictionary of property name to property definitions
(BoundProperty) for this callable.
+ inspectable_obj: a function to inspect instead of callable_obj.
+ Useful when callback_obj is wrapped.
additional_args: kwargs to pass through to the callable.
Note that the names of the arguments can correspond to
positional arguments as well.
@@ -568,18 +602,20 @@ def invoke_with_properties(callable_obj, all_props, prop_defs,
"""
# Check that we got passed BoundProperties, and not Properties
+ inspectable_obj = inspectable_obj or callable_obj
+
# 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.
- if inspect.isclass(callable_obj):
- arg_names = inspect.getargspec(callable_obj.__init__).args
+ if inspect.isclass(inspectable_obj):
+ arg_names = inspect.getargspec(inspectable_obj.__init__).args
arg_names.pop(0)
else:
- arg_names = inspect.getargspec(callable_obj).args
+ arg_names = inspect.getargspec(inspectable_obj).args
return _invoke_with_properties(callable_obj, all_props, prop_defs, arg_names,
**additional_args)
« no previous file with comments | « no previous file | recipe_engine/result.proto » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698