blob: a427e3510ecaaa6dadeb2a4e957bb6d4880576c7 [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
165 assert issubclass(category, Warning)
166 # Get context information
167 try:
168 caller = sys._getframe(stacklevel)
169 except ValueError:
170 globals = sys.__dict__
171 lineno = 1
172 else:
173 globals = caller.f_globals
174 lineno = caller.f_lineno
175 if '__name__' in globals:
176 module = globals['__name__']
177 else:
178 module = "<string>"
179 filename = globals.get('__file__')
180 if filename:
181 fnl = filename.lower()
182 if fnl.endswith((".pyc", ".pyo")):
183 filename = filename[:-1]
184 else:
185 if module == "__main__":
186 try:
187 filename = sys.argv[0]
188 except AttributeError:
189 # embedded interpreters don't have sys.argv, see bug #839151
190 filename = '__main__'
191 if not filename:
192 filename = module
193 registry = globals.setdefault("__warningregistry__", {})
194 warn_explicit(message, category, filename, lineno, module, registry,
195 globals)
196
197def warn_explicit(message, category, filename, lineno,
198 module=None, registry=None, module_globals=None):
Brett Cannondb734912008-06-27 00:52:15 +0000199 lineno = int(lineno)
Christian Heimes33fe8092008-04-13 13:53:33 +0000200 if module is None:
201 module = filename or "<unknown>"
202 if module[-3:].lower() == ".py":
203 module = module[:-3] # XXX What about leading pathname?
204 if registry is None:
205 registry = {}
206 if isinstance(message, Warning):
207 text = str(message)
208 category = message.__class__
209 else:
210 text = message
211 message = category(message)
212 key = (text, category, lineno)
213 # Quick test for common case
214 if registry.get(key):
215 return
216 # Search the filters
217 for item in filters:
218 action, msg, cat, mod, ln = item
219 if ((msg is None or msg.match(text)) and
220 issubclass(category, cat) and
221 (mod is None or mod.match(module)) and
222 (ln == 0 or lineno == ln)):
223 break
224 else:
225 action = defaultaction
226 # Early exit actions
227 if action == "ignore":
228 registry[key] = 1
229 return
230
231 # Prime the linecache for formatting, in case the
232 # "file" is actually in a zipfile or something.
Antoine Pitrou7cb11fa2013-10-24 22:23:42 +0200233 import linecache
Christian Heimes33fe8092008-04-13 13:53:33 +0000234 linecache.getlines(filename, module_globals)
235
236 if action == "error":
237 raise message
238 # Other actions
239 if action == "once":
240 registry[key] = 1
241 oncekey = (text, category)
242 if onceregistry.get(oncekey):
243 return
244 onceregistry[oncekey] = 1
245 elif action == "always":
246 pass
247 elif action == "module":
248 registry[key] = 1
249 altkey = (text, category, 0)
250 if registry.get(altkey):
251 return
252 registry[altkey] = 1
253 elif action == "default":
254 registry[key] = 1
255 else:
256 # Unrecognized actions are errors
257 raise RuntimeError(
258 "Unrecognized action (%r) in warnings.filters:\n %s" %
259 (action, item))
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200260 if not callable(showwarning):
Christian Heimes8dc226f2008-05-06 23:45:46 +0000261 raise TypeError("warnings.showwarning() must be set to a "
262 "function or method")
Christian Heimes33fe8092008-04-13 13:53:33 +0000263 # Print message and context
264 showwarning(message, category, filename, lineno)
265
266
Brett Cannonec92e182008-09-02 02:46:59 +0000267class WarningMessage(object):
268
269 """Holds the result of a single showwarning() call."""
270
271 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
272 "line")
273
274 def __init__(self, message, category, filename, lineno, file=None,
275 line=None):
276 local_values = locals()
277 for attr in self._WARNING_DETAILS:
278 setattr(self, attr, local_values[attr])
279 self._category_name = category.__name__ if category else None
280
281 def __str__(self):
282 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
283 "line : %r}" % (self.message, self._category_name,
284 self.filename, self.lineno, self.line))
285
286
Brett Cannonec92e182008-09-02 02:46:59 +0000287class catch_warnings(object):
288
Brett Cannon1cd02472008-09-09 01:52:27 +0000289 """A context manager that copies and restores the warnings filter upon
290 exiting the context.
Brett Cannonec92e182008-09-02 02:46:59 +0000291
Brett Cannon1cd02472008-09-09 01:52:27 +0000292 The 'record' argument specifies whether warnings should be captured by a
293 custom implementation of warnings.showwarning() and be appended to a list
294 returned by the context manager. Otherwise None is returned by the context
295 manager. The objects appended to the list are arguments whose attributes
296 mirror the arguments to showwarning().
297
298 The 'module' argument is to specify an alternative module to the module
299 named 'warnings' and imported under that name. This argument is only useful
300 when testing the warnings module itself.
Brett Cannonec92e182008-09-02 02:46:59 +0000301
302 """
303
304 def __init__(self, *, record=False, module=None):
305 """Specify whether to record warnings and if an alternative module
306 should be used other than sys.modules['warnings'].
307
308 For compatibility with Python 3.0, please consider all arguments to be
309 keyword-only.
310
311 """
Brett Cannon1cd02472008-09-09 01:52:27 +0000312 self._record = record
Brett Cannonec92e182008-09-02 02:46:59 +0000313 self._module = sys.modules['warnings'] if module is None else module
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000314 self._entered = False
315
316 def __repr__(self):
317 args = []
318 if self._record:
319 args.append("record=True")
320 if self._module is not sys.modules['warnings']:
321 args.append("module=%r" % self._module)
322 name = type(self).__name__
323 return "%s(%s)" % (name, ", ".join(args))
Brett Cannonec92e182008-09-02 02:46:59 +0000324
325 def __enter__(self):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000326 if self._entered:
327 raise RuntimeError("Cannot enter %r twice" % self)
328 self._entered = True
Brett Cannonec92e182008-09-02 02:46:59 +0000329 self._filters = self._module.filters
330 self._module.filters = self._filters[:]
331 self._showwarning = self._module.showwarning
Brett Cannon1cd02472008-09-09 01:52:27 +0000332 if self._record:
333 log = []
334 def showwarning(*args, **kwargs):
335 log.append(WarningMessage(*args, **kwargs))
336 self._module.showwarning = showwarning
337 return log
338 else:
339 return None
Brett Cannonec92e182008-09-02 02:46:59 +0000340
341 def __exit__(self, *exc_info):
Benjamin Petersonfcf5d632008-10-16 23:24:44 +0000342 if not self._entered:
343 raise RuntimeError("Cannot exit %r without entering first" % self)
Brett Cannonec92e182008-09-02 02:46:59 +0000344 self._module.filters = self._filters
345 self._module.showwarning = self._showwarning
346
347
Christian Heimes33fe8092008-04-13 13:53:33 +0000348# filters contains a sequence of filter 5-tuples
349# The components of the 5-tuple are:
350# - an action: error, ignore, always, default, module, or once
351# - a compiled regex that must match the warning message
352# - a class representing the warning category
353# - a compiled regex that must match the module that is being warned
354# - a line number for the line being warning, or 0 to mean any line
355# If either if the compiled regexs are None, match anything.
356_warnings_defaults = False
357try:
Brett Cannonef0e6c32010-09-04 18:24:04 +0000358 from _warnings import (filters, _defaultaction, _onceregistry,
Christian Heimes33fe8092008-04-13 13:53:33 +0000359 warn, warn_explicit)
Brett Cannonef0e6c32010-09-04 18:24:04 +0000360 defaultaction = _defaultaction
361 onceregistry = _onceregistry
Christian Heimes33fe8092008-04-13 13:53:33 +0000362 _warnings_defaults = True
Brett Cannoncd171c82013-07-04 17:43:24 -0400363except ImportError:
Christian Heimes33fe8092008-04-13 13:53:33 +0000364 filters = []
365 defaultaction = "default"
366 onceregistry = {}
367
368
Guido van Rossum2a862c62000-12-15 21:59:53 +0000369# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000370_processoptions(sys.warnoptions)
Christian Heimes33fe8092008-04-13 13:53:33 +0000371if not _warnings_defaults:
Benjamin Peterson7ab4b8d2010-06-28 00:01:59 +0000372 silence = [ImportWarning, PendingDeprecationWarning]
373 silence.append(DeprecationWarning)
374 for cls in silence:
375 simplefilter("ignore", category=cls)
Christian Heimes33fe8092008-04-13 13:53:33 +0000376 bytes_warning = sys.flags.bytes_warning
377 if bytes_warning > 1:
378 bytes_action = "error"
379 elif bytes_warning:
380 bytes_action = "default"
381 else:
382 bytes_action = "ignore"
383 simplefilter(bytes_action, category=BytesWarning, append=1)
Georg Brandl08be72d2010-10-24 15:11:22 +0000384 # resource usage warnings are enabled by default in pydebug mode
385 if hasattr(sys, 'gettotalrefcount'):
386 resource_action = "always"
387 else:
388 resource_action = "ignore"
389 simplefilter(resource_action, category=ResourceWarning, append=1)
390
Christian Heimes33fe8092008-04-13 13:53:33 +0000391del _warnings_defaults