14 """Utilities for working with callables."""
24 _LOGGER = logging.getLogger(__name__)
27 class Outcome(six.with_metaclass(abc.ABCMeta)):
28 """A sum type describing the outcome of some call.
31 kind: One of Kind.RETURNED or Kind.RAISED respectively indicating that the
32 call returned a value or raised an exception.
33 return_value: The value returned by the call. Must be present if kind is
35 exception: The exception raised by the call. Must be present if kind is
41 """Identifies the general kind of the outcome of some call."""
48 collections.namedtuple(
'_EasyOutcome',
49 [
'kind',
'return_value',
'exception']), Outcome):
50 """A trivial implementation of Outcome."""
55 return _EasyOutcome(Outcome.Kind.RETURNED, behavior(*args, **kwargs),
57 except Exception
as e:
58 _LOGGER.exception(message)
63 """Wraps a callable in a try-except that logs any exceptions it raises.
66 behavior: Any callable.
67 message: A string to log if the behavior raises an exception.
70 A callable that when executed invokes the given behavior. The returned
71 callable takes the same arguments as the given behavior but returns a
72 future.Outcome describing whether the given behavior returned a value or
76 @functools.wraps(behavior)
77 def wrapped_behavior(*args, **kwargs):
80 return wrapped_behavior
84 """Calls a behavior in a try-except that logs any exceptions it raises.
87 behavior: Any callable.
88 message: A string to log if the behavior raises an exception.
89 *args: Positional arguments to pass to the given behavior.
90 **kwargs: Keyword arguments to pass to the given behavior.
93 An Outcome describing whether the given behavior returned a value or raised