blob: 70d087e6d9ada8ce3695e9038e93562426bfa8ab [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
172 assert issubclass(category, Warning)
173 # Get context information
174 try:
175 caller = sys._getframe(stacklevel)
176 except ValueError:
177 globals = sys.__dict__
178 lineno = 1
179 else:
180 globals = caller.f_globals
181 lineno = caller.f_lineno
182 if '__name__' in globals:
183 module = globals['__name__']
184 else:
185 module = "<string>"
186 filename = globals.get('__file__')
187 if filename:
188 fnl = filename.lower()
189 if fnl.endswith((".pyc", ".pyo")):
190 filename = filename[:-1]
191 else:
192 if module == "__main__":
193 try:
194 filename = sys.argv[0]
195 except AttributeError:
196 # embedded interpreters don't have sys.argv, see bug #839151
197 filename = '__main__'
198 if not filename:
199 filename = module
200 registry = globals.setdefault("__warningregistry__", {})
201 warn_explicit(message, category, filename, lineno, module, registry,
202 globals)
203
204def warn_explicit(message, category, filename, lineno,
205 module=None, registry=None, module_globals=None):
Brett Cannondb734912008-06-27 00:52:15 +0000206 lineno = int(lineno)
Christian Heimes33fe8092008-04-13 13:53:33 +0000207 if module is None:
208 module = filename or "<unknown>"
209 if module[-3:].lower() == ".py":
210 module = module[:-3] # XXX What about leading pathname?
211 if registry is None:
212 registry = {}
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200213 if registry.get('version', 0) != _filters_version:
214 registry.clear()
215 registry['version'] = _filters_version
Christian Heimes33fe8092008-04-13 13:53:33 +0000216 if isinstance(message, Warning):
217 text = str(message)
218 category = message.__class__
219 else:
220 text = message
221 message = category(message)
222 key = (text, category, lineno)
223 # Quick test for common case
224 if registry.get(key):
225 return
226 # Search the filters
227 for item in filters:
228 action, msg, cat, mod, ln = item
229 if ((msg is None or msg.match(text)) and
230 issubclass(category, cat) and
231 (mod is None or mod.match(module)) and
232 (ln == 0 or lineno == ln)):
233 break
234 else:
235 action = defaultaction
236 # Early exit actions
237 if action == "ignore":
238 registry[key] = 1
239 return
240
241 # Prime the linecache for formatting, in case the
242 # "file" is actually in a zipfile or something.
Antoine Pitrou7cb11fa2013-10-24 22:23:42 +0200243 import linecache
Christian Heimes33fe8092008-04-13 13:53:33 +0000244 linecache.getlines(filename, module_globals)
245
246 if action == "error":
247 raise message
248 # Other actions
249 if action == "once":
250 registry[key] = 1
251 oncekey = (text, category)
252 if onceregistry.get(oncekey):
253 return
254 onceregistry[oncekey] = 1
255 elif action == "always":
256 pass
257 elif action == "module":
258 registry[key] = 1
259 altkey = (text, category, 0)
260 if registry.get(altkey):
261 return
262 registry[altkey] = 1
263 elif action == "default":
264 registry[key] = 1
265 else:
266 # Unrecognized actions are errors
267 raise RuntimeError(
268 "Unrecognized action (%r) in warnings.filters:\n %s" %
269 (action, item))
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200270 if not callable(showwarning):
Christian Heimes8dc226f2008-05-06 23:45:46 +0000271 raise TypeError("warnings.showwarning() must be set to a "
272 "function or method")
Christian Heimes33fe8092008-04-13 13:53:33 +0000273 # Print message and context
274 showwarning(message, category, filename, lineno)
275
276
Brett Cannonec92e182008-09-02 02:46:59 +0000277class WarningMessage(object):
278
279 """Holds the result of a single showwarning() call."""
280
281 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
282 "line")
283
284 def __init__(self, message, category, filename, lineno, file=None,
285 line=None):
286 local_values = locals()
287 for attr in self._WARNING_DETAILS:
288 setattr(self, attr, local_values[attr])
289 self._category_name = category.__name__ if category else None
290
291 def __str__(self):
292 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
293 "line : %r}" % (self.message, self._category_name,
294 self.filename, self.lineno, self.line))
295
296
Brett Cannonec92e182008-09-02 02:46:59 +0000297class catch_warnings(object):
298
Brett Cannon1cd02472008-09-09 01:52:27 +0000299 """A context manager that copies and restores the warnings filter upon
300 exiting the context.
Brett Cannonec92e182008-09-02 02:46:59 +0000301
Brett Cannon1cd02472008-09-09 01:52:27 +0000302 The 'record' argument specifies whether warnings should be captured by a
303 custom implementation of warnings.showwarning() and be appended to a list
304 returned by the context manager. Otherwise None is returned by the context
305 manager. The objects appended to the list are arguments whose attributes
306 mirror the arguments to showwarning().
307
308 The 'module' argument is to specify an alternative module to the module
309 named 'warnings' and imported under that name. This argument is only useful
310 when testing the warnings module itself.
Brett Cannonec92e182008-09-02 02:46:59 +0000311
312 """
313
314 def __init__(self, *, record=False, module=None):
315 """Specify whether to record warnings and if an alternative module
316 should be used other than sys.modules['warnings'].
317
318 For compatibility with Python 3.0, please consider all arguments to be
319 keyword-only.
320
321 """
Brett Cannon1cd02472008-09-09 01:52:27 +0000322 self._record = record
Brett Cannonec92e182008-09-02 02:46:59 +0000323 self._module = sys.modules['warnings'] if module is None else module
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000324 self._entered = False
325
326 def __repr__(self):
327 args = []
328 if self._record:
329 args.append("record=True")
330 if self._module is not sys.modules['warnings']:
331 args.append("module=%r" % self._module)
332 name = type(self).__name__
333 return "%s(%s)" % (name, ", ".join(args))
Brett Cannonec92e182008-09-02 02:46:59 +0000334
335 def __enter__(self):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000336 if self._entered:
337 raise RuntimeError("Cannot enter %r twice" % self)
338 self._entered = True
Brett Cannonec92e182008-09-02 02:46:59 +0000339 self._filters = self._module.filters
340 self._module.filters = self._filters[:]
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200341 self._module._filters_mutated()
Brett Cannonec92e182008-09-02 02:46:59 +0000342 self._showwarning = self._module.showwarning
Brett Cannon1cd02472008-09-09 01:52:27 +0000343 if self._record:
344 log = []
345 def showwarning(*args, **kwargs):
346 log.append(WarningMessage(*args, **kwargs))
347 self._module.showwarning = showwarning
348 return log
349 else:
350 return None
Brett Cannonec92e182008-09-02 02:46:59 +0000351
352 def __exit__(self, *exc_info):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000353 if not self._entered:
354 raise RuntimeError("Cannot exit %r without entering first" % self)
Brett Cannonec92e182008-09-02 02:46:59 +0000355 self._module.filters = self._filters
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200356 self._module._filters_mutated()
Brett Cannonec92e182008-09-02 02:46:59 +0000357 self._module.showwarning = self._showwarning
358
359
Christian Heimes33fe8092008-04-13 13:53:33 +0000360# filters contains a sequence of filter 5-tuples
361# The components of the 5-tuple are:
362# - an action: error, ignore, always, default, module, or once
363# - a compiled regex that must match the warning message
364# - a class representing the warning category
365# - a compiled regex that must match the module that is being warned
366# - a line number for the line being warning, or 0 to mean any line
367# If either if the compiled regexs are None, match anything.
368_warnings_defaults = False
369try:
Brett Cannonef0e6c32010-09-04 18:24:04 +0000370 from _warnings import (filters, _defaultaction, _onceregistry,
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200371 warn, warn_explicit, _filters_mutated)
Brett Cannonef0e6c32010-09-04 18:24:04 +0000372 defaultaction = _defaultaction
373 onceregistry = _onceregistry
Christian Heimes33fe8092008-04-13 13:53:33 +0000374 _warnings_defaults = True
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200375
Brett Cannoncd171c82013-07-04 17:43:24 -0400376except ImportError:
Christian Heimes33fe8092008-04-13 13:53:33 +0000377 filters = []
378 defaultaction = "default"
379 onceregistry = {}
380
Antoine Pitroucb0a0062014-09-18 02:40:46 +0200381 _filters_version = 1
382
383 def _filters_mutated():
384 global _filters_version
385 _filters_version += 1
386
Christian Heimes33fe8092008-04-13 13:53:33 +0000387
Guido van Rossum2a862c62000-12-15 21:59:53 +0000388# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000389_processoptions(sys.warnoptions)
Christian Heimes33fe8092008-04-13 13:53:33 +0000390if not _warnings_defaults:
Benjamin Peterson7ab4b8d2010-06-28 00:01:59 +0000391 silence = [ImportWarning, PendingDeprecationWarning]
392 silence.append(DeprecationWarning)
393 for cls in silence:
394 simplefilter("ignore", category=cls)
Christian Heimes33fe8092008-04-13 13:53:33 +0000395 bytes_warning = sys.flags.bytes_warning
396 if bytes_warning > 1:
397 bytes_action = "error"
398 elif bytes_warning:
399 bytes_action = "default"
400 else:
401 bytes_action = "ignore"
402 simplefilter(bytes_action, category=BytesWarning, append=1)
Georg Brandl08be72d2010-10-24 15:11:22 +0000403 # resource usage warnings are enabled by default in pydebug mode
404 if hasattr(sys, 'gettotalrefcount'):
405 resource_action = "always"
406 else:
407 resource_action = "ignore"
408 simplefilter(resource_action, category=ResourceWarning, append=1)
409
Christian Heimes33fe8092008-04-13 13:53:33 +0000410del _warnings_defaults