blob: f54726a45fc8b7025759dc8f91e48a0c5403b838 [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
Christian Heimes33fe8092008-04-13 13:53:33 +00009def showwarning(message, category, filename, lineno, file=None, line=None):
Guido van Rossum2a862c62000-12-15 21:59:53 +000010 """Hook to write a warning to a file; replace if you like."""
Victor Stinner1231a462016-03-19 00:47:17 +010011 msg = WarningMessage(message, category, filename, lineno, file, line)
12 _showwarnmsg(msg)
Guido van Rossum2a862c62000-12-15 21:59:53 +000013
Christian Heimes33fe8092008-04-13 13:53:33 +000014def formatwarning(message, category, filename, lineno, line=None):
Guido van Rossum9464a7d2001-01-14 14:08:40 +000015 """Function to format a warning the standard way."""
Victor Stinner1231a462016-03-19 00:47:17 +010016 msg = WarningMessage(message, category, filename, lineno, None, line)
17 return _formatwarnmsg(msg)
18
19# Keep references to check if the functions were replaced
20_showwarning = showwarning
21_formatwarning = formatwarning
22
23def _showwarnmsg(msg):
24 """Hook to write a warning to a file; replace if you like."""
25 showwarning = globals().get('showwarning', _showwarning)
26 if showwarning is not _showwarning:
27 # warnings.showwarning() was replaced
28 if not callable(showwarning):
29 raise TypeError("warnings.showwarning() must be set to a "
30 "function or method")
31
32 showwarning(msg.message, msg.category, msg.filename, msg.lineno,
33 msg.file, msg.line)
34 return
35
36 file = msg.file
37 if file is None:
38 file = sys.stderr
39 if file is None:
40 # sys.stderr is None when run with pythonw.exe:
41 # warnings get lost
42 return
43 text = _formatwarnmsg(msg)
44 try:
45 file.write(text)
46 except OSError:
47 # the file (probably stderr) is invalid - this warning gets lost.
48 pass
49
50def _formatwarnmsg(msg):
51 """Function to format a warning the standard way."""
52 formatwarning = globals().get('formatwarning', _formatwarning)
53 if formatwarning is not _formatwarning:
54 # warnings.formatwarning() was replaced
55 return formatwarning(msg.message, msg.category,
56 msg.filename, msg.lineno, line=msg.line)
57
Antoine Pitrou7cb11fa2013-10-24 22:23:42 +020058 import linecache
Victor Stinner1231a462016-03-19 00:47:17 +010059 s = ("%s:%s: %s: %s\n"
60 % (msg.filename, msg.lineno, msg.category.__name__,
61 msg.message))
62 if msg.line is None:
63 line = linecache.getline(msg.filename, msg.lineno)
64 else:
65 line = msg.line
Guido van Rossum2a862c62000-12-15 21:59:53 +000066 if line:
Christian Heimes33fe8092008-04-13 13:53:33 +000067 line = line.strip()
68 s += " %s\n" % line
Guido van Rossum2a862c62000-12-15 21:59:53 +000069 return s
70
Guido van Rossum9464a7d2001-01-14 14:08:40 +000071def filterwarnings(action, message="", category=Warning, module="", lineno=0,
Georg Brandlfe991052009-09-16 15:54:04 +000072 append=False):
Guido van Rossum2a862c62000-12-15 21:59:53 +000073 """Insert an entry into the list of warnings filters (at the front).
74
Georg Brandl495f7b52009-10-27 15:28:25 +000075 'action' -- one of "error", "ignore", "always", "default", "module",
76 or "once"
77 'message' -- a regex that the warning message must match
78 'category' -- a class that the warning must be a subclass of
79 'module' -- a regex that the module name must match
80 'lineno' -- an integer line number, 0 matches all warnings
81 'append' -- if true, append to the list of filters
82 """
Skip Montanarod8f21202003-05-14 17:33:53 +000083 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +000084 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000085 "once"), "invalid action: %r" % (action,)
Guido van Rossum3172c5d2007-10-16 18:12:55 +000086 assert isinstance(message, str), "message must be a string"
Guido van Rossum13257902007-06-07 23:15:56 +000087 assert isinstance(category, type), "category must be a class"
Guido van Rossum2a862c62000-12-15 21:59:53 +000088 assert issubclass(category, Warning), "category must be a Warning subclass"
Guido van Rossum3172c5d2007-10-16 18:12:55 +000089 assert isinstance(module, str), "module must be a string"
Walter Dörwald65230a22002-06-03 15:58:32 +000090 assert isinstance(lineno, int) and lineno >= 0, \
Guido van Rossum2a862c62000-12-15 21:59:53 +000091 "lineno must be an int >= 0"
Guido van Rossum9464a7d2001-01-14 14:08:40 +000092 item = (action, re.compile(message, re.I), category,
93 re.compile(module), lineno)
94 if append:
95 filters.append(item)
96 else:
97 filters.insert(0, item)
Antoine Pitroucb0a0062014-09-18 02:40:46 +020098 _filters_mutated()
Guido van Rossum2a862c62000-12-15 21:59:53 +000099
Georg Brandlfe991052009-09-16 15:54:04 +0000100def simplefilter(action, category=Warning, lineno=0, append=False):
Jeremy Hylton85014662003-07-11 15:37:59 +0000101 """Insert a simple entry into the list of warnings filters (at the front).
102
103 A simple filter matches all modules and messages.
Georg Brandl495f7b52009-10-27 15:28:25 +0000104 'action' -- one of "error", "ignore", "always", "default", "module",
105 or "once"
106 'category' -- a class that the warning must be a subclass of
107 'lineno' -- an integer line number, 0 matches all warnings
108 'append' -- if true, append to the list of filters
Jeremy Hylton85014662003-07-11 15:37:59 +0000109 """
110 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +0000111 "once"), "invalid action: %r" % (action,)
Jeremy Hylton85014662003-07-11 15:37:59 +0000112 assert isinstance(lineno, int) and lineno >= 0, \
113 "lineno must be an int >= 0"
114 item = (action, None, category, None, lineno)
115 if append:
116 filters.append(item)
117 else:
118 filters.insert(0, item)
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200119 _filters_mutated()
Jeremy Hylton85014662003-07-11 15:37:59 +0000120
Guido van Rossum2a862c62000-12-15 21:59:53 +0000121def resetwarnings():
Tim Petersd0cc4f02002-04-16 01:51:25 +0000122 """Clear the list of warning filters, so that no filters are active."""
Guido van Rossum2a862c62000-12-15 21:59:53 +0000123 filters[:] = []
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200124 _filters_mutated()
Guido van Rossum2a862c62000-12-15 21:59:53 +0000125
126class _OptionError(Exception):
127 """Exception used by option processing helpers."""
128 pass
129
130# Helper to process -W options passed via sys.warnoptions
131def _processoptions(args):
132 for arg in args:
133 try:
134 _setoption(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +0000135 except _OptionError as msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000136 print("Invalid -W option ignored:", msg, file=sys.stderr)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000137
138# Helper for _processoptions()
139def _setoption(arg):
Skip Montanarod8f21202003-05-14 17:33:53 +0000140 import re
Tim Peterse1190062001-01-15 03:34:38 +0000141 parts = arg.split(':')
142 if len(parts) > 5:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000143 raise _OptionError("too many fields (max 5): %r" % (arg,))
Tim Peterse1190062001-01-15 03:34:38 +0000144 while len(parts) < 5:
145 parts.append('')
146 action, message, category, module, lineno = [s.strip()
147 for s in parts]
148 action = _getaction(action)
149 message = re.escape(message)
150 category = _getcategory(category)
151 module = re.escape(module)
152 if module:
153 module = module + '$'
154 if lineno:
155 try:
156 lineno = int(lineno)
157 if lineno < 0:
158 raise ValueError
159 except (ValueError, OverflowError):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000160 raise _OptionError("invalid lineno %r" % (lineno,))
Tim Peterse1190062001-01-15 03:34:38 +0000161 else:
162 lineno = 0
163 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000164
165# Helper for _setoption()
166def _getaction(action):
167 if not action:
168 return "default"
169 if action == "all": return "always" # Alias
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000170 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000171 if a.startswith(action):
172 return a
Walter Dörwald70a6b492004-02-12 17:35:32 +0000173 raise _OptionError("invalid action: %r" % (action,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000174
175# Helper for _setoption()
176def _getcategory(category):
Skip Montanarod8f21202003-05-14 17:33:53 +0000177 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000178 if not category:
179 return Warning
180 if re.match("^[a-zA-Z0-9_]+$", category):
181 try:
182 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000183 except NameError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000184 raise _OptionError("unknown warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000185 else:
186 i = category.rfind(".")
187 module = category[:i]
188 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000189 try:
Brett Cannoncd171c82013-07-04 17:43:24 -0400190 m = __import__(module, None, None, [klass])
191 except ImportError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000192 raise _OptionError("invalid module name: %r" % (module,))
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000193 try:
194 cat = getattr(m, klass)
195 except AttributeError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000196 raise _OptionError("unknown warning category: %r" % (category,))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000197 if not issubclass(cat, Warning):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000198 raise _OptionError("invalid warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000199 return cat
200
Christian Heimes33fe8092008-04-13 13:53:33 +0000201
Larry Hastings714e4932015-09-06 00:39:37 -0700202def _is_internal_frame(frame):
203 """Signal whether the frame is an internal CPython implementation detail."""
204 filename = frame.f_code.co_filename
205 return 'importlib' in filename and '_bootstrap' in filename
206
207
208def _next_external_frame(frame):
209 """Find the next frame that doesn't involve CPython internals."""
210 frame = frame.f_back
211 while frame is not None and _is_internal_frame(frame):
212 frame = frame.f_back
213 return frame
214
215
Christian Heimes33fe8092008-04-13 13:53:33 +0000216# Code typically replaced by _warnings
217def warn(message, category=None, stacklevel=1):
218 """Issue a warning, or maybe ignore it or raise an exception."""
219 # Check if message is already a Warning object
220 if isinstance(message, Warning):
221 category = message.__class__
222 # Check category argument
223 if category is None:
224 category = UserWarning
Berker Peksagd8089e02014-07-11 19:50:25 +0300225 if not (isinstance(category, type) and issubclass(category, Warning)):
226 raise TypeError("category must be a Warning subclass, "
227 "not '{:s}'".format(type(category).__name__))
Christian Heimes33fe8092008-04-13 13:53:33 +0000228 # Get context information
229 try:
Larry Hastings714e4932015-09-06 00:39:37 -0700230 if stacklevel <= 1 or _is_internal_frame(sys._getframe(1)):
231 # If frame is too small to care or if the warning originated in
232 # internal code, then do not try to hide any frames.
233 frame = sys._getframe(stacklevel)
234 else:
235 frame = sys._getframe(1)
236 # Look for one frame less since the above line starts us off.
237 for x in range(stacklevel-1):
238 frame = _next_external_frame(frame)
239 if frame is None:
240 raise ValueError
Christian Heimes33fe8092008-04-13 13:53:33 +0000241 except ValueError:
242 globals = sys.__dict__
243 lineno = 1
244 else:
Larry Hastings714e4932015-09-06 00:39:37 -0700245 globals = frame.f_globals
246 lineno = frame.f_lineno
Christian Heimes33fe8092008-04-13 13:53:33 +0000247 if '__name__' in globals:
248 module = globals['__name__']
249 else:
250 module = "<string>"
251 filename = globals.get('__file__')
252 if filename:
253 fnl = filename.lower()
Brett Cannonf299abd2015-04-13 14:21:02 -0400254 if fnl.endswith(".pyc"):
Christian Heimes33fe8092008-04-13 13:53:33 +0000255 filename = filename[:-1]
256 else:
257 if module == "__main__":
258 try:
259 filename = sys.argv[0]
260 except AttributeError:
261 # embedded interpreters don't have sys.argv, see bug #839151
262 filename = '__main__'
263 if not filename:
264 filename = module
265 registry = globals.setdefault("__warningregistry__", {})
266 warn_explicit(message, category, filename, lineno, module, registry,
267 globals)
268
269def warn_explicit(message, category, filename, lineno,
270 module=None, registry=None, module_globals=None):
Brett Cannondb734912008-06-27 00:52:15 +0000271 lineno = int(lineno)
Christian Heimes33fe8092008-04-13 13:53:33 +0000272 if module is None:
273 module = filename or "<unknown>"
274 if module[-3:].lower() == ".py":
275 module = module[:-3] # XXX What about leading pathname?
276 if registry is None:
277 registry = {}
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200278 if registry.get('version', 0) != _filters_version:
279 registry.clear()
280 registry['version'] = _filters_version
Christian Heimes33fe8092008-04-13 13:53:33 +0000281 if isinstance(message, Warning):
282 text = str(message)
283 category = message.__class__
284 else:
285 text = message
286 message = category(message)
287 key = (text, category, lineno)
288 # Quick test for common case
289 if registry.get(key):
290 return
291 # Search the filters
292 for item in filters:
293 action, msg, cat, mod, ln = item
294 if ((msg is None or msg.match(text)) and
295 issubclass(category, cat) and
296 (mod is None or mod.match(module)) and
297 (ln == 0 or lineno == ln)):
298 break
299 else:
300 action = defaultaction
301 # Early exit actions
302 if action == "ignore":
303 registry[key] = 1
304 return
305
306 # Prime the linecache for formatting, in case the
307 # "file" is actually in a zipfile or something.
Antoine Pitrou7cb11fa2013-10-24 22:23:42 +0200308 import linecache
Christian Heimes33fe8092008-04-13 13:53:33 +0000309 linecache.getlines(filename, module_globals)
310
311 if action == "error":
312 raise message
313 # Other actions
314 if action == "once":
315 registry[key] = 1
316 oncekey = (text, category)
317 if onceregistry.get(oncekey):
318 return
319 onceregistry[oncekey] = 1
320 elif action == "always":
321 pass
322 elif action == "module":
323 registry[key] = 1
324 altkey = (text, category, 0)
325 if registry.get(altkey):
326 return
327 registry[altkey] = 1
328 elif action == "default":
329 registry[key] = 1
330 else:
331 # Unrecognized actions are errors
332 raise RuntimeError(
333 "Unrecognized action (%r) in warnings.filters:\n %s" %
334 (action, item))
335 # Print message and context
Victor Stinner1231a462016-03-19 00:47:17 +0100336 msg = WarningMessage(message, category, filename, lineno)
337 _showwarnmsg(msg)
Christian Heimes33fe8092008-04-13 13:53:33 +0000338
339
Brett Cannonec92e182008-09-02 02:46:59 +0000340class WarningMessage(object):
341
Brett Cannonec92e182008-09-02 02:46:59 +0000342 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
343 "line")
344
345 def __init__(self, message, category, filename, lineno, file=None,
346 line=None):
347 local_values = locals()
348 for attr in self._WARNING_DETAILS:
349 setattr(self, attr, local_values[attr])
350 self._category_name = category.__name__ if category else None
351
352 def __str__(self):
353 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
354 "line : %r}" % (self.message, self._category_name,
355 self.filename, self.lineno, self.line))
356
357
Brett Cannonec92e182008-09-02 02:46:59 +0000358class catch_warnings(object):
359
Brett Cannon1cd02472008-09-09 01:52:27 +0000360 """A context manager that copies and restores the warnings filter upon
361 exiting the context.
Brett Cannonec92e182008-09-02 02:46:59 +0000362
Brett Cannon1cd02472008-09-09 01:52:27 +0000363 The 'record' argument specifies whether warnings should be captured by a
364 custom implementation of warnings.showwarning() and be appended to a list
365 returned by the context manager. Otherwise None is returned by the context
366 manager. The objects appended to the list are arguments whose attributes
367 mirror the arguments to showwarning().
368
369 The 'module' argument is to specify an alternative module to the module
370 named 'warnings' and imported under that name. This argument is only useful
371 when testing the warnings module itself.
Brett Cannonec92e182008-09-02 02:46:59 +0000372
373 """
374
375 def __init__(self, *, record=False, module=None):
376 """Specify whether to record warnings and if an alternative module
377 should be used other than sys.modules['warnings'].
378
379 For compatibility with Python 3.0, please consider all arguments to be
380 keyword-only.
381
382 """
Brett Cannon1cd02472008-09-09 01:52:27 +0000383 self._record = record
Brett Cannonec92e182008-09-02 02:46:59 +0000384 self._module = sys.modules['warnings'] if module is None else module
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000385 self._entered = False
386
387 def __repr__(self):
388 args = []
389 if self._record:
390 args.append("record=True")
391 if self._module is not sys.modules['warnings']:
392 args.append("module=%r" % self._module)
393 name = type(self).__name__
394 return "%s(%s)" % (name, ", ".join(args))
Brett Cannonec92e182008-09-02 02:46:59 +0000395
396 def __enter__(self):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000397 if self._entered:
398 raise RuntimeError("Cannot enter %r twice" % self)
399 self._entered = True
Brett Cannonec92e182008-09-02 02:46:59 +0000400 self._filters = self._module.filters
401 self._module.filters = self._filters[:]
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200402 self._module._filters_mutated()
Brett Cannonec92e182008-09-02 02:46:59 +0000403 self._showwarning = self._module.showwarning
Victor Stinner1231a462016-03-19 00:47:17 +0100404 self._showwarnmsg = self._module._showwarnmsg
Brett Cannon1cd02472008-09-09 01:52:27 +0000405 if self._record:
406 log = []
Victor Stinner1231a462016-03-19 00:47:17 +0100407 def showarnmsg(msg):
408 log.append(msg)
409 self._module._showwarnmsg = showarnmsg
Brett Cannon1cd02472008-09-09 01:52:27 +0000410 return log
411 else:
412 return None
Brett Cannonec92e182008-09-02 02:46:59 +0000413
414 def __exit__(self, *exc_info):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000415 if not self._entered:
416 raise RuntimeError("Cannot exit %r without entering first" % self)
Brett Cannonec92e182008-09-02 02:46:59 +0000417 self._module.filters = self._filters
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200418 self._module._filters_mutated()
Brett Cannonec92e182008-09-02 02:46:59 +0000419 self._module.showwarning = self._showwarning
Victor Stinner1231a462016-03-19 00:47:17 +0100420 self._module._showwarnmsg = self._showwarnmsg
Brett Cannonec92e182008-09-02 02:46:59 +0000421
422
Christian Heimes33fe8092008-04-13 13:53:33 +0000423# filters contains a sequence of filter 5-tuples
424# The components of the 5-tuple are:
425# - an action: error, ignore, always, default, module, or once
426# - a compiled regex that must match the warning message
427# - a class representing the warning category
428# - a compiled regex that must match the module that is being warned
429# - a line number for the line being warning, or 0 to mean any line
430# If either if the compiled regexs are None, match anything.
431_warnings_defaults = False
432try:
Brett Cannonef0e6c32010-09-04 18:24:04 +0000433 from _warnings import (filters, _defaultaction, _onceregistry,
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200434 warn, warn_explicit, _filters_mutated)
Brett Cannonef0e6c32010-09-04 18:24:04 +0000435 defaultaction = _defaultaction
436 onceregistry = _onceregistry
Christian Heimes33fe8092008-04-13 13:53:33 +0000437 _warnings_defaults = True
Brett Cannoncd171c82013-07-04 17:43:24 -0400438except ImportError:
Christian Heimes33fe8092008-04-13 13:53:33 +0000439 filters = []
440 defaultaction = "default"
441 onceregistry = {}
442
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200443 _filters_version = 1
444
445 def _filters_mutated():
446 global _filters_version
447 _filters_version += 1
448
Christian Heimes33fe8092008-04-13 13:53:33 +0000449
Guido van Rossum2a862c62000-12-15 21:59:53 +0000450# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000451_processoptions(sys.warnoptions)
Christian Heimes33fe8092008-04-13 13:53:33 +0000452if not _warnings_defaults:
Benjamin Peterson7ab4b8d2010-06-28 00:01:59 +0000453 silence = [ImportWarning, PendingDeprecationWarning]
454 silence.append(DeprecationWarning)
455 for cls in silence:
456 simplefilter("ignore", category=cls)
Christian Heimes33fe8092008-04-13 13:53:33 +0000457 bytes_warning = sys.flags.bytes_warning
458 if bytes_warning > 1:
459 bytes_action = "error"
460 elif bytes_warning:
461 bytes_action = "default"
462 else:
463 bytes_action = "ignore"
464 simplefilter(bytes_action, category=BytesWarning, append=1)
Georg Brandl08be72d2010-10-24 15:11:22 +0000465 # resource usage warnings are enabled by default in pydebug mode
466 if hasattr(sys, 'gettotalrefcount'):
467 resource_action = "always"
468 else:
469 resource_action = "ignore"
470 simplefilter(resource_action, category=ResourceWarning, append=1)
471
Christian Heimes33fe8092008-04-13 13:53:33 +0000472del _warnings_defaults