blob: 5b5821b1c3d818277ef8fb293fa3b4d83318d139 [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.
Mark Hammonda43fd0c2003-02-19 00:33:33 +00006import linecache
Christian Heimes33fe8092008-04-13 13:53:33 +00007import sys
Guido van Rossum2a862c62000-12-15 21:59:53 +00008
Skip Montanaro40fc1602001-03-01 04:27:19 +00009__all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
Brett Cannon1cd02472008-09-09 01:52:27 +000010 "resetwarnings", "catch_warnings"]
Skip Montanaro40fc1602001-03-01 04:27:19 +000011
Guido van Rossum2a862c62000-12-15 21:59:53 +000012
Christian Heimes33fe8092008-04-13 13:53:33 +000013def showwarning(message, category, filename, lineno, file=None, line=None):
Guido van Rossum2a862c62000-12-15 21:59:53 +000014 """Hook to write a warning to a file; replace if you like."""
15 if file is None:
16 file = sys.stderr
Mark Hammond51a0ae32002-09-11 13:22:35 +000017 try:
Christian Heimes33fe8092008-04-13 13:53:33 +000018 file.write(formatwarning(message, category, filename, lineno, line))
Mark Hammond51a0ae32002-09-11 13:22:35 +000019 except IOError:
20 pass # the file (probably stderr) is invalid - this warning gets lost.
Guido van Rossum2a862c62000-12-15 21:59:53 +000021
Christian Heimes33fe8092008-04-13 13:53:33 +000022def formatwarning(message, category, filename, lineno, line=None):
Guido van Rossum9464a7d2001-01-14 14:08:40 +000023 """Function to format a warning the standard way."""
Guido van Rossum2a862c62000-12-15 21:59:53 +000024 s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
Christian Heimes33fe8092008-04-13 13:53:33 +000025 line = linecache.getline(filename, lineno) if line is None else line
Guido van Rossum2a862c62000-12-15 21:59:53 +000026 if line:
Christian Heimes33fe8092008-04-13 13:53:33 +000027 line = line.strip()
28 s += " %s\n" % line
Guido van Rossum2a862c62000-12-15 21:59:53 +000029 return s
30
Guido van Rossum9464a7d2001-01-14 14:08:40 +000031def filterwarnings(action, message="", category=Warning, module="", lineno=0,
Georg Brandlfe991052009-09-16 15:54:04 +000032 append=False):
Guido van Rossum2a862c62000-12-15 21:59:53 +000033 """Insert an entry into the list of warnings filters (at the front).
34
Georg Brandl495f7b52009-10-27 15:28:25 +000035 'action' -- one of "error", "ignore", "always", "default", "module",
36 or "once"
37 'message' -- a regex that the warning message must match
38 'category' -- a class that the warning must be a subclass of
39 'module' -- a regex that the module name must match
40 'lineno' -- an integer line number, 0 matches all warnings
41 'append' -- if true, append to the list of filters
42 """
Skip Montanarod8f21202003-05-14 17:33:53 +000043 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +000044 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000045 "once"), "invalid action: %r" % (action,)
Guido van Rossum3172c5d2007-10-16 18:12:55 +000046 assert isinstance(message, str), "message must be a string"
Guido van Rossum13257902007-06-07 23:15:56 +000047 assert isinstance(category, type), "category must be a class"
Guido van Rossum2a862c62000-12-15 21:59:53 +000048 assert issubclass(category, Warning), "category must be a Warning subclass"
Guido van Rossum3172c5d2007-10-16 18:12:55 +000049 assert isinstance(module, str), "module must be a string"
Walter Dörwald65230a22002-06-03 15:58:32 +000050 assert isinstance(lineno, int) and lineno >= 0, \
Guido van Rossum2a862c62000-12-15 21:59:53 +000051 "lineno must be an int >= 0"
Guido van Rossum9464a7d2001-01-14 14:08:40 +000052 item = (action, re.compile(message, re.I), category,
53 re.compile(module), lineno)
54 if append:
55 filters.append(item)
56 else:
57 filters.insert(0, item)
Guido van Rossum2a862c62000-12-15 21:59:53 +000058
Georg Brandlfe991052009-09-16 15:54:04 +000059def simplefilter(action, category=Warning, lineno=0, append=False):
Jeremy Hylton85014662003-07-11 15:37:59 +000060 """Insert a simple entry into the list of warnings filters (at the front).
61
62 A simple filter matches all modules and messages.
Georg Brandl495f7b52009-10-27 15:28:25 +000063 'action' -- one of "error", "ignore", "always", "default", "module",
64 or "once"
65 'category' -- a class that the warning must be a subclass of
66 'lineno' -- an integer line number, 0 matches all warnings
67 'append' -- if true, append to the list of filters
Jeremy Hylton85014662003-07-11 15:37:59 +000068 """
69 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000070 "once"), "invalid action: %r" % (action,)
Jeremy Hylton85014662003-07-11 15:37:59 +000071 assert isinstance(lineno, int) and lineno >= 0, \
72 "lineno must be an int >= 0"
73 item = (action, None, category, None, lineno)
74 if append:
75 filters.append(item)
76 else:
77 filters.insert(0, item)
78
Guido van Rossum2a862c62000-12-15 21:59:53 +000079def resetwarnings():
Tim Petersd0cc4f02002-04-16 01:51:25 +000080 """Clear the list of warning filters, so that no filters are active."""
Guido van Rossum2a862c62000-12-15 21:59:53 +000081 filters[:] = []
82
83class _OptionError(Exception):
84 """Exception used by option processing helpers."""
85 pass
86
87# Helper to process -W options passed via sys.warnoptions
88def _processoptions(args):
89 for arg in args:
90 try:
91 _setoption(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +000092 except _OptionError as msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000093 print("Invalid -W option ignored:", msg, file=sys.stderr)
Guido van Rossum2a862c62000-12-15 21:59:53 +000094
95# Helper for _processoptions()
96def _setoption(arg):
Skip Montanarod8f21202003-05-14 17:33:53 +000097 import re
Tim Peterse1190062001-01-15 03:34:38 +000098 parts = arg.split(':')
99 if len(parts) > 5:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000100 raise _OptionError("too many fields (max 5): %r" % (arg,))
Tim Peterse1190062001-01-15 03:34:38 +0000101 while len(parts) < 5:
102 parts.append('')
103 action, message, category, module, lineno = [s.strip()
104 for s in parts]
105 action = _getaction(action)
106 message = re.escape(message)
107 category = _getcategory(category)
108 module = re.escape(module)
109 if module:
110 module = module + '$'
111 if lineno:
112 try:
113 lineno = int(lineno)
114 if lineno < 0:
115 raise ValueError
116 except (ValueError, OverflowError):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000117 raise _OptionError("invalid lineno %r" % (lineno,))
Tim Peterse1190062001-01-15 03:34:38 +0000118 else:
119 lineno = 0
120 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000121
122# Helper for _setoption()
123def _getaction(action):
124 if not action:
125 return "default"
126 if action == "all": return "always" # Alias
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000127 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000128 if a.startswith(action):
129 return a
Walter Dörwald70a6b492004-02-12 17:35:32 +0000130 raise _OptionError("invalid action: %r" % (action,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000131
132# Helper for _setoption()
133def _getcategory(category):
Skip Montanarod8f21202003-05-14 17:33:53 +0000134 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000135 if not category:
136 return Warning
137 if re.match("^[a-zA-Z0-9_]+$", category):
138 try:
139 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000140 except NameError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000141 raise _OptionError("unknown warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000142 else:
143 i = category.rfind(".")
144 module = category[:i]
145 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000146 try:
147 m = __import__(module, None, None, [klass])
148 except ImportError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000149 raise _OptionError("invalid module name: %r" % (module,))
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000150 try:
151 cat = getattr(m, klass)
152 except AttributeError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000153 raise _OptionError("unknown warning category: %r" % (category,))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000154 if not issubclass(cat, Warning):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000155 raise _OptionError("invalid warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000156 return cat
157
Christian Heimes33fe8092008-04-13 13:53:33 +0000158
159# Code typically replaced by _warnings
160def warn(message, category=None, stacklevel=1):
161 """Issue a warning, or maybe ignore it or raise an exception."""
162 # Check if message is already a Warning object
163 if isinstance(message, Warning):
164 category = message.__class__
165 # Check category argument
166 if category is None:
167 category = UserWarning
168 assert issubclass(category, Warning)
169 # Get context information
170 try:
171 caller = sys._getframe(stacklevel)
172 except ValueError:
173 globals = sys.__dict__
174 lineno = 1
175 else:
176 globals = caller.f_globals
177 lineno = caller.f_lineno
178 if '__name__' in globals:
179 module = globals['__name__']
180 else:
181 module = "<string>"
182 filename = globals.get('__file__')
183 if filename:
184 fnl = filename.lower()
185 if fnl.endswith((".pyc", ".pyo")):
186 filename = filename[:-1]
187 else:
188 if module == "__main__":
189 try:
190 filename = sys.argv[0]
191 except AttributeError:
192 # embedded interpreters don't have sys.argv, see bug #839151
193 filename = '__main__'
194 if not filename:
195 filename = module
196 registry = globals.setdefault("__warningregistry__", {})
197 warn_explicit(message, category, filename, lineno, module, registry,
198 globals)
199
200def warn_explicit(message, category, filename, lineno,
201 module=None, registry=None, module_globals=None):
Brett Cannondb734912008-06-27 00:52:15 +0000202 lineno = int(lineno)
Christian Heimes33fe8092008-04-13 13:53:33 +0000203 if module is None:
204 module = filename or "<unknown>"
205 if module[-3:].lower() == ".py":
206 module = module[:-3] # XXX What about leading pathname?
207 if registry is None:
208 registry = {}
209 if isinstance(message, Warning):
210 text = str(message)
211 category = message.__class__
212 else:
213 text = message
214 message = category(message)
215 key = (text, category, lineno)
216 # Quick test for common case
217 if registry.get(key):
218 return
219 # Search the filters
220 for item in filters:
221 action, msg, cat, mod, ln = item
222 if ((msg is None or msg.match(text)) and
223 issubclass(category, cat) and
224 (mod is None or mod.match(module)) and
225 (ln == 0 or lineno == ln)):
226 break
227 else:
228 action = defaultaction
229 # Early exit actions
230 if action == "ignore":
231 registry[key] = 1
232 return
233
234 # Prime the linecache for formatting, in case the
235 # "file" is actually in a zipfile or something.
236 linecache.getlines(filename, module_globals)
237
238 if action == "error":
239 raise message
240 # Other actions
241 if action == "once":
242 registry[key] = 1
243 oncekey = (text, category)
244 if onceregistry.get(oncekey):
245 return
246 onceregistry[oncekey] = 1
247 elif action == "always":
248 pass
249 elif action == "module":
250 registry[key] = 1
251 altkey = (text, category, 0)
252 if registry.get(altkey):
253 return
254 registry[altkey] = 1
255 elif action == "default":
256 registry[key] = 1
257 else:
258 # Unrecognized actions are errors
259 raise RuntimeError(
260 "Unrecognized action (%r) in warnings.filters:\n %s" %
261 (action, item))
Christian Heimes8dc226f2008-05-06 23:45:46 +0000262 if not hasattr(showwarning, "__call__"):
263 raise TypeError("warnings.showwarning() must be set to a "
264 "function or method")
Christian Heimes33fe8092008-04-13 13:53:33 +0000265 # Print message and context
266 showwarning(message, category, filename, lineno)
267
268
Brett Cannonec92e182008-09-02 02:46:59 +0000269class WarningMessage(object):
270
271 """Holds the result of a single showwarning() call."""
272
273 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
274 "line")
275
276 def __init__(self, message, category, filename, lineno, file=None,
277 line=None):
278 local_values = locals()
279 for attr in self._WARNING_DETAILS:
280 setattr(self, attr, local_values[attr])
281 self._category_name = category.__name__ if category else None
282
283 def __str__(self):
284 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
285 "line : %r}" % (self.message, self._category_name,
286 self.filename, self.lineno, self.line))
287
288
Brett Cannonec92e182008-09-02 02:46:59 +0000289class catch_warnings(object):
290
Brett Cannon1cd02472008-09-09 01:52:27 +0000291 """A context manager that copies and restores the warnings filter upon
292 exiting the context.
Brett Cannonec92e182008-09-02 02:46:59 +0000293
Brett Cannon1cd02472008-09-09 01:52:27 +0000294 The 'record' argument specifies whether warnings should be captured by a
295 custom implementation of warnings.showwarning() and be appended to a list
296 returned by the context manager. Otherwise None is returned by the context
297 manager. The objects appended to the list are arguments whose attributes
298 mirror the arguments to showwarning().
299
300 The 'module' argument is to specify an alternative module to the module
301 named 'warnings' and imported under that name. This argument is only useful
302 when testing the warnings module itself.
Brett Cannonec92e182008-09-02 02:46:59 +0000303
304 """
305
306 def __init__(self, *, record=False, module=None):
307 """Specify whether to record warnings and if an alternative module
308 should be used other than sys.modules['warnings'].
309
310 For compatibility with Python 3.0, please consider all arguments to be
311 keyword-only.
312
313 """
Brett Cannon1cd02472008-09-09 01:52:27 +0000314 self._record = record
Brett Cannonec92e182008-09-02 02:46:59 +0000315 self._module = sys.modules['warnings'] if module is None else module
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000316 self._entered = False
317
318 def __repr__(self):
319 args = []
320 if self._record:
321 args.append("record=True")
322 if self._module is not sys.modules['warnings']:
323 args.append("module=%r" % self._module)
324 name = type(self).__name__
325 return "%s(%s)" % (name, ", ".join(args))
Brett Cannonec92e182008-09-02 02:46:59 +0000326
327 def __enter__(self):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000328 if self._entered:
329 raise RuntimeError("Cannot enter %r twice" % self)
330 self._entered = True
Brett Cannonec92e182008-09-02 02:46:59 +0000331 self._filters = self._module.filters
332 self._module.filters = self._filters[:]
333 self._showwarning = self._module.showwarning
Brett Cannon1cd02472008-09-09 01:52:27 +0000334 if self._record:
335 log = []
336 def showwarning(*args, **kwargs):
337 log.append(WarningMessage(*args, **kwargs))
338 self._module.showwarning = showwarning
339 return log
340 else:
341 return None
Brett Cannonec92e182008-09-02 02:46:59 +0000342
343 def __exit__(self, *exc_info):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000344 if not self._entered:
345 raise RuntimeError("Cannot exit %r without entering first" % self)
Brett Cannonec92e182008-09-02 02:46:59 +0000346 self._module.filters = self._filters
347 self._module.showwarning = self._showwarning
348
349
Christian Heimes33fe8092008-04-13 13:53:33 +0000350# filters contains a sequence of filter 5-tuples
351# The components of the 5-tuple are:
352# - an action: error, ignore, always, default, module, or once
353# - a compiled regex that must match the warning message
354# - a class representing the warning category
355# - a compiled regex that must match the module that is being warned
356# - a line number for the line being warning, or 0 to mean any line
357# If either if the compiled regexs are None, match anything.
358_warnings_defaults = False
359try:
Brett Cannonef0e6c32010-09-04 18:24:04 +0000360 from _warnings import (filters, _defaultaction, _onceregistry,
Christian Heimes33fe8092008-04-13 13:53:33 +0000361 warn, warn_explicit)
Brett Cannonef0e6c32010-09-04 18:24:04 +0000362 defaultaction = _defaultaction
363 onceregistry = _onceregistry
Christian Heimes33fe8092008-04-13 13:53:33 +0000364 _warnings_defaults = True
365except ImportError:
366 filters = []
367 defaultaction = "default"
368 onceregistry = {}
369
370
Guido van Rossum2a862c62000-12-15 21:59:53 +0000371# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000372_processoptions(sys.warnoptions)
Christian Heimes33fe8092008-04-13 13:53:33 +0000373if not _warnings_defaults:
Benjamin Peterson7ab4b8d2010-06-28 00:01:59 +0000374 silence = [ImportWarning, PendingDeprecationWarning]
375 silence.append(DeprecationWarning)
376 for cls in silence:
377 simplefilter("ignore", category=cls)
Christian Heimes33fe8092008-04-13 13:53:33 +0000378 bytes_warning = sys.flags.bytes_warning
379 if bytes_warning > 1:
380 bytes_action = "error"
381 elif bytes_warning:
382 bytes_action = "default"
383 else:
384 bytes_action = "ignore"
385 simplefilter(bytes_action, category=BytesWarning, append=1)
Georg Brandl08be72d2010-10-24 15:11:22 +0000386 # resource usage warnings are enabled by default in pydebug mode
387 if hasattr(sys, 'gettotalrefcount'):
388 resource_action = "always"
389 else:
390 resource_action = "ignore"
391 simplefilter(resource_action, category=ResourceWarning, append=1)
392
Christian Heimes33fe8092008-04-13 13:53:33 +0000393del _warnings_defaults