blob: fbec94b7f07aeab475367270b2bca71de343c0e3 [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))
Mark Hammond51a0ae32002-09-11 13:22:35 +000034 except IOError:
35 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."""
Guido van Rossum2a862c62000-12-15 21:59:53 +000042 s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
Brett Cannone9746892008-04-12 23:44:07 +000043 line = linecache.getline(filename, lineno) if line is None else line
Guido van Rossum2a862c62000-12-15 21:59:53 +000044 if line:
Brett Cannone9746892008-04-12 23:44:07 +000045 line = line.strip()
46 s += " %s\n" % line
Guido van Rossum2a862c62000-12-15 21:59:53 +000047 return s
48
Guido van Rossum9464a7d2001-01-14 14:08:40 +000049def filterwarnings(action, message="", category=Warning, module="", lineno=0,
50 append=0):
Guido van Rossum2a862c62000-12-15 21:59:53 +000051 """Insert an entry into the list of warnings filters (at the front).
52
Neil Schemenauerd87affe2009-10-23 19:58:17 +000053 'action' -- one of "error", "ignore", "always", "default", "module",
54 or "once"
55 'message' -- a regex that the warning message must match
56 'category' -- a class that the warning must be a subclass of
57 'module' -- a regex that the module name must match
58 'lineno' -- an integer line number, 0 matches all warnings
59 'append' -- if true, append to the list of filters
60 """
Skip Montanarod8f21202003-05-14 17:33:53 +000061 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +000062 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000063 "once"), "invalid action: %r" % (action,)
Martin v. Löwisff9284b2002-10-14 21:06:02 +000064 assert isinstance(message, basestring), "message must be a string"
Brett Cannonbf364092006-03-01 04:25:17 +000065 assert isinstance(category, (type, types.ClassType)), \
66 "category must be a class"
Guido van Rossum2a862c62000-12-15 21:59:53 +000067 assert issubclass(category, Warning), "category must be a Warning subclass"
Martin v. Löwisff9284b2002-10-14 21:06:02 +000068 assert isinstance(module, basestring), "module must be a string"
Walter Dörwald65230a22002-06-03 15:58:32 +000069 assert isinstance(lineno, int) and lineno >= 0, \
Guido van Rossum2a862c62000-12-15 21:59:53 +000070 "lineno must be an int >= 0"
Guido van Rossum9464a7d2001-01-14 14:08:40 +000071 item = (action, re.compile(message, re.I), category,
72 re.compile(module), lineno)
73 if append:
74 filters.append(item)
75 else:
76 filters.insert(0, item)
Guido van Rossum2a862c62000-12-15 21:59:53 +000077
Jeremy Hylton85014662003-07-11 15:37:59 +000078def simplefilter(action, category=Warning, lineno=0, append=0):
79 """Insert a simple entry into the list of warnings filters (at the front).
80
81 A simple filter matches all modules and messages.
Neil Schemenauerd87affe2009-10-23 19:58:17 +000082 'action' -- one of "error", "ignore", "always", "default", "module",
83 or "once"
84 'category' -- a class that the warning must be a subclass of
85 'lineno' -- an integer line number, 0 matches all warnings
86 'append' -- if true, append to the list of filters
Jeremy Hylton85014662003-07-11 15:37:59 +000087 """
88 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000089 "once"), "invalid action: %r" % (action,)
Jeremy Hylton85014662003-07-11 15:37:59 +000090 assert isinstance(lineno, int) and lineno >= 0, \
91 "lineno must be an int >= 0"
92 item = (action, None, category, None, lineno)
93 if append:
94 filters.append(item)
95 else:
96 filters.insert(0, item)
97
Guido van Rossum2a862c62000-12-15 21:59:53 +000098def resetwarnings():
Tim Petersd0cc4f02002-04-16 01:51:25 +000099 """Clear the list of warning filters, so that no filters are active."""
Guido van Rossum2a862c62000-12-15 21:59:53 +0000100 filters[:] = []
101
102class _OptionError(Exception):
103 """Exception used by option processing helpers."""
104 pass
105
106# Helper to process -W options passed via sys.warnoptions
107def _processoptions(args):
108 for arg in args:
109 try:
110 _setoption(arg)
111 except _OptionError, msg:
112 print >>sys.stderr, "Invalid -W option ignored:", msg
113
114# Helper for _processoptions()
115def _setoption(arg):
Skip Montanarod8f21202003-05-14 17:33:53 +0000116 import re
Tim Peterse1190062001-01-15 03:34:38 +0000117 parts = arg.split(':')
118 if len(parts) > 5:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000119 raise _OptionError("too many fields (max 5): %r" % (arg,))
Tim Peterse1190062001-01-15 03:34:38 +0000120 while len(parts) < 5:
121 parts.append('')
122 action, message, category, module, lineno = [s.strip()
123 for s in parts]
124 action = _getaction(action)
125 message = re.escape(message)
126 category = _getcategory(category)
127 module = re.escape(module)
128 if module:
129 module = module + '$'
130 if lineno:
131 try:
132 lineno = int(lineno)
133 if lineno < 0:
134 raise ValueError
135 except (ValueError, OverflowError):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000136 raise _OptionError("invalid lineno %r" % (lineno,))
Tim Peterse1190062001-01-15 03:34:38 +0000137 else:
138 lineno = 0
139 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000140
141# Helper for _setoption()
142def _getaction(action):
143 if not action:
144 return "default"
145 if action == "all": return "always" # Alias
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000146 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000147 if a.startswith(action):
148 return a
Walter Dörwald70a6b492004-02-12 17:35:32 +0000149 raise _OptionError("invalid action: %r" % (action,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000150
151# Helper for _setoption()
152def _getcategory(category):
Skip Montanarod8f21202003-05-14 17:33:53 +0000153 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000154 if not category:
155 return Warning
156 if re.match("^[a-zA-Z0-9_]+$", category):
157 try:
158 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000159 except NameError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000160 raise _OptionError("unknown warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000161 else:
162 i = category.rfind(".")
163 module = category[:i]
164 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000165 try:
166 m = __import__(module, None, None, [klass])
167 except ImportError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000168 raise _OptionError("invalid module name: %r" % (module,))
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000169 try:
170 cat = getattr(m, klass)
171 except AttributeError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000172 raise _OptionError("unknown warning category: %r" % (category,))
Brett Cannon53ab5b72006-06-22 16:49:14 +0000173 if not issubclass(cat, Warning):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000174 raise _OptionError("invalid warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000175 return cat
176
Brett Cannone9746892008-04-12 23:44:07 +0000177
178# Code typically replaced by _warnings
179def warn(message, category=None, stacklevel=1):
180 """Issue a warning, or maybe ignore it or raise an exception."""
181 # Check if message is already a Warning object
182 if isinstance(message, Warning):
183 category = message.__class__
184 # Check category argument
185 if category is None:
186 category = UserWarning
187 assert issubclass(category, Warning)
188 # Get context information
189 try:
190 caller = sys._getframe(stacklevel)
191 except ValueError:
192 globals = sys.__dict__
193 lineno = 1
194 else:
195 globals = caller.f_globals
196 lineno = caller.f_lineno
197 if '__name__' in globals:
198 module = globals['__name__']
199 else:
200 module = "<string>"
201 filename = globals.get('__file__')
202 if filename:
203 fnl = filename.lower()
204 if fnl.endswith((".pyc", ".pyo")):
205 filename = filename[:-1]
206 else:
207 if module == "__main__":
208 try:
209 filename = sys.argv[0]
210 except AttributeError:
211 # embedded interpreters don't have sys.argv, see bug #839151
212 filename = '__main__'
213 if not filename:
214 filename = module
215 registry = globals.setdefault("__warningregistry__", {})
216 warn_explicit(message, category, filename, lineno, module, registry,
217 globals)
218
219def warn_explicit(message, category, filename, lineno,
220 module=None, registry=None, module_globals=None):
Brett Cannondea1b562008-06-27 00:31:13 +0000221 lineno = int(lineno)
Brett Cannone9746892008-04-12 23:44:07 +0000222 if module is None:
223 module = filename or "<unknown>"
224 if module[-3:].lower() == ".py":
225 module = module[:-3] # XXX What about leading pathname?
226 if registry is None:
227 registry = {}
228 if isinstance(message, Warning):
229 text = str(message)
230 category = message.__class__
231 else:
232 text = message
233 message = category(message)
234 key = (text, category, lineno)
235 # Quick test for common case
236 if registry.get(key):
237 return
238 # Search the filters
239 for item in filters:
240 action, msg, cat, mod, ln = item
241 if ((msg is None or msg.match(text)) and
242 issubclass(category, cat) and
243 (mod is None or mod.match(module)) and
244 (ln == 0 or lineno == ln)):
245 break
246 else:
247 action = defaultaction
248 # Early exit actions
249 if action == "ignore":
250 registry[key] = 1
251 return
252
253 # Prime the linecache for formatting, in case the
254 # "file" is actually in a zipfile or something.
255 linecache.getlines(filename, module_globals)
256
257 if action == "error":
258 raise message
259 # Other actions
260 if action == "once":
261 registry[key] = 1
262 oncekey = (text, category)
263 if onceregistry.get(oncekey):
264 return
265 onceregistry[oncekey] = 1
266 elif action == "always":
267 pass
268 elif action == "module":
269 registry[key] = 1
270 altkey = (text, category, 0)
271 if registry.get(altkey):
272 return
273 registry[altkey] = 1
274 elif action == "default":
275 registry[key] = 1
276 else:
277 # Unrecognized actions are errors
278 raise RuntimeError(
279 "Unrecognized action (%r) in warnings.filters:\n %s" %
280 (action, item))
Brett Cannon9c19bc62008-05-05 16:57:38 +0000281 # Print message and context
Brett Cannone9746892008-04-12 23:44:07 +0000282 showwarning(message, category, filename, lineno)
283
284
Brett Cannon1eaf0742008-09-02 01:25:16 +0000285class WarningMessage(object):
286
287 """Holds the result of a single showwarning() call."""
288
289 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
290 "line")
291
292 def __init__(self, message, category, filename, lineno, file=None,
293 line=None):
294 local_values = locals()
295 for attr in self._WARNING_DETAILS:
296 setattr(self, attr, local_values[attr])
297 self._category_name = category.__name__ if category else None
298
299 def __str__(self):
300 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
301 "line : %r}" % (self.message, self._category_name,
302 self.filename, self.lineno, self.line))
303
304
Brett Cannon1eaf0742008-09-02 01:25:16 +0000305class catch_warnings(object):
306
Brett Cannon672237d2008-09-09 00:49:16 +0000307 """A context manager that copies and restores the warnings filter upon
308 exiting the context.
Brett Cannon1eaf0742008-09-02 01:25:16 +0000309
Brett Cannon672237d2008-09-09 00:49:16 +0000310 The 'record' argument specifies whether warnings should be captured by a
311 custom implementation of warnings.showwarning() and be appended to a list
312 returned by the context manager. Otherwise None is returned by the context
313 manager. The objects appended to the list are arguments whose attributes
314 mirror the arguments to showwarning().
315
316 The 'module' argument is to specify an alternative module to the module
317 named 'warnings' and imported under that name. This argument is only useful
318 when testing the warnings module itself.
Brett Cannon1eaf0742008-09-02 01:25:16 +0000319
320 """
321
322 def __init__(self, record=False, module=None):
323 """Specify whether to record warnings and if an alternative module
324 should be used other than sys.modules['warnings'].
325
326 For compatibility with Python 3.0, please consider all arguments to be
327 keyword-only.
328
329 """
Brett Cannon672237d2008-09-09 00:49:16 +0000330 self._record = record
Brett Cannon1eaf0742008-09-02 01:25:16 +0000331 self._module = sys.modules['warnings'] if module is None else module
Nick Coghland2e09382008-09-11 12:11:06 +0000332 self._entered = False
333
334 def __repr__(self):
335 args = []
336 if self._record:
337 args.append("record=True")
338 if self._module is not sys.modules['warnings']:
339 args.append("module=%r" % self._module)
340 name = type(self).__name__
341 return "%s(%s)" % (name, ", ".join(args))
Brett Cannon1eaf0742008-09-02 01:25:16 +0000342
343 def __enter__(self):
Nick Coghland2e09382008-09-11 12:11:06 +0000344 if self._entered:
345 raise RuntimeError("Cannot enter %r twice" % self)
346 self._entered = True
Brett Cannon1eaf0742008-09-02 01:25:16 +0000347 self._filters = self._module.filters
348 self._module.filters = self._filters[:]
349 self._showwarning = self._module.showwarning
Brett Cannon672237d2008-09-09 00:49:16 +0000350 if self._record:
351 log = []
352 def showwarning(*args, **kwargs):
353 log.append(WarningMessage(*args, **kwargs))
354 self._module.showwarning = showwarning
355 return log
356 else:
357 return None
Brett Cannon1eaf0742008-09-02 01:25:16 +0000358
359 def __exit__(self, *exc_info):
Nick Coghland2e09382008-09-11 12:11:06 +0000360 if not self._entered:
361 raise RuntimeError("Cannot exit %r without entering first" % self)
Brett Cannon1eaf0742008-09-02 01:25:16 +0000362 self._module.filters = self._filters
363 self._module.showwarning = self._showwarning
364
365
Brett Cannone9746892008-04-12 23:44:07 +0000366# filters contains a sequence of filter 5-tuples
367# The components of the 5-tuple are:
368# - an action: error, ignore, always, default, module, or once
369# - a compiled regex that must match the warning message
370# - a class representing the warning category
371# - a compiled regex that must match the module that is being warned
372# - a line number for the line being warning, or 0 to mean any line
373# If either if the compiled regexs are None, match anything.
374_warnings_defaults = False
375try:
376 from _warnings import (filters, default_action, once_registry,
377 warn, warn_explicit)
378 defaultaction = default_action
379 onceregistry = once_registry
380 _warnings_defaults = True
381except ImportError:
382 filters = []
383 defaultaction = "default"
384 onceregistry = {}
385
386
Guido van Rossum2a862c62000-12-15 21:59:53 +0000387# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000388_processoptions(sys.warnoptions)
Brett Cannone9746892008-04-12 23:44:07 +0000389if not _warnings_defaults:
Brett Cannon3ffa43d2010-01-14 20:00:28 +0000390 silence = [ImportWarning, PendingDeprecationWarning]
Brett Cannon19949692010-04-25 22:33:36 +0000391 # Don't silence DeprecationWarning if -3 or -Q was used.
392 if not sys.py3kwarning and not sys.flags.division_warning:
Brett Cannon3ffa43d2010-01-14 20:00:28 +0000393 silence.append(DeprecationWarning)
394 for cls in silence:
395 simplefilter("ignore", category=cls)
Brett Cannone9746892008-04-12 23:44:07 +0000396 bytes_warning = sys.flags.bytes_warning
397 if bytes_warning > 1:
398 bytes_action = "error"
399 elif bytes_warning:
400 bytes_action = "default"
401 else:
402 bytes_action = "ignore"
403 simplefilter(bytes_action, category=BytesWarning, append=1)
404del _warnings_defaults