summaryrefslogtreecommitdiffstats
path: root/Lib/test/support.py
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2008-07-13 12:25:08 (GMT)
committerNick Coghlan <ncoghlan@gmail.com>2008-07-13 12:25:08 (GMT)
commitb130493834e5bd807ab80dcd8b417d7623baca24 (patch)
tree3842a93fe70989950ba9db64bc8d4a5543286e59 /Lib/test/support.py
parent628b1b3659d9db96210cb599579b79625eed1488 (diff)
downloadcpython-b130493834e5bd807ab80dcd8b417d7623baca24.zip
cpython-b130493834e5bd807ab80dcd8b417d7623baca24.tar.gz
cpython-b130493834e5bd807ab80dcd8b417d7623baca24.tar.bz2
Make test.test_support.catch_warnings more robust as discussed on python-dev. Also add explicit tests for it to test_warnings. (forward port of r64910 from trunk)
Diffstat (limited to 'Lib/test/support.py')
-rw-r--r--Lib/test/support.py71
1 files changed, 44 insertions, 27 deletions
diff --git a/Lib/test/support.py b/Lib/test/support.py
index c6ce760..d026984 100644
--- a/Lib/test/support.py
+++ b/Lib/test/support.py
@@ -368,36 +368,49 @@ def open_urlresource(url, *args, **kw):
class WarningMessage(object):
- "Holds the result of the latest showwarning() call"
+ "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.message = None
- self.category = None
- self.filename = None
- self.lineno = None
-
- def _showwarning(self, message, category, filename, lineno, file=None,
- line=None):
- self.message = message
- self.category = category
- self.filename = filename
- self.lineno = lineno
- self.line = line
+ 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._showwarning(*((None,)*6))
+ self.warnings = []
+ self._set_last(None)
def __str__(self):
- return ("{message : %r, category : %r, filename : %r, lineno : %s, "
- "line : %r}" % (self.message,
- self.category.__name__ if self.category else None,
- self.filename, self.lineno, self.line))
-
+ 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 record the
- data of the last warning that has been issued.
+ """Guard the warnings filter from being permanently changed and
+ optionally record the details of any warnings that are issued.
Use like this:
@@ -405,13 +418,17 @@ def catch_warning(module=warnings, record=True):
warnings.warn("foo")
assert str(w.message) == "foo"
"""
- original_filters = module.filters[:]
+ original_filters = module.filters
original_showwarning = module.showwarning
if record:
- warning_obj = WarningMessage()
- module.showwarning = warning_obj._showwarning
+ recorder = WarningRecorder()
+ module.showwarning = recorder._showwarning
+ else:
+ recorder = None
try:
- yield warning_obj if record else None
+ # Replace the filters with a copy of the original
+ module.filters = module.filters[:]
+ yield recorder
finally:
module.showwarning = original_showwarning
module.filters = original_filters
@@ -421,7 +438,7 @@ class CleanImport(object):
"""Context manager to force import to return a new module reference.
This is useful for testing module-level behaviours, such as
- the emission of a DepreciationWarning on import.
+ the emission of a DeprecationWarning on import.
Use like this: