Index: Misc/NEWS =================================================================== --- Misc/NEWS (revision 66339) +++ Misc/NEWS (working copy) @@ -67,8 +67,8 @@ - Issue #3809: Fixed spurious 'test.blah' file left behind by test_logging. -- Issue 3781: Clean up the API for warnings.catch_warnings() by having it - return a list or None rather than a custom object. +- Issue 3781: Revert relocation of catch_warnings() to the warnings module. + It is once again only accessible as test.test_support.catch_warnings() - Issue #1638033: Cookie.Morsel gained the httponly attribute. Index: Doc/library/warnings.rst =================================================================== --- Doc/library/warnings.rst (revision 66339) +++ Doc/library/warnings.rst (working copy) @@ -158,67 +158,6 @@ warnings.simplefilter('default', ImportWarning) -.. _warning-suppress: - -Temporarily Suppressing Warnings --------------------------------- - -If you are using code that you know will raise a warning, such some deprecated -function, but do not want to see the warning, then suppress the warning using -the :class:`catch_warnings` context manager:: - - import warnings - - def fxn(): - warnings.warn("deprecated", DeprecationWarning) - - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - fxn() - -While within the context manager all warnings will simply be ignored. This -allows you to use known-deprecated code without having to see the warning while -not suppressing the warning for other code that might not be aware of its use -of deprecated code. - - -.. _warning-testing: - -Testing Warnings ----------------- - -To test warnings raised by code, use the :class:`catch_warnings` context -manager. With it you can temporarily mutate the warnings filter to facilitate -your testing. For instance, do the following to capture all raised warnings to -check:: - - import warnings - - def fxn(): - warnings.warn("deprecated", DeprecationWarning) - - with warnings.catch_warnings(record=True) as w: - # Cause all warnings to always be triggered. - warnings.simplefilter("always") - # Trigger a warning. - fxn() - # Verify some things - assert len(w) == 1 - assert isinstance(w[-1].category, DeprecationWarning) - assert "deprecated" in str(w[-1].message) - -One can also cause all warnings to be exceptions by using ``error`` instead of -``always``. One thing to be aware of is that if a warning has already been -raised because of a ``once``/``default`` rule, then no matter what filters are -set the warning will not be seen again unless the warnings registry related to -the warning has been cleared. - -Once the context manager exits, the warnings filter is restored to its state -when the context was entered. This prevents tests from changing the warnings -filter in unexpected ways between tests and leading to indeterminate test -results. - - .. _warning-functions: Available Functions @@ -324,28 +263,3 @@ :func:`filterwarnings`, including that of the :option:`-W` command line options and calls to :func:`simplefilter`. - -Available Context Managers --------------------------- - -.. class:: catch_warnings([\*, record=False, module=None]) - - A context manager that copies and, upon exit, restores the warnings filter. - If the *record* argument is False (the default) the context manager returns - :class:`None`. If *record* is true, a list is returned that is populated - with objects as seen by a custom :func:`showwarning` function (which also - suppresses output to ``sys.stdout``). Each object has attributes with the - same names as the arguments to :func:`showwarning`. - - The *module* argument takes a module that will be used instead of the - module returned when you import :mod:`warnings` whose filter will be - protected. This arguments exists primarily for testing the :mod:`warnings` - module itself. - - .. note:: - - In Python 3.0, the arguments to the constructor for - :class:`catch_warnings` are keyword-only arguments. - - .. versionadded:: 2.6 - Index: Lib/asynchat.py =================================================================== --- Lib/asynchat.py (revision 66339) +++ Lib/asynchat.py (working copy) @@ -49,8 +49,8 @@ import socket import asyncore from collections import deque -from sys import py3kwarning -from warnings import filterwarnings, catch_warnings +from test.test_support import catch_warning +from warnings import filterwarnings class async_chat (asyncore.dispatcher): """This is an abstract class. You must derive from this class, and add @@ -218,9 +218,8 @@ # handle classic producer behavior obs = self.ac_out_buffer_size try: - with catch_warnings(): - if py3kwarning: - filterwarnings("ignore", ".*buffer", DeprecationWarning) + with catch_warning(record=False): + filterwarnings("ignore", ".*buffer", DeprecationWarning) data = buffer(first, 0, obs) except TypeError: data = first.more() Index: Lib/warnings.py =================================================================== --- Lib/warnings.py (revision 66339) +++ Lib/warnings.py (working copy) @@ -8,7 +8,7 @@ import types __all__ = ["warn", "showwarning", "formatwarning", "filterwarnings", - "resetwarnings", "catch_warnings"] + "resetwarnings"] def warnpy3k(message, category=None, stacklevel=1): @@ -272,8 +272,7 @@ fxn_code = showwarning.__func__.func_code if fxn_code: args = fxn_code.co_varnames[:fxn_code.co_argcount] - CO_VARARGS = 0x4 - if 'line' not in args and not fxn_code.co_flags & CO_VARARGS: + if 'line' not in args: showwarning_msg = ("functions overriding warnings.showwarning() " "must support the 'line' argument") if message == showwarning_msg: @@ -284,72 +283,6 @@ showwarning(message, category, filename, lineno) -class WarningMessage(object): - - """Holds the result of a single showwarning() call.""" - - _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file", - "line") - - def __init__(self, message, category, filename, lineno, file=None, - line=None): - local_values = locals() - for attr in self._WARNING_DETAILS: - setattr(self, attr, local_values[attr]) - self._category_name = category.__name__ if category else None - - def __str__(self): - return ("{message : %r, category : %r, filename : %r, lineno : %s, " - "line : %r}" % (self.message, self._category_name, - self.filename, self.lineno, self.line)) - - -class catch_warnings(object): - - """A context manager that copies and restores the warnings filter upon - exiting the context. - - The 'record' argument specifies whether warnings should be captured by a - custom implementation of warnings.showwarning() and be appended to a list - returned by the context manager. Otherwise None is returned by the context - manager. The objects appended to the list are arguments whose attributes - mirror the arguments to showwarning(). - - The 'module' argument is to specify an alternative module to the module - named 'warnings' and imported under that name. This argument is only useful - when testing the warnings module itself. - - """ - - def __init__(self, record=False, module=None): - """Specify whether to record warnings and if an alternative module - should be used other than sys.modules['warnings']. - - For compatibility with Python 3.0, please consider all arguments to be - keyword-only. - - """ - self._record = record - self._module = sys.modules['warnings'] if module is None else module - - def __enter__(self): - self._filters = self._module.filters - self._module.filters = self._filters[:] - self._showwarning = self._module.showwarning - if self._record: - log = [] - def showwarning(*args, **kwargs): - log.append(WarningMessage(*args, **kwargs)) - self._module.showwarning = showwarning - return log - else: - return None - - def __exit__(self, *exc_info): - self._module.filters = self._filters - self._module.showwarning = self._showwarning - - # filters contains a sequence of filter 5-tuples # The components of the 5-tuple are: # - an action: error, ignore, always, default, module, or once Index: Lib/BaseHTTPServer.py =================================================================== --- Lib/BaseHTTPServer.py (revision 66339) +++ Lib/BaseHTTPServer.py (working copy) @@ -73,11 +73,11 @@ import sys import time import socket # For gethostbyaddr() -from warnings import filterwarnings, catch_warnings -with catch_warnings(): - if sys.py3kwarning: - filterwarnings("ignore", ".*mimetools has been removed", - DeprecationWarning) +from test.test_support import catch_warning +from warnings import filterwarnings +with catch_warning(record=False): + filterwarnings("ignore", ".*mimetools has been removed", + DeprecationWarning) import mimetools import SocketServer Index: Lib/mimetools.py =================================================================== --- Lib/mimetools.py (revision 66339) +++ Lib/mimetools.py (working copy) @@ -2,12 +2,11 @@ import os -import sys import tempfile -from warnings import filterwarnings, catch_warnings -with catch_warnings(): - if sys.py3kwarning: - filterwarnings("ignore", ".*rfc822 has been removed", DeprecationWarning) +from test.test_support import catch_warning +from warnings import filterwarnings +with catch_warning(record=False): + filterwarnings("ignore", ".*rfc822 has been removed", DeprecationWarning) import rfc822 from warnings import warnpy3k Index: Lib/cgi.py =================================================================== --- Lib/cgi.py (revision 66339) +++ Lib/cgi.py (working copy) @@ -40,16 +40,16 @@ import urllib import UserDict import urlparse +from warnings import filterwarnings, warn -from warnings import filterwarnings, catch_warnings, warn -with catch_warnings(): - if sys.py3kwarning: +if sys.py3kwarning: + from test.test_support import catch_warning + with catch_warning(record=False): filterwarnings("ignore", ".*mimetools has been removed", DeprecationWarning) - import mimetools - if sys.py3kwarning: + import mimetools filterwarnings("ignore", ".*rfc822 has been removed", DeprecationWarning) - import rfc822 + import rfc822 try: from cStringIO import StringIO Index: Lib/bsddb/test/test_early_close.py =================================================================== --- Lib/bsddb/test/test_early_close.py (revision 66339) +++ Lib/bsddb/test/test_early_close.py (working copy) @@ -168,9 +168,9 @@ self.assertEquals(("XXX", "yyy"), c1.first()) import warnings # Not interested in warnings about implicit close. - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - txn.commit() + warnings.simplefilter("ignore") + txn.commit() + warnings.resetwarnings() self.assertRaises(db.DBCursorClosedError, c2.first) if db.version() > (4,3,0) : Index: Lib/httplib.py =================================================================== --- Lib/httplib.py (revision 66339) +++ Lib/httplib.py (working copy) @@ -67,13 +67,12 @@ """ import socket -from sys import py3kwarning from urlparse import urlsplit import warnings -with warnings.catch_warnings(): - if py3kwarning: - warnings.filterwarnings("ignore", ".*mimetools has been removed", - DeprecationWarning) +from test.test_support import catch_warning +with catch_warning(record=False): + warnings.filterwarnings("ignore", ".*mimetools has been removed", + DeprecationWarning) import mimetools try: Index: Lib/test/test_pep352.py =================================================================== --- Lib/test/test_pep352.py (revision 66339) +++ Lib/test/test_pep352.py (working copy) @@ -2,7 +2,7 @@ import __builtin__ import exceptions import warnings -from test.test_support import run_unittest +from test.test_support import run_unittest, catch_warning import os from platform import system as platform_system @@ -22,7 +22,7 @@ self.failUnless(issubclass(Exception, object)) def verify_instance_interface(self, ins): - with warnings.catch_warnings(): + with catch_warning(): ignore_message_warning() for attr in ("args", "message", "__str__", "__repr__", "__getitem__"): @@ -95,7 +95,7 @@ # Make sure interface works properly when given a single argument arg = "spam" exc = Exception(arg) - with warnings.catch_warnings(): + with catch_warning(): ignore_message_warning() results = ([len(exc.args), 1], [exc.args[0], arg], [exc.message, arg], @@ -109,7 +109,7 @@ arg_count = 3 args = tuple(range(arg_count)) exc = Exception(*args) - with warnings.catch_warnings(): + with catch_warning(): ignore_message_warning() results = ([len(exc.args), arg_count], [exc.args, args], [exc.message, ''], [str(exc), str(args)], @@ -121,7 +121,7 @@ def test_interface_no_arg(self): # Make sure that with no args that interface is correct exc = Exception() - with warnings.catch_warnings(): + with catch_warning(): ignore_message_warning() results = ([len(exc.args), 0], [exc.args, tuple()], [exc.message, ''], @@ -132,7 +132,7 @@ def test_message_deprecation(self): # As of Python 2.6, BaseException.message is deprecated. - with warnings.catch_warnings(): + with catch_warning(): warnings.resetwarnings() warnings.filterwarnings('error') @@ -219,7 +219,7 @@ def test_catch_string(self): # Catching a string should trigger a DeprecationWarning. - with warnings.catch_warnings(): + with catch_warning(): warnings.resetwarnings() warnings.filterwarnings("error") str_exc = "spam" Index: Lib/test/test_symtable.py =================================================================== --- Lib/test/test_symtable.py (revision 66339) +++ Lib/test/test_symtable.py (working copy) @@ -44,7 +44,7 @@ class SymtableTest(unittest.TestCase): - with warnings.catch_warnings(): + with test_support.catch_warning(record=False): # Ignore warnings about "from blank import *" warnings.simplefilter("ignore", SyntaxWarning) top = symtable.symtable(TEST_CODE, "?", "exec") @@ -60,16 +60,16 @@ def check(w, msg): self.assertEqual(str(w.message), msg) sym = self.top.lookup("glob") - with warnings.catch_warnings(record=True) as w: + with test_support.catch_warning() as w: warnings.simplefilter("always", DeprecationWarning) self.assertFalse(sym.is_vararg()) - check(w[-1].message, "is_vararg() is obsolete and will be removed") + check(w, "is_vararg() is obsolete and will be removed") + w.reset() self.assertFalse(sym.is_keywordarg()) - check(w[-1].message, - "is_keywordarg() is obsolete and will be removed") + check(w, "is_keywordarg() is obsolete and will be removed") + w.reset() self.assertFalse(sym.is_in_tuple()) - check(w[-1].message, - "is_in_tuple() is obsolete and will be removed") + check(w, "is_in_tuple() is obsolete and will be removed") def test_type(self): self.assertEqual(self.top.get_type(), "module") Index: Lib/test/test_exceptions.py =================================================================== --- Lib/test/test_exceptions.py (revision 66339) +++ Lib/test/test_exceptions.py (working copy) @@ -4,9 +4,9 @@ import sys import unittest import pickle, cPickle -import warnings -from test.test_support import TESTFN, unlink, run_unittest, captured_output +from test.test_support import (TESTFN, unlink, run_unittest, + catch_warning, captured_output) from test.test_pep352 import ignore_message_warning # XXX This is not really enough, each *operation* should be tested! @@ -274,7 +274,7 @@ except NameError: pass - with warnings.catch_warnings(): + with catch_warning(): ignore_message_warning() for exc, args, expected in exceptionList: try: Index: Lib/test/test_sundry.py =================================================================== --- Lib/test/test_sundry.py (revision 66339) +++ Lib/test/test_sundry.py (working copy) @@ -8,7 +8,7 @@ class TestUntestedModules(unittest.TestCase): def test_at_least_import_untested_modules(self): - with warnings.catch_warnings(record=True): + with test_support.catch_warning(): import CGIHTTPServer import aifc import audiodev Index: Lib/test/test_warnings.py =================================================================== --- Lib/test/test_warnings.py (revision 66339) +++ Lib/test/test_warnings.py (working copy) @@ -72,123 +72,117 @@ """Testing the filtering functionality.""" def test_error(self): - with original_warnings.catch_warnings(module=self.module) as w: + with test_support.catch_warning(self.module) as w: self.module.resetwarnings() self.module.filterwarnings("error", category=UserWarning) self.assertRaises(UserWarning, self.module.warn, "FilterTests.test_error") def test_ignore(self): - with original_warnings.catch_warnings(record=True, - module=self.module) as w: + with test_support.catch_warning(self.module) as w: self.module.resetwarnings() self.module.filterwarnings("ignore", category=UserWarning) self.module.warn("FilterTests.test_ignore", UserWarning) - self.assertEquals(len(w), 0) + self.assert_(not w.message) def test_always(self): - with original_warnings.catch_warnings(record=True, - module=self.module) as w: + with test_support.catch_warning(self.module) as w: self.module.resetwarnings() self.module.filterwarnings("always", category=UserWarning) message = "FilterTests.test_always" self.module.warn(message, UserWarning) - self.assert_(message, w[-1].message) + self.assert_(message, w.message) + w.message = None # Reset. self.module.warn(message, UserWarning) - self.assert_(w[-1].message, message) + self.assert_(w.message, message) def test_default(self): - with original_warnings.catch_warnings(record=True, - module=self.module) as w: + with test_support.catch_warning(self.module) as w: self.module.resetwarnings() self.module.filterwarnings("default", category=UserWarning) message = UserWarning("FilterTests.test_default") for x in xrange(2): self.module.warn(message, UserWarning) if x == 0: - self.assertEquals(w[-1].message, message) - del w[:] + self.assertEquals(w.message, message) + w.reset() elif x == 1: - self.assertEquals(len(w), 0) + self.assert_(not w.message, "unexpected warning: " + str(w)) else: raise ValueError("loop variant unhandled") def test_module(self): - with original_warnings.catch_warnings(record=True, - module=self.module) as w: + with test_support.catch_warning(self.module) as w: self.module.resetwarnings() self.module.filterwarnings("module", category=UserWarning) message = UserWarning("FilterTests.test_module") self.module.warn(message, UserWarning) - self.assertEquals(w[-1].message, message) - del w[:] + self.assertEquals(w.message, message) + w.reset() self.module.warn(message, UserWarning) - self.assertEquals(len(w), 0) + self.assert_(not w.message, "unexpected message: " + str(w)) def test_once(self): - with original_warnings.catch_warnings(record=True, - module=self.module) as w: + with test_support.catch_warning(self.module) as w: self.module.resetwarnings() self.module.filterwarnings("once", category=UserWarning) message = UserWarning("FilterTests.test_once") self.module.warn_explicit(message, UserWarning, "test_warnings.py", 42) - self.assertEquals(w[-1].message, message) - del w[:] + self.assertEquals(w.message, message) + w.reset() self.module.warn_explicit(message, UserWarning, "test_warnings.py", 13) - self.assertEquals(len(w), 0) + self.assert_(not w.message) self.module.warn_explicit(message, UserWarning, "test_warnings2.py", 42) - self.assertEquals(len(w), 0) + self.assert_(not w.message) def test_inheritance(self): - with original_warnings.catch_warnings(module=self.module) as w: + with test_support.catch_warning(self.module) as w: self.module.resetwarnings() self.module.filterwarnings("error", category=Warning) self.assertRaises(UserWarning, self.module.warn, "FilterTests.test_inheritance", UserWarning) def test_ordering(self): - with original_warnings.catch_warnings(record=True, - module=self.module) as w: + with test_support.catch_warning(self.module) as w: self.module.resetwarnings() self.module.filterwarnings("ignore", category=UserWarning) self.module.filterwarnings("error", category=UserWarning, append=True) - del w[:] + w.reset() try: self.module.warn("FilterTests.test_ordering", UserWarning) except UserWarning: self.fail("order handling for actions failed") - self.assertEquals(len(w), 0) + self.assert_(not w.message) def test_filterwarnings(self): # Test filterwarnings(). # Implicitly also tests resetwarnings(). - with original_warnings.catch_warnings(record=True, - module=self.module) as w: + with test_support.catch_warning(self.module) as w: self.module.filterwarnings("error", "", Warning, "", 0) self.assertRaises(UserWarning, self.module.warn, 'convert to error') self.module.resetwarnings() text = 'handle normally' self.module.warn(text) - self.assertEqual(str(w[-1].message), text) - self.assert_(w[-1].category is UserWarning) + self.assertEqual(str(w.message), text) + self.assert_(w.category is UserWarning) self.module.filterwarnings("ignore", "", Warning, "", 0) text = 'filtered out' self.module.warn(text) - self.assertNotEqual(str(w[-1].message), text) + self.assertNotEqual(str(w.message), text) self.module.resetwarnings() self.module.filterwarnings("error", "hex*", Warning, "", 0) self.assertRaises(UserWarning, self.module.warn, 'hex/oct') text = 'nonmatching text' self.module.warn(text) - self.assertEqual(str(w[-1].message), text) - self.assert_(w[-1].category is UserWarning) + self.assertEqual(str(w.message), text) + self.assert_(w.category is UserWarning) class CFilterTests(BaseTest, FilterTests): module = c_warnings @@ -202,51 +196,40 @@ """Test warnings.warn() and warnings.warn_explicit().""" def test_message(self): - with original_warnings.catch_warnings(record=True, - module=self.module) as w: + with test_support.catch_warning(self.module) as w: for i in range(4): text = 'multi %d' %i # Different text on each call. self.module.warn(text) - self.assertEqual(str(w[-1].message), text) - self.assert_(w[-1].category is UserWarning) + self.assertEqual(str(w.message), text) + self.assert_(w.category is UserWarning) def test_filename(self): with warnings_state(self.module): - with original_warnings.catch_warnings(record=True, - module=self.module) as w: + with test_support.catch_warning(self.module) as w: warning_tests.inner("spam1") - self.assertEqual(os.path.basename(w[-1].filename), - "warning_tests.py") + self.assertEqual(os.path.basename(w.filename), "warning_tests.py") warning_tests.outer("spam2") - self.assertEqual(os.path.basename(w[-1].filename), - "warning_tests.py") + self.assertEqual(os.path.basename(w.filename), "warning_tests.py") def test_stacklevel(self): # Test stacklevel argument # make sure all messages are different, so the warning won't be skipped with warnings_state(self.module): - with original_warnings.catch_warnings(record=True, - module=self.module) as w: + with test_support.catch_warning(self.module) as w: warning_tests.inner("spam3", stacklevel=1) - self.assertEqual(os.path.basename(w[-1].filename), - "warning_tests.py") + self.assertEqual(os.path.basename(w.filename), "warning_tests.py") warning_tests.outer("spam4", stacklevel=1) - self.assertEqual(os.path.basename(w[-1].filename), - "warning_tests.py") + self.assertEqual(os.path.basename(w.filename), "warning_tests.py") warning_tests.inner("spam5", stacklevel=2) - self.assertEqual(os.path.basename(w[-1].filename), - "test_warnings.py") + self.assertEqual(os.path.basename(w.filename), "test_warnings.py") warning_tests.outer("spam6", stacklevel=2) - self.assertEqual(os.path.basename(w[-1].filename), - "warning_tests.py") + self.assertEqual(os.path.basename(w.filename), "warning_tests.py") warning_tests.outer("spam6.5", stacklevel=3) - self.assertEqual(os.path.basename(w[-1].filename), - "test_warnings.py") + self.assertEqual(os.path.basename(w.filename), "test_warnings.py") warning_tests.inner("spam7", stacklevel=9999) - self.assertEqual(os.path.basename(w[-1].filename), - "sys") + self.assertEqual(os.path.basename(w.filename), "sys") def test_missing_filename_not_main(self): # If __file__ is not specified and __main__ is not the module name, @@ -255,10 +238,9 @@ try: del warning_tests.__file__ with warnings_state(self.module): - with original_warnings.catch_warnings(record=True, - module=self.module) as w: + with test_support.catch_warning(self.module) as w: warning_tests.inner("spam8", stacklevel=1) - self.assertEqual(w[-1].filename, warning_tests.__name__) + self.assertEqual(w.filename, warning_tests.__name__) finally: warning_tests.__file__ = filename @@ -273,10 +255,9 @@ del warning_tests.__file__ warning_tests.__name__ = '__main__' with warnings_state(self.module): - with original_warnings.catch_warnings(record=True, - module=self.module) as w: + with test_support.catch_warning(self.module) as w: warning_tests.inner('spam9', stacklevel=1) - self.assertEqual(w[-1].filename, sys.argv[0]) + self.assertEqual(w.filename, sys.argv[0]) finally: warning_tests.__file__ = filename warning_tests.__name__ = module_name @@ -292,10 +273,9 @@ warning_tests.__name__ = '__main__' del sys.argv with warnings_state(self.module): - with original_warnings.catch_warnings(record=True, - module=self.module) as w: + with test_support.catch_warning(self.module) as w: warning_tests.inner('spam10', stacklevel=1) - self.assertEqual(w[-1].filename, '__main__') + self.assertEqual(w.filename, '__main__') finally: warning_tests.__file__ = filename warning_tests.__name__ = module_name @@ -313,10 +293,9 @@ warning_tests.__name__ = '__main__' sys.argv = [''] with warnings_state(self.module): - with original_warnings.catch_warnings(record=True, - module=self.module) as w: + with test_support.catch_warning(self.module) as w: warning_tests.inner('spam11', stacklevel=1) - self.assertEqual(w[-1].filename, '__main__') + self.assertEqual(w.filename, '__main__') finally: warning_tests.__file__ = file_name warning_tests.__name__ = module_name @@ -338,6 +317,7 @@ None, Warning, None, 1, registry=42) + class CWarnTests(BaseTest, WarnTests): module = c_warnings @@ -350,7 +330,7 @@ def test_improper_input(self): # Uses the private _setoption() function to test the parsing # of command-line warning arguments - with original_warnings.catch_warnings(module=self.module): + with test_support.catch_warning(self.module): self.assertRaises(self.module._OptionError, self.module._setoption, '1:2:3:4:5:6') self.assertRaises(self.module._OptionError, @@ -375,7 +355,7 @@ def test_filter(self): # Everything should function even if 'filters' is not in warnings. - with original_warnings.catch_warnings(module=self.module) as w: + with test_support.catch_warning(self.module) as w: self.module.filterwarnings("error", "", Warning, "", 0) self.assertRaises(UserWarning, self.module.warn, 'convert to error') @@ -390,33 +370,32 @@ try: original_registry = self.module.onceregistry __warningregistry__ = {} - with original_warnings.catch_warnings(record=True, - module=self.module) as w: + with test_support.catch_warning(self.module) as w: self.module.resetwarnings() self.module.filterwarnings("once", category=UserWarning) self.module.warn_explicit(message, UserWarning, "file", 42) - self.failUnlessEqual(w[-1].message, message) - del w[:] + self.failUnlessEqual(w.message, message) + w.reset() self.module.warn_explicit(message, UserWarning, "file", 42) - self.assertEquals(len(w), 0) + self.assert_(not w.message) # Test the resetting of onceregistry. self.module.onceregistry = {} __warningregistry__ = {} self.module.warn('onceregistry test') - self.failUnlessEqual(w[-1].message.args, message.args) + self.failUnlessEqual(w.message.args, message.args) # Removal of onceregistry is okay. - del w[:] + w.reset() del self.module.onceregistry __warningregistry__ = {} self.module.warn_explicit(message, UserWarning, "file", 42) - self.assertEquals(len(w), 0) + self.failUnless(not w.message) finally: self.module.onceregistry = original_registry def test_showwarning_missing(self): # Test that showwarning() missing is okay. text = 'del showwarning test' - with original_warnings.catch_warnings(module=self.module): + with test_support.catch_warning(self.module): self.module.filterwarnings("always", category=UserWarning) del self.module.showwarning with test_support.captured_output('stderr') as stream: @@ -437,7 +416,7 @@ def test_show_warning_output(self): # With showarning() missing, make sure that output is okay. text = 'test show_warning' - with original_warnings.catch_warnings(module=self.module): + with test_support.catch_warning(self.module): self.module.filterwarnings("always", category=UserWarning) del self.module.showwarning with test_support.captured_output('stderr') as stream: @@ -509,46 +488,46 @@ module = py_warnings -class CatchWarningTests(BaseTest): - """Test catch_warnings().""" +class WarningsSupportTests(object): + """Test the warning tools from test support module""" - def test_catch_warnings_restore(self): + def test_catch_warning_restore(self): wmod = self.module orig_filters = wmod.filters orig_showwarning = wmod.showwarning - with wmod.catch_warnings(record=True, module=wmod): + with test_support.catch_warning(wmod): wmod.filters = wmod.showwarning = object() self.assert_(wmod.filters is orig_filters) self.assert_(wmod.showwarning is orig_showwarning) - with wmod.catch_warnings(module=wmod, record=False): + with test_support.catch_warning(wmod, record=False): wmod.filters = wmod.showwarning = object() self.assert_(wmod.filters is orig_filters) self.assert_(wmod.showwarning is orig_showwarning) - def test_catch_warnings_recording(self): + def test_catch_warning_recording(self): wmod = self.module - with wmod.catch_warnings(module=wmod, record=True) as w: - self.assertEqual(w, []) - self.assertRaises(AttributeError, getattr, w, 'message') + with test_support.catch_warning(wmod) as w: + self.assertEqual(w.warnings, []) wmod.simplefilter("always") wmod.warn("foo") - self.assertEqual(str(w[-1].message), "foo") + self.assertEqual(str(w.message), "foo") wmod.warn("bar") - self.assertEqual(str(w[-1].message), "bar") - self.assertEqual(str(w[0].message), "foo") - self.assertEqual(str(w[1].message), "bar") - del w[:] - self.assertEqual(w, []) + self.assertEqual(str(w.message), "bar") + self.assertEqual(str(w.warnings[0].message), "foo") + self.assertEqual(str(w.warnings[1].message), "bar") + w.reset() + self.assertEqual(w.warnings, []) orig_showwarning = wmod.showwarning - with wmod.catch_warnings(module=wmod, record=False) as w: + with test_support.catch_warning(wmod, record=False) as w: self.assert_(w is None) self.assert_(wmod.showwarning is orig_showwarning) -class CCatchWarningTests(CatchWarningTests): + +class CWarningsSupportTests(BaseTest, WarningsSupportTests): module = c_warnings -class PyCatchWarningTests(CatchWarningTests): +class PyWarningsSupportTests(BaseTest, WarningsSupportTests): module = py_warnings @@ -560,24 +539,14 @@ def bad_showwarning(message, category, filename, lineno, file=None): pass - @staticmethod - def ok_showwarning(*args): - pass - def test_deprecation(self): # message, category, filename, lineno[, file[, line]] args = ("message", UserWarning, "file name", 42) - with original_warnings.catch_warnings(module=self.module): + with test_support.catch_warning(self.module): self.module.filterwarnings("error", category=DeprecationWarning) self.module.showwarning = self.bad_showwarning self.assertRaises(DeprecationWarning, self.module.warn_explicit, *args) - self.module.showwarning = self.ok_showwarning - try: - self.module.warn_explicit(*args) - except DeprecationWarning as exc: - self.fail('showwarning(*args) should not trigger a ' - 'DeprecationWarning') class CShowwarningDeprecationTests(ShowwarningDeprecationTests): module = c_warnings @@ -590,14 +559,16 @@ def test_main(): py_warnings.onceregistry.clear() c_warnings.onceregistry.clear() - test_support.run_unittest(CFilterTests, PyFilterTests, - CWarnTests, PyWarnTests, + test_support.run_unittest(CFilterTests, + PyFilterTests, + CWarnTests, + PyWarnTests, CWCmdLineTests, PyWCmdLineTests, _WarningsTests, CWarningsDisplayTests, PyWarningsDisplayTests, - CCatchWarningTests, PyCatchWarningTests, + CWarningsSupportTests, PyWarningsSupportTests, CShowwarningDeprecationTests, - PyShowwarningDeprecationTests, + PyShowwarningDeprecationTests, ) Index: Lib/test/test_macostools.py =================================================================== --- Lib/test/test_macostools.py (revision 66339) +++ Lib/test/test_macostools.py (working copy) @@ -52,7 +52,7 @@ def test_touched(self): # This really only tests that nothing unforeseen happens. import warnings - with warnings.catch_warnings(): + with test_support.catch_warning(): warnings.filterwarnings('ignore', 'macostools.touched*', DeprecationWarning) macostools.touched(test_support.TESTFN) Index: Lib/test/test_hmac.py =================================================================== --- Lib/test/test_hmac.py (revision 66339) +++ Lib/test/test_hmac.py (working copy) @@ -211,7 +211,7 @@ def digest(self): return self._x.digest() - with warnings.catch_warnings(): + with test_support.catch_warning(): warnings.simplefilter('error', RuntimeWarning) try: hmac.HMAC('a', 'b', digestmod=MockCrazyHash) Index: Lib/test/test_py3kwarn.py =================================================================== --- Lib/test/test_py3kwarn.py (revision 66339) +++ Lib/test/test_py3kwarn.py (working copy) @@ -1,6 +1,7 @@ import unittest import sys -from test.test_support import CleanImport, TestSkipped, run_unittest +from test.test_support import (catch_warning, CleanImport, + TestSkipped, run_unittest) import warnings from contextlib import nested @@ -12,11 +13,11 @@ class TestPy3KWarnings(unittest.TestCase): def assertWarning(self, _, warning, expected_message): - self.assertEqual(str(warning[-1].message), expected_message) + self.assertEqual(str(warning.message), expected_message) def test_backquote(self): expected = 'backquote not supported in 3.x; use repr()' - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: exec "`2`" in {} self.assertWarning(None, w, expected) @@ -27,55 +28,71 @@ exec expr in {'f' : f} expected = "assignment to True or False is forbidden in 3.x" - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: safe_exec("True = False") self.assertWarning(None, w, expected) + w.reset() safe_exec("False = True") self.assertWarning(None, w, expected) + w.reset() try: safe_exec("obj.False = True") except NameError: pass self.assertWarning(None, w, expected) + w.reset() try: safe_exec("obj.True = False") except NameError: pass self.assertWarning(None, w, expected) + w.reset() safe_exec("def False(): pass") self.assertWarning(None, w, expected) + w.reset() safe_exec("def True(): pass") self.assertWarning(None, w, expected) + w.reset() safe_exec("class False: pass") self.assertWarning(None, w, expected) + w.reset() safe_exec("class True: pass") self.assertWarning(None, w, expected) + w.reset() safe_exec("def f(True=43): pass") self.assertWarning(None, w, expected) + w.reset() safe_exec("def f(False=None): pass") self.assertWarning(None, w, expected) + w.reset() safe_exec("f(False=True)") self.assertWarning(None, w, expected) + w.reset() safe_exec("f(True=1)") self.assertWarning(None, w, expected) def test_type_inequality_comparisons(self): expected = 'type inequality comparisons not supported in 3.x' - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: self.assertWarning(int < str, w, expected) + w.reset() self.assertWarning(type < object, w, expected) def test_object_inequality_comparisons(self): expected = 'comparing unequal types not supported in 3.x' - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: self.assertWarning(str < [], w, expected) + w.reset() self.assertWarning(object() < (1, 2), w, expected) def test_dict_inequality_comparisons(self): expected = 'dict inequality comparisons not supported in 3.x' - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: self.assertWarning({} < {2:3}, w, expected) + w.reset() self.assertWarning({} <= {}, w, expected) + w.reset() self.assertWarning({} > {2:3}, w, expected) + w.reset() self.assertWarning({2:3} >= {}, w, expected) def test_cell_inequality_comparisons(self): @@ -86,8 +103,9 @@ return g cell0, = f(0).func_closure cell1, = f(1).func_closure - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: self.assertWarning(cell0 == cell1, w, expected) + w.reset() self.assertWarning(cell0 < cell1, w, expected) def test_code_inequality_comparisons(self): @@ -96,10 +114,13 @@ pass def g(x): pass - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: self.assertWarning(f.func_code < g.func_code, w, expected) + w.reset() self.assertWarning(f.func_code <= g.func_code, w, expected) + w.reset() self.assertWarning(f.func_code >= g.func_code, w, expected) + w.reset() self.assertWarning(f.func_code > g.func_code, w, expected) def test_builtin_function_or_method_comparisons(self): @@ -107,10 +128,13 @@ 'inequality comparisons not supported in 3.x') func = eval meth = {}.get - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: self.assertWarning(func < meth, w, expected) + w.reset() self.assertWarning(func > meth, w, expected) + w.reset() self.assertWarning(meth <= func, w, expected) + w.reset() self.assertWarning(meth >= func, w, expected) def test_sort_cmp_arg(self): @@ -118,15 +142,18 @@ lst = range(5) cmp = lambda x,y: -1 - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: self.assertWarning(lst.sort(cmp=cmp), w, expected) + w.reset() self.assertWarning(sorted(lst, cmp=cmp), w, expected) + w.reset() self.assertWarning(lst.sort(cmp), w, expected) + w.reset() self.assertWarning(sorted(lst, cmp), w, expected) def test_sys_exc_clear(self): expected = 'sys.exc_clear() not supported in 3.x; use except clauses' - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: self.assertWarning(sys.exc_clear(), w, expected) def test_methods_members(self): @@ -135,17 +162,17 @@ __methods__ = ['a'] __members__ = ['b'] c = C() - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: self.assertWarning(dir(c), w, expected) def test_softspace(self): expected = 'file.softspace not supported in 3.x' with file(__file__) as f: - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: self.assertWarning(f.softspace, w, expected) def set(): f.softspace = 0 - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: self.assertWarning(set(), w, expected) def test_slice_methods(self): @@ -161,59 +188,60 @@ expected = "in 3.x, __{0}slice__ has been removed; use __{0}item__" for obj in (Spam(), Egg()): - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: self.assertWarning(obj[1:2], w, expected.format('get')) + w.reset() del obj[3:4] self.assertWarning(None, w, expected.format('del')) + w.reset() obj[4:5] = "eggs" self.assertWarning(None, w, expected.format('set')) def test_tuple_parameter_unpacking(self): expected = "tuple parameter unpacking has been removed in 3.x" - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: exec "def f((a, b)): pass" self.assertWarning(None, w, expected) def test_buffer(self): expected = 'buffer() not supported in 3.x' - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: self.assertWarning(buffer('a'), w, expected) def test_file_xreadlines(self): expected = ("f.xreadlines() not supported in 3.x, " "try 'for line in f' instead") with file(__file__) as f: - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: self.assertWarning(f.xreadlines(), w, expected) def test_hash_inheritance(self): - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: # With object as the base class class WarnOnlyCmp(object): def __cmp__(self, other): pass - self.assertEqual(len(w), 1) + self.assertEqual(len(w.warnings), 1) self.assertWarning(None, w, "Overriding __cmp__ blocks inheritance of __hash__ in 3.x") - del w[:] + w.reset() class WarnOnlyEq(object): def __eq__(self, other): pass - self.assertEqual(len(w), 1) + self.assertEqual(len(w.warnings), 1) self.assertWarning(None, w, "Overriding __eq__ blocks inheritance of __hash__ in 3.x") - del w[:] + w.reset() class WarnCmpAndEq(object): def __cmp__(self, other): pass def __eq__(self, other): pass - self.assertEqual(len(w), 2) - self.assertWarning(None, w[:1], + self.assertEqual(len(w.warnings), 2) + self.assertWarning(None, w.warnings[-2], "Overriding __cmp__ blocks inheritance of __hash__ in 3.x") self.assertWarning(None, w, "Overriding __eq__ blocks inheritance of __hash__ in 3.x") - del w[:] + w.reset() class NoWarningOnlyHash(object): def __hash__(self): pass - self.assertEqual(len(w), 0) - del w[:] + self.assertEqual(len(w.warnings), 0) # With an intermediate class in the heirarchy class DefinesAllThree(object): def __cmp__(self, other): pass @@ -221,28 +249,28 @@ def __hash__(self): pass class WarnOnlyCmp(DefinesAllThree): def __cmp__(self, other): pass - self.assertEqual(len(w), 1) + self.assertEqual(len(w.warnings), 1) self.assertWarning(None, w, "Overriding __cmp__ blocks inheritance of __hash__ in 3.x") - del w[:] + w.reset() class WarnOnlyEq(DefinesAllThree): def __eq__(self, other): pass - self.assertEqual(len(w), 1) + self.assertEqual(len(w.warnings), 1) self.assertWarning(None, w, "Overriding __eq__ blocks inheritance of __hash__ in 3.x") - del w[:] + w.reset() class WarnCmpAndEq(DefinesAllThree): def __cmp__(self, other): pass def __eq__(self, other): pass - self.assertEqual(len(w), 2) - self.assertWarning(None, w[:1], + self.assertEqual(len(w.warnings), 2) + self.assertWarning(None, w.warnings[-2], "Overriding __cmp__ blocks inheritance of __hash__ in 3.x") self.assertWarning(None, w, "Overriding __eq__ blocks inheritance of __hash__ in 3.x") - del w[:] + w.reset() class NoWarningOnlyHash(DefinesAllThree): def __hash__(self): pass - self.assertEqual(len(w), 0) + self.assertEqual(len(w.warnings), 0) class TestStdlibRemovals(unittest.TestCase): @@ -282,7 +310,7 @@ def check_removal(self, module_name, optional=False): """Make sure the specified module, when imported, raises a DeprecationWarning and specifies itself in the message.""" - with nested(CleanImport(module_name), warnings.catch_warnings()): + with nested(CleanImport(module_name), catch_warning(record=False)): warnings.filterwarnings("error", ".+ removed", DeprecationWarning, __name__) try: @@ -320,36 +348,36 @@ def dumbo(where, names, args): pass for path_mod in ("ntpath", "macpath", "os2emxpath", "posixpath"): mod = __import__(path_mod) - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: mod.walk("crashers", dumbo, None) - self.assertEquals(str(w[-1].message), msg) + self.assertEquals(str(w.message), msg) def test_commands_members(self): import commands members = {"mk2arg" : 2, "mkarg" : 1, "getstatus" : 1} for name, arg_count in members.items(): - with warnings.catch_warnings(): + with catch_warning(record=False): warnings.filterwarnings("error") func = getattr(commands, name) self.assertRaises(DeprecationWarning, func, *([None]*arg_count)) def test_reduce_move(self): from operator import add - with warnings.catch_warnings(): + with catch_warning(record=False): warnings.filterwarnings("error", "reduce") self.assertRaises(DeprecationWarning, reduce, add, range(10)) def test_mutablestring_removal(self): # UserString.MutableString has been removed in 3.0. import UserString - with warnings.catch_warnings(): + with catch_warning(record=False): warnings.filterwarnings("error", ".*MutableString", DeprecationWarning) self.assertRaises(DeprecationWarning, UserString.MutableString) def test_main(): - with warnings.catch_warnings(): + with catch_warning(): warnings.simplefilter("always") run_unittest(TestPy3KWarnings, TestStdlibRemovals) Index: Lib/test/test_re.py =================================================================== --- Lib/test/test_re.py (revision 66339) +++ Lib/test/test_re.py (working copy) @@ -1,7 +1,7 @@ import sys sys.path = ['.'] + sys.path -from test.test_support import verbose, run_unittest +from test.test_support import verbose, run_unittest, catch_warning import re from re import Scanner import sys, os, traceback @@ -447,7 +447,7 @@ self.pickle_test(cPickle) # old pickles expect the _compile() reconstructor in sre module import warnings - with warnings.catch_warnings(): + with catch_warning(): warnings.filterwarnings("ignore", "The sre module is deprecated", DeprecationWarning) from sre import _compile Index: Lib/test/test_urllibnet.py =================================================================== --- Lib/test/test_urllibnet.py (revision 66339) +++ Lib/test/test_urllibnet.py (working copy) @@ -182,8 +182,8 @@ def test_main(): test_support.requires('network') - from warnings import filterwarnings, catch_warnings - with catch_warnings(): + from warnings import filterwarnings + with test_support.catch_warning(record=False): filterwarnings('ignore', '.*urllib\.urlopen.*Python 3.0', DeprecationWarning) test_support.run_unittest(URLTimeoutTest, Index: Lib/test/test_random.py =================================================================== --- Lib/test/test_random.py (revision 66339) +++ Lib/test/test_random.py (working copy) @@ -191,7 +191,7 @@ def test_bigrand(self): # Verify warnings are raised when randrange is too large for random() - with warnings.catch_warnings(): + with test_support.catch_warning(): warnings.filterwarnings("error", "Underlying random") self.assertRaises(UserWarning, self.gen.randrange, 2**60) Index: Lib/test/test_struct.py =================================================================== --- Lib/test/test_struct.py (revision 66339) +++ Lib/test/test_struct.py (working copy) @@ -4,7 +4,7 @@ import warnings from functools import wraps -from test.test_support import TestFailed, verbose, run_unittest +from test.test_support import TestFailed, verbose, run_unittest, catch_warning import sys ISBIGENDIAN = sys.byteorder == "big" @@ -34,7 +34,7 @@ def with_warning_restore(func): @wraps(func) def decorator(*args, **kw): - with warnings.catch_warnings(): + with catch_warning(): # We need this function to warn every time, so stick an # unqualifed 'always' at the head of the filter list warnings.simplefilter("always") Index: Lib/test/test_import.py =================================================================== --- Lib/test/test_import.py (revision 66339) +++ Lib/test/test_import.py (working copy) @@ -5,7 +5,7 @@ import sys import py_compile import warnings -from test.test_support import unlink, TESTFN, unload, run_unittest +from test.test_support import unlink, TESTFN, unload, run_unittest, catch_warning def remove_files(name): @@ -215,7 +215,7 @@ self.assert_(y is test.test_support, y.__name__) def test_import_initless_directory_warning(self): - with warnings.catch_warnings(): + with catch_warning(): # Just a random non-package directory we always expect to be # somewhere in sys.path... warnings.simplefilter('error', ImportWarning) @@ -279,17 +279,17 @@ check_relative() # Check relative fails with only __package__ wrong ns = dict(__package__='foo', __name__='test.notarealmodule') - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: check_absolute() - self.assert_('foo' in str(w[-1].message)) - self.assertEqual(w[-1].category, RuntimeWarning) + self.assert_('foo' in str(w.message)) + self.assertEqual(w.category, RuntimeWarning) self.assertRaises(SystemError, check_relative) # Check relative fails with __package__ and __name__ wrong ns = dict(__package__='foo', __name__='notarealpkg.notarealmodule') - with warnings.catch_warnings(record=True) as w: + with catch_warning() as w: check_absolute() - self.assert_('foo' in str(w[-1].message)) - self.assertEqual(w[-1].category, RuntimeWarning) + self.assert_('foo' in str(w.message)) + self.assertEqual(w.category, RuntimeWarning) self.assertRaises(SystemError, check_relative) # Check both fail with package set to a non-string ns = dict(__package__=object()) Index: Lib/test/test_structmembers.py =================================================================== --- Lib/test/test_structmembers.py (revision 66339) +++ Lib/test/test_structmembers.py (working copy) @@ -66,35 +66,35 @@ class TestWarnings(unittest.TestCase): def has_warned(self, w): - self.assertEqual(w[-1].category, RuntimeWarning) + self.assertEqual(w.category, RuntimeWarning) def test_byte_max(self): - with warnings.catch_warnings(record=True) as w: + with test_support.catch_warning() as w: ts.T_BYTE = CHAR_MAX+1 self.has_warned(w) def test_byte_min(self): - with warnings.catch_warnings(record=True) as w: + with test_support.catch_warning() as w: ts.T_BYTE = CHAR_MIN-1 self.has_warned(w) def test_ubyte_max(self): - with warnings.catch_warnings(record=True) as w: + with test_support.catch_warning() as w: ts.T_UBYTE = UCHAR_MAX+1 self.has_warned(w) def test_short_max(self): - with warnings.catch_warnings(record=True) as w: + with test_support.catch_warning() as w: ts.T_SHORT = SHRT_MAX+1 self.has_warned(w) def test_short_min(self): - with warnings.catch_warnings(record=True) as w: + with test_support.catch_warning() as w: ts.T_SHORT = SHRT_MIN-1 self.has_warned(w) def test_ushort_max(self): - with warnings.catch_warnings(record=True) as w: + with test_support.catch_warning() as w: ts.T_USHORT = USHRT_MAX+1 self.has_warned(w) Index: Lib/test/test___all__.py =================================================================== --- Lib/test/test___all__.py (revision 66339) +++ Lib/test/test___all__.py (working copy) @@ -1,5 +1,5 @@ import unittest -from test.test_support import run_unittest +from test.test_support import run_unittest, catch_warning import sys import warnings @@ -9,7 +9,7 @@ def check_all(self, modname): names = {} - with warnings.catch_warnings(): + with catch_warning(): warnings.filterwarnings("ignore", ".* (module|package)", DeprecationWarning) try: Index: Lib/test/test_urllib.py =================================================================== --- Lib/test/test_urllib.py (revision 66339) +++ Lib/test/test_urllib.py (working copy) @@ -641,7 +641,7 @@ def test_main(): import warnings - with warnings.catch_warnings(): + with test_support.catch_warning(record=False): warnings.filterwarnings('ignore', ".*urllib\.urlopen.*Python 3.0", DeprecationWarning) test_support.run_unittest( Index: Lib/test/test_userstring.py =================================================================== --- Lib/test/test_userstring.py (revision 66339) +++ Lib/test/test_userstring.py (working copy) @@ -135,7 +135,7 @@ self.assertEqual(s, "") def test_main(): - with warnings.catch_warnings(): + with test_support.catch_warning(record=False): warnings.filterwarnings("ignore", ".*MutableString", DeprecationWarning) test_support.run_unittest(UserStringTest, MutableStringTest) Index: Lib/test/test_support.py =================================================================== --- Lib/test/test_support.py (revision 66339) +++ Lib/test/test_support.py (working copy) @@ -18,7 +18,7 @@ "is_resource_enabled", "requires", "find_unused_port", "bind_port", "fcmp", "have_unicode", "is_jython", "TESTFN", "HOST", "FUZZ", "findfile", "verify", "vereq", "sortdict", "check_syntax_error", - "open_urlresource", "CleanImport", + "open_urlresource", "WarningMessage", "catch_warning", "CleanImport", "EnvironmentVarGuard", "captured_output", "captured_stdout", "TransientResource", "transient_internet", "run_with_locale", "set_memlimit", "bigmemtest", "bigaddrspacetest", @@ -52,7 +52,7 @@ def import_module(name, deprecated=False): """Import the module to be tested, raising TestSkipped if it is not available.""" - with warnings.catch_warnings(): + with catch_warning(record=False): if deprecated: warnings.filterwarnings("ignore", ".+ (module|package)", DeprecationWarning) @@ -381,6 +381,73 @@ return open(fn) +class WarningMessage(object): + "Holds the result of a single showwarning() call" + _WARNING_DETAILS = "message category filename lineno line".split() + def __init__(self, message, category, filename, lineno, line=None): + for attr in self._WARNING_DETAILS: + setattr(self, attr, locals()[attr]) + self._category_name = category.__name__ if category else None + + def __str__(self): + return ("{message : %r, category : %r, filename : %r, lineno : %s, " + "line : %r}" % (self.message, self._category_name, + self.filename, self.lineno, self.line)) + +class WarningRecorder(object): + "Records the result of any showwarning calls" + def __init__(self): + self.warnings = [] + self._set_last(None) + + def _showwarning(self, message, category, filename, lineno, + file=None, line=None): + wm = WarningMessage(message, category, filename, lineno, line) + self.warnings.append(wm) + self._set_last(wm) + + def _set_last(self, last_warning): + if last_warning is None: + for attr in WarningMessage._WARNING_DETAILS: + setattr(self, attr, None) + else: + for attr in WarningMessage._WARNING_DETAILS: + setattr(self, attr, getattr(last_warning, attr)) + + def reset(self): + self.warnings = [] + self._set_last(None) + + def __str__(self): + return '[%s]' % (', '.join(map(str, self.warnings))) + +@contextlib.contextmanager +def catch_warning(module=warnings, record=True): + """Guard the warnings filter from being permanently changed and + optionally record the details of any warnings that are issued. + + Use like this: + + with catch_warning() as w: + warnings.warn("foo") + assert str(w.message) == "foo" + """ + original_filters = module.filters + original_showwarning = module.showwarning + if record: + recorder = WarningRecorder() + module.showwarning = recorder._showwarning + else: + recorder = None + try: + # Replace the filters with a copy of the original + module.filters = module.filters[:] + yield recorder + finally: + module.showwarning = original_showwarning + module.filters = original_filters + + class CleanImport(object): """Context manager to force import to return a new module reference.