Handle BaseException resource leaks as well.
The change to handle resource leaks incorrectly ignored BaseException - e.g. KeyboardInterrupt.
This commit is contained in:
parent
5355689a2a
commit
3f965dd8a9
4
NEWS
4
NEWS
|
@ -6,6 +6,10 @@ fixtures release notes
|
|||
NEXT
|
||||
~~~~
|
||||
|
||||
* ``Fixture.setUp`` now uses a bare except: and will thus catch BaseException.
|
||||
Any non-Exception-subclass errors are raised verbatim after calling
|
||||
``cleanUp``, to avoid inappropriate masking in callers. (Robert Collins)
|
||||
|
||||
1.3.0
|
||||
~~~~~
|
||||
|
||||
|
|
7
README
7
README
|
@ -235,6 +235,13 @@ the error. As long as you take care to register any cleanups before calling
|
|||
the code that may fail, this will cause them to be cleaned up. The captured
|
||||
detail objects are provided to the args of the raised exception.
|
||||
|
||||
If the error that occured was a subclass of ``Exception`` then ``setUp`` will
|
||||
raise ``MultipleExceptions`` with the last element being a ``SetupError`` that
|
||||
contains the detail objects. Otherwise, to prevent causing normally
|
||||
uncatchable errors like KeyboardInterrupt being caught inappropriately in the
|
||||
calling layer, the original exception will be raised as-is and no diagnostic
|
||||
data other than that from the original exception will be available.
|
||||
|
||||
Shared Dependencies
|
||||
+++++++++++++++++++
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ __all__ = [
|
|||
import itertools
|
||||
import sys
|
||||
|
||||
import six
|
||||
from testtools.compat import (
|
||||
advance_iterator,
|
||||
reraise,
|
||||
|
@ -174,9 +175,8 @@ class Fixture(object):
|
|||
def setUp(self):
|
||||
"""Prepare the Fixture for use.
|
||||
|
||||
This should not be overridden.
|
||||
|
||||
Concrete fixtures should implement _setUp.
|
||||
This should not be overridden. Concrete fixtures should implement
|
||||
_setUp. Overriding of setUp is still supported, just not recommended.
|
||||
|
||||
After setUp has completed, the fixture will have one or more attributes
|
||||
which can be used (these depend totally on the concrete subclass).
|
||||
|
@ -189,11 +189,13 @@ class Fixture(object):
|
|||
:changed in 1.3: The recommendation to override setUp has been
|
||||
reversed - before 1.3, setUp() should be overridden, now it should
|
||||
not be.
|
||||
:changed in 1.3.1: BaseException is now caught, and only subclasses of
|
||||
Exception are wrapped in MultipleExceptions.
|
||||
"""
|
||||
self._clear_cleanups()
|
||||
try:
|
||||
self._setUp()
|
||||
except Exception:
|
||||
except:
|
||||
err = sys.exc_info()
|
||||
details = {}
|
||||
if gather_details is not None:
|
||||
|
@ -206,7 +208,10 @@ class Fixture(object):
|
|||
raise SetupError(details)
|
||||
except SetupError as e:
|
||||
errors.append(sys.exc_info())
|
||||
if issubclass(err[0], Exception):
|
||||
raise MultipleExceptions(*errors)
|
||||
else:
|
||||
six.reraise(*err)
|
||||
|
||||
def _setUp(self):
|
||||
"""Template method for subclasses to override.
|
||||
|
|
|
@ -257,6 +257,21 @@ class TestFixture(testtools.TestCase):
|
|||
self.assertEqual(fixtures.SetupError, e.args[2][0])
|
||||
self.assertEqual('stuff', e.args[2][1].args[0]['log'].as_text())
|
||||
|
||||
def test_setup_failures_with_base_exception(self):
|
||||
# when _setUp fails with a BaseException (or subclass thereof) that
|
||||
# exception is propogated as is, but we still call cleanups etc.
|
||||
class MyBase(BaseException):pass
|
||||
log = []
|
||||
class Subclass(fixtures.Fixture):
|
||||
def _setUp(self):
|
||||
self.addDetail('log', text_content('stuff'))
|
||||
self.addCleanup(log.append, 'cleaned')
|
||||
raise MyBase('fred')
|
||||
f = Subclass()
|
||||
e = self.assertRaises(MyBase, f.setUp)
|
||||
self.assertRaises(TypeError, f.cleanUp)
|
||||
self.assertEqual(['cleaned'], log)
|
||||
|
||||
|
||||
class TestFunctionFixture(testtools.TestCase):
|
||||
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
pbr>=0.11
|
||||
six
|
||||
testtools>=0.9.22
|
||||
|
|
Loading…
Reference in New Issue