summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/output/test_warnings10
-rw-r--r--Lib/test/test_warnings.py53
-rw-r--r--Lib/warnings.py71
3 files changed, 91 insertions, 43 deletions
diff --git a/Lib/test/output/test_warnings b/Lib/test/output/test_warnings
new file mode 100644
index 0000000..9b45e42
--- /dev/null
+++ b/Lib/test/output/test_warnings
@@ -0,0 +1,10 @@
+test_warnings
+('ignore', False, 'FutureWarning', False, 0)
+('ignore', True, 'OverflowWarning', True, 0)
+('ignore', True, 'PendingDeprecationWarning', True, 0)
+Lib/test/test_warnings.py:31: UserWarning: hello world
+Lib/test/test_warnings.py:32: UserWarning: hello world
+Lib/test/test_warnings.py:33: DeprecationWarning: hello world
+Lib/test/test_warnings.py:35: UserWarning: hello world
+Caught UserWarning: hello world
+Caught AssertionError: invalid action: 'booh'
diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py
new file mode 100644
index 0000000..9cd3c30
--- /dev/null
+++ b/Lib/test/test_warnings.py
@@ -0,0 +1,53 @@
+import warnings
+
+# The warnings module isn't easily tested, because it relies on module
+# globals to store configuration information. We need to extract the
+# current settings to avoid bashing them while running tests.
+
+_filters = []
+_showwarning = None
+
+def showwarning(message, category, filename, lineno, file=None):
+ i = filename.find("Lib/")
+ filename = filename[i:]
+ print "%s:%s: %s: %s" % (filename, lineno, category.__name__, message)
+
+def monkey():
+ global _filters, _showwarning
+ _filters = warnings.filters[:]
+ _showwarning = warnings.showwarning
+ warnings.showwarning = showwarning
+
+def unmonkey():
+ warnings.filters = _filters[:]
+ warnings.showwarning = _showwarning
+
+def test():
+ for item in warnings.filters:
+ print (item[0], item[1] is None, item[2].__name__, item[3] is None,
+ item[4])
+ hello = "hello world"
+ for i in range(4):
+ warnings.warn(hello)
+ warnings.warn(hello, UserWarning)
+ warnings.warn(hello, DeprecationWarning)
+ for i in range(3):
+ warnings.warn(hello)
+ warnings.filterwarnings("error", "", Warning, "", 0)
+ try:
+ warnings.warn(hello)
+ except Exception, msg:
+ print "Caught", msg.__class__.__name__ + ":", msg
+ else:
+ print "No exception"
+ warnings.resetwarnings()
+ try:
+ warnings.filterwarnings("booh", "", Warning, "", 0)
+ except Exception, msg:
+ print "Caught", msg.__class__.__name__ + ":", msg
+ else:
+ print "No exception"
+
+monkey()
+test()
+unmonkey()
diff --git a/Lib/warnings.py b/Lib/warnings.py
index 1c55fb2..c2bc06e 100644
--- a/Lib/warnings.py
+++ b/Lib/warnings.py
@@ -9,8 +9,16 @@ import linecache
__all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
"resetwarnings"]
-defaultaction = "default"
+# filters contains a sequence of filter 5-tuples
+# The components of the 5-tuple are:
+# - an action: error, ignore, always, default, module, or once
+# - a compiled regex that must match the warning message
+# - a class representing the warning category
+# - a compiled regex that must match the module that is being warned
+# - a line number for the line being warning, or 0 to mean any line
+# If either if the compiled regexs are None, match anything.
filters = []
+defaultaction = "default"
onceregistry = {}
def warn(message, category=None, stacklevel=1):
@@ -69,9 +77,9 @@ def warn_explicit(message, category, filename, lineno,
# Search the filters
for item in filters:
action, msg, cat, mod, ln = item
- if (msg.match(text) and
+ if ((msg is None or msg.match(text)) and
issubclass(category, cat) and
- mod.match(module) and
+ (msg is None or mod.match(module)) and
(ln == 0 or lineno == ln)):
break
else:
@@ -145,6 +153,21 @@ def filterwarnings(action, message="", category=Warning, module="", lineno=0,
else:
filters.insert(0, item)
+def simplefilter(action, category=Warning, lineno=0, append=0):
+ """Insert a simple entry into the list of warnings filters (at the front).
+
+ A simple filter matches all modules and messages.
+ """
+ assert action in ("error", "ignore", "always", "default", "module",
+ "once"), "invalid action: %s" % `action`
+ assert isinstance(lineno, int) and lineno >= 0, \
+ "lineno must be an int >= 0"
+ item = (action, None, category, None, lineno)
+ if append:
+ filters.append(item)
+ else:
+ filters.insert(0, item)
+
def resetwarnings():
"""Clear the list of warning filters, so that no filters are active."""
filters[:] = []
@@ -225,44 +248,6 @@ def _getcategory(category):
raise _OptionError("invalid warning category: %s" % `category`)
return cat
-# Self-test
-def _test():
- import getopt
- testoptions = []
- try:
- opts, args = getopt.getopt(sys.argv[1:], "W:")
- except getopt.error, msg:
- print >>sys.stderr, msg
- return
- for o, a in opts:
- testoptions.append(a)
- try:
- _processoptions(testoptions)
- except _OptionError, msg:
- print >>sys.stderr, msg
- return
- for item in filters: print item
- hello = "hello world"
- warn(hello); warn(hello); warn(hello); warn(hello)
- warn(hello, UserWarning)
- warn(hello, DeprecationWarning)
- for i in range(3):
- warn(hello)
- filterwarnings("error", "", Warning, "", 0)
- try:
- warn(hello)
- except Exception, msg:
- print "Caught", msg.__class__.__name__ + ":", msg
- else:
- print "No exception"
- resetwarnings()
- try:
- filterwarnings("booh", "", Warning, "", 0)
- except Exception, msg:
- print "Caught", msg.__class__.__name__ + ":", msg
- else:
- print "No exception"
-
# Module initialization
if __name__ == "__main__":
import __main__
@@ -270,5 +255,5 @@ if __name__ == "__main__":
_test()
else:
_processoptions(sys.warnoptions)
- filterwarnings("ignore", category=OverflowWarning, append=1)
- filterwarnings("ignore", category=PendingDeprecationWarning, append=1)
+ simplefilter("ignore", category=OverflowWarning, append=1)
+ simplefilter("ignore", category=PendingDeprecationWarning, append=1)