From 6b49167c3134e695efb1a122f73c3524a9049db5 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Wed, 19 Oct 2016 15:57:35 +0200 Subject: [PATCH] MAINT: Add python 3.6 support to suppress_warnings Python 3.6 has two methods for showing warnings, so we have to support both ways (strictly speaking, on python 3.6 itself only the new would probably be needed). Also adds the _filters_mutated() call to replace manual registry clearing. This is basically the fix that newer python versions have to avoid the issue making the manual clearing unnecessary. Closes gh-8176 --- numpy/testing/utils.py | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index b01de173d82d..d17e7e404e14 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -2027,6 +2027,11 @@ def __init__(self, forwarding_rule="always"): self._forwarding_rule = forwarding_rule def _clear_registries(self): + if hasattr(warnings, "_filters_mutated"): + # clearing the registry should not be necessary on new pythons, + # instead the filters should be mutated. + warnings._filters_mutated() + return # Simply clear the registry, this should normally be harmless, # note that on new pythons it would be invalidated anyway. for module in self._tmp_modules: @@ -2116,6 +2121,8 @@ def __enter__(self): raise RuntimeError("cannot enter suppress_warnings twice.") self._orig_show = warnings.showwarning + if hasattr(warnings, "_showwarnmsg"): + self._orig_showmsg = warnings._showwarnmsg self._filters = warnings.filters warnings.filters = self._filters[:] @@ -2139,20 +2146,29 @@ def __enter__(self): module=module_regex) self._tmp_modules.add(mod) warnings.showwarning = self._showwarning + if hasattr(warnings, "_showwarnmsg"): + warnings._showwarnmsg = self._showwarnmsg self._clear_registries() return self def __exit__(self, *exc_info): warnings.showwarning = self._orig_show + if hasattr(warnings, "_showwarnmsg"): + warnings._showwarnmsg = self._orig_showmsg warnings.filters = self._filters self._clear_registries() self._entered = False del self._orig_show del self._filters + def _showwarnmsg(self, msg): + self._showwarning(msg.message, msg.category, msg.filename, msg.lineno, + msg.file, msg.line, use_warnmsg=msg) + def _showwarning(self, message, category, filename, lineno, *args, **kwargs): + use_warnmsg = kwargs.pop("use_warnmsg", None) for cat, _, pattern, mod, rec in ( self._suppressions + self._tmp_suppressions)[::-1]: if (issubclass(category, cat) and @@ -2179,8 +2195,11 @@ def _showwarning(self, message, category, filename, lineno, # There is no filter in place, so pass to the outside handler # unless we should only pass it once if self._forwarding_rule == "always": - self._orig_show(message, category, filename, lineno, - *args, **kwargs) + if use_warnmsg is None: + self._orig_show(message, category, filename, lineno, + *args, **kwargs) + else: + self._orig_showmsg(use_warnmsg) return if self._forwarding_rule == "once": @@ -2193,7 +2212,11 @@ def _showwarning(self, message, category, filename, lineno, if signature in self._forwarded: return self._forwarded.add(signature) - self._orig_show(message, category, filename, lineno, *args, **kwargs) + if use_warnmsg is None: + self._orig_show(message, category, filename, lineno, *args, + **kwargs) + else: + self._orig_showmsg(use_warnmsg) def __call__(self, func): """