blob: bf9a5d86e14b4038795ab33d6ec6349078f4a22e [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
Mark Hammond51a0ae32002-09-11 13:22:35 +000029 try:
Brett Cannone9746892008-04-12 23:44:07 +000030 file.write(formatwarning(message, category, filename, lineno, line))
Mark Hammond51a0ae32002-09-11 13:22:35 +000031 except IOError:
32 pass # the file (probably stderr) is invalid - this warning gets lost.
Florent Xicluna1f3b4e12010-03-07 12:14:25 +000033# Keep a working version around in case the deprecation of the old API is
Brett Cannon8a232cc2008-05-05 05:32:07 +000034# triggered.
35showwarning = _show_warning
Guido van Rossum2a862c62000-12-15 21:59:53 +000036
Brett Cannone9746892008-04-12 23:44:07 +000037def formatwarning(message, category, filename, lineno, line=None):
Guido van Rossum9464a7d2001-01-14 14:08:40 +000038 """Function to format a warning the standard way."""
Guido van Rossum2a862c62000-12-15 21:59:53 +000039 s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
Brett Cannone9746892008-04-12 23:44:07 +000040 line = linecache.getline(filename, lineno) if line is None else line
Guido van Rossum2a862c62000-12-15 21:59:53 +000041 if line:
Brett Cannone9746892008-04-12 23:44:07 +000042 line = line.strip()
43 s += " %s\n" % line
Guido van Rossum2a862c62000-12-15 21:59:53 +000044 return s
45
Guido van Rossum9464a7d2001-01-14 14:08:40 +000046def filterwarnings(action, message="", category=Warning, module="", lineno=0,
47 append=0):
Guido van Rossum2a862c62000-12-15 21:59:53 +000048 """Insert an entry into the list of warnings filters (at the front).
49
Neil Schemenauerd87affe2009-10-23 19:58:17 +000050 'action' -- one of "error", "ignore", "always", "default", "module",
51 or "once"
52 'message' -- a regex that the warning message must match
53 'category' -- a class that the warning must be a subclass of
54 'module' -- a regex that the module name must match
55 'lineno' -- an integer line number, 0 matches all warnings
56 'append' -- if true, append to the list of filters
57 """
Skip Montanarod8f21202003-05-14 17:33:53 +000058 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +000059 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000060 "once"), "invalid action: %r" % (action,)
Martin v. Löwisff9284b2002-10-14 21:06:02 +000061 assert isinstance(message, basestring), "message must be a string"
Brett Cannonbf364092006-03-01 04:25:17 +000062 assert isinstance(category, (type, types.ClassType)), \
63 "category must be a class"
Guido van Rossum2a862c62000-12-15 21:59:53 +000064 assert issubclass(category, Warning), "category must be a Warning subclass"
Martin v. Löwisff9284b2002-10-14 21:06:02 +000065 assert isinstance(module, basestring), "module must be a string"
Walter Dörwald65230a22002-06-03 15:58:32 +000066 assert isinstance(lineno, int) and lineno >= 0, \
Guido van Rossum2a862c62000-12-15 21:59:53 +000067 "lineno must be an int >= 0"
Guido van Rossum9464a7d2001-01-14 14:08:40 +000068 item = (action, re.compile(message, re.I), category,
69 re.compile(module), lineno)
70 if append:
71 filters.append(item)
72 else:
73 filters.insert(0, item)
Guido van Rossum2a862c62000-12-15 21:59:53 +000074
Jeremy Hylton85014662003-07-11 15:37:59 +000075def simplefilter(action, category=Warning, lineno=0, append=0):
76 """Insert a simple entry into the list of warnings filters (at the front).
77
78 A simple filter matches all modules and messages.
Neil Schemenauerd87affe2009-10-23 19:58:17 +000079 'action' -- one of "error", "ignore", "always", "default", "module",
80 or "once"
81 'category' -- a class that the warning must be a subclass of
82 'lineno' -- an integer line number, 0 matches all warnings
83 'append' -- if true, append to the list of filters
Jeremy Hylton85014662003-07-11 15:37:59 +000084 """
85 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000086 "once"), "invalid action: %r" % (action,)
Jeremy Hylton85014662003-07-11 15:37:59 +000087 assert isinstance(lineno, int) and lineno >= 0, \
88 "lineno must be an int >= 0"
89 item = (action, None, category, None, lineno)
90 if append:
91 filters.append(item)
92 else:
93 filters.insert(0, item)
94
Guido van Rossum2a862c62000-12-15 21:59:53 +000095def resetwarnings():
Tim Petersd0cc4f02002-04-16 01:51:25 +000096 """Clear the list of warning filters, so that no filters are active."""
Guido van Rossum2a862c62000-12-15 21:59:53 +000097 filters[:] = []
98
99class _OptionError(Exception):
100 """Exception used by option processing helpers."""
101 pass
102
103# Helper to process -W options passed via sys.warnoptions
104def _processoptions(args):
105 for arg in args:
106 try:
107 _setoption(arg)
108 except _OptionError, msg:
109 print >>sys.stderr, "Invalid -W option ignored:", msg
110
111# Helper for _processoptions()
112def _setoption(arg):
Skip Montanarod8f21202003-05-14 17:33:53 +0000113 import re
Tim Peterse1190062001-01-15 03:34:38 +0000114 parts = arg.split(':')
115 if len(parts) > 5:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000116 raise _OptionError("too many fields (max 5): %r" % (arg,))
Tim Peterse1190062001-01-15 03:34:38 +0000117 while len(parts) < 5:
118 parts.append('')
119 action, message, category, module, lineno = [s.strip()
120 for s in parts]
121 action = _getaction(action)
122 message = re.escape(message)
123 category = _getcategory(category)
124 module = re.escape(module)
125 if module:
126 module = module + '$'
127 if lineno:
128 try:
129 lineno = int(lineno)
130 if lineno < 0:
131 raise ValueError
132 except (ValueError, OverflowError):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000133 raise _OptionError("invalid lineno %r" % (lineno,))
Tim Peterse1190062001-01-15 03:34:38 +0000134 else:
135 lineno = 0
136 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000137
138# Helper for _setoption()
139def _getaction(action):
140 if not action:
141 return "default"
142 if action == "all": return "always" # Alias
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000143 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000144 if a.startswith(action):
145 return a
Walter Dörwald70a6b492004-02-12 17:35:32 +0000146 raise _OptionError("invalid action: %r" % (action,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000147
148# Helper for _setoption()
149def _getcategory(category):
Skip Montanarod8f21202003-05-14 17:33:53 +0000150 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000151 if not category:
152 return Warning
153 if re.match("^[a-zA-Z0-9_]+$", category):
154 try:
155 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000156 except NameError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000157 raise _OptionError("unknown warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000158 else:
159 i = category.rfind(".")
160 module = category[:i]
161 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000162 try:
163 m = __import__(module, None, None, [klass])
164 except ImportError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000165 raise _OptionError("invalid module name: %r" % (module,))
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000166 try:
167 cat = getattr(m, klass)
168 except AttributeError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000169 raise _OptionError("unknown warning category: %r" % (category,))
Brett Cannon53ab5b72006-06-22 16:49:14 +0000170 if not issubclass(cat, Warning):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000171 raise _OptionError("invalid warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000172 return cat
173
Brett Cannone9746892008-04-12 23:44:07 +0000174
175# Code typically replaced by _warnings
176def warn(message, category=None, stacklevel=1):
177 """Issue a warning, or maybe ignore it or raise an exception."""
178 # Check if message is already a Warning object
179 if isinstance(message, Warning):
180 category = message.__class__
181 # Check category argument
182 if category is None:
183 category = UserWarning
184 assert issubclass(category, Warning)
185 # Get context information
186 try:
187 caller = sys._getframe(stacklevel)
188 except ValueError:
189 globals = sys.__dict__
190 lineno = 1
191 else:
192 globals = caller.f_globals
193 lineno = caller.f_lineno
194 if '__name__' in globals:
195 module = globals['__name__']
196 else:
197 module = "<string>"
198 filename = globals.get('__file__')
199 if filename:
200 fnl = filename.lower()
201 if fnl.endswith((".pyc", ".pyo")):
202 filename = filename[:-1]
203 else:
204 if module == "__main__":
205 try:
206 filename = sys.argv[0]
207 except AttributeError:
208 # embedded interpreters don't have sys.argv, see bug #839151
209 filename = '__main__'
210 if not filename:
211 filename = module
212 registry = globals.setdefault("__warningregistry__", {})
213 warn_explicit(message, category, filename, lineno, module, registry,
214 globals)
215
216def warn_explicit(message, category, filename, lineno,
217 module=None, registry=None, module_globals=None):
Brett Cannondea1b562008-06-27 00:31:13 +0000218 lineno = int(lineno)
Brett Cannone9746892008-04-12 23:44:07 +0000219 if module is None:
220 module = filename or "<unknown>"
221 if module[-3:].lower() == ".py":
222 module = module[:-3] # XXX What about leading pathname?
223 if registry is None:
224 registry = {}
225 if isinstance(message, Warning):
226 text = str(message)
227 category = message.__class__
228 else:
229 text = message
230 message = category(message)
231 key = (text, category, lineno)
232 # Quick test for common case
233 if registry.get(key):
234 return
235 # Search the filters
236 for item in filters:
237 action, msg, cat, mod, ln = item
238 if ((msg is None or msg.match(text)) and
239 issubclass(category, cat) and
240 (mod is None or mod.match(module)) and
241 (ln == 0 or lineno == ln)):
242 break
243 else:
244 action = defaultaction
245 # Early exit actions
246 if action == "ignore":
247 registry[key] = 1
248 return
249
250 # Prime the linecache for formatting, in case the
251 # "file" is actually in a zipfile or something.
252 linecache.getlines(filename, module_globals)
253
254 if action == "error":
255 raise message
256 # Other actions
257 if action == "once":
258 registry[key] = 1
259 oncekey = (text, category)
260 if onceregistry.get(oncekey):
261 return
262 onceregistry[oncekey] = 1
263 elif action == "always":
264 pass
265 elif action == "module":
266 registry[key] = 1
267 altkey = (text, category, 0)
268 if registry.get(altkey):
269 return
270 registry[altkey] = 1
271 elif action == "default":
272 registry[key] = 1
273 else:
274 # Unrecognized actions are errors
275 raise RuntimeError(
276 "Unrecognized action (%r) in warnings.filters:\n %s" %
277 (action, item))
Brett Cannon9c19bc62008-05-05 16:57:38 +0000278 # Print message and context
Brett Cannone9746892008-04-12 23:44:07 +0000279 showwarning(message, category, filename, lineno)
280
281
Brett Cannon1eaf0742008-09-02 01:25:16 +0000282class WarningMessage(object):
283
284 """Holds the result of a single showwarning() call."""
285
286 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
287 "line")
288
289 def __init__(self, message, category, filename, lineno, file=None,
290 line=None):
291 local_values = locals()
292 for attr in self._WARNING_DETAILS:
293 setattr(self, attr, local_values[attr])
294 self._category_name = category.__name__ if category else None
295
296 def __str__(self):
297 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
298 "line : %r}" % (self.message, self._category_name,
299 self.filename, self.lineno, self.line))
300
301
Brett Cannon1eaf0742008-09-02 01:25:16 +0000302class catch_warnings(object):
303
Brett Cannon672237d2008-09-09 00:49:16 +0000304 """A context manager that copies and restores the warnings filter upon
305 exiting the context.
Brett Cannon1eaf0742008-09-02 01:25:16 +0000306
Brett Cannon672237d2008-09-09 00:49:16 +0000307 The 'record' argument specifies whether warnings should be captured by a
308 custom implementation of warnings.showwarning() and be appended to a list
309 returned by the context manager. Otherwise None is returned by the context
310 manager. The objects appended to the list are arguments whose attributes
311 mirror the arguments to showwarning().
312
313 The 'module' argument is to specify an alternative module to the module
314 named 'warnings' and imported under that name. This argument is only useful
315 when testing the warnings module itself.
Brett Cannon1eaf0742008-09-02 01:25:16 +0000316
317 """
318
319 def __init__(self, record=False, module=None):
320 """Specify whether to record warnings and if an alternative module
321 should be used other than sys.modules['warnings'].
322
323 For compatibility with Python 3.0, please consider all arguments to be
324 keyword-only.
325
326 """
Brett Cannon672237d2008-09-09 00:49:16 +0000327 self._record = record
Brett Cannon1eaf0742008-09-02 01:25:16 +0000328 self._module = sys.modules['warnings'] if module is None else module
Nick Coghland2e09382008-09-11 12:11:06 +0000329 self._entered = False
330
331 def __repr__(self):
332 args = []
333 if self._record:
334 args.append("record=True")
335 if self._module is not sys.modules['warnings']:
336 args.append("module=%r" % self._module)
337 name = type(self).__name__
338 return "%s(%s)" % (name, ", ".join(args))
Brett Cannon1eaf0742008-09-02 01:25:16 +0000339
340 def __enter__(self):
Nick Coghland2e09382008-09-11 12:11:06 +0000341 if self._entered:
342 raise RuntimeError("Cannot enter %r twice" % self)
343 self._entered = True
Brett Cannon1eaf0742008-09-02 01:25:16 +0000344 self._filters = self._module.filters
345 self._module.filters = self._filters[:]
346 self._showwarning = self._module.showwarning
Brett Cannon672237d2008-09-09 00:49:16 +0000347 if self._record:
348 log = []
349 def showwarning(*args, **kwargs):
350 log.append(WarningMessage(*args, **kwargs))
351 self._module.showwarning = showwarning
352 return log
353 else:
354 return None
Brett Cannon1eaf0742008-09-02 01:25:16 +0000355
356 def __exit__(self, *exc_info):
Nick Coghland2e09382008-09-11 12:11:06 +0000357 if not self._entered:
358 raise RuntimeError("Cannot exit %r without entering first" % self)
Brett Cannon1eaf0742008-09-02 01:25:16 +0000359 self._module.filters = self._filters
360 self._module.showwarning = self._showwarning
361
362
Brett Cannone9746892008-04-12 23:44:07 +0000363# filters contains a sequence of filter 5-tuples
364# The components of the 5-tuple are:
365# - an action: error, ignore, always, default, module, or once
366# - a compiled regex that must match the warning message
367# - a class representing the warning category
368# - a compiled regex that must match the module that is being warned
369# - a line number for the line being warning, or 0 to mean any line
370# If either if the compiled regexs are None, match anything.
371_warnings_defaults = False
372try:
373 from _warnings import (filters, default_action, once_registry,
374 warn, warn_explicit)
375 defaultaction = default_action
376 onceregistry = once_registry
377 _warnings_defaults = True
378except ImportError:
379 filters = []
380 defaultaction = "default"
381 onceregistry = {}
382
383
Guido van Rossum2a862c62000-12-15 21:59:53 +0000384# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000385_processoptions(sys.warnoptions)
Brett Cannone9746892008-04-12 23:44:07 +0000386if not _warnings_defaults:
Brett Cannon3ffa43d2010-01-14 20:00:28 +0000387 silence = [ImportWarning, PendingDeprecationWarning]
Brett Cannon19949692010-04-25 22:33:36 +0000388 # Don't silence DeprecationWarning if -3 or -Q was used.
389 if not sys.py3kwarning and not sys.flags.division_warning:
Brett Cannon3ffa43d2010-01-14 20:00:28 +0000390 silence.append(DeprecationWarning)
391 for cls in silence:
392 simplefilter("ignore", category=cls)
Brett Cannone9746892008-04-12 23:44:07 +0000393 bytes_warning = sys.flags.bytes_warning
394 if bytes_warning > 1:
395 bytes_action = "error"
396 elif bytes_warning:
397 bytes_action = "default"
398 else:
399 bytes_action = "ignore"
400 simplefilter(bytes_action, category=BytesWarning, append=1)
401del _warnings_defaults