bpo-23890: Fix ref cycle in TestCase.assertRaises (#858)

unittest.TestCase.assertRaises() now manually breaks a
reference cycle to not keep objects alive longer than expected.
(cherry picked from commit bbd3cf8f1e)
This commit is contained in:
Victor Stinner 2017-06-16 00:18:15 +02:00 committed by GitHub
parent e064d4dfed
commit 50dbf577e1
3 changed files with 46 additions and 22 deletions

View file

@ -153,6 +153,7 @@ class _AssertRaisesBaseContext(_BaseTestCaseContext):
If args is not empty, call a callable passing positional and keyword
arguments.
"""
try:
if not _is_subtype(self.expected, self._base_type):
raise TypeError('%s() arg 1 must be %s' %
(name, self._base_type_str))
@ -175,6 +176,9 @@ class _AssertRaisesBaseContext(_BaseTestCaseContext):
self.obj_name = str(callable_obj)
with self:
callable_obj(*args, **kwargs)
finally:
# bpo-23890: manually break a reference cycle
self = None
class _AssertRaisesContext(_AssertRaisesBaseContext):
@ -725,7 +729,11 @@ class TestCase(object):
self.assertEqual(the_exception.error_code, 3)
"""
context = _AssertRaisesContext(expected_exception, self)
try:
return context.handle('assertRaises', args, kwargs)
finally:
# bpo-23890: manually break a reference cycle
context = None
def assertWarns(self, expected_warning, *args, **kwargs):
"""Fail unless a warning of class warnClass is triggered

View file

@ -1273,6 +1273,19 @@ test case
with self.assertRaises(TypeError):
self.assertRaises((ValueError, object))
def testAssertRaisesRefcount(self):
# bpo-23890: assertRaises() must not keep objects alive longer
# than expected
def func() :
try:
raise ValueError
except ValueError:
raise ValueError
refcount = sys.getrefcount(func)
self.assertRaises(ValueError, func)
self.assertEqual(refcount, sys.getrefcount(func))
def testAssertRaisesRegex(self):
class ExceptionMock(Exception):
pass

View file

@ -51,6 +51,9 @@ Core and Builtins
Library
-------
- bpo-23890: unittest.TestCase.assertRaises() now manually breaks a reference
cycle to not keep objects alive longer than expected.
- bpo-30149: inspect.signature() now supports callables with
variable-argument parameters wrapped with partialmethod.
Patch by Dong-hee Na.