bpo-29620: iterate over a copy of sys.modules (GH-4800)

unittest.TestCase.assertWarns no longer raises a RuntimeException
when accessing a module's ``__warningregistry__`` causes importation of a new
module, or when a new module is imported in another thread. 

Patch by Kernc.
This commit is contained in:
kernc 2020-06-11 20:03:29 +02:00 committed by GitHub
parent 436b648910
commit 46398fba4d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 1 deletions

View file

@ -252,7 +252,7 @@ class _AssertWarnsContext(_AssertRaisesBaseContext):
def __enter__(self): def __enter__(self):
# The __warningregistry__'s need to be in a pristine state for tests # The __warningregistry__'s need to be in a pristine state for tests
# to work properly. # to work properly.
for v in sys.modules.values(): for v in list(sys.modules.values()):
if getattr(v, '__warningregistry__', None): if getattr(v, '__warningregistry__', None):
v.__warningregistry__ = {} v.__warningregistry__ = {}
self.warnings_manager = warnings.catch_warnings(record=True) self.warnings_manager = warnings.catch_warnings(record=True)

View file

@ -8,6 +8,7 @@ import logging
import warnings import warnings
import weakref import weakref
import inspect import inspect
import types
from copy import deepcopy from copy import deepcopy
from test import support from test import support
@ -1350,6 +1351,20 @@ test case
pass pass
self.assertRaises(TypeError, self.assertWarnsRegex, MyWarn, lambda: True) self.assertRaises(TypeError, self.assertWarnsRegex, MyWarn, lambda: True)
def testAssertWarnsModifySysModules(self):
# bpo-29620: handle modified sys.modules during iteration
class Foo(types.ModuleType):
@property
def __warningregistry__(self):
sys.modules['@bar@'] = 'bar'
sys.modules['@foo@'] = Foo('foo')
try:
self.assertWarns(UserWarning, warnings.warn, 'expected')
finally:
del sys.modules['@foo@']
del sys.modules['@bar@']
def testAssertRaisesRegexMismatch(self): def testAssertRaisesRegexMismatch(self):
def Stub(): def Stub():
raise Exception('Unexpected') raise Exception('Unexpected')

View file

@ -0,0 +1,3 @@
:func:`~unittest.TestCase.assertWarns` no longer raises a ``RuntimeException``
when accessing a module's ``__warningregistry__`` causes importation of a new
module, or when a new module is imported in another thread. Patch by Kernc.