blob: 84f111d6c97fef6a49fea32a6343b8bd866f7669 [file] [log] [blame]
Guido van Rossum2a862c62000-12-15 21:59:53 +00001"""Python part of the warnings subsystem."""
2
Mark Hammonda43fd0c2003-02-19 00:33:33 +00003# Note: function level imports should *not* be used
4# in this module as it may cause import lock deadlock.
5# See bug 683658.
Mark Hammonda43fd0c2003-02-19 00:33:33 +00006import linecache
Brett Cannone9746892008-04-12 23:44:07 +00007import sys
8import types
Guido van Rossum2a862c62000-12-15 21:59:53 +00009
Brett Cannon01408452014-08-22 10:50:47 -040010__all__ = ["warn", "warn_explicit", "showwarning",
11 "formatwarning", "filterwarnings", "simplefilter",
Brett Cannon672237d2008-09-09 00:49:16 +000012 "resetwarnings", "catch_warnings"]
Skip Montanaro40fc1602001-03-01 04:27:19 +000013
Guido van Rossum2a862c62000-12-15 21:59:53 +000014
Christian Heimes28104c52007-11-27 23:16:44 +000015def warnpy3k(message, category=None, stacklevel=1):
16 """Issue a deprecation warning for Python 3.x related changes.
17
18 Warnings are omitted unless Python is started with the -3 option.
19 """
20 if sys.py3kwarning:
21 if category is None:
22 category = DeprecationWarning
23 warn(message, category, stacklevel+1)
24
Brett Cannon8a232cc2008-05-05 05:32:07 +000025def _show_warning(message, category, filename, lineno, file=None, line=None):
Guido van Rossum2a862c62000-12-15 21:59:53 +000026 """Hook to write a warning to a file; replace if you like."""
27 if file is None:
28 file = sys.stderr
Serhiy Storchakae6b42432014-12-10 23:05:33 +020029 if file is None:
30 # sys.stderr is None - warnings get lost
31 return
Mark Hammond51a0ae32002-09-11 13:22:35 +000032 try:
Brett Cannone9746892008-04-12 23:44:07 +000033 file.write(formatwarning(message, category, filename, lineno, line))
Serhiy Storchakaf40fcb32015-05-16 16:42:18 +030034 except (IOError, UnicodeError):
Mark Hammond51a0ae32002-09-11 13:22:35 +000035 pass # the file (probably stderr) is invalid - this warning gets lost.
Florent Xicluna1f3b4e12010-03-07 12:14:25 +000036# Keep a working version around in case the deprecation of the old API is
Brett Cannon8a232cc2008-05-05 05:32:07 +000037# triggered.
38showwarning = _show_warning
Guido van Rossum2a862c62000-12-15 21:59:53 +000039
Brett Cannone9746892008-04-12 23:44:07 +000040def formatwarning(message, category, filename, lineno, line=None):
Guido van Rossum9464a7d2001-01-14 14:08:40 +000041 """Function to format a warning the standard way."""
Serhiy Storchakaf40fcb32015-05-16 16:42:18 +030042 try:
43 unicodetype = unicode
44 except NameError:
45 unicodetype = ()
46 try:
47 message = str(message)
48 except UnicodeEncodeError:
49 pass
50 s = "%s: %s: %s\n" % (lineno, category.__name__, message)
Brett Cannone9746892008-04-12 23:44:07 +000051 line = linecache.getline(filename, lineno) if line is None else line
Guido van Rossum2a862c62000-12-15 21:59:53 +000052 if line:
Brett Cannone9746892008-04-12 23:44:07 +000053 line = line.strip()
Serhiy Storchakaf40fcb32015-05-16 16:42:18 +030054 if isinstance(s, unicodetype) and isinstance(line, str):
55 line = unicode(line, 'latin1')
Brett Cannone9746892008-04-12 23:44:07 +000056 s += " %s\n" % line
Serhiy Storchakaf40fcb32015-05-16 16:42:18 +030057 if isinstance(s, unicodetype) and isinstance(filename, str):
58 enc = sys.getfilesystemencoding()
59 if enc:
60 try:
61 filename = unicode(filename, enc)
62 except UnicodeDecodeError:
63 pass
64 s = "%s:%s" % (filename, s)
Guido van Rossum2a862c62000-12-15 21:59:53 +000065 return s
66
Guido van Rossum9464a7d2001-01-14 14:08:40 +000067def filterwarnings(action, message="", category=Warning, module="", lineno=0,
68 append=0):
Guido van Rossum2a862c62000-12-15 21:59:53 +000069 """Insert an entry into the list of warnings filters (at the front).
70
Neil Schemenauerd87affe2009-10-23 19:58:17 +000071 'action' -- one of "error", "ignore", "always", "default", "module",
72 or "once"
73 'message' -- a regex that the warning message must match
74 'category' -- a class that the warning must be a subclass of
75 'module' -- a regex that the module name must match
76 'lineno' -- an integer line number, 0 matches all warnings
77 'append' -- if true, append to the list of filters
78 """
Skip Montanarod8f21202003-05-14 17:33:53 +000079 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +000080 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000081 "once"), "invalid action: %r" % (action,)
Martin v. Löwisff9284b2002-10-14 21:06:02 +000082 assert isinstance(message, basestring), "message must be a string"
Brett Cannonbf364092006-03-01 04:25:17 +000083 assert isinstance(category, (type, types.ClassType)), \
84 "category must be a class"
Guido van Rossum2a862c62000-12-15 21:59:53 +000085 assert issubclass(category, Warning), "category must be a Warning subclass"
Martin v. Löwisff9284b2002-10-14 21:06:02 +000086 assert isinstance(module, basestring), "module must be a string"
Serhiy Storchaka994f04d2016-12-27 15:09:36 +020087 assert isinstance(lineno, (int, long)) and lineno >= 0, \
Guido van Rossum2a862c62000-12-15 21:59:53 +000088 "lineno must be an int >= 0"
Guido van Rossum9464a7d2001-01-14 14:08:40 +000089 item = (action, re.compile(message, re.I), category,
Serhiy Storchaka994f04d2016-12-27 15:09:36 +020090 re.compile(module), int(lineno))
Guido van Rossum9464a7d2001-01-14 14:08:40 +000091 if append:
92 filters.append(item)
93 else:
94 filters.insert(0, item)
Guido van Rossum2a862c62000-12-15 21:59:53 +000095
Jeremy Hylton85014662003-07-11 15:37:59 +000096def simplefilter(action, category=Warning, lineno=0, append=0):
97 """Insert a simple entry into the list of warnings filters (at the front).
98
99 A simple filter matches all modules and messages.
Neil Schemenauerd87affe2009-10-23 19:58:17 +0000100 'action' -- one of "error", "ignore", "always", "default", "module",
101 or "once"
102 'category' -- a class that the warning must be a subclass of
103 'lineno' -- an integer line number, 0 matches all warnings
104 'append' -- if true, append to the list of filters
Jeremy Hylton85014662003-07-11 15:37:59 +0000105 """
106 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +0000107 "once"), "invalid action: %r" % (action,)
Serhiy Storchaka994f04d2016-12-27 15:09:36 +0200108 assert isinstance(lineno, (int, long)) and lineno >= 0, \
Jeremy Hylton85014662003-07-11 15:37:59 +0000109 "lineno must be an int >= 0"
Serhiy Storchaka994f04d2016-12-27 15:09:36 +0200110 item = (action, None, category, None, int(lineno))
Jeremy Hylton85014662003-07-11 15:37:59 +0000111 if append:
112 filters.append(item)
113 else:
114 filters.insert(0, item)
115
Guido van Rossum2a862c62000-12-15 21:59:53 +0000116def resetwarnings():
Tim Petersd0cc4f02002-04-16 01:51:25 +0000117 """Clear the list of warning filters, so that no filters are active."""
Guido van Rossum2a862c62000-12-15 21:59:53 +0000118 filters[:] = []
119
120class _OptionError(Exception):
121 """Exception used by option processing helpers."""
122 pass
123
124# Helper to process -W options passed via sys.warnoptions
125def _processoptions(args):
126 for arg in args:
127 try:
128 _setoption(arg)
129 except _OptionError, msg:
130 print >>sys.stderr, "Invalid -W option ignored:", msg
131
132# Helper for _processoptions()
133def _setoption(arg):
Skip Montanarod8f21202003-05-14 17:33:53 +0000134 import re
Tim Peterse1190062001-01-15 03:34:38 +0000135 parts = arg.split(':')
136 if len(parts) > 5:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000137 raise _OptionError("too many fields (max 5): %r" % (arg,))
Tim Peterse1190062001-01-15 03:34:38 +0000138 while len(parts) < 5:
139 parts.append('')
140 action, message, category, module, lineno = [s.strip()
141 for s in parts]
142 action = _getaction(action)
143 message = re.escape(message)
144 category = _getcategory(category)
145 module = re.escape(module)
146 if module:
147 module = module + '$'
148 if lineno:
149 try:
150 lineno = int(lineno)
151 if lineno < 0:
152 raise ValueError
153 except (ValueError, OverflowError):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000154 raise _OptionError("invalid lineno %r" % (lineno,))
Tim Peterse1190062001-01-15 03:34:38 +0000155 else:
156 lineno = 0
157 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000158
159# Helper for _setoption()
160def _getaction(action):
161 if not action:
162 return "default"
163 if action == "all": return "always" # Alias
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000164 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000165 if a.startswith(action):
166 return a
Walter Dörwald70a6b492004-02-12 17:35:32 +0000167 raise _OptionError("invalid action: %r" % (action,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000168
169# Helper for _setoption()
170def _getcategory(category):
Skip Montanarod8f21202003-05-14 17:33:53 +0000171 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000172 if not category:
173 return Warning
174 if re.match("^[a-zA-Z0-9_]+$", category):
175 try:
176 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000177 except NameError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000178 raise _OptionError("unknown warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000179 else:
180 i = category.rfind(".")
181 module = category[:i]
182 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000183 try:
184 m = __import__(module, None, None, [klass])
185 except ImportError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000186 raise _OptionError("invalid module name: %r" % (module,))
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000187 try:
188 cat = getattr(m, klass)
189 except AttributeError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000190 raise _OptionError("unknown warning category: %r" % (category,))
Brett Cannon53ab5b72006-06-22 16:49:14 +0000191 if not issubclass(cat, Warning):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000192 raise _OptionError("invalid warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000193 return cat
194
Brett Cannone9746892008-04-12 23:44:07 +0000195
196# Code typically replaced by _warnings
197def warn(message, category=None, stacklevel=1):
198 """Issue a warning, or maybe ignore it or raise an exception."""
199 # Check if message is already a Warning object
200 if isinstance(message, Warning):
201 category = message.__class__
202 # Check category argument
203 if category is None:
204 category = UserWarning
205 assert issubclass(category, Warning)
206 # Get context information
207 try:
208 caller = sys._getframe(stacklevel)
209 except ValueError:
210 globals = sys.__dict__
211 lineno = 1
212 else:
213 globals = caller.f_globals
214 lineno = caller.f_lineno
215 if '__name__' in globals:
216 module = globals['__name__']
217 else:
218 module = "<string>"
219 filename = globals.get('__file__')
220 if filename:
221 fnl = filename.lower()
222 if fnl.endswith((".pyc", ".pyo")):
223 filename = filename[:-1]
224 else:
225 if module == "__main__":
226 try:
227 filename = sys.argv[0]
228 except AttributeError:
229 # embedded interpreters don't have sys.argv, see bug #839151
230 filename = '__main__'
231 if not filename:
232 filename = module
233 registry = globals.setdefault("__warningregistry__", {})
234 warn_explicit(message, category, filename, lineno, module, registry,
235 globals)
236
237def warn_explicit(message, category, filename, lineno,
238 module=None, registry=None, module_globals=None):
Brett Cannondea1b562008-06-27 00:31:13 +0000239 lineno = int(lineno)
Brett Cannone9746892008-04-12 23:44:07 +0000240 if module is None:
241 module = filename or "<unknown>"
242 if module[-3:].lower() == ".py":
243 module = module[:-3] # XXX What about leading pathname?
244 if registry is None:
245 registry = {}
246 if isinstance(message, Warning):
247 text = str(message)
248 category = message.__class__
249 else:
250 text = message
251 message = category(message)
252 key = (text, category, lineno)
253 # Quick test for common case
254 if registry.get(key):
255 return
256 # Search the filters
257 for item in filters:
258 action, msg, cat, mod, ln = item
259 if ((msg is None or msg.match(text)) and
260 issubclass(category, cat) and
261 (mod is None or mod.match(module)) and
262 (ln == 0 or lineno == ln)):
263 break
264 else:
265 action = defaultaction
266 # Early exit actions
267 if action == "ignore":
268 registry[key] = 1
269 return
270
271 # Prime the linecache for formatting, in case the
272 # "file" is actually in a zipfile or something.
273 linecache.getlines(filename, module_globals)
274
275 if action == "error":
276 raise message
277 # Other actions
278 if action == "once":
279 registry[key] = 1
280 oncekey = (text, category)
281 if onceregistry.get(oncekey):
282 return
283 onceregistry[oncekey] = 1
284 elif action == "always":
285 pass
286 elif action == "module":
287 registry[key] = 1
288 altkey = (text, category, 0)
289 if registry.get(altkey):
290 return
291 registry[altkey] = 1
292 elif action == "default":
293 registry[key] = 1
294 else:
295 # Unrecognized actions are errors
296 raise RuntimeError(
297 "Unrecognized action (%r) in warnings.filters:\n %s" %
298 (action, item))
Brett Cannon9c19bc62008-05-05 16:57:38 +0000299 # Print message and context
Brett Cannone9746892008-04-12 23:44:07 +0000300 showwarning(message, category, filename, lineno)
301
302
Brett Cannon1eaf0742008-09-02 01:25:16 +0000303class WarningMessage(object):
304
305 """Holds the result of a single showwarning() call."""
306
307 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
308 "line")
309
310 def __init__(self, message, category, filename, lineno, file=None,
311 line=None):
Alex Gaynore14af322017-06-05 09:13:50 -0400312 self.message = message
313 self.category = category
314 self.filename = filename
315 self.lineno = lineno
316 self.file = file
317 self.line = line
Brett Cannon1eaf0742008-09-02 01:25:16 +0000318 self._category_name = category.__name__ if category else None
319
320 def __str__(self):
321 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
322 "line : %r}" % (self.message, self._category_name,
323 self.filename, self.lineno, self.line))
324
325
Brett Cannon1eaf0742008-09-02 01:25:16 +0000326class catch_warnings(object):
327
Brett Cannon672237d2008-09-09 00:49:16 +0000328 """A context manager that copies and restores the warnings filter upon
329 exiting the context.
Brett Cannon1eaf0742008-09-02 01:25:16 +0000330
Brett Cannon672237d2008-09-09 00:49:16 +0000331 The 'record' argument specifies whether warnings should be captured by a
332 custom implementation of warnings.showwarning() and be appended to a list
333 returned by the context manager. Otherwise None is returned by the context
334 manager. The objects appended to the list are arguments whose attributes
335 mirror the arguments to showwarning().
336
337 The 'module' argument is to specify an alternative module to the module
338 named 'warnings' and imported under that name. This argument is only useful
339 when testing the warnings module itself.
Brett Cannon1eaf0742008-09-02 01:25:16 +0000340
341 """
342
343 def __init__(self, record=False, module=None):
344 """Specify whether to record warnings and if an alternative module
345 should be used other than sys.modules['warnings'].
346
347 For compatibility with Python 3.0, please consider all arguments to be
348 keyword-only.
349
350 """
Brett Cannon672237d2008-09-09 00:49:16 +0000351 self._record = record
Brett Cannon1eaf0742008-09-02 01:25:16 +0000352 self._module = sys.modules['warnings'] if module is None else module
Nick Coghland2e09382008-09-11 12:11:06 +0000353 self._entered = False
354
355 def __repr__(self):
356 args = []
357 if self._record:
358 args.append("record=True")
359 if self._module is not sys.modules['warnings']:
360 args.append("module=%r" % self._module)
361 name = type(self).__name__
362 return "%s(%s)" % (name, ", ".join(args))
Brett Cannon1eaf0742008-09-02 01:25:16 +0000363
364 def __enter__(self):
Nick Coghland2e09382008-09-11 12:11:06 +0000365 if self._entered:
366 raise RuntimeError("Cannot enter %r twice" % self)
367 self._entered = True
Brett Cannon1eaf0742008-09-02 01:25:16 +0000368 self._filters = self._module.filters
369 self._module.filters = self._filters[:]
370 self._showwarning = self._module.showwarning
Brett Cannon672237d2008-09-09 00:49:16 +0000371 if self._record:
372 log = []
373 def showwarning(*args, **kwargs):
374 log.append(WarningMessage(*args, **kwargs))
375 self._module.showwarning = showwarning
376 return log
377 else:
378 return None
Brett Cannon1eaf0742008-09-02 01:25:16 +0000379
380 def __exit__(self, *exc_info):
Nick Coghland2e09382008-09-11 12:11:06 +0000381 if not self._entered:
382 raise RuntimeError("Cannot exit %r without entering first" % self)
Brett Cannon1eaf0742008-09-02 01:25:16 +0000383 self._module.filters = self._filters
384 self._module.showwarning = self._showwarning
385
386
Brett Cannone9746892008-04-12 23:44:07 +0000387# filters contains a sequence of filter 5-tuples
388# The components of the 5-tuple are:
389# - an action: error, ignore, always, default, module, or once
390# - a compiled regex that must match the warning message
391# - a class representing the warning category
392# - a compiled regex that must match the module that is being warned
393# - a line number for the line being warning, or 0 to mean any line
394# If either if the compiled regexs are None, match anything.
395_warnings_defaults = False
396try:
397 from _warnings import (filters, default_action, once_registry,
398 warn, warn_explicit)
399 defaultaction = default_action
400 onceregistry = once_registry
401 _warnings_defaults = True
402except ImportError:
403 filters = []
404 defaultaction = "default"
405 onceregistry = {}
406
407
Guido van Rossum2a862c62000-12-15 21:59:53 +0000408# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000409_processoptions(sys.warnoptions)
Brett Cannone9746892008-04-12 23:44:07 +0000410if not _warnings_defaults:
Brett Cannon3ffa43d2010-01-14 20:00:28 +0000411 silence = [ImportWarning, PendingDeprecationWarning]
Brett Cannon19949692010-04-25 22:33:36 +0000412 # Don't silence DeprecationWarning if -3 or -Q was used.
413 if not sys.py3kwarning and not sys.flags.division_warning:
Brett Cannon3ffa43d2010-01-14 20:00:28 +0000414 silence.append(DeprecationWarning)
415 for cls in silence:
416 simplefilter("ignore", category=cls)
Brett Cannone9746892008-04-12 23:44:07 +0000417 bytes_warning = sys.flags.bytes_warning
418 if bytes_warning > 1:
419 bytes_action = "error"
420 elif bytes_warning:
421 bytes_action = "default"
422 else:
423 bytes_action = "ignore"
424 simplefilter(bytes_action, category=BytesWarning, append=1)
425del _warnings_defaults