blob: 16246b436582269ec6bf6e0ad480a322e3a71079 [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
163# Code typically replaced by _warnings
164def warn(message, category=None, stacklevel=1):
165 """Issue a warning, or maybe ignore it or raise an exception."""
166 # Check if message is already a Warning object
167 if isinstance(message, Warning):
168 category = message.__class__
169 # Check category argument
170 if category is None:
171 category = UserWarning
Berker Peksagd8089e02014-07-11 19:50:25 +0300172 if not (isinstance(category, type) and issubclass(category, Warning)):
173 raise TypeError("category must be a Warning subclass, "
174 "not '{:s}'".format(type(category).__name__))
Christian Heimes33fe8092008-04-13 13:53:33 +0000175 # Get context information
176 try:
177 caller = sys._getframe(stacklevel)
178 except ValueError:
179 globals = sys.__dict__
180 lineno = 1
181 else:
182 globals = caller.f_globals
183 lineno = caller.f_lineno
184 if '__name__' in globals:
185 module = globals['__name__']
186 else:
187 module = "<string>"
188 filename = globals.get('__file__')
189 if filename:
190 fnl = filename.lower()
Brett Cannonf299abd2015-04-13 14:21:02 -0400191 if fnl.endswith(".pyc"):
Christian Heimes33fe8092008-04-13 13:53:33 +0000192 filename = filename[:-1]
193 else:
194 if module == "__main__":
195 try:
196 filename = sys.argv[0]
197 except AttributeError:
198 # embedded interpreters don't have sys.argv, see bug #839151
199 filename = '__main__'
200 if not filename:
201 filename = module
202 registry = globals.setdefault("__warningregistry__", {})
203 warn_explicit(message, category, filename, lineno, module, registry,
204 globals)
205
206def warn_explicit(message, category, filename, lineno,
207 module=None, registry=None, module_globals=None):
Brett Cannondb734912008-06-27 00:52:15 +0000208 lineno = int(lineno)
Christian Heimes33fe8092008-04-13 13:53:33 +0000209 if module is None:
210 module = filename or "<unknown>"
211 if module[-3:].lower() == ".py":
212 module = module[:-3] # XXX What about leading pathname?
213 if registry is None:
214 registry = {}
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200215 if registry.get('version', 0) != _filters_version:
216 registry.clear()
217 registry['version'] = _filters_version
Christian Heimes33fe8092008-04-13 13:53:33 +0000218 if isinstance(message, Warning):
219 text = str(message)
220 category = message.__class__
221 else:
222 text = message
223 message = category(message)
224 key = (text, category, lineno)
225 # Quick test for common case
226 if registry.get(key):
227 return
228 # Search the filters
229 for item in filters:
230 action, msg, cat, mod, ln = item
231 if ((msg is None or msg.match(text)) and
232 issubclass(category, cat) and
233 (mod is None or mod.match(module)) and
234 (ln == 0 or lineno == ln)):
235 break
236 else:
237 action = defaultaction
238 # Early exit actions
239 if action == "ignore":
240 registry[key] = 1
241 return
242
243 # Prime the linecache for formatting, in case the
244 # "file" is actually in a zipfile or something.
Antoine Pitrou7cb11fa2013-10-24 22:23:42 +0200245 import linecache
Christian Heimes33fe8092008-04-13 13:53:33 +0000246 linecache.getlines(filename, module_globals)
247
248 if action == "error":
249 raise message
250 # Other actions
251 if action == "once":
252 registry[key] = 1
253 oncekey = (text, category)
254 if onceregistry.get(oncekey):
255 return
256 onceregistry[oncekey] = 1
257 elif action == "always":
258 pass
259 elif action == "module":
260 registry[key] = 1
261 altkey = (text, category, 0)
262 if registry.get(altkey):
263 return
264 registry[altkey] = 1
265 elif action == "default":
266 registry[key] = 1
267 else:
268 # Unrecognized actions are errors
269 raise RuntimeError(
270 "Unrecognized action (%r) in warnings.filters:\n %s" %
271 (action, item))
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200272 if not callable(showwarning):
Christian Heimes8dc226f2008-05-06 23:45:46 +0000273 raise TypeError("warnings.showwarning() must be set to a "
274 "function or method")
Christian Heimes33fe8092008-04-13 13:53:33 +0000275 # Print message and context
276 showwarning(message, category, filename, lineno)
277
278
Brett Cannonec92e182008-09-02 02:46:59 +0000279class WarningMessage(object):
280
281 """Holds the result of a single showwarning() call."""
282
283 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
284 "line")
285
286 def __init__(self, message, category, filename, lineno, file=None,
287 line=None):
288 local_values = locals()
289 for attr in self._WARNING_DETAILS:
290 setattr(self, attr, local_values[attr])
291 self._category_name = category.__name__ if category else None
292
293 def __str__(self):
294 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
295 "line : %r}" % (self.message, self._category_name,
296 self.filename, self.lineno, self.line))
297
298
Brett Cannonec92e182008-09-02 02:46:59 +0000299class catch_warnings(object):
300
Brett Cannon1cd02472008-09-09 01:52:27 +0000301 """A context manager that copies and restores the warnings filter upon
302 exiting the context.
Brett Cannonec92e182008-09-02 02:46:59 +0000303
Brett Cannon1cd02472008-09-09 01:52:27 +0000304 The 'record' argument specifies whether warnings should be captured by a
305 custom implementation of warnings.showwarning() and be appended to a list
306 returned by the context manager. Otherwise None is returned by the context
307 manager. The objects appended to the list are arguments whose attributes
308 mirror the arguments to showwarning().
309
310 The 'module' argument is to specify an alternative module to the module
311 named 'warnings' and imported under that name. This argument is only useful
312 when testing the warnings module itself.
Brett Cannonec92e182008-09-02 02:46:59 +0000313
314 """
315
316 def __init__(self, *, record=False, module=None):
317 """Specify whether to record warnings and if an alternative module
318 should be used other than sys.modules['warnings'].
319
320 For compatibility with Python 3.0, please consider all arguments to be
321 keyword-only.
322
323 """
Brett Cannon1cd02472008-09-09 01:52:27 +0000324 self._record = record
Brett Cannonec92e182008-09-02 02:46:59 +0000325 self._module = sys.modules['warnings'] if module is None else module
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000326 self._entered = False
327
328 def __repr__(self):
329 args = []
330 if self._record:
331 args.append("record=True")
332 if self._module is not sys.modules['warnings']:
333 args.append("module=%r" % self._module)
334 name = type(self).__name__
335 return "%s(%s)" % (name, ", ".join(args))
Brett Cannonec92e182008-09-02 02:46:59 +0000336
337 def __enter__(self):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000338 if self._entered:
339 raise RuntimeError("Cannot enter %r twice" % self)
340 self._entered = True
Brett Cannonec92e182008-09-02 02:46:59 +0000341 self._filters = self._module.filters
342 self._module.filters = self._filters[:]
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200343 self._module._filters_mutated()
Brett Cannonec92e182008-09-02 02:46:59 +0000344 self._showwarning = self._module.showwarning
Brett Cannon1cd02472008-09-09 01:52:27 +0000345 if self._record:
346 log = []
347 def showwarning(*args, **kwargs):
348 log.append(WarningMessage(*args, **kwargs))
349 self._module.showwarning = showwarning
350 return log
351 else:
352 return None
Brett Cannonec92e182008-09-02 02:46:59 +0000353
354 def __exit__(self, *exc_info):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000355 if not self._entered:
356 raise RuntimeError("Cannot exit %r without entering first" % self)
Brett Cannonec92e182008-09-02 02:46:59 +0000357 self._module.filters = self._filters
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200358 self._module._filters_mutated()
Brett Cannonec92e182008-09-02 02:46:59 +0000359 self._module.showwarning = self._showwarning
360
361
Christian Heimes33fe8092008-04-13 13:53:33 +0000362# filters contains a sequence of filter 5-tuples
363# The components of the 5-tuple are:
364# - an action: error, ignore, always, default, module, or once
365# - a compiled regex that must match the warning message
366# - a class representing the warning category
367# - a compiled regex that must match the module that is being warned
368# - a line number for the line being warning, or 0 to mean any line
369# If either if the compiled regexs are None, match anything.
370_warnings_defaults = False
371try:
Brett Cannonef0e6c32010-09-04 18:24:04 +0000372 from _warnings import (filters, _defaultaction, _onceregistry,
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200373 warn, warn_explicit, _filters_mutated)
Brett Cannonef0e6c32010-09-04 18:24:04 +0000374 defaultaction = _defaultaction
375 onceregistry = _onceregistry
Christian Heimes33fe8092008-04-13 13:53:33 +0000376 _warnings_defaults = True
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200377
Brett Cannoncd171c82013-07-04 17:43:24 -0400378except ImportError:
Christian Heimes33fe8092008-04-13 13:53:33 +0000379 filters = []
380 defaultaction = "default"
381 onceregistry = {}
382
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200383 _filters_version = 1
384
385 def _filters_mutated():
386 global _filters_version
387 _filters_version += 1
388
Christian Heimes33fe8092008-04-13 13:53:33 +0000389
Guido van Rossum2a862c62000-12-15 21:59:53 +0000390# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000391_processoptions(sys.warnoptions)
Christian Heimes33fe8092008-04-13 13:53:33 +0000392if not _warnings_defaults:
Benjamin Peterson7ab4b8d2010-06-28 00:01:59 +0000393 silence = [ImportWarning, PendingDeprecationWarning]
394 silence.append(DeprecationWarning)
395 for cls in silence:
396 simplefilter("ignore", category=cls)
Christian Heimes33fe8092008-04-13 13:53:33 +0000397 bytes_warning = sys.flags.bytes_warning
398 if bytes_warning > 1:
399 bytes_action = "error"
400 elif bytes_warning:
401 bytes_action = "default"
402 else:
403 bytes_action = "ignore"
404 simplefilter(bytes_action, category=BytesWarning, append=1)
Georg Brandl08be72d2010-10-24 15:11:22 +0000405 # resource usage warnings are enabled by default in pydebug mode
406 if hasattr(sys, 'gettotalrefcount'):
407 resource_action = "always"
408 else:
409 resource_action = "ignore"
410 simplefilter(resource_action, category=ResourceWarning, append=1)
411
Christian Heimes33fe8092008-04-13 13:53:33 +0000412del _warnings_defaults