diff options
author | Benjamin Peterson <benjamin@python.org> | 2008-10-16 23:24:44 (GMT) |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2008-10-16 23:24:44 (GMT) |
commit | fcf5d639f508b5a7ebf42d858390a6bd3bbb2c61 (patch) | |
tree | 193a1dd1d41e2403c61cd021409c28b843760cc6 /Lib | |
parent | d31fdc547b1805516f6013af672e43cc66bd8c22 (diff) | |
download | cpython-fcf5d639f508b5a7ebf42d858390a6bd3bbb2c61.zip cpython-fcf5d639f508b5a7ebf42d858390a6bd3bbb2c61.tar.gz cpython-fcf5d639f508b5a7ebf42d858390a6bd3bbb2c61.tar.bz2 |
forward port r66386
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/support.py | 32 | ||||
-rw-r--r-- | Lib/test/test_import.py | 13 | ||||
-rw-r--r-- | Lib/test/test_structmembers.py | 14 | ||||
-rw-r--r-- | Lib/test/test_sundry.py | 2 | ||||
-rw-r--r-- | Lib/test/test_threading.py | 2 | ||||
-rw-r--r-- | Lib/test/test_warnings.py | 63 | ||||
-rw-r--r-- | Lib/warnings.py | 15 |
7 files changed, 111 insertions, 30 deletions
diff --git a/Lib/test/support.py b/Lib/test/support.py index a23c99b..5f8b1ba 100644 --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -19,7 +19,7 @@ __all__ = ["Error", "TestFailed", "TestSkipped", "ResourceDenied", "import_modul "is_resource_enabled", "requires", "find_unused_port", "bind_port", "fcmp", "is_jython", "TESTFN", "HOST", "FUZZ", "findfile", "verify", "vereq", "sortdict", "check_syntax_error", "open_urlresource", - "catch_warning", "CleanImport", "EnvironmentVarGuard", + "check_warnings", "CleanImport", "EnvironmentVarGuard", "TransientResource", "captured_output", "captured_stdout", "TransientResource", "transient_internet", "run_with_locale", "set_memlimit", "bigmemtest", "bigaddrspacetest", "BasicTestRunner", @@ -53,7 +53,7 @@ class ResourceDenied(TestSkipped): def import_module(name, deprecated=False): """Import the module to be tested, raising TestSkipped if it is not available.""" - with catch_warning(record=False): + with warnings.catch_warnings(): if deprecated: warnings.filterwarnings("ignore", ".+ (module|package)", DeprecationWarning) @@ -368,17 +368,27 @@ def open_urlresource(url, *args, **kw): return open(fn, *args, **kw) -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. +class WarningsRecorder(object): + """Convenience wrapper for the warnings list returned on + entry to the warnings.catch_warnings() context manager. + """ + def __init__(self, warnings_list): + self.warnings = warnings_list - Use like this: + def __getattr__(self, attr): + if self.warnings: + return getattr(self.warnings[-1], attr) + elif attr in warnings.WarningMessage._WARNING_DETAILS: + return None + raise AttributeError("%r has no attribute %r" % (self, attr)) - with catch_warning() as w: - warnings.warn("foo") - assert str(w.message) == "foo" - """ - return warnings.catch_warnings(record=record, module=module) + def reset(self): + del self.warnings[:] + +@contextlib.contextmanager +def check_warnings(): + with warnings.catch_warnings(record=True) as w: + yield WarningsRecorder(w) class CleanImport(object): diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py index 0dbbbf0..6598d4e 100644 --- a/Lib/test/test_import.py +++ b/Lib/test/test_import.py @@ -266,21 +266,24 @@ class RelativeImport(unittest.TestCase): self.assertTrue(hasattr(relimport, "RelativeImport")) def test_issue3221(self): + # Note for mergers: the 'absolute' tests from the 2.x branch + # are missing in Py3k because implicit relative imports are + # a thing of the past def check_relative(): exec("from . import relimport", ns) - # Check both OK with __package__ and __name__ correct + # Check relative import OK with __package__ and __name__ correct ns = dict(__package__='test', __name__='test.notarealmodule') check_relative() - # Check both OK with only __name__ wrong + # Check relative import OK with only __name__ wrong ns = dict(__package__='test', __name__='notarealpkg.notarealmodule') check_relative() - # Check relative fails with only __package__ wrong + # Check relative import fails with only __package__ wrong ns = dict(__package__='foo', __name__='test.notarealmodule') self.assertRaises(SystemError, check_relative) - # Check relative fails with __package__ and __name__ wrong + # Check relative import fails with __package__ and __name__ wrong ns = dict(__package__='foo', __name__='notarealpkg.notarealmodule') self.assertRaises(SystemError, check_relative) - # Check both fail with package set to a non-string + # Check relative import fails with package set to a non-string ns = dict(__package__=object()) self.assertRaises(ValueError, check_relative) diff --git a/Lib/test/test_structmembers.py b/Lib/test/test_structmembers.py index 878223a..93e040c 100644 --- a/Lib/test/test_structmembers.py +++ b/Lib/test/test_structmembers.py @@ -66,35 +66,35 @@ class ReadWriteTests(unittest.TestCase): 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 support.check_warnings() 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 support.check_warnings() 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 support.check_warnings() 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 support.check_warnings() 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 support.check_warnings() 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 support.check_warnings() as w: ts.T_USHORT = USHRT_MAX+1 self.has_warned(w) diff --git a/Lib/test/test_sundry.py b/Lib/test/test_sundry.py index 6b425c6..49813a3 100644 --- a/Lib/test/test_sundry.py +++ b/Lib/test/test_sundry.py @@ -7,7 +7,7 @@ import warnings class TestUntestedModules(unittest.TestCase): def test_at_least_import_untested_modules(self): - with warnings.catch_warnings(record=True): + with warnings.catch_warnings(): import aifc import bdb import cgitb diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index f26e7bb..956672d 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -1,7 +1,7 @@ # Very rudimentary test of threading module import test.support -from test.support import verbose, catch_warning +from test.support import verbose import random import re import sys diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py index 199e6fc..4b6feb3 100644 --- a/Lib/test/test_warnings.py +++ b/Lib/test/test_warnings.py @@ -214,7 +214,8 @@ class WarnTests(unittest.TestCase): def test_warn_nonstandard_types(self): # warn() should handle non-standard types without issue. for ob in (Warning, None, 42): - with support.catch_warning(self.module) as w: + with original_warnings.catch_warnings(record=True, + module=self.module) as w: self.module.warn(ob) # Don't directly compare objects since # ``Warning() != Warning()``. @@ -526,19 +527,23 @@ class CatchWarningTests(BaseTest): wmod = self.module orig_filters = wmod.filters orig_showwarning = wmod.showwarning - with support.catch_warning(module=wmod): + # Ensure both showwarning and filters are restored when recording + with wmod.catch_warnings(module=wmod, record=True): wmod.filters = wmod.showwarning = object() self.assert_(wmod.filters is orig_filters) self.assert_(wmod.showwarning is orig_showwarning) - with support.catch_warning(module=wmod, record=False): + # Same test, but with recording disabled + with wmod.catch_warnings(module=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): wmod = self.module - with support.catch_warning(module=wmod) as w: + # Ensure warnings are recorded when requested + with wmod.catch_warnings(module=wmod, record=True) as w: self.assertEqual(w, []) + self.assert_(type(w) is list) wmod.simplefilter("always") wmod.warn("foo") self.assertEqual(str(w[-1].message), "foo") @@ -548,11 +553,59 @@ class CatchWarningTests(BaseTest): self.assertEqual(str(w[1].message), "bar") del w[:] self.assertEqual(w, []) + # Ensure warnings are not recorded when not requested orig_showwarning = wmod.showwarning - with support.catch_warning(module=wmod, record=False) as w: + with wmod.catch_warnings(module=wmod, record=False) as w: self.assert_(w is None) self.assert_(wmod.showwarning is orig_showwarning) + def test_catch_warnings_reentry_guard(self): + wmod = self.module + # Ensure catch_warnings is protected against incorrect usage + x = wmod.catch_warnings(module=wmod, record=True) + self.assertRaises(RuntimeError, x.__exit__) + with x: + self.assertRaises(RuntimeError, x.__enter__) + # Same test, but with recording disabled + x = wmod.catch_warnings(module=wmod, record=False) + self.assertRaises(RuntimeError, x.__exit__) + with x: + self.assertRaises(RuntimeError, x.__enter__) + + def test_catch_warnings_defaults(self): + wmod = self.module + orig_filters = wmod.filters + orig_showwarning = wmod.showwarning + # Ensure default behaviour is not to record warnings + with wmod.catch_warnings(module=wmod) as w: + self.assert_(w is None) + self.assert_(wmod.showwarning is orig_showwarning) + self.assert_(wmod.filters is not orig_filters) + self.assert_(wmod.filters is orig_filters) + if wmod is sys.modules['warnings']: + # Ensure the default module is this one + with wmod.catch_warnings() as w: + self.assert_(w is None) + self.assert_(wmod.showwarning is orig_showwarning) + self.assert_(wmod.filters is not orig_filters) + self.assert_(wmod.filters is orig_filters) + + def test_check_warnings(self): + # Explicit tests for the test.support convenience wrapper + wmod = self.module + if wmod is sys.modules['warnings']: + with support.check_warnings() as w: + self.assertEqual(w.warnings, []) + wmod.simplefilter("always") + wmod.warn("foo") + self.assertEqual(str(w.message), "foo") + wmod.warn("bar") + 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, []) + class CCatchWarningTests(CatchWarningTests): module = c_warnings diff --git a/Lib/warnings.py b/Lib/warnings.py index 0e147db..b87d1be 100644 --- a/Lib/warnings.py +++ b/Lib/warnings.py @@ -301,8 +301,21 @@ class catch_warnings(object): """ self._record = record self._module = sys.modules['warnings'] if module is None else module + self._entered = False + + def __repr__(self): + args = [] + if self._record: + args.append("record=True") + if self._module is not sys.modules['warnings']: + args.append("module=%r" % self._module) + name = type(self).__name__ + return "%s(%s)" % (name, ", ".join(args)) def __enter__(self): + if self._entered: + raise RuntimeError("Cannot enter %r twice" % self) + self._entered = True self._filters = self._module.filters self._module.filters = self._filters[:] self._showwarning = self._module.showwarning @@ -316,6 +329,8 @@ class catch_warnings(object): return None def __exit__(self, *exc_info): + if not self._entered: + raise RuntimeError("Cannot exit %r without entering first" % self) self._module.filters = self._filters self._module.showwarning = self._showwarning |