Merge "Trap and expose exception any 'args'"

This commit is contained in:
Jenkins 2016-01-06 19:31:47 +00:00 committed by Gerrit Code Review
commit a0207ecd41
2 changed files with 37 additions and 3 deletions

View File

@ -181,6 +181,14 @@ class FailureObjectTestCase(test.TestCase):
d_f['exc_type_names'] = ['RuntimeError', 'Exception', 'BaseException']
failure.Failure.validate(d_f)
def test_cause_exception_args(self):
f = _captured_failure('Woot!')
d_f = f.to_dict()
self.assertEqual(1, len(d_f['exc_args']))
self.assertEqual(("Woot!",), d_f['exc_args'])
f2 = failure.Failure.from_dict(d_f)
self.assertEqual(f.exception_args, f2.exception_args)
def test_dont_catch_base_exception(self):
try:
raise SystemExit()
@ -236,7 +244,8 @@ class FailureObjectTestCase(test.TestCase):
captured = _captured_failure('Woot!')
fail_obj = failure.Failure(exception_str=captured.exception_str,
traceback_str=captured.traceback_str,
exc_type_names=list(captured))
exc_type_names=list(captured),
exc_args=list(captured.exception_args))
self.assertFalse(fail_obj == captured)
self.assertTrue(fail_obj != captured)
self.assertTrue(fail_obj.matches(captured))

View File

@ -141,6 +141,10 @@ class Failure(mixins.StrMixin):
"type": "integer",
"minimum": 0,
},
'exc_args': {
"type": "array",
"minItems": 0,
},
'exception_str': {
"type": "string",
},
@ -183,6 +187,7 @@ class Failure(mixins.StrMixin):
raise ValueError("Provided 'exc_info' must contain three"
" elements")
self._exc_info = exc_info
self._exc_args = tuple(getattr(exc_info[1], 'args', []))
self._exc_type_names = tuple(
reflection.get_all_class_names(exc_info[0], up_to=Exception))
if not self._exc_type_names:
@ -195,6 +200,7 @@ class Failure(mixins.StrMixin):
else:
self._causes = kwargs.pop('causes', None)
self._exc_info = exc_info
self._exc_args = tuple(kwargs.pop('exc_args', []))
self._exception_str = kwargs.pop('exception_str')
self._exc_type_names = tuple(kwargs.pop('exc_type_names', []))
self._traceback_str = kwargs.pop('traceback_str', None)
@ -243,6 +249,7 @@ class Failure(mixins.StrMixin):
if self is other:
return True
return (self._exc_type_names == other._exc_type_names
and self.exception_args == other.exception_args
and self.exception_str == other.exception_str
and self.traceback_str == other.traceback_str
and self.causes == other.causes)
@ -278,7 +285,7 @@ class Failure(mixins.StrMixin):
@property
def exception(self):
"""Exception value, or None if exception value is not present.
"""Exception value, or none if exception value is not present.
Exception value may be lost during serialization.
"""
@ -292,9 +299,19 @@ class Failure(mixins.StrMixin):
"""String representation of exception."""
return self._exception_str
@property
def exception_args(self):
"""Tuple of arguments given to the exception constructor."""
return self._exc_args
@property
def exc_info(self):
"""Exception info tuple or None."""
"""Exception info tuple or none.
See: https://docs.python.org/2/library/sys.html#sys.exc_info for what
the contents of this tuple are (if none, then no contents can
be examined).
"""
return self._exc_info
@property
@ -444,6 +461,12 @@ class Failure(mixins.StrMixin):
def __setstate__(self, dct):
self._exception_str = dct['exception_str']
if 'exc_args' in dct:
self._exc_args = tuple(dct['exc_args'])
else:
# Guess we got an older version somehow, before this
# was added, so at that point just set to an empty tuple...
self._exc_args = ()
self._traceback_str = dct['traceback_str']
self._exc_type_names = dct['exc_type_names']
if 'exc_info' in dct:
@ -483,6 +506,7 @@ class Failure(mixins.StrMixin):
'traceback_str': self.traceback_str,
'exc_type_names': list(self),
'version': self.DICT_VERSION,
'exc_args': self.exception_args,
'causes': [f.to_dict() for f in self.causes],
}
@ -491,5 +515,6 @@ class Failure(mixins.StrMixin):
return Failure(exc_info=_copy_exc_info(self.exc_info),
exception_str=self.exception_str,
traceback_str=self.traceback_str,
exc_args=self.exception_args,
exc_type_names=self._exc_type_names[:],
causes=self._causes)