Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-29620: iterate over a tuple of sys.modules #4800

Open
wants to merge 1 commit into
base: master
from

Conversation

Projects
None yet
4 participants
@kernc
Copy link

commented Dec 11, 2017

Fixes https://bugs.python.org/issue29620 by wrapping sys.modules.values() into a tuple before iteration.

The change is so miniscule I was not sure it warrants tests.

https://bugs.python.org/issue29620

@serhiy-storchaka
Copy link
Member

left a comment

Could you please add a test? It is enough to create a types.ModuleType subclass with the __warningregistry__ property (or the __getattr__() method) which mutates sys.modules and add its instance to sys.modules.

Add also a news entry (see https://devguide.python.org/committing/#what-s-new-and-news-entries).

@@ -227,7 +227,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 tuple(sys.modules.values()):

This comment has been minimized.

Copy link
@serhiy-storchaka

serhiy-storchaka Aug 21, 2018

Member

Use list(). There is no benefit of using a tuple, but creating a list from a general iterable is a tiny bit faster.

tuple(x) is expanded to tuple(list(x)) in most cases (if x is not a tuple or list).

@kernc kernc force-pushed the kernc:patch-1 branch from 2fe6671 to 5651335 Aug 21, 2018

@kernc

This comment has been minimized.

Copy link
Author

commented Aug 21, 2018

Done. Hope it's ok.

sys.modules['@bar@'] = 'bar'

sys.modules['@foo@'] = Foo('foo')
self.assertWarns(Warning, lambda: warnings.warn('Ok'))

This comment has been minimized.

Copy link
@serhiy-storchaka

serhiy-storchaka Aug 21, 2018

Member

I prefer either

self.assertWarns(UserWarning, warnings.warn, 'Ok')

or

with self.assertWarns(UserWarning):
    warnings.warn('Ok')

sys.modules['@foo@'] = Foo('foo')
self.assertWarns(Warning, lambda: warnings.warn('Ok'))
del sys.modules['@foo@'], \

This comment has been minimized.

Copy link
@serhiy-storchaka

serhiy-storchaka Aug 21, 2018

Member

Use two separate statements.

@@ -0,0 +1,2 @@
In :func:`~unittest.TestCase.assertWarns`, iterate over a copy of

This comment has been minimized.

Copy link
@serhiy-storchaka

serhiy-storchaka Aug 21, 2018

Member

Making a copy for iteration is an implementation detail. The user visible change is that assertWarns() no longer raises a RuntimeException when __warningregistry__ causes importing a module or a module is imported in other thread.

@@ -0,0 +1,2 @@
In :func:`~unittest.TestCase.assertWarns`, iterate over a copy of
``sys.modules``, which may change size during iteration.

This comment has been minimized.

Copy link
@serhiy-storchaka

serhiy-storchaka Aug 21, 2018

Member

Add please "Patch by yourname."

@kernc kernc force-pushed the kernc:patch-1 branch from 5651335 to 7f7fdac Aug 22, 2018

@kernc

This comment has been minimized.

Copy link
Author

commented Aug 22, 2018

Updated. Thanks.

@kernc

This comment has been minimized.

Copy link
Author

commented Sep 17, 2018

@serhiy-storchaka Do you find any other issues?

@csabella csabella requested a review from serhiy-storchaka Mar 18, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.