summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2014-04-28 23:25:07 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2014-04-28 23:25:07 (GMT)
commitb1e58440f87f921bd51396f4e9a4b18dcd2def6b (patch)
tree1a2bc9fbf06db1f5df349b53251ddc79dedafb47
parenta171979a19b46194f2926522073622d64d7a8fc6 (diff)
parent9681022f1ee5c6c9160c515b24d2a3d1efe8b90d (diff)
downloadcpython-b1e58440f87f921bd51396f4e9a4b18dcd2def6b.zip
cpython-b1e58440f87f921bd51396f4e9a4b18dcd2def6b.tar.gz
cpython-b1e58440f87f921bd51396f4e9a4b18dcd2def6b.tar.bz2
Issue #9815: assertRaises now tries to clear references to local variables in the exception's traceback.
-rw-r--r--Lib/unittest/case.py3
-rw-r--r--Lib/unittest/test/test_assertions.py31
-rw-r--r--Misc/NEWS3
3 files changed, 37 insertions, 0 deletions
diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py
index bedbc67..aa00b7a 100644
--- a/Lib/unittest/case.py
+++ b/Lib/unittest/case.py
@@ -9,6 +9,7 @@ import re
import warnings
import collections
import contextlib
+import traceback
from . import result
from .util import (strclass, safe_repr, _count_diff_all_purpose,
@@ -178,6 +179,8 @@ class _AssertRaisesContext(_AssertRaisesBaseContext):
self.obj_name))
else:
self._raiseFailure("{} not raised".format(exc_name))
+ else:
+ traceback.clear_frames(tb)
if not issubclass(exc_type, self.expected):
# let unexpected exceptions pass through
return False
diff --git a/Lib/unittest/test/test_assertions.py b/Lib/unittest/test/test_assertions.py
index af08d5a..c349a95 100644
--- a/Lib/unittest/test/test_assertions.py
+++ b/Lib/unittest/test/test_assertions.py
@@ -1,5 +1,6 @@
import datetime
import warnings
+import weakref
import unittest
from itertools import product
@@ -97,6 +98,36 @@ class Test_Assertions(unittest.TestCase):
else:
self.fail("assertRaises() didn't let exception pass through")
+ def test_assertRaises_frames_survival(self):
+ # Issue #9815: assertRaises should avoid keeping local variables
+ # in a traceback alive.
+ class A:
+ pass
+ wr = None
+
+ class Foo(unittest.TestCase):
+
+ def foo(self):
+ nonlocal wr
+ a = A()
+ wr = weakref.ref(a)
+ try:
+ raise IOError
+ except IOError:
+ raise ValueError
+
+ def test_functional(self):
+ self.assertRaises(ValueError, self.foo)
+
+ def test_with(self):
+ with self.assertRaises(ValueError):
+ self.foo()
+
+ Foo("test_functional").run()
+ self.assertIsNone(wr())
+ Foo("test_with").run()
+ self.assertIsNone(wr())
+
def testAssertNotRegex(self):
self.assertNotRegex('Ala ma kota', r'r+')
try:
diff --git a/Misc/NEWS b/Misc/NEWS
index 4539f4d..c711571 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -60,6 +60,9 @@ Core and Builtins
Library
-------
+- Issue #9815: assertRaises now tries to clear references to local variables
+ in the exception's traceback.
+
- Issue #19940: ssl.cert_time_to_seconds() now interprets the given time
string in the UTC timezone (as specified in RFC 5280), not the local
timezone.