blob: 1d4fb208f831c8ec92472114e5127bfbf09c0554 [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."""
Antoine Pitrou7cb11fa2013-10-24 22:23:42 +020024 import linecache
Guido van Rossum2a862c62000-12-15 21:59:53 +000025 s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
Christian Heimes33fe8092008-04-13 13:53:33 +000026 line = linecache.getline(filename, lineno) if line is None else line
Guido van Rossum2a862c62000-12-15 21:59:53 +000027 if line:
Christian Heimes33fe8092008-04-13 13:53:33 +000028 line = line.strip()
29 s += " %s\n" % line
Guido van Rossum2a862c62000-12-15 21:59:53 +000030 return s
31
Guido van Rossum9464a7d2001-01-14 14:08:40 +000032def filterwarnings(action, message="", category=Warning, module="", lineno=0,
Georg Brandlfe991052009-09-16 15:54:04 +000033 append=False):
Guido van Rossum2a862c62000-12-15 21:59:53 +000034 """Insert an entry into the list of warnings filters (at the front).
35
Georg Brandl495f7b52009-10-27 15:28:25 +000036 'action' -- one of "error", "ignore", "always", "default", "module",
37 or "once"
38 'message' -- a regex that the warning message must match
39 'category' -- a class that the warning must be a subclass of
40 'module' -- a regex that the module name must match
41 'lineno' -- an integer line number, 0 matches all warnings
42 'append' -- if true, append to the list of filters
43 """
Skip Montanarod8f21202003-05-14 17:33:53 +000044 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +000045 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000046 "once"), "invalid action: %r" % (action,)
Guido van Rossum3172c5d2007-10-16 18:12:55 +000047 assert isinstance(message, str), "message must be a string"
Guido van Rossum13257902007-06-07 23:15:56 +000048 assert isinstance(category, type), "category must be a class"
Guido van Rossum2a862c62000-12-15 21:59:53 +000049 assert issubclass(category, Warning), "category must be a Warning subclass"
Guido van Rossum3172c5d2007-10-16 18:12:55 +000050 assert isinstance(module, str), "module must be a string"
Walter Dörwald65230a22002-06-03 15:58:32 +000051 assert isinstance(lineno, int) and lineno >= 0, \
Guido van Rossum2a862c62000-12-15 21:59:53 +000052 "lineno must be an int >= 0"
Guido van Rossum9464a7d2001-01-14 14:08:40 +000053 item = (action, re.compile(message, re.I), category,
54 re.compile(module), lineno)
55 if append:
56 filters.append(item)
57 else:
58 filters.insert(0, item)
Antoine Pitroucb0a0062014-09-18 02:40:46 +020059 _filters_mutated()
Guido van Rossum2a862c62000-12-15 21:59:53 +000060
Georg Brandlfe991052009-09-16 15:54:04 +000061def simplefilter(action, category=Warning, lineno=0, append=False):
Jeremy Hylton85014662003-07-11 15:37:59 +000062 """Insert a simple entry into the list of warnings filters (at the front).
63
64 A simple filter matches all modules and messages.
Georg Brandl495f7b52009-10-27 15:28:25 +000065 'action' -- one of "error", "ignore", "always", "default", "module",
66 or "once"
67 'category' -- a class that the warning must be a subclass of
68 'lineno' -- an integer line number, 0 matches all warnings
69 'append' -- if true, append to the list of filters
Jeremy Hylton85014662003-07-11 15:37:59 +000070 """
71 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000072 "once"), "invalid action: %r" % (action,)
Jeremy Hylton85014662003-07-11 15:37:59 +000073 assert isinstance(lineno, int) and lineno >= 0, \
74 "lineno must be an int >= 0"
75 item = (action, None, category, None, lineno)
76 if append:
77 filters.append(item)
78 else:
79 filters.insert(0, item)
Antoine Pitroucb0a0062014-09-18 02:40:46 +020080 _filters_mutated()
Jeremy Hylton85014662003-07-11 15:37:59 +000081
Guido van Rossum2a862c62000-12-15 21:59:53 +000082def resetwarnings():
Tim Petersd0cc4f02002-04-16 01:51:25 +000083 """Clear the list of warning filters, so that no filters are active."""
Guido van Rossum2a862c62000-12-15 21:59:53 +000084 filters[:] = []
Antoine Pitroucb0a0062014-09-18 02:40:46 +020085 _filters_mutated()
Guido van Rossum2a862c62000-12-15 21:59:53 +000086
87class _OptionError(Exception):
88 """Exception used by option processing helpers."""
89 pass
90
91# Helper to process -W options passed via sys.warnoptions
92def _processoptions(args):
93 for arg in args:
94 try:
95 _setoption(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +000096 except _OptionError as msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000097 print("Invalid -W option ignored:", msg, file=sys.stderr)
Guido van Rossum2a862c62000-12-15 21:59:53 +000098
99# Helper for _processoptions()
100def _setoption(arg):
Skip Montanarod8f21202003-05-14 17:33:53 +0000101 import re
Tim Peterse1190062001-01-15 03:34:38 +0000102 parts = arg.split(':')
103 if len(parts) > 5:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000104 raise _OptionError("too many fields (max 5): %r" % (arg,))
Tim Peterse1190062001-01-15 03:34:38 +0000105 while len(parts) < 5:
106 parts.append('')
107 action, message, category, module, lineno = [s.strip()
108 for s in parts]
109 action = _getaction(action)
110 message = re.escape(message)
111 category = _getcategory(category)
112 module = re.escape(module)
113 if module:
114 module = module + '$'
115 if lineno:
116 try:
117 lineno = int(lineno)
118 if lineno < 0:
119 raise ValueError
120 except (ValueError, OverflowError):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000121 raise _OptionError("invalid lineno %r" % (lineno,))
Tim Peterse1190062001-01-15 03:34:38 +0000122 else:
123 lineno = 0
124 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000125
126# Helper for _setoption()
127def _getaction(action):
128 if not action:
129 return "default"
130 if action == "all": return "always" # Alias
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000131 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000132 if a.startswith(action):
133 return a
Walter Dörwald70a6b492004-02-12 17:35:32 +0000134 raise _OptionError("invalid action: %r" % (action,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000135
136# Helper for _setoption()
137def _getcategory(category):
Skip Montanarod8f21202003-05-14 17:33:53 +0000138 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000139 if not category:
140 return Warning
141 if re.match("^[a-zA-Z0-9_]+$", category):
142 try:
143 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000144 except NameError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000145 raise _OptionError("unknown warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000146 else:
147 i = category.rfind(".")
148 module = category[:i]
149 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000150 try:
Brett Cannoncd171c82013-07-04 17:43:24 -0400151 m = __import__(module, None, None, [klass])
152 except ImportError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000153 raise _OptionError("invalid module name: %r" % (module,))
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000154 try:
155 cat = getattr(m, klass)
156 except AttributeError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000157 raise _OptionError("unknown warning category: %r" % (category,))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000158 if not issubclass(cat, Warning):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000159 raise _OptionError("invalid warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000160 return cat
161
Christian Heimes33fe8092008-04-13 13:53:33 +0000162
Larry Hastings714e4932015-09-06 00:39:37 -0700163def _is_internal_frame(frame):
164 """Signal whether the frame is an internal CPython implementation detail."""
165 filename = frame.f_code.co_filename
166 return 'importlib' in filename and '_bootstrap' in filename
167
168
169def _next_external_frame(frame):
170 """Find the next frame that doesn't involve CPython internals."""
171 frame = frame.f_back
172 while frame is not None and _is_internal_frame(frame):
173 frame = frame.f_back
174 return frame
175
176
Christian Heimes33fe8092008-04-13 13:53:33 +0000177# Code typically replaced by _warnings
178def warn(message, category=None, stacklevel=1):
179 """Issue a warning, or maybe ignore it or raise an exception."""
180 # Check if message is already a Warning object
181 if isinstance(message, Warning):
182 category = message.__class__
183 # Check category argument
184 if category is None:
185 category = UserWarning
Berker Peksagd8089e02014-07-11 19:50:25 +0300186 if not (isinstance(category, type) and issubclass(category, Warning)):
187 raise TypeError("category must be a Warning subclass, "
188 "not '{:s}'".format(type(category).__name__))
Christian Heimes33fe8092008-04-13 13:53:33 +0000189 # Get context information
190 try:
Larry Hastings714e4932015-09-06 00:39:37 -0700191 if stacklevel <= 1 or _is_internal_frame(sys._getframe(1)):
192 # If frame is too small to care or if the warning originated in
193 # internal code, then do not try to hide any frames.
194 frame = sys._getframe(stacklevel)
195 else:
196 frame = sys._getframe(1)
197 # Look for one frame less since the above line starts us off.
198 for x in range(stacklevel-1):
199 frame = _next_external_frame(frame)
200 if frame is None:
201 raise ValueError
Christian Heimes33fe8092008-04-13 13:53:33 +0000202 except ValueError:
203 globals = sys.__dict__
204 lineno = 1
205 else:
Larry Hastings714e4932015-09-06 00:39:37 -0700206 globals = frame.f_globals
207 lineno = frame.f_lineno
Christian Heimes33fe8092008-04-13 13:53:33 +0000208 if '__name__' in globals:
209 module = globals['__name__']
210 else:
211 module = "<string>"
212 filename = globals.get('__file__')
213 if filename:
214 fnl = filename.lower()
Brett Cannonf299abd2015-04-13 14:21:02 -0400215 if fnl.endswith(".pyc"):
Christian Heimes33fe8092008-04-13 13:53:33 +0000216 filename = filename[:-1]
217 else:
218 if module == "__main__":
219 try:
220 filename = sys.argv[0]
221 except AttributeError:
222 # embedded interpreters don't have sys.argv, see bug #839151
223 filename = '__main__'
224 if not filename:
225 filename = module
226 registry = globals.setdefault("__warningregistry__", {})
227 warn_explicit(message, category, filename, lineno, module, registry,
228 globals)
229
230def warn_explicit(message, category, filename, lineno,
231 module=None, registry=None, module_globals=None):
Brett Cannondb734912008-06-27 00:52:15 +0000232 lineno = int(lineno)
Christian Heimes33fe8092008-04-13 13:53:33 +0000233 if module is None:
234 module = filename or "<unknown>"
235 if module[-3:].lower() == ".py":
236 module = module[:-3] # XXX What about leading pathname?
237 if registry is None:
238 registry = {}
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200239 if registry.get('version', 0) != _filters_version:
240 registry.clear()
241 registry['version'] = _filters_version
Christian Heimes33fe8092008-04-13 13:53:33 +0000242 if isinstance(message, Warning):
243 text = str(message)
244 category = message.__class__
245 else:
246 text = message
247 message = category(message)
248 key = (text, category, lineno)
249 # Quick test for common case
250 if registry.get(key):
251 return
252 # Search the filters
253 for item in filters:
254 action, msg, cat, mod, ln = item
255 if ((msg is None or msg.match(text)) and
256 issubclass(category, cat) and
257 (mod is None or mod.match(module)) and
258 (ln == 0 or lineno == ln)):
259 break
260 else:
261 action = defaultaction
262 # Early exit actions
263 if action == "ignore":
264 registry[key] = 1
265 return
266
267 # Prime the linecache for formatting, in case the
268 # "file" is actually in a zipfile or something.
Antoine Pitrou7cb11fa2013-10-24 22:23:42 +0200269 import linecache
Christian Heimes33fe8092008-04-13 13:53:33 +0000270 linecache.getlines(filename, module_globals)
271
272 if action == "error":
273 raise message
274 # Other actions
275 if action == "once":
276 registry[key] = 1
277 oncekey = (text, category)
278 if onceregistry.get(oncekey):
279 return
280 onceregistry[oncekey] = 1
281 elif action == "always":
282 pass
283 elif action == "module":
284 registry[key] = 1
285 altkey = (text, category, 0)
286 if registry.get(altkey):
287 return
288 registry[altkey] = 1
289 elif action == "default":
290 registry[key] = 1
291 else:
292 # Unrecognized actions are errors
293 raise RuntimeError(
294 "Unrecognized action (%r) in warnings.filters:\n %s" %
295 (action, item))
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200296 if not callable(showwarning):
Christian Heimes8dc226f2008-05-06 23:45:46 +0000297 raise TypeError("warnings.showwarning() must be set to a "
298 "function or method")
Christian Heimes33fe8092008-04-13 13:53:33 +0000299 # Print message and context
300 showwarning(message, category, filename, lineno)
301
302
Brett Cannonec92e182008-09-02 02:46:59 +0000303class WarningMessage(object):
304
305 """Holds the result of a single showwarning() call."""
306
307 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
308 "line")
309
310 def __init__(self, message, category, filename, lineno, file=None,
311 line=None):
312 local_values = locals()
313 for attr in self._WARNING_DETAILS:
314 setattr(self, attr, local_values[attr])
315 self._category_name = category.__name__ if category else None
316
317 def __str__(self):
318 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
319 "line : %r}" % (self.message, self._category_name,
320 self.filename, self.lineno, self.line))
321
322
Brett Cannonec92e182008-09-02 02:46:59 +0000323class catch_warnings(object):
324
Brett Cannon1cd02472008-09-09 01:52:27 +0000325 """A context manager that copies and restores the warnings filter upon
326 exiting the context.
Brett Cannonec92e182008-09-02 02:46:59 +0000327
Brett Cannon1cd02472008-09-09 01:52:27 +0000328 The 'record' argument specifies whether warnings should be captured by a
329 custom implementation of warnings.showwarning() and be appended to a list
330 returned by the context manager. Otherwise None is returned by the context
331 manager. The objects appended to the list are arguments whose attributes
332 mirror the arguments to showwarning().
333
334 The 'module' argument is to specify an alternative module to the module
335 named 'warnings' and imported under that name. This argument is only useful
336 when testing the warnings module itself.
Brett Cannonec92e182008-09-02 02:46:59 +0000337
338 """
339
340 def __init__(self, *, record=False, module=None):
341 """Specify whether to record warnings and if an alternative module
342 should be used other than sys.modules['warnings'].
343
344 For compatibility with Python 3.0, please consider all arguments to be
345 keyword-only.
346
347 """
Brett Cannon1cd02472008-09-09 01:52:27 +0000348 self._record = record
Brett Cannonec92e182008-09-02 02:46:59 +0000349 self._module = sys.modules['warnings'] if module is None else module
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000350 self._entered = False
351
352 def __repr__(self):
353 args = []
354 if self._record:
355 args.append("record=True")
356 if self._module is not sys.modules['warnings']:
357 args.append("module=%r" % self._module)
358 name = type(self).__name__
359 return "%s(%s)" % (name, ", ".join(args))
Brett Cannonec92e182008-09-02 02:46:59 +0000360
361 def __enter__(self):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000362 if self._entered:
363 raise RuntimeError("Cannot enter %r twice" % self)
364 self._entered = True
Brett Cannonec92e182008-09-02 02:46:59 +0000365 self._filters = self._module.filters
366 self._module.filters = self._filters[:]
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200367 self._module._filters_mutated()
Brett Cannonec92e182008-09-02 02:46:59 +0000368 self._showwarning = self._module.showwarning
Brett Cannon1cd02472008-09-09 01:52:27 +0000369 if self._record:
370 log = []
371 def showwarning(*args, **kwargs):
372 log.append(WarningMessage(*args, **kwargs))
373 self._module.showwarning = showwarning
374 return log
375 else:
376 return None
Brett Cannonec92e182008-09-02 02:46:59 +0000377
378 def __exit__(self, *exc_info):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000379 if not self._entered:
380 raise RuntimeError("Cannot exit %r without entering first" % self)
Brett Cannonec92e182008-09-02 02:46:59 +0000381 self._module.filters = self._filters
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200382 self._module._filters_mutated()
Brett Cannonec92e182008-09-02 02:46:59 +0000383 self._module.showwarning = self._showwarning
384
385
Christian Heimes33fe8092008-04-13 13:53:33 +0000386# filters contains a sequence of filter 5-tuples
387# The components of the 5-tuple are:
388# - an action: error, ignore, always, default, module, or once
389# - a compiled regex that must match the warning message
390# - a class representing the warning category
391# - a compiled regex that must match the module that is being warned
392# - a line number for the line being warning, or 0 to mean any line
393# If either if the compiled regexs are None, match anything.
394_warnings_defaults = False
395try:
Brett Cannonef0e6c32010-09-04 18:24:04 +0000396 from _warnings import (filters, _defaultaction, _onceregistry,
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200397 warn, warn_explicit, _filters_mutated)
Brett Cannonef0e6c32010-09-04 18:24:04 +0000398 defaultaction = _defaultaction
399 onceregistry = _onceregistry
Christian Heimes33fe8092008-04-13 13:53:33 +0000400 _warnings_defaults = True
Brett Cannoncd171c82013-07-04 17:43:24 -0400401except ImportError:
Christian Heimes33fe8092008-04-13 13:53:33 +0000402 filters = []
403 defaultaction = "default"
404 onceregistry = {}
405
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200406 _filters_version = 1
407
408 def _filters_mutated():
409 global _filters_version
410 _filters_version += 1
411
Christian Heimes33fe8092008-04-13 13:53:33 +0000412
Guido van Rossum2a862c62000-12-15 21:59:53 +0000413# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000414_processoptions(sys.warnoptions)
Christian Heimes33fe8092008-04-13 13:53:33 +0000415if not _warnings_defaults:
Benjamin Peterson7ab4b8d2010-06-28 00:01:59 +0000416 silence = [ImportWarning, PendingDeprecationWarning]
417 silence.append(DeprecationWarning)
418 for cls in silence:
419 simplefilter("ignore", category=cls)
Christian Heimes33fe8092008-04-13 13:53:33 +0000420 bytes_warning = sys.flags.bytes_warning
421 if bytes_warning > 1:
422 bytes_action = "error"
423 elif bytes_warning:
424 bytes_action = "default"
425 else:
426 bytes_action = "ignore"
427 simplefilter(bytes_action, category=BytesWarning, append=1)
Georg Brandl08be72d2010-10-24 15:11:22 +0000428 # resource usage warnings are enabled by default in pydebug mode
429 if hasattr(sys, 'gettotalrefcount'):
430 resource_action = "always"
431 else:
432 resource_action = "ignore"
433 simplefilter(resource_action, category=ResourceWarning, append=1)
434
Christian Heimes33fe8092008-04-13 13:53:33 +0000435del _warnings_defaults