blob: 134ba13cc131ef91c182f8bc01dac8fc69b6f5cc [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
Skip Montanaro40fc1602001-03-01 04:27:19 +000010__all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
Brett Cannon672237d2008-09-09 00:49:16 +000011 "resetwarnings", "catch_warnings"]
Skip Montanaro40fc1602001-03-01 04:27:19 +000012
Guido van Rossum2a862c62000-12-15 21:59:53 +000013
Christian Heimes28104c52007-11-27 23:16:44 +000014def warnpy3k(message, category=None, stacklevel=1):
15 """Issue a deprecation warning for Python 3.x related changes.
16
17 Warnings are omitted unless Python is started with the -3 option.
18 """
19 if sys.py3kwarning:
20 if category is None:
21 category = DeprecationWarning
22 warn(message, category, stacklevel+1)
23
Brett Cannon8a232cc2008-05-05 05:32:07 +000024def _show_warning(message, category, filename, lineno, file=None, line=None):
Guido van Rossum2a862c62000-12-15 21:59:53 +000025 """Hook to write a warning to a file; replace if you like."""
26 if file is None:
27 file = sys.stderr
Mark Hammond51a0ae32002-09-11 13:22:35 +000028 try:
Brett Cannone9746892008-04-12 23:44:07 +000029 file.write(formatwarning(message, category, filename, lineno, line))
Mark Hammond51a0ae32002-09-11 13:22:35 +000030 except IOError:
31 pass # the file (probably stderr) is invalid - this warning gets lost.
Florent Xicluna1f3b4e12010-03-07 12:14:25 +000032# Keep a working version around in case the deprecation of the old API is
Brett Cannon8a232cc2008-05-05 05:32:07 +000033# triggered.
34showwarning = _show_warning
Guido van Rossum2a862c62000-12-15 21:59:53 +000035
Brett Cannone9746892008-04-12 23:44:07 +000036def formatwarning(message, category, filename, lineno, line=None):
Guido van Rossum9464a7d2001-01-14 14:08:40 +000037 """Function to format a warning the standard way."""
Guido van Rossum2a862c62000-12-15 21:59:53 +000038 s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
Brett Cannone9746892008-04-12 23:44:07 +000039 line = linecache.getline(filename, lineno) if line is None else line
Guido van Rossum2a862c62000-12-15 21:59:53 +000040 if line:
Brett Cannone9746892008-04-12 23:44:07 +000041 line = line.strip()
42 s += " %s\n" % line
Guido van Rossum2a862c62000-12-15 21:59:53 +000043 return s
44
Guido van Rossum9464a7d2001-01-14 14:08:40 +000045def filterwarnings(action, message="", category=Warning, module="", lineno=0,
46 append=0):
Guido van Rossum2a862c62000-12-15 21:59:53 +000047 """Insert an entry into the list of warnings filters (at the front).
48
Neil Schemenauerd87affe2009-10-23 19:58:17 +000049 'action' -- one of "error", "ignore", "always", "default", "module",
50 or "once"
51 'message' -- a regex that the warning message must match
52 'category' -- a class that the warning must be a subclass of
53 'module' -- a regex that the module name must match
54 'lineno' -- an integer line number, 0 matches all warnings
55 'append' -- if true, append to the list of filters
56 """
Skip Montanarod8f21202003-05-14 17:33:53 +000057 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +000058 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000059 "once"), "invalid action: %r" % (action,)
Martin v. Löwisff9284b2002-10-14 21:06:02 +000060 assert isinstance(message, basestring), "message must be a string"
Brett Cannonbf364092006-03-01 04:25:17 +000061 assert isinstance(category, (type, types.ClassType)), \
62 "category must be a class"
Guido van Rossum2a862c62000-12-15 21:59:53 +000063 assert issubclass(category, Warning), "category must be a Warning subclass"
Martin v. Löwisff9284b2002-10-14 21:06:02 +000064 assert isinstance(module, basestring), "module must be a string"
Walter Dörwald65230a22002-06-03 15:58:32 +000065 assert isinstance(lineno, int) and lineno >= 0, \
Guido van Rossum2a862c62000-12-15 21:59:53 +000066 "lineno must be an int >= 0"
Guido van Rossum9464a7d2001-01-14 14:08:40 +000067 item = (action, re.compile(message, re.I), category,
68 re.compile(module), lineno)
69 if append:
70 filters.append(item)
71 else:
72 filters.insert(0, item)
Guido van Rossum2a862c62000-12-15 21:59:53 +000073
Jeremy Hylton85014662003-07-11 15:37:59 +000074def simplefilter(action, category=Warning, lineno=0, append=0):
75 """Insert a simple entry into the list of warnings filters (at the front).
76
77 A simple filter matches all modules and messages.
Neil Schemenauerd87affe2009-10-23 19:58:17 +000078 'action' -- one of "error", "ignore", "always", "default", "module",
79 or "once"
80 'category' -- a class that the warning must be a subclass of
81 'lineno' -- an integer line number, 0 matches all warnings
82 'append' -- if true, append to the list of filters
Jeremy Hylton85014662003-07-11 15:37:59 +000083 """
84 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000085 "once"), "invalid action: %r" % (action,)
Jeremy Hylton85014662003-07-11 15:37:59 +000086 assert isinstance(lineno, int) and lineno >= 0, \
87 "lineno must be an int >= 0"
88 item = (action, None, category, None, lineno)
89 if append:
90 filters.append(item)
91 else:
92 filters.insert(0, item)
93
Guido van Rossum2a862c62000-12-15 21:59:53 +000094def resetwarnings():
Tim Petersd0cc4f02002-04-16 01:51:25 +000095 """Clear the list of warning filters, so that no filters are active."""
Guido van Rossum2a862c62000-12-15 21:59:53 +000096 filters[:] = []
97
98class _OptionError(Exception):
99 """Exception used by option processing helpers."""
100 pass
101
102# Helper to process -W options passed via sys.warnoptions
103def _processoptions(args):
104 for arg in args:
105 try:
106 _setoption(arg)
107 except _OptionError, msg:
108 print >>sys.stderr, "Invalid -W option ignored:", msg
109
110# Helper for _processoptions()
111def _setoption(arg):
Skip Montanarod8f21202003-05-14 17:33:53 +0000112 import re
Tim Peterse1190062001-01-15 03:34:38 +0000113 parts = arg.split(':')
114 if len(parts) > 5:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000115 raise _OptionError("too many fields (max 5): %r" % (arg,))
Tim Peterse1190062001-01-15 03:34:38 +0000116 while len(parts) < 5:
117 parts.append('')
118 action, message, category, module, lineno = [s.strip()
119 for s in parts]
120 action = _getaction(action)
121 message = re.escape(message)
122 category = _getcategory(category)
123 module = re.escape(module)
124 if module:
125 module = module + '$'
126 if lineno:
127 try:
128 lineno = int(lineno)
129 if lineno < 0:
130 raise ValueError
131 except (ValueError, OverflowError):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000132 raise _OptionError("invalid lineno %r" % (lineno,))
Tim Peterse1190062001-01-15 03:34:38 +0000133 else:
134 lineno = 0
135 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000136
137# Helper for _setoption()
138def _getaction(action):
139 if not action:
140 return "default"
141 if action == "all": return "always" # Alias
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000142 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000143 if a.startswith(action):
144 return a
Walter Dörwald70a6b492004-02-12 17:35:32 +0000145 raise _OptionError("invalid action: %r" % (action,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000146
147# Helper for _setoption()
148def _getcategory(category):
Skip Montanarod8f21202003-05-14 17:33:53 +0000149 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000150 if not category:
151 return Warning
152 if re.match("^[a-zA-Z0-9_]+$", category):
153 try:
154 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000155 except NameError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000156 raise _OptionError("unknown warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000157 else:
158 i = category.rfind(".")
159 module = category[:i]
160 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000161 try:
162 m = __import__(module, None, None, [klass])
163 except ImportError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000164 raise _OptionError("invalid module name: %r" % (module,))
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000165 try:
166 cat = getattr(m, klass)
167 except AttributeError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000168 raise _OptionError("unknown warning category: %r" % (category,))
Brett Cannon53ab5b72006-06-22 16:49:14 +0000169 if not issubclass(cat, Warning):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000170 raise _OptionError("invalid warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000171 return cat
172
Brett Cannone9746892008-04-12 23:44:07 +0000173
174# Code typically replaced by _warnings
175def warn(message, category=None, stacklevel=1):
176 """Issue a warning, or maybe ignore it or raise an exception."""
177 # Check if message is already a Warning object
178 if isinstance(message, Warning):
179 category = message.__class__
180 # Check category argument
181 if category is None:
182 category = UserWarning
183 assert issubclass(category, Warning)
184 # Get context information
185 try:
186 caller = sys._getframe(stacklevel)
187 except ValueError:
188 globals = sys.__dict__
189 lineno = 1
190 else:
191 globals = caller.f_globals
192 lineno = caller.f_lineno
193 if '__name__' in globals:
194 module = globals['__name__']
195 else:
196 module = "<string>"
197 filename = globals.get('__file__')
198 if filename:
199 fnl = filename.lower()
200 if fnl.endswith((".pyc", ".pyo")):
201 filename = filename[:-1]
202 else:
203 if module == "__main__":
204 try:
205 filename = sys.argv[0]
206 except AttributeError:
207 # embedded interpreters don't have sys.argv, see bug #839151
208 filename = '__main__'
209 if not filename:
210 filename = module
211 registry = globals.setdefault("__warningregistry__", {})
212 warn_explicit(message, category, filename, lineno, module, registry,
213 globals)
214
215def warn_explicit(message, category, filename, lineno,
216 module=None, registry=None, module_globals=None):
Brett Cannondea1b562008-06-27 00:31:13 +0000217 lineno = int(lineno)
Brett Cannone9746892008-04-12 23:44:07 +0000218 if module is None:
219 module = filename or "<unknown>"
220 if module[-3:].lower() == ".py":
221 module = module[:-3] # XXX What about leading pathname?
222 if registry is None:
223 registry = {}
224 if isinstance(message, Warning):
225 text = str(message)
226 category = message.__class__
227 else:
228 text = message
229 message = category(message)
230 key = (text, category, lineno)
231 # Quick test for common case
232 if registry.get(key):
233 return
234 # Search the filters
235 for item in filters:
236 action, msg, cat, mod, ln = item
237 if ((msg is None or msg.match(text)) and
238 issubclass(category, cat) and
239 (mod is None or mod.match(module)) and
240 (ln == 0 or lineno == ln)):
241 break
242 else:
243 action = defaultaction
244 # Early exit actions
245 if action == "ignore":
246 registry[key] = 1
247 return
248
249 # Prime the linecache for formatting, in case the
250 # "file" is actually in a zipfile or something.
251 linecache.getlines(filename, module_globals)
252
253 if action == "error":
254 raise message
255 # Other actions
256 if action == "once":
257 registry[key] = 1
258 oncekey = (text, category)
259 if onceregistry.get(oncekey):
260 return
261 onceregistry[oncekey] = 1
262 elif action == "always":
263 pass
264 elif action == "module":
265 registry[key] = 1
266 altkey = (text, category, 0)
267 if registry.get(altkey):
268 return
269 registry[altkey] = 1
270 elif action == "default":
271 registry[key] = 1
272 else:
273 # Unrecognized actions are errors
274 raise RuntimeError(
275 "Unrecognized action (%r) in warnings.filters:\n %s" %
276 (action, item))
Brett Cannon9c19bc62008-05-05 16:57:38 +0000277 # Print message and context
Brett Cannone9746892008-04-12 23:44:07 +0000278 showwarning(message, category, filename, lineno)
279
280
Brett Cannon1eaf0742008-09-02 01:25:16 +0000281class WarningMessage(object):
282
283 """Holds the result of a single showwarning() call."""
284
285 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
286 "line")
287
288 def __init__(self, message, category, filename, lineno, file=None,
289 line=None):
290 local_values = locals()
291 for attr in self._WARNING_DETAILS:
292 setattr(self, attr, local_values[attr])
293 self._category_name = category.__name__ if category else None
294
295 def __str__(self):
296 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
297 "line : %r}" % (self.message, self._category_name,
298 self.filename, self.lineno, self.line))
299
300
Brett Cannon1eaf0742008-09-02 01:25:16 +0000301class catch_warnings(object):
302
Brett Cannon672237d2008-09-09 00:49:16 +0000303 """A context manager that copies and restores the warnings filter upon
304 exiting the context.
Brett Cannon1eaf0742008-09-02 01:25:16 +0000305
Brett Cannon672237d2008-09-09 00:49:16 +0000306 The 'record' argument specifies whether warnings should be captured by a
307 custom implementation of warnings.showwarning() and be appended to a list
308 returned by the context manager. Otherwise None is returned by the context
309 manager. The objects appended to the list are arguments whose attributes
310 mirror the arguments to showwarning().
311
312 The 'module' argument is to specify an alternative module to the module
313 named 'warnings' and imported under that name. This argument is only useful
314 when testing the warnings module itself.
Brett Cannon1eaf0742008-09-02 01:25:16 +0000315
316 """
317
318 def __init__(self, record=False, module=None):
319 """Specify whether to record warnings and if an alternative module
320 should be used other than sys.modules['warnings'].
321
322 For compatibility with Python 3.0, please consider all arguments to be
323 keyword-only.
324
325 """
Brett Cannon672237d2008-09-09 00:49:16 +0000326 self._record = record
Brett Cannon1eaf0742008-09-02 01:25:16 +0000327 self._module = sys.modules['warnings'] if module is None else module
Nick Coghland2e09382008-09-11 12:11:06 +0000328 self._entered = False
329
330 def __repr__(self):
331 args = []
332 if self._record:
333 args.append("record=True")
334 if self._module is not sys.modules['warnings']:
335 args.append("module=%r" % self._module)
336 name = type(self).__name__
337 return "%s(%s)" % (name, ", ".join(args))
Brett Cannon1eaf0742008-09-02 01:25:16 +0000338
339 def __enter__(self):
Nick Coghland2e09382008-09-11 12:11:06 +0000340 if self._entered:
341 raise RuntimeError("Cannot enter %r twice" % self)
342 self._entered = True
Brett Cannon1eaf0742008-09-02 01:25:16 +0000343 self._filters = self._module.filters
344 self._module.filters = self._filters[:]
345 self._showwarning = self._module.showwarning
Brett Cannon672237d2008-09-09 00:49:16 +0000346 if self._record:
347 log = []
348 def showwarning(*args, **kwargs):
349 log.append(WarningMessage(*args, **kwargs))
350 self._module.showwarning = showwarning
351 return log
352 else:
353 return None
Brett Cannon1eaf0742008-09-02 01:25:16 +0000354
355 def __exit__(self, *exc_info):
Nick Coghland2e09382008-09-11 12:11:06 +0000356 if not self._entered:
357 raise RuntimeError("Cannot exit %r without entering first" % self)
Brett Cannon1eaf0742008-09-02 01:25:16 +0000358 self._module.filters = self._filters
359 self._module.showwarning = self._showwarning
360
361
Brett Cannone9746892008-04-12 23:44:07 +0000362# filters contains a sequence of filter 5-tuples
363# The components of the 5-tuple are:
364# - an action: error, ignore, always, default, module, or once
365# - a compiled regex that must match the warning message
366# - a class representing the warning category
367# - a compiled regex that must match the module that is being warned
368# - a line number for the line being warning, or 0 to mean any line
369# If either if the compiled regexs are None, match anything.
370_warnings_defaults = False
371try:
372 from _warnings import (filters, default_action, once_registry,
373 warn, warn_explicit)
374 defaultaction = default_action
375 onceregistry = once_registry
376 _warnings_defaults = True
377except ImportError:
378 filters = []
379 defaultaction = "default"
380 onceregistry = {}
381
382
Guido van Rossum2a862c62000-12-15 21:59:53 +0000383# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000384_processoptions(sys.warnoptions)
Brett Cannone9746892008-04-12 23:44:07 +0000385if not _warnings_defaults:
Brett Cannon3ffa43d2010-01-14 20:00:28 +0000386 silence = [ImportWarning, PendingDeprecationWarning]
387 if not sys.py3kwarning: # Don't silence DeprecationWarning if -3 was used.
388 silence.append(DeprecationWarning)
389 for cls in silence:
390 simplefilter("ignore", category=cls)
Brett Cannone9746892008-04-12 23:44:07 +0000391 bytes_warning = sys.flags.bytes_warning
392 if bytes_warning > 1:
393 bytes_action = "error"
394 elif bytes_warning:
395 bytes_action = "default"
396 else:
397 bytes_action = "ignore"
398 simplefilter(bytes_action, category=BytesWarning, append=1)
399del _warnings_defaults