Fix ref cycles in TestCase.assertRaises() (#193)
bpo-23890: unittest.TestCase.assertRaises() now manually breaks a reference cycle to not keep objects alive longer than expected.
This commit is contained in:
parent
6003db7db5
commit
bbd3cf8f1e
|
@ -153,28 +153,32 @@ class _AssertRaisesBaseContext(_BaseTestCaseContext):
|
||||||
If args is not empty, call a callable passing positional and keyword
|
If args is not empty, call a callable passing positional and keyword
|
||||||
arguments.
|
arguments.
|
||||||
"""
|
"""
|
||||||
if not _is_subtype(self.expected, self._base_type):
|
|
||||||
raise TypeError('%s() arg 1 must be %s' %
|
|
||||||
(name, self._base_type_str))
|
|
||||||
if args and args[0] is None:
|
|
||||||
warnings.warn("callable is None",
|
|
||||||
DeprecationWarning, 3)
|
|
||||||
args = ()
|
|
||||||
if not args:
|
|
||||||
self.msg = kwargs.pop('msg', None)
|
|
||||||
if kwargs:
|
|
||||||
warnings.warn('%r is an invalid keyword argument for '
|
|
||||||
'this function' % next(iter(kwargs)),
|
|
||||||
DeprecationWarning, 3)
|
|
||||||
return self
|
|
||||||
|
|
||||||
callable_obj, *args = args
|
|
||||||
try:
|
try:
|
||||||
self.obj_name = callable_obj.__name__
|
if not _is_subtype(self.expected, self._base_type):
|
||||||
except AttributeError:
|
raise TypeError('%s() arg 1 must be %s' %
|
||||||
self.obj_name = str(callable_obj)
|
(name, self._base_type_str))
|
||||||
with self:
|
if args and args[0] is None:
|
||||||
callable_obj(*args, **kwargs)
|
warnings.warn("callable is None",
|
||||||
|
DeprecationWarning, 3)
|
||||||
|
args = ()
|
||||||
|
if not args:
|
||||||
|
self.msg = kwargs.pop('msg', None)
|
||||||
|
if kwargs:
|
||||||
|
warnings.warn('%r is an invalid keyword argument for '
|
||||||
|
'this function' % next(iter(kwargs)),
|
||||||
|
DeprecationWarning, 3)
|
||||||
|
return self
|
||||||
|
|
||||||
|
callable_obj, *args = args
|
||||||
|
try:
|
||||||
|
self.obj_name = callable_obj.__name__
|
||||||
|
except AttributeError:
|
||||||
|
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):
|
class _AssertRaisesContext(_AssertRaisesBaseContext):
|
||||||
|
@ -725,7 +729,11 @@ class TestCase(object):
|
||||||
self.assertEqual(the_exception.error_code, 3)
|
self.assertEqual(the_exception.error_code, 3)
|
||||||
"""
|
"""
|
||||||
context = _AssertRaisesContext(expected_exception, self)
|
context = _AssertRaisesContext(expected_exception, self)
|
||||||
return context.handle('assertRaises', args, kwargs)
|
try:
|
||||||
|
return context.handle('assertRaises', args, kwargs)
|
||||||
|
finally:
|
||||||
|
# bpo-23890: manually break a reference cycle
|
||||||
|
context = None
|
||||||
|
|
||||||
def assertWarns(self, expected_warning, *args, **kwargs):
|
def assertWarns(self, expected_warning, *args, **kwargs):
|
||||||
"""Fail unless a warning of class warnClass is triggered
|
"""Fail unless a warning of class warnClass is triggered
|
||||||
|
|
|
@ -1273,6 +1273,19 @@ test case
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
self.assertRaises((ValueError, object))
|
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):
|
def testAssertRaisesRegex(self):
|
||||||
class ExceptionMock(Exception):
|
class ExceptionMock(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -291,6 +291,9 @@ Extension Modules
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- bpo-23890: unittest.TestCase.assertRaises() now manually breaks a reference
|
||||||
|
cycle to not keep objects alive longer than expected.
|
||||||
|
|
||||||
- bpo-29901: The zipapp module now supports general path-like objects, not
|
- bpo-29901: The zipapp module now supports general path-like objects, not
|
||||||
just pathlib.Path.
|
just pathlib.Path.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue