unittest.TestCase.assertWarns raises RuntimeEror if sys.modules changes size #73806
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
assignee = None closed_at = <Date 2020-06-11.18:36:06.899> created_at = <Date 2017-02-22.16:22:51.894> labels = ['3.7', '3.8', 'type-bug', 'library'] title = 'unittest.TestCase.assertWarns raises RuntimeEror if sys.modules changes size' updated_at = <Date 2021-11-18.16:09:52.825> user = 'https://github.com/kernc'
activity = <Date 2021-11-18.16:09:52.825> actor = 'lukasz.langa' assignee = 'none' closed = True closed_date = <Date 2020-06-11.18:36:06.899> closer = 'akuchling' components = ['Library (Lib)'] creation = <Date 2017-02-22.16:22:51.894> creator = 'kernc' dependencies =  files =  hgrepos =  issue_num = 29620 keywords = ['patch'] message_count = 9.0 messages = ['288370', '323821', '356671', '361886', '371315', '371317', '371318', '371319', '406547'] nosy_count = 8.0 nosy_names = ['akuchling', 'lukasz.langa', 'serhiy.storchaka', 'William.Schwartz', 'kernc', 'miss-islington', 'Arthit Suriyawongkul', 'Maximilian Peters'] pr_nums = ['4800', '20816', '20817', '29605'] priority = 'normal' resolution = 'fixed' stage = 'resolved' status = 'closed' superseder = None type = 'behavior' url = 'https://bugs.python.org/issue29620' versions = ['Python 2.7', 'Python 3.6', 'Python 3.7', 'Python 3.8']
The text was updated successfully, but these errors were encountered:
If any of the objects in sys.modules is a module-like object that performs some additional imports in its __getattribute__ (as appropriate) handler, the following simple unit test test case:
import unittest import warnings
class Case(unittest.TestCase): def test_assertWarns(self): with self.assertWarns(UserWarning): warnings.warn('Some warning')
Traceback (most recent call last): File "/tmp/example.py", line 9, in test_assertWarns with self.assertWarns(UserWarning): File "/usr/lib/python3.4/unittest/case.py", line 205, in __enter__ for v in sys.modules.values(): RuntimeError: dictionary changed size during iteration
The problem is in the iteration over sys.modules in unittest.case._AssertWarnsContext.__enter__() and accessing every module's __warningregistry__ attribute. On this access, the module-like objects may perform arbitrary actions including importing of further modules which extends sys.modules.
The simple proposed fix with no foreseen side-effects is to wrap sys.modules.values() call as a tuple().
I am also running into this problem. I'm not 100%, but I'm pretty sure that looping over sys.modules and accessing __warningregistry__ on each module triggers one of my module's __getattr__ functions (PEP-562), which in turn uses setuptools entry points to import an arbitrary set of other modules.
Bizarrely, however, I cannot reproduce on macOS, only Linux. Presumably there's something platform dependent about how the default unittest test runner orders my tests, and hence which modules have already been loaded by the time I call assertWarnsRegex.