blob: f37b8a771aa6c966f8410deebe41b45bb9e76ae8 [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
Skip Montanaro40fc1602001-03-01 04:27:19 +00005__all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
Brett Cannon1cd02472008-09-09 01:52:27 +00006 "resetwarnings", "catch_warnings"]
Skip Montanaro40fc1602001-03-01 04:27:19 +00007
Guido van Rossum2a862c62000-12-15 21:59:53 +00008
Christian Heimes33fe8092008-04-13 13:53:33 +00009def showwarning(message, category, filename, lineno, file=None, line=None):
Guido van Rossum2a862c62000-12-15 21:59:53 +000010 """Hook to write a warning to a file; replace if you like."""
11 if file is None:
12 file = sys.stderr
Mark Hammond51a0ae32002-09-11 13:22:35 +000013 try:
Christian Heimes33fe8092008-04-13 13:53:33 +000014 file.write(formatwarning(message, category, filename, lineno, line))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +020015 except OSError:
Mark Hammond51a0ae32002-09-11 13:22:35 +000016 pass # the file (probably stderr) is invalid - this warning gets lost.
Guido van Rossum2a862c62000-12-15 21:59:53 +000017
Christian Heimes33fe8092008-04-13 13:53:33 +000018def formatwarning(message, category, filename, lineno, line=None):
Guido van Rossum9464a7d2001-01-14 14:08:40 +000019 """Function to format a warning the standard way."""
Antoine Pitrou7cb11fa2013-10-24 22:23:42 +020020 import linecache
Guido van Rossum2a862c62000-12-15 21:59:53 +000021 s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
Christian Heimes33fe8092008-04-13 13:53:33 +000022 line = linecache.getline(filename, lineno) if line is None else line
Guido van Rossum2a862c62000-12-15 21:59:53 +000023 if line:
Christian Heimes33fe8092008-04-13 13:53:33 +000024 line = line.strip()
25 s += " %s\n" % line
Guido van Rossum2a862c62000-12-15 21:59:53 +000026 return s
27
Guido van Rossum9464a7d2001-01-14 14:08:40 +000028def filterwarnings(action, message="", category=Warning, module="", lineno=0,
Georg Brandlfe991052009-09-16 15:54:04 +000029 append=False):
Guido van Rossum2a862c62000-12-15 21:59:53 +000030 """Insert an entry into the list of warnings filters (at the front).
31
Georg Brandl495f7b52009-10-27 15:28:25 +000032 'action' -- one of "error", "ignore", "always", "default", "module",
33 or "once"
34 'message' -- a regex that the warning message must match
35 'category' -- a class that the warning must be a subclass of
36 'module' -- a regex that the module name must match
37 'lineno' -- an integer line number, 0 matches all warnings
38 'append' -- if true, append to the list of filters
39 """
Skip Montanarod8f21202003-05-14 17:33:53 +000040 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +000041 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000042 "once"), "invalid action: %r" % (action,)
Guido van Rossum3172c5d2007-10-16 18:12:55 +000043 assert isinstance(message, str), "message must be a string"
Guido van Rossum13257902007-06-07 23:15:56 +000044 assert isinstance(category, type), "category must be a class"
Guido van Rossum2a862c62000-12-15 21:59:53 +000045 assert issubclass(category, Warning), "category must be a Warning subclass"
Guido van Rossum3172c5d2007-10-16 18:12:55 +000046 assert isinstance(module, str), "module must be a string"
Walter Dörwald65230a22002-06-03 15:58:32 +000047 assert isinstance(lineno, int) and lineno >= 0, \
Guido van Rossum2a862c62000-12-15 21:59:53 +000048 "lineno must be an int >= 0"
Guido van Rossum9464a7d2001-01-14 14:08:40 +000049 item = (action, re.compile(message, re.I), category,
50 re.compile(module), lineno)
51 if append:
52 filters.append(item)
53 else:
54 filters.insert(0, item)
Guido van Rossum2a862c62000-12-15 21:59:53 +000055
Georg Brandlfe991052009-09-16 15:54:04 +000056def simplefilter(action, category=Warning, lineno=0, append=False):
Jeremy Hylton85014662003-07-11 15:37:59 +000057 """Insert a simple entry into the list of warnings filters (at the front).
58
59 A simple filter matches all modules and messages.
Georg Brandl495f7b52009-10-27 15:28:25 +000060 'action' -- one of "error", "ignore", "always", "default", "module",
61 or "once"
62 'category' -- a class that the warning must be a subclass of
63 'lineno' -- an integer line number, 0 matches all warnings
64 'append' -- if true, append to the list of filters
Jeremy Hylton85014662003-07-11 15:37:59 +000065 """
66 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000067 "once"), "invalid action: %r" % (action,)
Jeremy Hylton85014662003-07-11 15:37:59 +000068 assert isinstance(lineno, int) and lineno >= 0, \
69 "lineno must be an int >= 0"
70 item = (action, None, category, None, lineno)
71 if append:
72 filters.append(item)
73 else:
74 filters.insert(0, item)
75
Guido van Rossum2a862c62000-12-15 21:59:53 +000076def resetwarnings():
Tim Petersd0cc4f02002-04-16 01:51:25 +000077 """Clear the list of warning filters, so that no filters are active."""
Guido van Rossum2a862c62000-12-15 21:59:53 +000078 filters[:] = []
79
80class _OptionError(Exception):
81 """Exception used by option processing helpers."""
82 pass
83
84# Helper to process -W options passed via sys.warnoptions
85def _processoptions(args):
86 for arg in args:
87 try:
88 _setoption(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +000089 except _OptionError as msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000090 print("Invalid -W option ignored:", msg, file=sys.stderr)
Guido van Rossum2a862c62000-12-15 21:59:53 +000091
92# Helper for _processoptions()
93def _setoption(arg):
Skip Montanarod8f21202003-05-14 17:33:53 +000094 import re
Tim Peterse1190062001-01-15 03:34:38 +000095 parts = arg.split(':')
96 if len(parts) > 5:
Walter Dörwald70a6b492004-02-12 17:35:32 +000097 raise _OptionError("too many fields (max 5): %r" % (arg,))
Tim Peterse1190062001-01-15 03:34:38 +000098 while len(parts) < 5:
99 parts.append('')
100 action, message, category, module, lineno = [s.strip()
101 for s in parts]
102 action = _getaction(action)
103 message = re.escape(message)
104 category = _getcategory(category)
105 module = re.escape(module)
106 if module:
107 module = module + '$'
108 if lineno:
109 try:
110 lineno = int(lineno)
111 if lineno < 0:
112 raise ValueError
113 except (ValueError, OverflowError):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000114 raise _OptionError("invalid lineno %r" % (lineno,))
Tim Peterse1190062001-01-15 03:34:38 +0000115 else:
116 lineno = 0
117 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000118
119# Helper for _setoption()
120def _getaction(action):
121 if not action:
122 return "default"
123 if action == "all": return "always" # Alias
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000124 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000125 if a.startswith(action):
126 return a
Walter Dörwald70a6b492004-02-12 17:35:32 +0000127 raise _OptionError("invalid action: %r" % (action,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000128
129# Helper for _setoption()
130def _getcategory(category):
Skip Montanarod8f21202003-05-14 17:33:53 +0000131 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000132 if not category:
133 return Warning
134 if re.match("^[a-zA-Z0-9_]+$", category):
135 try:
136 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000137 except NameError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000138 raise _OptionError("unknown warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000139 else:
140 i = category.rfind(".")
141 module = category[:i]
142 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000143 try:
Brett Cannoncd171c82013-07-04 17:43:24 -0400144 m = __import__(module, None, None, [klass])
145 except ImportError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000146 raise _OptionError("invalid module name: %r" % (module,))
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000147 try:
148 cat = getattr(m, klass)
149 except AttributeError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000150 raise _OptionError("unknown warning category: %r" % (category,))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000151 if not issubclass(cat, Warning):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000152 raise _OptionError("invalid warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000153 return cat
154
Christian Heimes33fe8092008-04-13 13:53:33 +0000155
156# Code typically replaced by _warnings
157def warn(message, category=None, stacklevel=1):
158 """Issue a warning, or maybe ignore it or raise an exception."""
159 # Check if message is already a Warning object
160 if isinstance(message, Warning):
161 category = message.__class__
162 # Check category argument
163 if category is None:
164 category = UserWarning
Berker Peksagd8089e02014-07-11 19:50:25 +0300165 if not (isinstance(category, type) and issubclass(category, Warning)):
166 raise TypeError("category must be a Warning subclass, "
167 "not '{:s}'".format(type(category).__name__))
Christian Heimes33fe8092008-04-13 13:53:33 +0000168 # Get context information
169 try:
170 caller = sys._getframe(stacklevel)
171 except ValueError:
172 globals = sys.__dict__
173 lineno = 1
174 else:
175 globals = caller.f_globals
176 lineno = caller.f_lineno
177 if '__name__' in globals:
178 module = globals['__name__']
179 else:
180 module = "<string>"
181 filename = globals.get('__file__')
182 if filename:
183 fnl = filename.lower()
184 if fnl.endswith((".pyc", ".pyo")):
185 filename = filename[:-1]
186 else:
187 if module == "__main__":
188 try:
189 filename = sys.argv[0]
190 except AttributeError:
191 # embedded interpreters don't have sys.argv, see bug #839151
192 filename = '__main__'
193 if not filename:
194 filename = module
195 registry = globals.setdefault("__warningregistry__", {})
196 warn_explicit(message, category, filename, lineno, module, registry,
197 globals)
198
199def warn_explicit(message, category, filename, lineno,
200 module=None, registry=None, module_globals=None):
Brett Cannondb734912008-06-27 00:52:15 +0000201 lineno = int(lineno)
Christian Heimes33fe8092008-04-13 13:53:33 +0000202 if module is None:
203 module = filename or "<unknown>"
204 if module[-3:].lower() == ".py":
205 module = module[:-3] # XXX What about leading pathname?
206 if registry is None:
207 registry = {}
208 if isinstance(message, Warning):
209 text = str(message)
210 category = message.__class__
211 else:
212 text = message
213 message = category(message)
214 key = (text, category, lineno)
215 # Quick test for common case
216 if registry.get(key):
217 return
218 # Search the filters
219 for item in filters:
220 action, msg, cat, mod, ln = item
221 if ((msg is None or msg.match(text)) and
222 issubclass(category, cat) and
223 (mod is None or mod.match(module)) and
224 (ln == 0 or lineno == ln)):
225 break
226 else:
227 action = defaultaction
228 # Early exit actions
229 if action == "ignore":
230 registry[key] = 1
231 return
232
233 # Prime the linecache for formatting, in case the
234 # "file" is actually in a zipfile or something.
Antoine Pitrou7cb11fa2013-10-24 22:23:42 +0200235 import linecache
Christian Heimes33fe8092008-04-13 13:53:33 +0000236 linecache.getlines(filename, module_globals)
237
238 if action == "error":
239 raise message
240 # Other actions
241 if action == "once":
242 registry[key] = 1
243 oncekey = (text, category)
244 if onceregistry.get(oncekey):
245 return
246 onceregistry[oncekey] = 1
247 elif action == "always":
248 pass
249 elif action == "module":
250 registry[key] = 1
251 altkey = (text, category, 0)
252 if registry.get(altkey):
253 return
254 registry[altkey] = 1
255 elif action == "default":
256 registry[key] = 1
257 else:
258 # Unrecognized actions are errors
259 raise RuntimeError(
260 "Unrecognized action (%r) in warnings.filters:\n %s" %
261 (action, item))
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200262 if not callable(showwarning):
Christian Heimes8dc226f2008-05-06 23:45:46 +0000263 raise TypeError("warnings.showwarning() must be set to a "
264 "function or method")
Christian Heimes33fe8092008-04-13 13:53:33 +0000265 # Print message and context
266 showwarning(message, category, filename, lineno)
267
268
Brett Cannonec92e182008-09-02 02:46:59 +0000269class WarningMessage(object):
270
271 """Holds the result of a single showwarning() call."""
272
273 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
274 "line")
275
276 def __init__(self, message, category, filename, lineno, file=None,
277 line=None):
278 local_values = locals()
279 for attr in self._WARNING_DETAILS:
280 setattr(self, attr, local_values[attr])
281 self._category_name = category.__name__ if category else None
282
283 def __str__(self):
284 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
285 "line : %r}" % (self.message, self._category_name,
286 self.filename, self.lineno, self.line))
287
288
Brett Cannonec92e182008-09-02 02:46:59 +0000289class catch_warnings(object):
290
Brett Cannon1cd02472008-09-09 01:52:27 +0000291 """A context manager that copies and restores the warnings filter upon
292 exiting the context.
Brett Cannonec92e182008-09-02 02:46:59 +0000293
Brett Cannon1cd02472008-09-09 01:52:27 +0000294 The 'record' argument specifies whether warnings should be captured by a
295 custom implementation of warnings.showwarning() and be appended to a list
296 returned by the context manager. Otherwise None is returned by the context
297 manager. The objects appended to the list are arguments whose attributes
298 mirror the arguments to showwarning().
299
300 The 'module' argument is to specify an alternative module to the module
301 named 'warnings' and imported under that name. This argument is only useful
302 when testing the warnings module itself.
Brett Cannonec92e182008-09-02 02:46:59 +0000303
304 """
305
306 def __init__(self, *, record=False, module=None):
307 """Specify whether to record warnings and if an alternative module
308 should be used other than sys.modules['warnings'].
309
310 For compatibility with Python 3.0, please consider all arguments to be
311 keyword-only.
312
313 """
Brett Cannon1cd02472008-09-09 01:52:27 +0000314 self._record = record
Brett Cannonec92e182008-09-02 02:46:59 +0000315 self._module = sys.modules['warnings'] if module is None else module
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000316 self._entered = False
317
318 def __repr__(self):
319 args = []
320 if self._record:
321 args.append("record=True")
322 if self._module is not sys.modules['warnings']:
323 args.append("module=%r" % self._module)
324 name = type(self).__name__
325 return "%s(%s)" % (name, ", ".join(args))
Brett Cannonec92e182008-09-02 02:46:59 +0000326
327 def __enter__(self):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000328 if self._entered:
329 raise RuntimeError("Cannot enter %r twice" % self)
330 self._entered = True
Brett Cannonec92e182008-09-02 02:46:59 +0000331 self._filters = self._module.filters
332 self._module.filters = self._filters[:]
333 self._showwarning = self._module.showwarning
Brett Cannon1cd02472008-09-09 01:52:27 +0000334 if self._record:
335 log = []
336 def showwarning(*args, **kwargs):
337 log.append(WarningMessage(*args, **kwargs))
338 self._module.showwarning = showwarning
339 return log
340 else:
341 return None
Brett Cannonec92e182008-09-02 02:46:59 +0000342
343 def __exit__(self, *exc_info):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000344 if not self._entered:
345 raise RuntimeError("Cannot exit %r without entering first" % self)
Brett Cannonec92e182008-09-02 02:46:59 +0000346 self._module.filters = self._filters
347 self._module.showwarning = self._showwarning
348
349
Christian Heimes33fe8092008-04-13 13:53:33 +0000350# filters contains a sequence of filter 5-tuples
351# The components of the 5-tuple are:
352# - an action: error, ignore, always, default, module, or once
353# - a compiled regex that must match the warning message
354# - a class representing the warning category
355# - a compiled regex that must match the module that is being warned
356# - a line number for the line being warning, or 0 to mean any line
357# If either if the compiled regexs are None, match anything.
358_warnings_defaults = False
359try:
Brett Cannonef0e6c32010-09-04 18:24:04 +0000360 from _warnings import (filters, _defaultaction, _onceregistry,
Christian Heimes33fe8092008-04-13 13:53:33 +0000361 warn, warn_explicit)
Brett Cannonef0e6c32010-09-04 18:24:04 +0000362 defaultaction = _defaultaction
363 onceregistry = _onceregistry
Christian Heimes33fe8092008-04-13 13:53:33 +0000364 _warnings_defaults = True
Brett Cannoncd171c82013-07-04 17:43:24 -0400365except ImportError:
Christian Heimes33fe8092008-04-13 13:53:33 +0000366 filters = []
367 defaultaction = "default"
368 onceregistry = {}
369
370
Guido van Rossum2a862c62000-12-15 21:59:53 +0000371# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000372_processoptions(sys.warnoptions)
Christian Heimes33fe8092008-04-13 13:53:33 +0000373if not _warnings_defaults:
Benjamin Peterson7ab4b8d2010-06-28 00:01:59 +0000374 silence = [ImportWarning, PendingDeprecationWarning]
375 silence.append(DeprecationWarning)
376 for cls in silence:
377 simplefilter("ignore", category=cls)
Christian Heimes33fe8092008-04-13 13:53:33 +0000378 bytes_warning = sys.flags.bytes_warning
379 if bytes_warning > 1:
380 bytes_action = "error"
381 elif bytes_warning:
382 bytes_action = "default"
383 else:
384 bytes_action = "ignore"
385 simplefilter(bytes_action, category=BytesWarning, append=1)
Georg Brandl08be72d2010-10-24 15:11:22 +0000386 # resource usage warnings are enabled by default in pydebug mode
387 if hasattr(sys, 'gettotalrefcount'):
388 resource_action = "always"
389 else:
390 resource_action = "ignore"
391 simplefilter(resource_action, category=ResourceWarning, append=1)
392
Christian Heimes33fe8092008-04-13 13:53:33 +0000393del _warnings_defaults