summaryrefslogtreecommitdiff
path: root/fixtures
diff options
context:
space:
mode:
authorRobert Collins <robertc@robertcollins.net>2015-06-30 12:58:56 +1200
committerRobert Collins <robertc@robertcollins.net>2015-06-30 13:00:55 +1200
commit3f965dd8a9d60950a6d24be2a2c87a24b6f82196 (patch)
treeb5dd3181360902f571b7894e284fb093a14e8884 /fixtures
parent5355689a2aa85e58b29e3c88e32ff9521dc5bd17 (diff)
downloadfixtures-git-3f965dd8a9d60950a6d24be2a2c87a24b6f82196.tar.gz
Handle BaseException resource leaks as well.
The change to handle resource leaks incorrectly ignored BaseException - e.g. KeyboardInterrupt.
Diffstat (limited to 'fixtures')
-rw-r--r--fixtures/fixture.py13
-rw-r--r--fixtures/tests/test_fixture.py15
2 files changed, 24 insertions, 4 deletions
diff --git a/fixtures/fixture.py b/fixtures/fixture.py
index 48bf8e4..91ae8a1 100644
--- a/fixtures/fixture.py
+++ b/fixtures/fixture.py
@@ -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.
diff --git a/fixtures/tests/test_fixture.py b/fixtures/tests/test_fixture.py
index 737ae41..cf3ed3c 100644
--- a/fixtures/tests/test_fixture.py
+++ b/fixtures/tests/test_fixture.py
@@ -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):