mirror of
https://github.com/python/cpython.git
synced 2025-07-28 21:55:21 +00:00
Move test.test_support.catch_warning() to the warnings module, rename it
catch_warnings(), and clean up the API. While expanding the test suite, a bug was found where a warning about the 'line' argument to showwarning() was not letting functions with '*args' go without a warning. Closes issue 3602. Code review by Benjamin Peterson.
This commit is contained in:
parent
86533776c2
commit
1eaf0742d8
11 changed files with 208 additions and 126 deletions
|
@ -18,7 +18,7 @@ __all__ = ["Error", "TestFailed", "TestSkipped", "ResourceDenied", "import_modul
|
|||
"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", "WarningMessage", "catch_warning", "CleanImport",
|
||||
"open_urlresource", "catch_warning", "CleanImport",
|
||||
"EnvironmentVarGuard", "captured_output",
|
||||
"captured_stdout", "TransientResource", "transient_internet",
|
||||
"run_with_locale", "set_memlimit", "bigmemtest", "bigaddrspacetest",
|
||||
|
@ -381,71 +381,8 @@ def open_urlresource(url):
|
|||
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
|
||||
return warnings.catch_warnings(record=record, module=module)
|
||||
|
||||
|
||||
class CleanImport(object):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue