Skip to content

Commit 8501466

Browse files
committed
Change warnings to avoid importing re module during startup.
Add API function simplefilter() that does not create or install regular expressions to match message or module. Extend the filters data structure to store None as an alternative to re.compile(""). Move the _test() function to test_warnings and add some code to try and avoid disturbing the global state of the warnings module.
1 parent 1e5fc55 commit 8501466

File tree

3 files changed

+91
-43
lines changed

3 files changed

+91
-43
lines changed

Lib/test/output/test_warnings

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
test_warnings
2+
('ignore', False, 'FutureWarning', False, 0)
3+
('ignore', True, 'OverflowWarning', True, 0)
4+
('ignore', True, 'PendingDeprecationWarning', True, 0)
5+
Lib/test/test_warnings.py:31: UserWarning: hello world
6+
Lib/test/test_warnings.py:32: UserWarning: hello world
7+
Lib/test/test_warnings.py:33: DeprecationWarning: hello world
8+
Lib/test/test_warnings.py:35: UserWarning: hello world
9+
Caught UserWarning: hello world
10+
Caught AssertionError: invalid action: 'booh'

Lib/test/test_warnings.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import warnings
2+
3+
# The warnings module isn't easily tested, because it relies on module
4+
# globals to store configuration information. We need to extract the
5+
# current settings to avoid bashing them while running tests.
6+
7+
_filters = []
8+
_showwarning = None
9+
10+
def showwarning(message, category, filename, lineno, file=None):
11+
i = filename.find("Lib/")
12+
filename = filename[i:]
13+
print "%s:%s: %s: %s" % (filename, lineno, category.__name__, message)
14+
15+
def monkey():
16+
global _filters, _showwarning
17+
_filters = warnings.filters[:]
18+
_showwarning = warnings.showwarning
19+
warnings.showwarning = showwarning
20+
21+
def unmonkey():
22+
warnings.filters = _filters[:]
23+
warnings.showwarning = _showwarning
24+
25+
def test():
26+
for item in warnings.filters:
27+
print (item[0], item[1] is None, item[2].__name__, item[3] is None,
28+
item[4])
29+
hello = "hello world"
30+
for i in range(4):
31+
warnings.warn(hello)
32+
warnings.warn(hello, UserWarning)
33+
warnings.warn(hello, DeprecationWarning)
34+
for i in range(3):
35+
warnings.warn(hello)
36+
warnings.filterwarnings("error", "", Warning, "", 0)
37+
try:
38+
warnings.warn(hello)
39+
except Exception, msg:
40+
print "Caught", msg.__class__.__name__ + ":", msg
41+
else:
42+
print "No exception"
43+
warnings.resetwarnings()
44+
try:
45+
warnings.filterwarnings("booh", "", Warning, "", 0)
46+
except Exception, msg:
47+
print "Caught", msg.__class__.__name__ + ":", msg
48+
else:
49+
print "No exception"
50+
51+
monkey()
52+
test()
53+
unmonkey()

Lib/warnings.py

Lines changed: 28 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,16 @@
99
__all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
1010
"resetwarnings"]
1111

12-
defaultaction = "default"
12+
# filters contains a sequence of filter 5-tuples
13+
# The components of the 5-tuple are:
14+
# - an action: error, ignore, always, default, module, or once
15+
# - a compiled regex that must match the warning message
16+
# - a class representing the warning category
17+
# - a compiled regex that must match the module that is being warned
18+
# - a line number for the line being warning, or 0 to mean any line
19+
# If either if the compiled regexs are None, match anything.
1320
filters = []
21+
defaultaction = "default"
1422
onceregistry = {}
1523

1624
def warn(message, category=None, stacklevel=1):
@@ -69,9 +77,9 @@ def warn_explicit(message, category, filename, lineno,
6977
# Search the filters
7078
for item in filters:
7179
action, msg, cat, mod, ln = item
72-
if (msg.match(text) and
80+
if ((msg is None or msg.match(text)) and
7381
issubclass(category, cat) and
74-
mod.match(module) and
82+
(msg is None or mod.match(module)) and
7583
(ln == 0 or lineno == ln)):
7684
break
7785
else:
@@ -145,6 +153,21 @@ def filterwarnings(action, message="", category=Warning, module="", lineno=0,
145153
else:
146154
filters.insert(0, item)
147155

156+
def simplefilter(action, category=Warning, lineno=0, append=0):
157+
"""Insert a simple entry into the list of warnings filters (at the front).
158+
159+
A simple filter matches all modules and messages.
160+
"""
161+
assert action in ("error", "ignore", "always", "default", "module",
162+
"once"), "invalid action: %s" % `action`
163+
assert isinstance(lineno, int) and lineno >= 0, \
164+
"lineno must be an int >= 0"
165+
item = (action, None, category, None, lineno)
166+
if append:
167+
filters.append(item)
168+
else:
169+
filters.insert(0, item)
170+
148171
def resetwarnings():
149172
"""Clear the list of warning filters, so that no filters are active."""
150173
filters[:] = []
@@ -225,50 +248,12 @@ def _getcategory(category):
225248
raise _OptionError("invalid warning category: %s" % `category`)
226249
return cat
227250

228-
# Self-test
229-
def _test():
230-
import getopt
231-
testoptions = []
232-
try:
233-
opts, args = getopt.getopt(sys.argv[1:], "W:")
234-
except getopt.error, msg:
235-
print >>sys.stderr, msg
236-
return
237-
for o, a in opts:
238-
testoptions.append(a)
239-
try:
240-
_processoptions(testoptions)
241-
except _OptionError, msg:
242-
print >>sys.stderr, msg
243-
return
244-
for item in filters: print item
245-
hello = "hello world"
246-
warn(hello); warn(hello); warn(hello); warn(hello)
247-
warn(hello, UserWarning)
248-
warn(hello, DeprecationWarning)
249-
for i in range(3):
250-
warn(hello)
251-
filterwarnings("error", "", Warning, "", 0)
252-
try:
253-
warn(hello)
254-
except Exception, msg:
255-
print "Caught", msg.__class__.__name__ + ":", msg
256-
else:
257-
print "No exception"
258-
resetwarnings()
259-
try:
260-
filterwarnings("booh", "", Warning, "", 0)
261-
except Exception, msg:
262-
print "Caught", msg.__class__.__name__ + ":", msg
263-
else:
264-
print "No exception"
265-
266251
# Module initialization
267252
if __name__ == "__main__":
268253
import __main__
269254
sys.modules['warnings'] = __main__
270255
_test()
271256
else:
272257
_processoptions(sys.warnoptions)
273-
filterwarnings("ignore", category=OverflowWarning, append=1)
274-
filterwarnings("ignore", category=PendingDeprecationWarning, append=1)
258+
simplefilter("ignore", category=OverflowWarning, append=1)
259+
simplefilter("ignore", category=PendingDeprecationWarning, append=1)

0 commit comments

Comments
 (0)