blob: c6631fcbf4758da73033b3fe080b2ccc27f3e597 [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
Serhiy Storchaka60599522014-12-10 22:59:55 +020014 if file is None:
Serhiy Storchakaeb9a9b62014-12-14 10:53:00 +020015 # sys.stderr is None when run with pythonw.exe - warnings get lost
Serhiy Storchaka60599522014-12-10 22:59:55 +020016 return
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))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +020019 except OSError:
Mark Hammond51a0ae32002-09-11 13:22:35 +000020 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)
Victor Stinner27461682016-03-25 00:30:32 +010025 if line is None:
26 try:
27 import linecache
28 line = linecache.getline(filename, lineno)
29 except Exception:
30 # When a warning is logged during Python shutdown, linecache
Martin Pantercc71a792016-04-05 06:19:42 +000031 # and the import machinery don't work anymore
Victor Stinner27461682016-03-25 00:30:32 +010032 line = None
Guido van Rossum2a862c62000-12-15 21:59:53 +000033 if line:
Christian Heimes33fe8092008-04-13 13:53:33 +000034 line = line.strip()
35 s += " %s\n" % line
Guido van Rossum2a862c62000-12-15 21:59:53 +000036 return s
37
Guido van Rossum9464a7d2001-01-14 14:08:40 +000038def filterwarnings(action, message="", category=Warning, module="", lineno=0,
Georg Brandlfe991052009-09-16 15:54:04 +000039 append=False):
Guido van Rossum2a862c62000-12-15 21:59:53 +000040 """Insert an entry into the list of warnings filters (at the front).
41
Georg Brandl495f7b52009-10-27 15:28:25 +000042 'action' -- one of "error", "ignore", "always", "default", "module",
43 or "once"
44 'message' -- a regex that the warning message must match
45 'category' -- a class that the warning must be a subclass of
46 'module' -- a regex that the module name must match
47 'lineno' -- an integer line number, 0 matches all warnings
48 'append' -- if true, append to the list of filters
49 """
Skip Montanarod8f21202003-05-14 17:33:53 +000050 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +000051 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000052 "once"), "invalid action: %r" % (action,)
Guido van Rossum3172c5d2007-10-16 18:12:55 +000053 assert isinstance(message, str), "message must be a string"
Guido van Rossum13257902007-06-07 23:15:56 +000054 assert isinstance(category, type), "category must be a class"
Guido van Rossum2a862c62000-12-15 21:59:53 +000055 assert issubclass(category, Warning), "category must be a Warning subclass"
Guido van Rossum3172c5d2007-10-16 18:12:55 +000056 assert isinstance(module, str), "module must be a string"
Walter Dörwald65230a22002-06-03 15:58:32 +000057 assert isinstance(lineno, int) and lineno >= 0, \
Guido van Rossum2a862c62000-12-15 21:59:53 +000058 "lineno must be an int >= 0"
Martin Panter43593a12016-05-26 09:10:55 +000059 _add_filter(action, re.compile(message, re.I), category,
60 re.compile(module), lineno, append=append)
Guido van Rossum2a862c62000-12-15 21:59:53 +000061
Georg Brandlfe991052009-09-16 15:54:04 +000062def simplefilter(action, category=Warning, lineno=0, append=False):
Jeremy Hylton85014662003-07-11 15:37:59 +000063 """Insert a simple entry into the list of warnings filters (at the front).
64
65 A simple filter matches all modules and messages.
Georg Brandl495f7b52009-10-27 15:28:25 +000066 'action' -- one of "error", "ignore", "always", "default", "module",
67 or "once"
68 'category' -- a class that the warning must be a subclass of
69 'lineno' -- an integer line number, 0 matches all warnings
70 'append' -- if true, append to the list of filters
Jeremy Hylton85014662003-07-11 15:37:59 +000071 """
72 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000073 "once"), "invalid action: %r" % (action,)
Jeremy Hylton85014662003-07-11 15:37:59 +000074 assert isinstance(lineno, int) and lineno >= 0, \
75 "lineno must be an int >= 0"
Martin Panter43593a12016-05-26 09:10:55 +000076 _add_filter(action, None, category, None, lineno, append=append)
77
78def _add_filter(*item, append):
79 # Remove possible duplicate filters, so new one will be placed
80 # in correct place. If append=True and duplicate exists, do nothing.
81 if not append:
82 try:
83 filters.remove(item)
84 except ValueError:
85 pass
Jeremy Hylton85014662003-07-11 15:37:59 +000086 filters.insert(0, item)
Martin Panter43593a12016-05-26 09:10:55 +000087 else:
88 if item not in filters:
89 filters.append(item)
Antoine Pitroucb0a0062014-09-18 02:40:46 +020090 _filters_mutated()
Jeremy Hylton85014662003-07-11 15:37:59 +000091
Guido van Rossum2a862c62000-12-15 21:59:53 +000092def resetwarnings():
Tim Petersd0cc4f02002-04-16 01:51:25 +000093 """Clear the list of warning filters, so that no filters are active."""
Guido van Rossum2a862c62000-12-15 21:59:53 +000094 filters[:] = []
Antoine Pitroucb0a0062014-09-18 02:40:46 +020095 _filters_mutated()
Guido van Rossum2a862c62000-12-15 21:59:53 +000096
97class _OptionError(Exception):
98 """Exception used by option processing helpers."""
99 pass
100
101# Helper to process -W options passed via sys.warnoptions
102def _processoptions(args):
103 for arg in args:
104 try:
105 _setoption(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +0000106 except _OptionError as msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000107 print("Invalid -W option ignored:", msg, file=sys.stderr)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000108
109# Helper for _processoptions()
110def _setoption(arg):
Skip Montanarod8f21202003-05-14 17:33:53 +0000111 import re
Tim Peterse1190062001-01-15 03:34:38 +0000112 parts = arg.split(':')
113 if len(parts) > 5:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000114 raise _OptionError("too many fields (max 5): %r" % (arg,))
Tim Peterse1190062001-01-15 03:34:38 +0000115 while len(parts) < 5:
116 parts.append('')
117 action, message, category, module, lineno = [s.strip()
118 for s in parts]
119 action = _getaction(action)
120 message = re.escape(message)
121 category = _getcategory(category)
122 module = re.escape(module)
123 if module:
124 module = module + '$'
125 if lineno:
126 try:
127 lineno = int(lineno)
128 if lineno < 0:
129 raise ValueError
130 except (ValueError, OverflowError):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000131 raise _OptionError("invalid lineno %r" % (lineno,))
Tim Peterse1190062001-01-15 03:34:38 +0000132 else:
133 lineno = 0
134 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000135
136# Helper for _setoption()
137def _getaction(action):
138 if not action:
139 return "default"
140 if action == "all": return "always" # Alias
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000141 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000142 if a.startswith(action):
143 return a
Walter Dörwald70a6b492004-02-12 17:35:32 +0000144 raise _OptionError("invalid action: %r" % (action,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000145
146# Helper for _setoption()
147def _getcategory(category):
Skip Montanarod8f21202003-05-14 17:33:53 +0000148 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000149 if not category:
150 return Warning
151 if re.match("^[a-zA-Z0-9_]+$", category):
152 try:
153 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000154 except NameError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000155 raise _OptionError("unknown warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000156 else:
157 i = category.rfind(".")
158 module = category[:i]
159 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000160 try:
Brett Cannoncd171c82013-07-04 17:43:24 -0400161 m = __import__(module, None, None, [klass])
162 except ImportError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000163 raise _OptionError("invalid module name: %r" % (module,))
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000164 try:
165 cat = getattr(m, klass)
166 except AttributeError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000167 raise _OptionError("unknown warning category: %r" % (category,))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000168 if not issubclass(cat, Warning):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000169 raise _OptionError("invalid warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000170 return cat
171
Christian Heimes33fe8092008-04-13 13:53:33 +0000172
Larry Hastings714e4932015-09-06 00:39:37 -0700173def _is_internal_frame(frame):
174 """Signal whether the frame is an internal CPython implementation detail."""
175 filename = frame.f_code.co_filename
176 return 'importlib' in filename and '_bootstrap' in filename
177
178
179def _next_external_frame(frame):
180 """Find the next frame that doesn't involve CPython internals."""
181 frame = frame.f_back
182 while frame is not None and _is_internal_frame(frame):
183 frame = frame.f_back
184 return frame
185
186
Christian Heimes33fe8092008-04-13 13:53:33 +0000187# Code typically replaced by _warnings
188def warn(message, category=None, stacklevel=1):
189 """Issue a warning, or maybe ignore it or raise an exception."""
190 # Check if message is already a Warning object
191 if isinstance(message, Warning):
192 category = message.__class__
193 # Check category argument
194 if category is None:
195 category = UserWarning
Berker Peksagd8089e02014-07-11 19:50:25 +0300196 if not (isinstance(category, type) and issubclass(category, Warning)):
197 raise TypeError("category must be a Warning subclass, "
198 "not '{:s}'".format(type(category).__name__))
Christian Heimes33fe8092008-04-13 13:53:33 +0000199 # Get context information
200 try:
Larry Hastings714e4932015-09-06 00:39:37 -0700201 if stacklevel <= 1 or _is_internal_frame(sys._getframe(1)):
202 # If frame is too small to care or if the warning originated in
203 # internal code, then do not try to hide any frames.
204 frame = sys._getframe(stacklevel)
205 else:
206 frame = sys._getframe(1)
207 # Look for one frame less since the above line starts us off.
208 for x in range(stacklevel-1):
209 frame = _next_external_frame(frame)
210 if frame is None:
211 raise ValueError
Christian Heimes33fe8092008-04-13 13:53:33 +0000212 except ValueError:
213 globals = sys.__dict__
214 lineno = 1
215 else:
Larry Hastings714e4932015-09-06 00:39:37 -0700216 globals = frame.f_globals
217 lineno = frame.f_lineno
Christian Heimes33fe8092008-04-13 13:53:33 +0000218 if '__name__' in globals:
219 module = globals['__name__']
220 else:
221 module = "<string>"
222 filename = globals.get('__file__')
223 if filename:
224 fnl = filename.lower()
Brett Cannonf299abd2015-04-13 14:21:02 -0400225 if fnl.endswith(".pyc"):
Christian Heimes33fe8092008-04-13 13:53:33 +0000226 filename = filename[:-1]
227 else:
228 if module == "__main__":
229 try:
230 filename = sys.argv[0]
231 except AttributeError:
232 # embedded interpreters don't have sys.argv, see bug #839151
233 filename = '__main__'
234 if not filename:
235 filename = module
236 registry = globals.setdefault("__warningregistry__", {})
237 warn_explicit(message, category, filename, lineno, module, registry,
238 globals)
239
240def warn_explicit(message, category, filename, lineno,
241 module=None, registry=None, module_globals=None):
Brett Cannondb734912008-06-27 00:52:15 +0000242 lineno = int(lineno)
Christian Heimes33fe8092008-04-13 13:53:33 +0000243 if module is None:
244 module = filename or "<unknown>"
245 if module[-3:].lower() == ".py":
246 module = module[:-3] # XXX What about leading pathname?
247 if registry is None:
248 registry = {}
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200249 if registry.get('version', 0) != _filters_version:
250 registry.clear()
251 registry['version'] = _filters_version
Christian Heimes33fe8092008-04-13 13:53:33 +0000252 if isinstance(message, Warning):
253 text = str(message)
254 category = message.__class__
255 else:
256 text = message
257 message = category(message)
258 key = (text, category, lineno)
259 # Quick test for common case
260 if registry.get(key):
261 return
262 # Search the filters
263 for item in filters:
264 action, msg, cat, mod, ln = item
265 if ((msg is None or msg.match(text)) and
266 issubclass(category, cat) and
267 (mod is None or mod.match(module)) and
268 (ln == 0 or lineno == ln)):
269 break
270 else:
271 action = defaultaction
272 # Early exit actions
273 if action == "ignore":
274 registry[key] = 1
275 return
276
277 # Prime the linecache for formatting, in case the
278 # "file" is actually in a zipfile or something.
Antoine Pitrou7cb11fa2013-10-24 22:23:42 +0200279 import linecache
Christian Heimes33fe8092008-04-13 13:53:33 +0000280 linecache.getlines(filename, module_globals)
281
282 if action == "error":
283 raise message
284 # Other actions
285 if action == "once":
286 registry[key] = 1
287 oncekey = (text, category)
288 if onceregistry.get(oncekey):
289 return
290 onceregistry[oncekey] = 1
291 elif action == "always":
292 pass
293 elif action == "module":
294 registry[key] = 1
295 altkey = (text, category, 0)
296 if registry.get(altkey):
297 return
298 registry[altkey] = 1
299 elif action == "default":
300 registry[key] = 1
301 else:
302 # Unrecognized actions are errors
303 raise RuntimeError(
304 "Unrecognized action (%r) in warnings.filters:\n %s" %
305 (action, item))
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200306 if not callable(showwarning):
Christian Heimes8dc226f2008-05-06 23:45:46 +0000307 raise TypeError("warnings.showwarning() must be set to a "
308 "function or method")
Christian Heimes33fe8092008-04-13 13:53:33 +0000309 # Print message and context
310 showwarning(message, category, filename, lineno)
311
312
Brett Cannonec92e182008-09-02 02:46:59 +0000313class WarningMessage(object):
314
315 """Holds the result of a single showwarning() call."""
316
317 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
318 "line")
319
320 def __init__(self, message, category, filename, lineno, file=None,
321 line=None):
322 local_values = locals()
323 for attr in self._WARNING_DETAILS:
324 setattr(self, attr, local_values[attr])
325 self._category_name = category.__name__ if category else None
326
327 def __str__(self):
328 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
329 "line : %r}" % (self.message, self._category_name,
330 self.filename, self.lineno, self.line))
331
332
Brett Cannonec92e182008-09-02 02:46:59 +0000333class catch_warnings(object):
334
Brett Cannon1cd02472008-09-09 01:52:27 +0000335 """A context manager that copies and restores the warnings filter upon
336 exiting the context.
Brett Cannonec92e182008-09-02 02:46:59 +0000337
Brett Cannon1cd02472008-09-09 01:52:27 +0000338 The 'record' argument specifies whether warnings should be captured by a
339 custom implementation of warnings.showwarning() and be appended to a list
340 returned by the context manager. Otherwise None is returned by the context
341 manager. The objects appended to the list are arguments whose attributes
342 mirror the arguments to showwarning().
343
344 The 'module' argument is to specify an alternative module to the module
345 named 'warnings' and imported under that name. This argument is only useful
346 when testing the warnings module itself.
Brett Cannonec92e182008-09-02 02:46:59 +0000347
348 """
349
350 def __init__(self, *, record=False, module=None):
351 """Specify whether to record warnings and if an alternative module
352 should be used other than sys.modules['warnings'].
353
354 For compatibility with Python 3.0, please consider all arguments to be
355 keyword-only.
356
357 """
Brett Cannon1cd02472008-09-09 01:52:27 +0000358 self._record = record
Brett Cannonec92e182008-09-02 02:46:59 +0000359 self._module = sys.modules['warnings'] if module is None else module
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000360 self._entered = False
361
362 def __repr__(self):
363 args = []
364 if self._record:
365 args.append("record=True")
366 if self._module is not sys.modules['warnings']:
367 args.append("module=%r" % self._module)
368 name = type(self).__name__
369 return "%s(%s)" % (name, ", ".join(args))
Brett Cannonec92e182008-09-02 02:46:59 +0000370
371 def __enter__(self):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000372 if self._entered:
373 raise RuntimeError("Cannot enter %r twice" % self)
374 self._entered = True
Brett Cannonec92e182008-09-02 02:46:59 +0000375 self._filters = self._module.filters
376 self._module.filters = self._filters[:]
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200377 self._module._filters_mutated()
Brett Cannonec92e182008-09-02 02:46:59 +0000378 self._showwarning = self._module.showwarning
Brett Cannon1cd02472008-09-09 01:52:27 +0000379 if self._record:
380 log = []
381 def showwarning(*args, **kwargs):
382 log.append(WarningMessage(*args, **kwargs))
383 self._module.showwarning = showwarning
384 return log
385 else:
386 return None
Brett Cannonec92e182008-09-02 02:46:59 +0000387
388 def __exit__(self, *exc_info):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000389 if not self._entered:
390 raise RuntimeError("Cannot exit %r without entering first" % self)
Brett Cannonec92e182008-09-02 02:46:59 +0000391 self._module.filters = self._filters
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200392 self._module._filters_mutated()
Brett Cannonec92e182008-09-02 02:46:59 +0000393 self._module.showwarning = self._showwarning
394
395
Christian Heimes33fe8092008-04-13 13:53:33 +0000396# filters contains a sequence of filter 5-tuples
397# The components of the 5-tuple are:
398# - an action: error, ignore, always, default, module, or once
399# - a compiled regex that must match the warning message
400# - a class representing the warning category
401# - a compiled regex that must match the module that is being warned
402# - a line number for the line being warning, or 0 to mean any line
403# If either if the compiled regexs are None, match anything.
404_warnings_defaults = False
405try:
Brett Cannonef0e6c32010-09-04 18:24:04 +0000406 from _warnings import (filters, _defaultaction, _onceregistry,
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200407 warn, warn_explicit, _filters_mutated)
Brett Cannonef0e6c32010-09-04 18:24:04 +0000408 defaultaction = _defaultaction
409 onceregistry = _onceregistry
Christian Heimes33fe8092008-04-13 13:53:33 +0000410 _warnings_defaults = True
Brett Cannoncd171c82013-07-04 17:43:24 -0400411except ImportError:
Christian Heimes33fe8092008-04-13 13:53:33 +0000412 filters = []
413 defaultaction = "default"
414 onceregistry = {}
415
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200416 _filters_version = 1
417
418 def _filters_mutated():
419 global _filters_version
420 _filters_version += 1
421
Christian Heimes33fe8092008-04-13 13:53:33 +0000422
Guido van Rossum2a862c62000-12-15 21:59:53 +0000423# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000424_processoptions(sys.warnoptions)
Christian Heimes33fe8092008-04-13 13:53:33 +0000425if not _warnings_defaults:
Benjamin Peterson7ab4b8d2010-06-28 00:01:59 +0000426 silence = [ImportWarning, PendingDeprecationWarning]
427 silence.append(DeprecationWarning)
428 for cls in silence:
429 simplefilter("ignore", category=cls)
Christian Heimes33fe8092008-04-13 13:53:33 +0000430 bytes_warning = sys.flags.bytes_warning
431 if bytes_warning > 1:
432 bytes_action = "error"
433 elif bytes_warning:
434 bytes_action = "default"
435 else:
436 bytes_action = "ignore"
437 simplefilter(bytes_action, category=BytesWarning, append=1)
Georg Brandl08be72d2010-10-24 15:11:22 +0000438 # resource usage warnings are enabled by default in pydebug mode
439 if hasattr(sys, 'gettotalrefcount'):
440 resource_action = "always"
441 else:
442 resource_action = "ignore"
443 simplefilter(resource_action, category=ResourceWarning, append=1)
444
Christian Heimes33fe8092008-04-13 13:53:33 +0000445del _warnings_defaults