blob: c2bc06ee704878bd6d7d95db1d3c192a36c85337 [file] [log] [blame]
Guido van Rossum2a862c62000-12-15 21:59:53 +00001"""Python part of the warnings subsystem."""
2
Mark Hammonda43fd0c2003-02-19 00:33:33 +00003# Note: function level imports should *not* be used
4# in this module as it may cause import lock deadlock.
5# See bug 683658.
Skip Montanarod8f21202003-05-14 17:33:53 +00006import sys, types
Mark Hammonda43fd0c2003-02-19 00:33:33 +00007import linecache
Guido van Rossum2a862c62000-12-15 21:59:53 +00008
Skip Montanaro40fc1602001-03-01 04:27:19 +00009__all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
10 "resetwarnings"]
11
Jeremy Hylton85014662003-07-11 15:37:59 +000012# 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.
Guido van Rossum2a862c62000-12-15 21:59:53 +000020filters = []
Jeremy Hylton85014662003-07-11 15:37:59 +000021defaultaction = "default"
Guido van Rossum2a862c62000-12-15 21:59:53 +000022onceregistry = {}
23
24def warn(message, category=None, stacklevel=1):
25 """Issue a warning, or maybe ignore it or raise an exception."""
Walter Dörwaldb25c2b02002-03-21 10:38:40 +000026 # Check if message is already a Warning object
27 if isinstance(message, Warning):
Tim Peters863ac442002-04-16 01:38:40 +000028 category = message.__class__
Guido van Rossum2a862c62000-12-15 21:59:53 +000029 # Check category argument
30 if category is None:
31 category = UserWarning
32 assert issubclass(category, Warning)
33 # Get context information
34 try:
35 caller = sys._getframe(stacklevel)
36 except ValueError:
37 globals = sys.__dict__
38 lineno = 1
39 else:
40 globals = caller.f_globals
41 lineno = caller.f_lineno
Raymond Hettinger54f02222002-06-01 14:18:47 +000042 if '__name__' in globals:
Guido van Rossum8031bbe2001-08-31 17:46:35 +000043 module = globals['__name__']
44 else:
45 module = "<string>"
Guido van Rossum2a862c62000-12-15 21:59:53 +000046 filename = globals.get('__file__')
47 if filename:
48 fnl = filename.lower()
49 if fnl.endswith(".pyc") or fnl.endswith(".pyo"):
50 filename = filename[:-1]
51 else:
52 if module == "__main__":
53 filename = sys.argv[0]
54 if not filename:
55 filename = module
Guido van Rossum2a862c62000-12-15 21:59:53 +000056 registry = globals.setdefault("__warningregistry__", {})
Guido van Rossum9e263182001-02-28 21:43:40 +000057 warn_explicit(message, category, filename, lineno, module, registry)
58
59def warn_explicit(message, category, filename, lineno,
60 module=None, registry=None):
61 if module is None:
62 module = filename
63 if module[-3:].lower() == ".py":
64 module = module[:-3] # XXX What about leading pathname?
65 if registry is None:
66 registry = {}
Walter Dörwaldb25c2b02002-03-21 10:38:40 +000067 if isinstance(message, Warning):
Tim Peters863ac442002-04-16 01:38:40 +000068 text = str(message)
69 category = message.__class__
Walter Dörwaldb25c2b02002-03-21 10:38:40 +000070 else:
Tim Peters863ac442002-04-16 01:38:40 +000071 text = message
72 message = category(message)
Walter Dörwaldb25c2b02002-03-21 10:38:40 +000073 key = (text, category, lineno)
Guido van Rossum3756fa32001-02-28 22:26:36 +000074 # Quick test for common case
Guido van Rossum2a862c62000-12-15 21:59:53 +000075 if registry.get(key):
76 return
77 # Search the filters
78 for item in filters:
79 action, msg, cat, mod, ln = item
Jeremy Hylton85014662003-07-11 15:37:59 +000080 if ((msg is None or msg.match(text)) and
Guido van Rossum2a862c62000-12-15 21:59:53 +000081 issubclass(category, cat) and
Jeremy Hylton85014662003-07-11 15:37:59 +000082 (msg is None or mod.match(module)) and
Guido van Rossum2a862c62000-12-15 21:59:53 +000083 (ln == 0 or lineno == ln)):
84 break
85 else:
86 action = defaultaction
87 # Early exit actions
88 if action == "ignore":
89 registry[key] = 1
90 return
91 if action == "error":
Walter Dörwaldb25c2b02002-03-21 10:38:40 +000092 raise message
Guido van Rossum2a862c62000-12-15 21:59:53 +000093 # Other actions
94 if action == "once":
95 registry[key] = 1
Walter Dörwaldb25c2b02002-03-21 10:38:40 +000096 oncekey = (text, category)
Guido van Rossum2a862c62000-12-15 21:59:53 +000097 if onceregistry.get(oncekey):
98 return
99 onceregistry[oncekey] = 1
100 elif action == "always":
101 pass
102 elif action == "module":
103 registry[key] = 1
Walter Dörwaldb25c2b02002-03-21 10:38:40 +0000104 altkey = (text, category, 0)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000105 if registry.get(altkey):
106 return
107 registry[altkey] = 1
108 elif action == "default":
109 registry[key] = 1
110 else:
111 # Unrecognized actions are errors
112 raise RuntimeError(
113 "Unrecognized action (%s) in warnings.filters:\n %s" %
114 (`action`, str(item)))
115 # Print message and context
116 showwarning(message, category, filename, lineno)
117
118def showwarning(message, category, filename, lineno, file=None):
119 """Hook to write a warning to a file; replace if you like."""
120 if file is None:
121 file = sys.stderr
Mark Hammond51a0ae32002-09-11 13:22:35 +0000122 try:
123 file.write(formatwarning(message, category, filename, lineno))
124 except IOError:
125 pass # the file (probably stderr) is invalid - this warning gets lost.
Guido van Rossum2a862c62000-12-15 21:59:53 +0000126
127def formatwarning(message, category, filename, lineno):
Guido van Rossum9464a7d2001-01-14 14:08:40 +0000128 """Function to format a warning the standard way."""
Guido van Rossum2a862c62000-12-15 21:59:53 +0000129 s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
130 line = linecache.getline(filename, lineno).strip()
131 if line:
132 s = s + " " + line + "\n"
133 return s
134
Guido van Rossum9464a7d2001-01-14 14:08:40 +0000135def filterwarnings(action, message="", category=Warning, module="", lineno=0,
136 append=0):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000137 """Insert an entry into the list of warnings filters (at the front).
138
139 Use assertions to check that all arguments have the right type."""
Skip Montanarod8f21202003-05-14 17:33:53 +0000140 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000141 assert action in ("error", "ignore", "always", "default", "module",
142 "once"), "invalid action: %s" % `action`
Martin v. Löwisff9284b2002-10-14 21:06:02 +0000143 assert isinstance(message, basestring), "message must be a string"
Guido van Rossum2a862c62000-12-15 21:59:53 +0000144 assert isinstance(category, types.ClassType), "category must be a class"
145 assert issubclass(category, Warning), "category must be a Warning subclass"
Martin v. Löwisff9284b2002-10-14 21:06:02 +0000146 assert isinstance(module, basestring), "module must be a string"
Walter Dörwald65230a22002-06-03 15:58:32 +0000147 assert isinstance(lineno, int) and lineno >= 0, \
Guido van Rossum2a862c62000-12-15 21:59:53 +0000148 "lineno must be an int >= 0"
Guido van Rossum9464a7d2001-01-14 14:08:40 +0000149 item = (action, re.compile(message, re.I), category,
150 re.compile(module), lineno)
151 if append:
152 filters.append(item)
153 else:
154 filters.insert(0, item)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000155
Jeremy Hylton85014662003-07-11 15:37:59 +0000156def 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
Guido van Rossum2a862c62000-12-15 21:59:53 +0000171def resetwarnings():
Tim Petersd0cc4f02002-04-16 01:51:25 +0000172 """Clear the list of warning filters, so that no filters are active."""
Guido van Rossum2a862c62000-12-15 21:59:53 +0000173 filters[:] = []
174
175class _OptionError(Exception):
176 """Exception used by option processing helpers."""
177 pass
178
179# Helper to process -W options passed via sys.warnoptions
180def _processoptions(args):
181 for arg in args:
182 try:
183 _setoption(arg)
184 except _OptionError, msg:
185 print >>sys.stderr, "Invalid -W option ignored:", msg
186
187# Helper for _processoptions()
188def _setoption(arg):
Skip Montanarod8f21202003-05-14 17:33:53 +0000189 import re
Tim Peterse1190062001-01-15 03:34:38 +0000190 parts = arg.split(':')
191 if len(parts) > 5:
192 raise _OptionError("too many fields (max 5): %s" % `arg`)
193 while len(parts) < 5:
194 parts.append('')
195 action, message, category, module, lineno = [s.strip()
196 for s in parts]
197 action = _getaction(action)
198 message = re.escape(message)
199 category = _getcategory(category)
200 module = re.escape(module)
201 if module:
202 module = module + '$'
203 if lineno:
204 try:
205 lineno = int(lineno)
206 if lineno < 0:
207 raise ValueError
208 except (ValueError, OverflowError):
209 raise _OptionError("invalid lineno %s" % `lineno`)
210 else:
211 lineno = 0
212 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000213
214# Helper for _setoption()
215def _getaction(action):
216 if not action:
217 return "default"
218 if action == "all": return "always" # Alias
219 for a in ['default', 'always', 'ignore', 'module', 'once', 'error']:
220 if a.startswith(action):
221 return a
222 raise _OptionError("invalid action: %s" % `action`)
223
224# Helper for _setoption()
225def _getcategory(category):
Skip Montanarod8f21202003-05-14 17:33:53 +0000226 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000227 if not category:
228 return Warning
229 if re.match("^[a-zA-Z0-9_]+$", category):
230 try:
231 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000232 except NameError:
233 raise _OptionError("unknown warning category: %s" % `category`)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000234 else:
235 i = category.rfind(".")
236 module = category[:i]
237 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000238 try:
239 m = __import__(module, None, None, [klass])
240 except ImportError:
241 raise _OptionError("invalid module name: %s" % `module`)
242 try:
243 cat = getattr(m, klass)
244 except AttributeError:
245 raise _OptionError("unknown warning category: %s" % `category`)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000246 if (not isinstance(cat, types.ClassType) or
247 not issubclass(cat, Warning)):
248 raise _OptionError("invalid warning category: %s" % `category`)
249 return cat
250
Guido van Rossum2a862c62000-12-15 21:59:53 +0000251# Module initialization
252if __name__ == "__main__":
253 import __main__
254 sys.modules['warnings'] = __main__
255 _test()
256else:
257 _processoptions(sys.warnoptions)
Jeremy Hylton85014662003-07-11 15:37:59 +0000258 simplefilter("ignore", category=OverflowWarning, append=1)
259 simplefilter("ignore", category=PendingDeprecationWarning, append=1)