blob: 59011caa46deef4ff80fdef2ed155e1585643fc0 [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.
Brett Cannon8a232cc2008-05-05 05:32:07 +000032# Keep a worrking version around in case the deprecation of the old API is
33# 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
49 Use assertions to check that all arguments have the right type."""
Skip Montanarod8f21202003-05-14 17:33:53 +000050 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +000051 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000052 "once"), "invalid action: %r" % (action,)
Martin v. Löwisff9284b2002-10-14 21:06:02 +000053 assert isinstance(message, basestring), "message must be a string"
Brett Cannonbf364092006-03-01 04:25:17 +000054 assert isinstance(category, (type, types.ClassType)), \
55 "category must be a class"
Guido van Rossum2a862c62000-12-15 21:59:53 +000056 assert issubclass(category, Warning), "category must be a Warning subclass"
Martin v. Löwisff9284b2002-10-14 21:06:02 +000057 assert isinstance(module, basestring), "module must be a string"
Walter Dörwald65230a22002-06-03 15:58:32 +000058 assert isinstance(lineno, int) and lineno >= 0, \
Guido van Rossum2a862c62000-12-15 21:59:53 +000059 "lineno must be an int >= 0"
Guido van Rossum9464a7d2001-01-14 14:08:40 +000060 item = (action, re.compile(message, re.I), category,
61 re.compile(module), lineno)
62 if append:
63 filters.append(item)
64 else:
65 filters.insert(0, item)
Guido van Rossum2a862c62000-12-15 21:59:53 +000066
Jeremy Hylton85014662003-07-11 15:37:59 +000067def simplefilter(action, category=Warning, lineno=0, append=0):
68 """Insert a simple entry into the list of warnings filters (at the front).
69
70 A simple filter matches all modules and messages.
71 """
72 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000073 "once"), "invalid action: %r" % (action,)
Jeremy Hylton85014662003-07-11 15:37:59 +000074 assert isinstance(lineno, int) and lineno >= 0, \
75 "lineno must be an int >= 0"
76 item = (action, None, category, None, lineno)
77 if append:
78 filters.append(item)
79 else:
80 filters.insert(0, item)
81
Guido van Rossum2a862c62000-12-15 21:59:53 +000082def resetwarnings():
Tim Petersd0cc4f02002-04-16 01:51:25 +000083 """Clear the list of warning filters, so that no filters are active."""
Guido van Rossum2a862c62000-12-15 21:59:53 +000084 filters[:] = []
85
86class _OptionError(Exception):
87 """Exception used by option processing helpers."""
88 pass
89
90# Helper to process -W options passed via sys.warnoptions
91def _processoptions(args):
92 for arg in args:
93 try:
94 _setoption(arg)
95 except _OptionError, msg:
96 print >>sys.stderr, "Invalid -W option ignored:", msg
97
98# Helper for _processoptions()
99def _setoption(arg):
Skip Montanarod8f21202003-05-14 17:33:53 +0000100 import re
Tim Peterse1190062001-01-15 03:34:38 +0000101 parts = arg.split(':')
102 if len(parts) > 5:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000103 raise _OptionError("too many fields (max 5): %r" % (arg,))
Tim Peterse1190062001-01-15 03:34:38 +0000104 while len(parts) < 5:
105 parts.append('')
106 action, message, category, module, lineno = [s.strip()
107 for s in parts]
108 action = _getaction(action)
109 message = re.escape(message)
110 category = _getcategory(category)
111 module = re.escape(module)
112 if module:
113 module = module + '$'
114 if lineno:
115 try:
116 lineno = int(lineno)
117 if lineno < 0:
118 raise ValueError
119 except (ValueError, OverflowError):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000120 raise _OptionError("invalid lineno %r" % (lineno,))
Tim Peterse1190062001-01-15 03:34:38 +0000121 else:
122 lineno = 0
123 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000124
125# Helper for _setoption()
126def _getaction(action):
127 if not action:
128 return "default"
129 if action == "all": return "always" # Alias
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000130 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000131 if a.startswith(action):
132 return a
Walter Dörwald70a6b492004-02-12 17:35:32 +0000133 raise _OptionError("invalid action: %r" % (action,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000134
135# Helper for _setoption()
136def _getcategory(category):
Skip Montanarod8f21202003-05-14 17:33:53 +0000137 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000138 if not category:
139 return Warning
140 if re.match("^[a-zA-Z0-9_]+$", category):
141 try:
142 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000143 except NameError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000144 raise _OptionError("unknown warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000145 else:
146 i = category.rfind(".")
147 module = category[:i]
148 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000149 try:
150 m = __import__(module, None, None, [klass])
151 except ImportError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000152 raise _OptionError("invalid module name: %r" % (module,))
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000153 try:
154 cat = getattr(m, klass)
155 except AttributeError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000156 raise _OptionError("unknown warning category: %r" % (category,))
Brett Cannon53ab5b72006-06-22 16:49:14 +0000157 if not issubclass(cat, Warning):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000158 raise _OptionError("invalid warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000159 return cat
160
Brett Cannone9746892008-04-12 23:44:07 +0000161
162# Code typically replaced by _warnings
163def warn(message, category=None, stacklevel=1):
164 """Issue a warning, or maybe ignore it or raise an exception."""
165 # Check if message is already a Warning object
166 if isinstance(message, Warning):
167 category = message.__class__
168 # Check category argument
169 if category is None:
170 category = UserWarning
171 assert issubclass(category, Warning)
172 # Get context information
173 try:
174 caller = sys._getframe(stacklevel)
175 except ValueError:
176 globals = sys.__dict__
177 lineno = 1
178 else:
179 globals = caller.f_globals
180 lineno = caller.f_lineno
181 if '__name__' in globals:
182 module = globals['__name__']
183 else:
184 module = "<string>"
185 filename = globals.get('__file__')
186 if filename:
187 fnl = filename.lower()
188 if fnl.endswith((".pyc", ".pyo")):
189 filename = filename[:-1]
190 else:
191 if module == "__main__":
192 try:
193 filename = sys.argv[0]
194 except AttributeError:
195 # embedded interpreters don't have sys.argv, see bug #839151
196 filename = '__main__'
197 if not filename:
198 filename = module
199 registry = globals.setdefault("__warningregistry__", {})
200 warn_explicit(message, category, filename, lineno, module, registry,
201 globals)
202
203def warn_explicit(message, category, filename, lineno,
204 module=None, registry=None, module_globals=None):
Brett Cannondea1b562008-06-27 00:31:13 +0000205 lineno = int(lineno)
Brett Cannone9746892008-04-12 23:44:07 +0000206 if module is None:
207 module = filename or "<unknown>"
208 if module[-3:].lower() == ".py":
209 module = module[:-3] # XXX What about leading pathname?
210 if registry is None:
211 registry = {}
212 if isinstance(message, Warning):
213 text = str(message)
214 category = message.__class__
215 else:
216 text = message
217 message = category(message)
218 key = (text, category, lineno)
219 # Quick test for common case
220 if registry.get(key):
221 return
222 # Search the filters
223 for item in filters:
224 action, msg, cat, mod, ln = item
225 if ((msg is None or msg.match(text)) and
226 issubclass(category, cat) and
227 (mod is None or mod.match(module)) and
228 (ln == 0 or lineno == ln)):
229 break
230 else:
231 action = defaultaction
232 # Early exit actions
233 if action == "ignore":
234 registry[key] = 1
235 return
236
237 # Prime the linecache for formatting, in case the
238 # "file" is actually in a zipfile or something.
239 linecache.getlines(filename, module_globals)
240
241 if action == "error":
242 raise message
243 # Other actions
244 if action == "once":
245 registry[key] = 1
246 oncekey = (text, category)
247 if onceregistry.get(oncekey):
248 return
249 onceregistry[oncekey] = 1
250 elif action == "always":
251 pass
252 elif action == "module":
253 registry[key] = 1
254 altkey = (text, category, 0)
255 if registry.get(altkey):
256 return
257 registry[altkey] = 1
258 elif action == "default":
259 registry[key] = 1
260 else:
261 # Unrecognized actions are errors
262 raise RuntimeError(
263 "Unrecognized action (%r) in warnings.filters:\n %s" %
264 (action, item))
Brett Cannon9c19bc62008-05-05 16:57:38 +0000265 # Warn if showwarning() does not support the 'line' argument.
266 # Don't use 'inspect' as it relies on an extension module, which break the
267 # build thanks to 'warnings' being imported by setup.py.
268 fxn_code = None
269 if hasattr(showwarning, 'func_code'):
270 fxn_code = showwarning.func_code
271 elif hasattr(showwarning, '__func__'):
272 fxn_code = showwarning.__func__.func_code
273 if fxn_code:
274 args = fxn_code.co_varnames[:fxn_code.co_argcount]
Brett Cannon1eaf0742008-09-02 01:25:16 +0000275 CO_VARARGS = 0x4
276 if 'line' not in args and not fxn_code.co_flags & CO_VARARGS:
Brett Cannon8a232cc2008-05-05 05:32:07 +0000277 showwarning_msg = ("functions overriding warnings.showwarning() "
278 "must support the 'line' argument")
279 if message == showwarning_msg:
280 _show_warning(message, category, filename, lineno)
281 else:
282 warn(showwarning_msg, DeprecationWarning)
Brett Cannon9c19bc62008-05-05 16:57:38 +0000283 # Print message and context
Brett Cannone9746892008-04-12 23:44:07 +0000284 showwarning(message, category, filename, lineno)
285
286
Brett Cannon1eaf0742008-09-02 01:25:16 +0000287class WarningMessage(object):
288
289 """Holds the result of a single showwarning() call."""
290
291 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
292 "line")
293
294 def __init__(self, message, category, filename, lineno, file=None,
295 line=None):
296 local_values = locals()
297 for attr in self._WARNING_DETAILS:
298 setattr(self, attr, local_values[attr])
299 self._category_name = category.__name__ if category else None
300
301 def __str__(self):
302 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
303 "line : %r}" % (self.message, self._category_name,
304 self.filename, self.lineno, self.line))
305
306
Brett Cannon1eaf0742008-09-02 01:25:16 +0000307class catch_warnings(object):
308
Brett Cannon672237d2008-09-09 00:49:16 +0000309 """A context manager that copies and restores the warnings filter upon
310 exiting the context.
Brett Cannon1eaf0742008-09-02 01:25:16 +0000311
Brett Cannon672237d2008-09-09 00:49:16 +0000312 The 'record' argument specifies whether warnings should be captured by a
313 custom implementation of warnings.showwarning() and be appended to a list
314 returned by the context manager. Otherwise None is returned by the context
315 manager. The objects appended to the list are arguments whose attributes
316 mirror the arguments to showwarning().
317
318 The 'module' argument is to specify an alternative module to the module
319 named 'warnings' and imported under that name. This argument is only useful
320 when testing the warnings module itself.
Brett Cannon1eaf0742008-09-02 01:25:16 +0000321
322 """
323
324 def __init__(self, record=False, module=None):
325 """Specify whether to record warnings and if an alternative module
326 should be used other than sys.modules['warnings'].
327
328 For compatibility with Python 3.0, please consider all arguments to be
329 keyword-only.
330
331 """
Brett Cannon672237d2008-09-09 00:49:16 +0000332 self._record = record
Brett Cannon1eaf0742008-09-02 01:25:16 +0000333 self._module = sys.modules['warnings'] if module is None else module
Nick Coghland2e09382008-09-11 12:11:06 +0000334 self._entered = False
335
336 def __repr__(self):
337 args = []
338 if self._record:
339 args.append("record=True")
340 if self._module is not sys.modules['warnings']:
341 args.append("module=%r" % self._module)
342 name = type(self).__name__
343 return "%s(%s)" % (name, ", ".join(args))
Brett Cannon1eaf0742008-09-02 01:25:16 +0000344
345 def __enter__(self):
Nick Coghland2e09382008-09-11 12:11:06 +0000346 if self._entered:
347 raise RuntimeError("Cannot enter %r twice" % self)
348 self._entered = True
Brett Cannon1eaf0742008-09-02 01:25:16 +0000349 self._filters = self._module.filters
350 self._module.filters = self._filters[:]
351 self._showwarning = self._module.showwarning
Brett Cannon672237d2008-09-09 00:49:16 +0000352 if self._record:
353 log = []
354 def showwarning(*args, **kwargs):
355 log.append(WarningMessage(*args, **kwargs))
356 self._module.showwarning = showwarning
357 return log
358 else:
359 return None
Brett Cannon1eaf0742008-09-02 01:25:16 +0000360
361 def __exit__(self, *exc_info):
Nick Coghland2e09382008-09-11 12:11:06 +0000362 if not self._entered:
363 raise RuntimeError("Cannot exit %r without entering first" % self)
Brett Cannon1eaf0742008-09-02 01:25:16 +0000364 self._module.filters = self._filters
365 self._module.showwarning = self._showwarning
366
367
Brett Cannone9746892008-04-12 23:44:07 +0000368# filters contains a sequence of filter 5-tuples
369# The components of the 5-tuple are:
370# - an action: error, ignore, always, default, module, or once
371# - a compiled regex that must match the warning message
372# - a class representing the warning category
373# - a compiled regex that must match the module that is being warned
374# - a line number for the line being warning, or 0 to mean any line
375# If either if the compiled regexs are None, match anything.
376_warnings_defaults = False
377try:
378 from _warnings import (filters, default_action, once_registry,
379 warn, warn_explicit)
380 defaultaction = default_action
381 onceregistry = once_registry
382 _warnings_defaults = True
383except ImportError:
384 filters = []
385 defaultaction = "default"
386 onceregistry = {}
387
388
Guido van Rossum2a862c62000-12-15 21:59:53 +0000389# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000390_processoptions(sys.warnoptions)
Brett Cannone9746892008-04-12 23:44:07 +0000391if not _warnings_defaults:
392 simplefilter("ignore", category=PendingDeprecationWarning, append=1)
393 simplefilter("ignore", category=ImportWarning, append=1)
394 bytes_warning = sys.flags.bytes_warning
395 if bytes_warning > 1:
396 bytes_action = "error"
397 elif bytes_warning:
398 bytes_action = "default"
399 else:
400 bytes_action = "ignore"
401 simplefilter(bytes_action, category=BytesWarning, append=1)
402del _warnings_defaults