blob: f7319258f8ed765fde12cec23303820fd0ad703d [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)
Antoine Pitroucb0a0062014-09-18 02:40:46 +020056 _filters_mutated()
Guido van Rossum2a862c62000-12-15 21:59:53 +000057
Georg Brandlfe991052009-09-16 15:54:04 +000058def simplefilter(action, category=Warning, lineno=0, append=False):
Jeremy Hylton85014662003-07-11 15:37:59 +000059 """Insert a simple entry into the list of warnings filters (at the front).
60
61 A simple filter matches all modules and messages.
Georg Brandl495f7b52009-10-27 15:28:25 +000062 'action' -- one of "error", "ignore", "always", "default", "module",
63 or "once"
64 'category' -- a class that the warning must be a subclass of
65 'lineno' -- an integer line number, 0 matches all warnings
66 'append' -- if true, append to the list of filters
Jeremy Hylton85014662003-07-11 15:37:59 +000067 """
68 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000069 "once"), "invalid action: %r" % (action,)
Jeremy Hylton85014662003-07-11 15:37:59 +000070 assert isinstance(lineno, int) and lineno >= 0, \
71 "lineno must be an int >= 0"
72 item = (action, None, category, None, lineno)
73 if append:
74 filters.append(item)
75 else:
76 filters.insert(0, item)
Antoine Pitroucb0a0062014-09-18 02:40:46 +020077 _filters_mutated()
Jeremy Hylton85014662003-07-11 15:37:59 +000078
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[:] = []
Antoine Pitroucb0a0062014-09-18 02:40:46 +020082 _filters_mutated()
Guido van Rossum2a862c62000-12-15 21:59:53 +000083
84class _OptionError(Exception):
85 """Exception used by option processing helpers."""
86 pass
87
88# Helper to process -W options passed via sys.warnoptions
89def _processoptions(args):
90 for arg in args:
91 try:
92 _setoption(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +000093 except _OptionError as msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000094 print("Invalid -W option ignored:", msg, file=sys.stderr)
Guido van Rossum2a862c62000-12-15 21:59:53 +000095
96# Helper for _processoptions()
97def _setoption(arg):
Skip Montanarod8f21202003-05-14 17:33:53 +000098 import re
Tim Peterse1190062001-01-15 03:34:38 +000099 parts = arg.split(':')
100 if len(parts) > 5:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000101 raise _OptionError("too many fields (max 5): %r" % (arg,))
Tim Peterse1190062001-01-15 03:34:38 +0000102 while len(parts) < 5:
103 parts.append('')
104 action, message, category, module, lineno = [s.strip()
105 for s in parts]
106 action = _getaction(action)
107 message = re.escape(message)
108 category = _getcategory(category)
109 module = re.escape(module)
110 if module:
111 module = module + '$'
112 if lineno:
113 try:
114 lineno = int(lineno)
115 if lineno < 0:
116 raise ValueError
117 except (ValueError, OverflowError):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000118 raise _OptionError("invalid lineno %r" % (lineno,))
Tim Peterse1190062001-01-15 03:34:38 +0000119 else:
120 lineno = 0
121 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000122
123# Helper for _setoption()
124def _getaction(action):
125 if not action:
126 return "default"
127 if action == "all": return "always" # Alias
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000128 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000129 if a.startswith(action):
130 return a
Walter Dörwald70a6b492004-02-12 17:35:32 +0000131 raise _OptionError("invalid action: %r" % (action,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000132
133# Helper for _setoption()
134def _getcategory(category):
Skip Montanarod8f21202003-05-14 17:33:53 +0000135 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000136 if not category:
137 return Warning
138 if re.match("^[a-zA-Z0-9_]+$", category):
139 try:
140 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000141 except NameError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000142 raise _OptionError("unknown warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000143 else:
144 i = category.rfind(".")
145 module = category[:i]
146 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000147 try:
Brett Cannoncd171c82013-07-04 17:43:24 -0400148 m = __import__(module, None, None, [klass])
149 except ImportError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000150 raise _OptionError("invalid module name: %r" % (module,))
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000151 try:
152 cat = getattr(m, klass)
153 except AttributeError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000154 raise _OptionError("unknown warning category: %r" % (category,))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000155 if not issubclass(cat, Warning):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000156 raise _OptionError("invalid warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000157 return cat
158
Christian Heimes33fe8092008-04-13 13:53:33 +0000159
160# Code typically replaced by _warnings
161def warn(message, category=None, stacklevel=1):
162 """Issue a warning, or maybe ignore it or raise an exception."""
163 # Check if message is already a Warning object
164 if isinstance(message, Warning):
165 category = message.__class__
166 # Check category argument
167 if category is None:
168 category = UserWarning
Berker Peksagd8089e02014-07-11 19:50:25 +0300169 if not (isinstance(category, type) and issubclass(category, Warning)):
170 raise TypeError("category must be a Warning subclass, "
171 "not '{:s}'".format(type(category).__name__))
Christian Heimes33fe8092008-04-13 13:53:33 +0000172 # Get context information
173 try:
174 caller = sys._getframe(stacklevel)
175 except ValueError:
176 globals = sys.__dict__
177 lineno = 1
178 else:
179 globals = caller.f_globals
180 lineno = caller.f_lineno
181 if '__name__' in globals:
182 module = globals['__name__']
183 else:
184 module = "<string>"
185 filename = globals.get('__file__')
186 if filename:
187 fnl = filename.lower()
188 if fnl.endswith((".pyc", ".pyo")):
189 filename = filename[:-1]
190 else:
191 if module == "__main__":
192 try:
193 filename = sys.argv[0]
194 except AttributeError:
195 # embedded interpreters don't have sys.argv, see bug #839151
196 filename = '__main__'
197 if not filename:
198 filename = module
199 registry = globals.setdefault("__warningregistry__", {})
200 warn_explicit(message, category, filename, lineno, module, registry,
201 globals)
202
203def warn_explicit(message, category, filename, lineno,
204 module=None, registry=None, module_globals=None):
Brett Cannondb734912008-06-27 00:52:15 +0000205 lineno = int(lineno)
Christian Heimes33fe8092008-04-13 13:53:33 +0000206 if module is None:
207 module = filename or "<unknown>"
208 if module[-3:].lower() == ".py":
209 module = module[:-3] # XXX What about leading pathname?
210 if registry is None:
211 registry = {}
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200212 if registry.get('version', 0) != _filters_version:
213 registry.clear()
214 registry['version'] = _filters_version
Christian Heimes33fe8092008-04-13 13:53:33 +0000215 if isinstance(message, Warning):
216 text = str(message)
217 category = message.__class__
218 else:
219 text = message
220 message = category(message)
221 key = (text, category, lineno)
222 # Quick test for common case
223 if registry.get(key):
224 return
225 # Search the filters
226 for item in filters:
227 action, msg, cat, mod, ln = item
228 if ((msg is None or msg.match(text)) and
229 issubclass(category, cat) and
230 (mod is None or mod.match(module)) and
231 (ln == 0 or lineno == ln)):
232 break
233 else:
234 action = defaultaction
235 # Early exit actions
236 if action == "ignore":
237 registry[key] = 1
238 return
239
240 # Prime the linecache for formatting, in case the
241 # "file" is actually in a zipfile or something.
Antoine Pitrou7cb11fa2013-10-24 22:23:42 +0200242 import linecache
Christian Heimes33fe8092008-04-13 13:53:33 +0000243 linecache.getlines(filename, module_globals)
244
245 if action == "error":
246 raise message
247 # Other actions
248 if action == "once":
249 registry[key] = 1
250 oncekey = (text, category)
251 if onceregistry.get(oncekey):
252 return
253 onceregistry[oncekey] = 1
254 elif action == "always":
255 pass
256 elif action == "module":
257 registry[key] = 1
258 altkey = (text, category, 0)
259 if registry.get(altkey):
260 return
261 registry[altkey] = 1
262 elif action == "default":
263 registry[key] = 1
264 else:
265 # Unrecognized actions are errors
266 raise RuntimeError(
267 "Unrecognized action (%r) in warnings.filters:\n %s" %
268 (action, item))
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200269 if not callable(showwarning):
Christian Heimes8dc226f2008-05-06 23:45:46 +0000270 raise TypeError("warnings.showwarning() must be set to a "
271 "function or method")
Christian Heimes33fe8092008-04-13 13:53:33 +0000272 # Print message and context
273 showwarning(message, category, filename, lineno)
274
275
Brett Cannonec92e182008-09-02 02:46:59 +0000276class WarningMessage(object):
277
278 """Holds the result of a single showwarning() call."""
279
280 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
281 "line")
282
283 def __init__(self, message, category, filename, lineno, file=None,
284 line=None):
285 local_values = locals()
286 for attr in self._WARNING_DETAILS:
287 setattr(self, attr, local_values[attr])
288 self._category_name = category.__name__ if category else None
289
290 def __str__(self):
291 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
292 "line : %r}" % (self.message, self._category_name,
293 self.filename, self.lineno, self.line))
294
295
Brett Cannonec92e182008-09-02 02:46:59 +0000296class catch_warnings(object):
297
Brett Cannon1cd02472008-09-09 01:52:27 +0000298 """A context manager that copies and restores the warnings filter upon
299 exiting the context.
Brett Cannonec92e182008-09-02 02:46:59 +0000300
Brett Cannon1cd02472008-09-09 01:52:27 +0000301 The 'record' argument specifies whether warnings should be captured by a
302 custom implementation of warnings.showwarning() and be appended to a list
303 returned by the context manager. Otherwise None is returned by the context
304 manager. The objects appended to the list are arguments whose attributes
305 mirror the arguments to showwarning().
306
307 The 'module' argument is to specify an alternative module to the module
308 named 'warnings' and imported under that name. This argument is only useful
309 when testing the warnings module itself.
Brett Cannonec92e182008-09-02 02:46:59 +0000310
311 """
312
313 def __init__(self, *, record=False, module=None):
314 """Specify whether to record warnings and if an alternative module
315 should be used other than sys.modules['warnings'].
316
317 For compatibility with Python 3.0, please consider all arguments to be
318 keyword-only.
319
320 """
Brett Cannon1cd02472008-09-09 01:52:27 +0000321 self._record = record
Brett Cannonec92e182008-09-02 02:46:59 +0000322 self._module = sys.modules['warnings'] if module is None else module
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000323 self._entered = False
324
325 def __repr__(self):
326 args = []
327 if self._record:
328 args.append("record=True")
329 if self._module is not sys.modules['warnings']:
330 args.append("module=%r" % self._module)
331 name = type(self).__name__
332 return "%s(%s)" % (name, ", ".join(args))
Brett Cannonec92e182008-09-02 02:46:59 +0000333
334 def __enter__(self):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000335 if self._entered:
336 raise RuntimeError("Cannot enter %r twice" % self)
337 self._entered = True
Brett Cannonec92e182008-09-02 02:46:59 +0000338 self._filters = self._module.filters
339 self._module.filters = self._filters[:]
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200340 self._module._filters_mutated()
Brett Cannonec92e182008-09-02 02:46:59 +0000341 self._showwarning = self._module.showwarning
Brett Cannon1cd02472008-09-09 01:52:27 +0000342 if self._record:
343 log = []
344 def showwarning(*args, **kwargs):
345 log.append(WarningMessage(*args, **kwargs))
346 self._module.showwarning = showwarning
347 return log
348 else:
349 return None
Brett Cannonec92e182008-09-02 02:46:59 +0000350
351 def __exit__(self, *exc_info):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000352 if not self._entered:
353 raise RuntimeError("Cannot exit %r without entering first" % self)
Brett Cannonec92e182008-09-02 02:46:59 +0000354 self._module.filters = self._filters
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200355 self._module._filters_mutated()
Brett Cannonec92e182008-09-02 02:46:59 +0000356 self._module.showwarning = self._showwarning
357
358
Christian Heimes33fe8092008-04-13 13:53:33 +0000359# filters contains a sequence of filter 5-tuples
360# The components of the 5-tuple are:
361# - an action: error, ignore, always, default, module, or once
362# - a compiled regex that must match the warning message
363# - a class representing the warning category
364# - a compiled regex that must match the module that is being warned
365# - a line number for the line being warning, or 0 to mean any line
366# If either if the compiled regexs are None, match anything.
367_warnings_defaults = False
368try:
Brett Cannonef0e6c32010-09-04 18:24:04 +0000369 from _warnings import (filters, _defaultaction, _onceregistry,
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200370 warn, warn_explicit, _filters_mutated)
Brett Cannonef0e6c32010-09-04 18:24:04 +0000371 defaultaction = _defaultaction
372 onceregistry = _onceregistry
Christian Heimes33fe8092008-04-13 13:53:33 +0000373 _warnings_defaults = True
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200374
Brett Cannoncd171c82013-07-04 17:43:24 -0400375except ImportError:
Christian Heimes33fe8092008-04-13 13:53:33 +0000376 filters = []
377 defaultaction = "default"
378 onceregistry = {}
379
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200380 _filters_version = 1
381
382 def _filters_mutated():
383 global _filters_version
384 _filters_version += 1
385
Christian Heimes33fe8092008-04-13 13:53:33 +0000386
Guido van Rossum2a862c62000-12-15 21:59:53 +0000387# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000388_processoptions(sys.warnoptions)
Christian Heimes33fe8092008-04-13 13:53:33 +0000389if not _warnings_defaults:
Benjamin Peterson7ab4b8d2010-06-28 00:01:59 +0000390 silence = [ImportWarning, PendingDeprecationWarning]
391 silence.append(DeprecationWarning)
392 for cls in silence:
393 simplefilter("ignore", category=cls)
Christian Heimes33fe8092008-04-13 13:53:33 +0000394 bytes_warning = sys.flags.bytes_warning
395 if bytes_warning > 1:
396 bytes_action = "error"
397 elif bytes_warning:
398 bytes_action = "default"
399 else:
400 bytes_action = "ignore"
401 simplefilter(bytes_action, category=BytesWarning, append=1)
Georg Brandl08be72d2010-10-24 15:11:22 +0000402 # resource usage warnings are enabled by default in pydebug mode
403 if hasattr(sys, 'gettotalrefcount'):
404 resource_action = "always"
405 else:
406 resource_action = "ignore"
407 simplefilter(resource_action, category=ResourceWarning, append=1)
408
Christian Heimes33fe8092008-04-13 13:53:33 +0000409del _warnings_defaults