blob: e53efa52b05819bebccf4d79597a4ca63602d73c [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)
Guido van Rossum2a862c62000-12-15 21:59:53 +000056
Georg Brandlfe991052009-09-16 15:54:04 +000057def simplefilter(action, category=Warning, lineno=0, append=False):
Jeremy Hylton85014662003-07-11 15:37:59 +000058 """Insert a simple entry into the list of warnings filters (at the front).
59
60 A simple filter matches all modules and messages.
Georg Brandl495f7b52009-10-27 15:28:25 +000061 'action' -- one of "error", "ignore", "always", "default", "module",
62 or "once"
63 'category' -- a class that the warning must be a subclass of
64 'lineno' -- an integer line number, 0 matches all warnings
65 'append' -- if true, append to the list of filters
Jeremy Hylton85014662003-07-11 15:37:59 +000066 """
67 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000068 "once"), "invalid action: %r" % (action,)
Jeremy Hylton85014662003-07-11 15:37:59 +000069 assert isinstance(lineno, int) and lineno >= 0, \
70 "lineno must be an int >= 0"
71 item = (action, None, category, None, lineno)
72 if append:
73 filters.append(item)
74 else:
75 filters.insert(0, item)
76
Guido van Rossum2a862c62000-12-15 21:59:53 +000077def resetwarnings():
Tim Petersd0cc4f02002-04-16 01:51:25 +000078 """Clear the list of warning filters, so that no filters are active."""
Guido van Rossum2a862c62000-12-15 21:59:53 +000079 filters[:] = []
80
81class _OptionError(Exception):
82 """Exception used by option processing helpers."""
83 pass
84
85# Helper to process -W options passed via sys.warnoptions
86def _processoptions(args):
87 for arg in args:
88 try:
89 _setoption(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +000090 except _OptionError as msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000091 print("Invalid -W option ignored:", msg, file=sys.stderr)
Guido van Rossum2a862c62000-12-15 21:59:53 +000092
93# Helper for _processoptions()
94def _setoption(arg):
Skip Montanarod8f21202003-05-14 17:33:53 +000095 import re
Tim Peterse1190062001-01-15 03:34:38 +000096 parts = arg.split(':')
97 if len(parts) > 5:
Walter Dörwald70a6b492004-02-12 17:35:32 +000098 raise _OptionError("too many fields (max 5): %r" % (arg,))
Tim Peterse1190062001-01-15 03:34:38 +000099 while len(parts) < 5:
100 parts.append('')
101 action, message, category, module, lineno = [s.strip()
102 for s in parts]
103 action = _getaction(action)
104 message = re.escape(message)
105 category = _getcategory(category)
106 module = re.escape(module)
107 if module:
108 module = module + '$'
109 if lineno:
110 try:
111 lineno = int(lineno)
112 if lineno < 0:
113 raise ValueError
114 except (ValueError, OverflowError):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000115 raise _OptionError("invalid lineno %r" % (lineno,))
Tim Peterse1190062001-01-15 03:34:38 +0000116 else:
117 lineno = 0
118 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000119
120# Helper for _setoption()
121def _getaction(action):
122 if not action:
123 return "default"
124 if action == "all": return "always" # Alias
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000125 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000126 if a.startswith(action):
127 return a
Walter Dörwald70a6b492004-02-12 17:35:32 +0000128 raise _OptionError("invalid action: %r" % (action,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000129
130# Helper for _setoption()
131def _getcategory(category):
Skip Montanarod8f21202003-05-14 17:33:53 +0000132 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000133 if not category:
134 return Warning
135 if re.match("^[a-zA-Z0-9_]+$", category):
136 try:
137 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000138 except NameError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000139 raise _OptionError("unknown warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000140 else:
141 i = category.rfind(".")
142 module = category[:i]
143 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000144 try:
Brett Cannoncd171c82013-07-04 17:43:24 -0400145 m = __import__(module, None, None, [klass])
146 except ImportError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000147 raise _OptionError("invalid module name: %r" % (module,))
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000148 try:
149 cat = getattr(m, klass)
150 except AttributeError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000151 raise _OptionError("unknown warning category: %r" % (category,))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000152 if not issubclass(cat, Warning):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000153 raise _OptionError("invalid warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000154 return cat
155
Christian Heimes33fe8092008-04-13 13:53:33 +0000156
157# Code typically replaced by _warnings
158def warn(message, category=None, stacklevel=1):
159 """Issue a warning, or maybe ignore it or raise an exception."""
160 # Check if message is already a Warning object
161 if isinstance(message, Warning):
162 category = message.__class__
163 # Check category argument
164 if category is None:
165 category = UserWarning
Berker Peksagd8089e02014-07-11 19:50:25 +0300166 if not (isinstance(category, type) and issubclass(category, Warning)):
167 raise TypeError("category must be a Warning subclass, "
168 "not '{:s}'".format(type(category).__name__))
Christian Heimes33fe8092008-04-13 13:53:33 +0000169 # Get context information
170 try:
171 caller = sys._getframe(stacklevel)
172 except ValueError:
173 globals = sys.__dict__
174 lineno = 1
175 else:
176 globals = caller.f_globals
177 lineno = caller.f_lineno
178 if '__name__' in globals:
179 module = globals['__name__']
180 else:
181 module = "<string>"
182 filename = globals.get('__file__')
183 if filename:
184 fnl = filename.lower()
185 if fnl.endswith((".pyc", ".pyo")):
186 filename = filename[:-1]
187 else:
188 if module == "__main__":
189 try:
190 filename = sys.argv[0]
191 except AttributeError:
192 # embedded interpreters don't have sys.argv, see bug #839151
193 filename = '__main__'
194 if not filename:
195 filename = module
196 registry = globals.setdefault("__warningregistry__", {})
197 warn_explicit(message, category, filename, lineno, module, registry,
198 globals)
199
200def warn_explicit(message, category, filename, lineno,
201 module=None, registry=None, module_globals=None):
Brett Cannondb734912008-06-27 00:52:15 +0000202 lineno = int(lineno)
Christian Heimes33fe8092008-04-13 13:53:33 +0000203 if module is None:
204 module = filename or "<unknown>"
205 if module[-3:].lower() == ".py":
206 module = module[:-3] # XXX What about leading pathname?
207 if registry is None:
208 registry = {}
209 if isinstance(message, Warning):
210 text = str(message)
211 category = message.__class__
212 else:
213 text = message
214 message = category(message)
215 key = (text, category, lineno)
216 # Quick test for common case
217 if registry.get(key):
218 return
219 # Search the filters
220 for item in filters:
221 action, msg, cat, mod, ln = item
222 if ((msg is None or msg.match(text)) and
223 issubclass(category, cat) and
224 (mod is None or mod.match(module)) and
225 (ln == 0 or lineno == ln)):
226 break
227 else:
228 action = defaultaction
229 # Early exit actions
230 if action == "ignore":
231 registry[key] = 1
232 return
233
234 # Prime the linecache for formatting, in case the
235 # "file" is actually in a zipfile or something.
Antoine Pitrou7cb11fa2013-10-24 22:23:42 +0200236 import linecache
Christian Heimes33fe8092008-04-13 13:53:33 +0000237 linecache.getlines(filename, module_globals)
238
239 if action == "error":
240 raise message
241 # Other actions
242 if action == "once":
243 registry[key] = 1
244 oncekey = (text, category)
245 if onceregistry.get(oncekey):
246 return
247 onceregistry[oncekey] = 1
248 elif action == "always":
249 pass
250 elif action == "module":
251 registry[key] = 1
252 altkey = (text, category, 0)
253 if registry.get(altkey):
254 return
255 registry[altkey] = 1
256 elif action == "default":
257 registry[key] = 1
258 else:
259 # Unrecognized actions are errors
260 raise RuntimeError(
261 "Unrecognized action (%r) in warnings.filters:\n %s" %
262 (action, item))
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200263 if not callable(showwarning):
Christian Heimes8dc226f2008-05-06 23:45:46 +0000264 raise TypeError("warnings.showwarning() must be set to a "
265 "function or method")
Christian Heimes33fe8092008-04-13 13:53:33 +0000266 # Print message and context
267 showwarning(message, category, filename, lineno)
268
269
Brett Cannonec92e182008-09-02 02:46:59 +0000270class WarningMessage(object):
271
272 """Holds the result of a single showwarning() call."""
273
274 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
275 "line")
276
277 def __init__(self, message, category, filename, lineno, file=None,
278 line=None):
279 local_values = locals()
280 for attr in self._WARNING_DETAILS:
281 setattr(self, attr, local_values[attr])
282 self._category_name = category.__name__ if category else None
283
284 def __str__(self):
285 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
286 "line : %r}" % (self.message, self._category_name,
287 self.filename, self.lineno, self.line))
288
289
Brett Cannonec92e182008-09-02 02:46:59 +0000290class catch_warnings(object):
291
Brett Cannon1cd02472008-09-09 01:52:27 +0000292 """A context manager that copies and restores the warnings filter upon
293 exiting the context.
Brett Cannonec92e182008-09-02 02:46:59 +0000294
Brett Cannon1cd02472008-09-09 01:52:27 +0000295 The 'record' argument specifies whether warnings should be captured by a
296 custom implementation of warnings.showwarning() and be appended to a list
297 returned by the context manager. Otherwise None is returned by the context
298 manager. The objects appended to the list are arguments whose attributes
299 mirror the arguments to showwarning().
300
301 The 'module' argument is to specify an alternative module to the module
302 named 'warnings' and imported under that name. This argument is only useful
303 when testing the warnings module itself.
Brett Cannonec92e182008-09-02 02:46:59 +0000304
305 """
306
307 def __init__(self, *, record=False, module=None):
308 """Specify whether to record warnings and if an alternative module
309 should be used other than sys.modules['warnings'].
310
311 For compatibility with Python 3.0, please consider all arguments to be
312 keyword-only.
313
314 """
Brett Cannon1cd02472008-09-09 01:52:27 +0000315 self._record = record
Brett Cannonec92e182008-09-02 02:46:59 +0000316 self._module = sys.modules['warnings'] if module is None else module
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000317 self._entered = False
318
319 def __repr__(self):
320 args = []
321 if self._record:
322 args.append("record=True")
323 if self._module is not sys.modules['warnings']:
324 args.append("module=%r" % self._module)
325 name = type(self).__name__
326 return "%s(%s)" % (name, ", ".join(args))
Brett Cannonec92e182008-09-02 02:46:59 +0000327
328 def __enter__(self):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000329 if self._entered:
330 raise RuntimeError("Cannot enter %r twice" % self)
331 self._entered = True
Brett Cannonec92e182008-09-02 02:46:59 +0000332 self._filters = self._module.filters
333 self._module.filters = self._filters[:]
334 self._showwarning = self._module.showwarning
Brett Cannon1cd02472008-09-09 01:52:27 +0000335 if self._record:
336 log = []
337 def showwarning(*args, **kwargs):
338 log.append(WarningMessage(*args, **kwargs))
339 self._module.showwarning = showwarning
340 return log
341 else:
342 return None
Brett Cannonec92e182008-09-02 02:46:59 +0000343
344 def __exit__(self, *exc_info):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000345 if not self._entered:
346 raise RuntimeError("Cannot exit %r without entering first" % self)
Brett Cannonec92e182008-09-02 02:46:59 +0000347 self._module.filters = self._filters
348 self._module.showwarning = self._showwarning
349
350
Christian Heimes33fe8092008-04-13 13:53:33 +0000351# filters contains a sequence of filter 5-tuples
352# The components of the 5-tuple are:
353# - an action: error, ignore, always, default, module, or once
354# - a compiled regex that must match the warning message
355# - a class representing the warning category
356# - a compiled regex that must match the module that is being warned
357# - a line number for the line being warning, or 0 to mean any line
358# If either if the compiled regexs are None, match anything.
359_warnings_defaults = False
360try:
Brett Cannonef0e6c32010-09-04 18:24:04 +0000361 from _warnings import (filters, _defaultaction, _onceregistry,
Christian Heimes33fe8092008-04-13 13:53:33 +0000362 warn, warn_explicit)
Brett Cannonef0e6c32010-09-04 18:24:04 +0000363 defaultaction = _defaultaction
364 onceregistry = _onceregistry
Christian Heimes33fe8092008-04-13 13:53:33 +0000365 _warnings_defaults = True
Brett Cannoncd171c82013-07-04 17:43:24 -0400366except ImportError:
Christian Heimes33fe8092008-04-13 13:53:33 +0000367 filters = []
368 defaultaction = "default"
369 onceregistry = {}
370
371
Guido van Rossum2a862c62000-12-15 21:59:53 +0000372# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000373_processoptions(sys.warnoptions)
Christian Heimes33fe8092008-04-13 13:53:33 +0000374if not _warnings_defaults:
Benjamin Peterson7ab4b8d2010-06-28 00:01:59 +0000375 silence = [ImportWarning, PendingDeprecationWarning]
376 silence.append(DeprecationWarning)
377 for cls in silence:
378 simplefilter("ignore", category=cls)
Christian Heimes33fe8092008-04-13 13:53:33 +0000379 bytes_warning = sys.flags.bytes_warning
380 if bytes_warning > 1:
381 bytes_action = "error"
382 elif bytes_warning:
383 bytes_action = "default"
384 else:
385 bytes_action = "ignore"
386 simplefilter(bytes_action, category=BytesWarning, append=1)
Georg Brandl08be72d2010-10-24 15:11:22 +0000387 # resource usage warnings are enabled by default in pydebug mode
388 if hasattr(sys, 'gettotalrefcount'):
389 resource_action = "always"
390 else:
391 resource_action = "ignore"
392 simplefilter(resource_action, category=ResourceWarning, append=1)
393
Christian Heimes33fe8092008-04-13 13:53:33 +0000394del _warnings_defaults