From 33a2cee6a690ecfdb2cecfe8f01b0b1dacb5bd17 Mon Sep 17 00:00:00 2001 From: Oleg Bondarev Date: Thu, 13 Mar 2014 13:32:09 +0400 Subject: [PATCH] save_and_reraise_exception: make logging respect the reraise parameter Do not log original exception if reraise is set to False Closes-Bug: #1291850 Related-Bug: #1288188 Change-Id: Icd5fcba25c2cd549cee70353a7a62d83bfe1255b --- openstack/common/excutils.py | 26 ++++++++++++++++++++------ tests/unit/test_excutils.py | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/openstack/common/excutils.py b/openstack/common/excutils.py index fb9f03e4d..07a02beb1 100644 --- a/openstack/common/excutils.py +++ b/openstack/common/excutils.py @@ -49,9 +49,22 @@ class save_and_reraise_exception(object): decide_if_need_reraise() if not should_be_reraised: ctxt.reraise = False + + If another exception occurs and reraise flag is False, + the saved exception will not be logged. + + If the caller wants to raise new exception during exception handling + he/she sets reraise to False initially with an ability to set it back to + True if needed:: + + except Exception: + with save_and_reraise_exception(reraise=False) as ctxt: + [if statements to determine whether to raise a new exception] + # Not raising a new exception, so reraise + ctxt.reraise = True """ - def __init__(self): - self.reraise = True + def __init__(self, reraise=True): + self.reraise = reraise def __enter__(self): self.type_, self.value, self.tb, = sys.exc_info() @@ -59,10 +72,11 @@ class save_and_reraise_exception(object): def __exit__(self, exc_type, exc_val, exc_tb): if exc_type is not None: - logging.error(_LE('Original exception being dropped: %s'), - traceback.format_exception(self.type_, - self.value, - self.tb)) + if self.reraise: + logging.error(_LE('Original exception being dropped: %s'), + traceback.format_exception(self.type_, + self.value, + self.tb)) return False if self.reraise: six.reraise(self.type_, self.value, self.tb) diff --git a/tests/unit/test_excutils.py b/tests/unit/test_excutils.py index 06a1878a9..61c85a8f6 100644 --- a/tests/unit/test_excutils.py +++ b/tests/unit/test_excutils.py @@ -15,6 +15,8 @@ import logging import time +import mock + from openstack.common import excutils from openstack.common.fixture import moxstubout from openstack.common import test @@ -42,16 +44,18 @@ class SaveAndReraiseTest(test.BaseTestCase): def test_save_and_reraise_exception_dropped(self): e = None msg = 'second exception' - try: + with mock.patch('logging.error') as log: try: - raise Exception('dropped') - except Exception: - with excutils.save_and_reraise_exception(): - raise Exception(msg) - except Exception as _e: - e = _e + try: + raise Exception('dropped') + except Exception: + with excutils.save_and_reraise_exception(): + raise Exception(msg) + except Exception as _e: + e = _e - self.assertEqual(str(e), msg) + self.assertEqual(str(e), msg) + self.assertTrue(log.called) def test_save_and_reraise_exception_no_reraise(self): """Test that suppressing the reraise works.""" @@ -61,6 +65,22 @@ class SaveAndReraiseTest(test.BaseTestCase): with excutils.save_and_reraise_exception() as ctxt: ctxt.reraise = False + def test_save_and_reraise_exception_dropped_no_reraise(self): + e = None + msg = 'second exception' + with mock.patch('logging.error') as log: + try: + try: + raise Exception('dropped') + except Exception: + with excutils.save_and_reraise_exception(reraise=False): + raise Exception(msg) + except Exception as _e: + e = _e + + self.assertEqual(str(e), msg) + self.assertFalse(log.called) + class ForeverRetryUncaughtExceptionsTest(test.BaseTestCase):