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):
# The __warningregistry__'s need to be in a pristine state for tests
# to work properly.
for v in sys.modules.values():
for v in list(sys.modules.values()):
if getattr(v, '__warningregistry__', None):
v.__warningregistry__ = {}
self.warnings_manager = warnings.catch_warnings(record=True)

View File

@ -8,6 +8,7 @@ import logging
import warnings
import weakref
import inspect
import types
from copy import deepcopy
from test import support
@ -1350,6 +1351,20 @@ test case
pass
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 Stub():
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.