blob: eeeba6537410d7f228ef1156053997e178da29b4 [file] [log] [blame]
Guido van Rossum2a862c62000-12-15 21:59:53 +00001"""Python part of the warnings subsystem."""
2
Christian Heimes33fe8092008-04-13 13:53:33 +00003import sys
Guido van Rossum2a862c62000-12-15 21:59:53 +00004
Brett Cannon14ad5312014-08-22 10:44:47 -04005__all__ = ["warn", "warn_explicit", "showwarning",
6 "formatwarning", "filterwarnings", "simplefilter",
Brett Cannon1cd02472008-09-09 01:52:27 +00007 "resetwarnings", "catch_warnings"]
Skip Montanaro40fc1602001-03-01 04:27:19 +00008
Guido van Rossum2a862c62000-12-15 21:59:53 +00009
Christian Heimes33fe8092008-04-13 13:53:33 +000010def showwarning(message, category, filename, lineno, file=None, line=None):
Guido van Rossum2a862c62000-12-15 21:59:53 +000011 """Hook to write a warning to a file; replace if you like."""
12 if file is None:
13 file = sys.stderr
Mark Hammond51a0ae32002-09-11 13:22:35 +000014 try:
Christian Heimes33fe8092008-04-13 13:53:33 +000015 file.write(formatwarning(message, category, filename, lineno, line))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +020016 except OSError:
Mark Hammond51a0ae32002-09-11 13:22:35 +000017 pass # the file (probably stderr) is invalid - this warning gets lost.
Guido van Rossum2a862c62000-12-15 21:59:53 +000018
Christian Heimes33fe8092008-04-13 13:53:33 +000019def formatwarning(message, category, filename, lineno, line=None):
Guido van Rossum9464a7d2001-01-14 14:08:40 +000020 """Function to format a warning the standard way."""
Antoine Pitrou7cb11fa2013-10-24 22:23:42 +020021 import linecache
Guido van Rossum2a862c62000-12-15 21:59:53 +000022 s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
Christian Heimes33fe8092008-04-13 13:53:33 +000023 line = linecache.getline(filename, lineno) if line is None else line
Guido van Rossum2a862c62000-12-15 21:59:53 +000024 if line:
Christian Heimes33fe8092008-04-13 13:53:33 +000025 line = line.strip()
26 s += " %s\n" % line
Guido van Rossum2a862c62000-12-15 21:59:53 +000027 return s
28
Guido van Rossum9464a7d2001-01-14 14:08:40 +000029def filterwarnings(action, message="", category=Warning, module="", lineno=0,
Georg Brandlfe991052009-09-16 15:54:04 +000030 append=False):
Guido van Rossum2a862c62000-12-15 21:59:53 +000031 """Insert an entry into the list of warnings filters (at the front).
32
Georg Brandl495f7b52009-10-27 15:28:25 +000033 'action' -- one of "error", "ignore", "always", "default", "module",
34 or "once"
35 'message' -- a regex that the warning message must match
36 'category' -- a class that the warning must be a subclass of
37 'module' -- a regex that the module name must match
38 'lineno' -- an integer line number, 0 matches all warnings
39 'append' -- if true, append to the list of filters
40 """
Skip Montanarod8f21202003-05-14 17:33:53 +000041 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +000042 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000043 "once"), "invalid action: %r" % (action,)
Guido van Rossum3172c5d2007-10-16 18:12:55 +000044 assert isinstance(message, str), "message must be a string"
Guido van Rossum13257902007-06-07 23:15:56 +000045 assert isinstance(category, type), "category must be a class"
Guido van Rossum2a862c62000-12-15 21:59:53 +000046 assert issubclass(category, Warning), "category must be a Warning subclass"
Guido van Rossum3172c5d2007-10-16 18:12:55 +000047 assert isinstance(module, str), "module must be a string"
Walter Dörwald65230a22002-06-03 15:58:32 +000048 assert isinstance(lineno, int) and lineno >= 0, \
Guido van Rossum2a862c62000-12-15 21:59:53 +000049 "lineno must be an int >= 0"
Guido van Rossum9464a7d2001-01-14 14:08:40 +000050 item = (action, re.compile(message, re.I), category,
51 re.compile(module), lineno)
52 if append:
53 filters.append(item)
54 else:
55 filters.insert(0, item)
Guido van Rossum2a862c62000-12-15 21:59:53 +000056
Georg Brandlfe991052009-09-16 15:54:04 +000057def simplefilter(action, category=Warning, lineno=0, append=False):
Jeremy Hylton85014662003-07-11 15:37:59 +000058 """Insert a simple entry into the list of warnings filters (at the front).
59
60 A simple filter matches all modules and messages.
Georg Brandl495f7b52009-10-27 15:28:25 +000061 'action' -- one of "error", "ignore", "always", "default", "module",
62 or "once"
63 'category' -- a class that the warning must be a subclass of
64 'lineno' -- an integer line number, 0 matches all warnings
65 'append' -- if true, append to the list of filters
Jeremy Hylton85014662003-07-11 15:37:59 +000066 """
67 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000068 "once"), "invalid action: %r" % (action,)
Jeremy Hylton85014662003-07-11 15:37:59 +000069 assert isinstance(lineno, int) and lineno >= 0, \
70 "lineno must be an int >= 0"
71 item = (action, None, category, None, lineno)
72 if append:
73 filters.append(item)
74 else:
75 filters.insert(0, item)
76
Guido van Rossum2a862c62000-12-15 21:59:53 +000077def resetwarnings():
Tim Petersd0cc4f02002-04-16 01:51:25 +000078 """Clear the list of warning filters, so that no filters are active."""
Guido van Rossum2a862c62000-12-15 21:59:53 +000079 filters[:] = []
80
81class _OptionError(Exception):
82 """Exception used by option processing helpers."""
83 pass
84
85# Helper to process -W options passed via sys.warnoptions
86def _processoptions(args):
87 for arg in args:
88 try:
89 _setoption(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +000090 except _OptionError as msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000091 print("Invalid -W option ignored:", msg, file=sys.stderr)
Guido van Rossum2a862c62000-12-15 21:59:53 +000092
93# Helper for _processoptions()
94def _setoption(arg):
Skip Montanarod8f21202003-05-14 17:33:53 +000095 import re
Tim Peterse1190062001-01-15 03:34:38 +000096 parts = arg.split(':')
97 if len(parts) > 5:
Walter Dörwald70a6b492004-02-12 17:35:32 +000098 raise _OptionError("too many fields (max 5): %r" % (arg,))
Tim Peterse1190062001-01-15 03:34:38 +000099 while len(parts) < 5:
100 parts.append('')
101 action, message, category, module, lineno = [s.strip()
102 for s in parts]
103 action = _getaction(action)
104 message = re.escape(message)
105 category = _getcategory(category)
106 module = re.escape(module)
107 if module:
108 module = module + '$'
109 if lineno:
110 try:
111 lineno = int(lineno)
112 if lineno < 0:
113 raise ValueError
114 except (ValueError, OverflowError):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000115 raise _OptionError("invalid lineno %r" % (lineno,))
Tim Peterse1190062001-01-15 03:34:38 +0000116 else:
117 lineno = 0
118 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000119
120# Helper for _setoption()
121def _getaction(action):
122 if not action:
123 return "default"
124 if action == "all": return "always" # Alias
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000125 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000126 if a.startswith(action):
127 return a
Walter Dörwald70a6b492004-02-12 17:35:32 +0000128 raise _OptionError("invalid action: %r" % (action,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000129
130# Helper for _setoption()
131def _getcategory(category):
Skip Montanarod8f21202003-05-14 17:33:53 +0000132 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000133 if not category:
134 return Warning
135 if re.match("^[a-zA-Z0-9_]+$", category):
136 try:
137 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000138 except NameError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000139 raise _OptionError("unknown warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000140 else:
141 i = category.rfind(".")
142 module = category[:i]
143 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000144 try:
Brett Cannoncd171c82013-07-04 17:43:24 -0400145 m = __import__(module, None, None, [klass])
146 except ImportError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000147 raise _OptionError("invalid module name: %r" % (module,))
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000148 try:
149 cat = getattr(m, klass)
150 except AttributeError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000151 raise _OptionError("unknown warning category: %r" % (category,))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000152 if not issubclass(cat, Warning):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000153 raise _OptionError("invalid warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000154 return cat
155
Christian Heimes33fe8092008-04-13 13:53:33 +0000156
157# Code typically replaced by _warnings
158def warn(message, category=None, stacklevel=1):
159 """Issue a warning, or maybe ignore it or raise an exception."""
160 # Check if message is already a Warning object
161 if isinstance(message, Warning):
162 category = message.__class__
163 # Check category argument
164 if category is None:
165 category = UserWarning
166 assert issubclass(category, Warning)
167 # Get context information
168 try:
169 caller = sys._getframe(stacklevel)
170 except ValueError:
171 globals = sys.__dict__
172 lineno = 1
173 else:
174 globals = caller.f_globals
175 lineno = caller.f_lineno
176 if '__name__' in globals:
177 module = globals['__name__']
178 else:
179 module = "<string>"
180 filename = globals.get('__file__')
181 if filename:
182 fnl = filename.lower()
183 if fnl.endswith((".pyc", ".pyo")):
184 filename = filename[:-1]
185 else:
186 if module == "__main__":
187 try:
188 filename = sys.argv[0]
189 except AttributeError:
190 # embedded interpreters don't have sys.argv, see bug #839151
191 filename = '__main__'
192 if not filename:
193 filename = module
194 registry = globals.setdefault("__warningregistry__", {})
195 warn_explicit(message, category, filename, lineno, module, registry,
196 globals)
197
198def warn_explicit(message, category, filename, lineno,
199 module=None, registry=None, module_globals=None):
Brett Cannondb734912008-06-27 00:52:15 +0000200 lineno = int(lineno)
Christian Heimes33fe8092008-04-13 13:53:33 +0000201 if module is None:
202 module = filename or "<unknown>"
203 if module[-3:].lower() == ".py":
204 module = module[:-3] # XXX What about leading pathname?
205 if registry is None:
206 registry = {}
207 if isinstance(message, Warning):
208 text = str(message)
209 category = message.__class__
210 else:
211 text = message
212 message = category(message)
213 key = (text, category, lineno)
214 # Quick test for common case
215 if registry.get(key):
216 return
217 # Search the filters
218 for item in filters:
219 action, msg, cat, mod, ln = item
220 if ((msg is None or msg.match(text)) and
221 issubclass(category, cat) and
222 (mod is None or mod.match(module)) and
223 (ln == 0 or lineno == ln)):
224 break
225 else:
226 action = defaultaction
227 # Early exit actions
228 if action == "ignore":
229 registry[key] = 1
230 return
231
232 # Prime the linecache for formatting, in case the
233 # "file" is actually in a zipfile or something.
Antoine Pitrou7cb11fa2013-10-24 22:23:42 +0200234 import linecache
Christian Heimes33fe8092008-04-13 13:53:33 +0000235 linecache.getlines(filename, module_globals)
236
237 if action == "error":
238 raise message
239 # Other actions
240 if action == "once":
241 registry[key] = 1
242 oncekey = (text, category)
243 if onceregistry.get(oncekey):
244 return
245 onceregistry[oncekey] = 1
246 elif action == "always":
247 pass
248 elif action == "module":
249 registry[key] = 1
250 altkey = (text, category, 0)
251 if registry.get(altkey):
252 return
253 registry[altkey] = 1
254 elif action == "default":
255 registry[key] = 1
256 else:
257 # Unrecognized actions are errors
258 raise RuntimeError(
259 "Unrecognized action (%r) in warnings.filters:\n %s" %
260 (action, item))
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200261 if not callable(showwarning):
Christian Heimes8dc226f2008-05-06 23:45:46 +0000262 raise TypeError("warnings.showwarning() must be set to a "
263 "function or method")
Christian Heimes33fe8092008-04-13 13:53:33 +0000264 # Print message and context
265 showwarning(message, category, filename, lineno)
266
267
Brett Cannonec92e182008-09-02 02:46:59 +0000268class WarningMessage(object):
269
270 """Holds the result of a single showwarning() call."""
271
272 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
273 "line")
274
275 def __init__(self, message, category, filename, lineno, file=None,
276 line=None):
277 local_values = locals()
278 for attr in self._WARNING_DETAILS:
279 setattr(self, attr, local_values[attr])
280 self._category_name = category.__name__ if category else None
281
282 def __str__(self):
283 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
284 "line : %r}" % (self.message, self._category_name,
285 self.filename, self.lineno, self.line))
286
287
Brett Cannonec92e182008-09-02 02:46:59 +0000288class catch_warnings(object):
289
Brett Cannon1cd02472008-09-09 01:52:27 +0000290 """A context manager that copies and restores the warnings filter upon
291 exiting the context.
Brett Cannonec92e182008-09-02 02:46:59 +0000292
Brett Cannon1cd02472008-09-09 01:52:27 +0000293 The 'record' argument specifies whether warnings should be captured by a
294 custom implementation of warnings.showwarning() and be appended to a list
295 returned by the context manager. Otherwise None is returned by the context
296 manager. The objects appended to the list are arguments whose attributes
297 mirror the arguments to showwarning().
298
299 The 'module' argument is to specify an alternative module to the module
300 named 'warnings' and imported under that name. This argument is only useful
301 when testing the warnings module itself.
Brett Cannonec92e182008-09-02 02:46:59 +0000302
303 """
304
305 def __init__(self, *, record=False, module=None):
306 """Specify whether to record warnings and if an alternative module
307 should be used other than sys.modules['warnings'].
308
309 For compatibility with Python 3.0, please consider all arguments to be
310 keyword-only.
311
312 """
Brett Cannon1cd02472008-09-09 01:52:27 +0000313 self._record = record
Brett Cannonec92e182008-09-02 02:46:59 +0000314 self._module = sys.modules['warnings'] if module is None else module
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000315 self._entered = False
316
317 def __repr__(self):
318 args = []
319 if self._record:
320 args.append("record=True")
321 if self._module is not sys.modules['warnings']:
322 args.append("module=%r" % self._module)
323 name = type(self).__name__
324 return "%s(%s)" % (name, ", ".join(args))
Brett Cannonec92e182008-09-02 02:46:59 +0000325
326 def __enter__(self):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000327 if self._entered:
328 raise RuntimeError("Cannot enter %r twice" % self)
329 self._entered = True
Brett Cannonec92e182008-09-02 02:46:59 +0000330 self._filters = self._module.filters
331 self._module.filters = self._filters[:]
332 self._showwarning = self._module.showwarning
Brett Cannon1cd02472008-09-09 01:52:27 +0000333 if self._record:
334 log = []
335 def showwarning(*args, **kwargs):
336 log.append(WarningMessage(*args, **kwargs))
337 self._module.showwarning = showwarning
338 return log
339 else:
340 return None
Brett Cannonec92e182008-09-02 02:46:59 +0000341
342 def __exit__(self, *exc_info):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000343 if not self._entered:
344 raise RuntimeError("Cannot exit %r without entering first" % self)
Brett Cannonec92e182008-09-02 02:46:59 +0000345 self._module.filters = self._filters
346 self._module.showwarning = self._showwarning
347
348
Christian Heimes33fe8092008-04-13 13:53:33 +0000349# filters contains a sequence of filter 5-tuples
350# The components of the 5-tuple are:
351# - an action: error, ignore, always, default, module, or once
352# - a compiled regex that must match the warning message
353# - a class representing the warning category
354# - a compiled regex that must match the module that is being warned
355# - a line number for the line being warning, or 0 to mean any line
356# If either if the compiled regexs are None, match anything.
357_warnings_defaults = False
358try:
Brett Cannonef0e6c32010-09-04 18:24:04 +0000359 from _warnings import (filters, _defaultaction, _onceregistry,
Christian Heimes33fe8092008-04-13 13:53:33 +0000360 warn, warn_explicit)
Brett Cannonef0e6c32010-09-04 18:24:04 +0000361 defaultaction = _defaultaction
362 onceregistry = _onceregistry
Christian Heimes33fe8092008-04-13 13:53:33 +0000363 _warnings_defaults = True
Brett Cannoncd171c82013-07-04 17:43:24 -0400364except ImportError:
Christian Heimes33fe8092008-04-13 13:53:33 +0000365 filters = []
366 defaultaction = "default"
367 onceregistry = {}
368
369
Guido van Rossum2a862c62000-12-15 21:59:53 +0000370# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000371_processoptions(sys.warnoptions)
Christian Heimes33fe8092008-04-13 13:53:33 +0000372if not _warnings_defaults:
Benjamin Peterson7ab4b8d2010-06-28 00:01:59 +0000373 silence = [ImportWarning, PendingDeprecationWarning]
374 silence.append(DeprecationWarning)
375 for cls in silence:
376 simplefilter("ignore", category=cls)
Christian Heimes33fe8092008-04-13 13:53:33 +0000377 bytes_warning = sys.flags.bytes_warning
378 if bytes_warning > 1:
379 bytes_action = "error"
380 elif bytes_warning:
381 bytes_action = "default"
382 else:
383 bytes_action = "ignore"
384 simplefilter(bytes_action, category=BytesWarning, append=1)
Georg Brandl08be72d2010-10-24 15:11:22 +0000385 # resource usage warnings are enabled by default in pydebug mode
386 if hasattr(sys, 'gettotalrefcount'):
387 resource_action = "always"
388 else:
389 resource_action = "ignore"
390 simplefilter(resource_action, category=ResourceWarning, append=1)
391
Christian Heimes33fe8092008-04-13 13:53:33 +0000392del _warnings_defaults