blob: 0e147db871540eee28ff61703dcdb41ccaacc1a9 [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
Christian Heimes33fe8092008-04-13 13:53:33 +00007import sys
Guido van Rossum2a862c62000-12-15 21:59:53 +00008
Skip Montanaro40fc1602001-03-01 04:27:19 +00009__all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
Brett Cannon1cd02472008-09-09 01:52:27 +000010 "resetwarnings", "catch_warnings"]
Skip Montanaro40fc1602001-03-01 04:27:19 +000011
Guido van Rossum2a862c62000-12-15 21:59:53 +000012
Christian Heimes33fe8092008-04-13 13:53:33 +000013def showwarning(message, category, filename, lineno, file=None, line=None):
Guido van Rossum2a862c62000-12-15 21:59:53 +000014 """Hook to write a warning to a file; replace if you like."""
15 if file is None:
16 file = sys.stderr
Mark Hammond51a0ae32002-09-11 13:22:35 +000017 try:
Christian Heimes33fe8092008-04-13 13:53:33 +000018 file.write(formatwarning(message, category, filename, lineno, line))
Mark Hammond51a0ae32002-09-11 13:22:35 +000019 except IOError:
20 pass # the file (probably stderr) is invalid - this warning gets lost.
Guido van Rossum2a862c62000-12-15 21:59:53 +000021
Christian Heimes33fe8092008-04-13 13:53:33 +000022def formatwarning(message, category, filename, lineno, line=None):
Guido van Rossum9464a7d2001-01-14 14:08:40 +000023 """Function to format a warning the standard way."""
Guido van Rossum2a862c62000-12-15 21:59:53 +000024 s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
Christian Heimes33fe8092008-04-13 13:53:33 +000025 line = linecache.getline(filename, lineno) if line is None else line
Guido van Rossum2a862c62000-12-15 21:59:53 +000026 if line:
Christian Heimes33fe8092008-04-13 13:53:33 +000027 line = line.strip()
28 s += " %s\n" % line
Guido van Rossum2a862c62000-12-15 21:59:53 +000029 return s
30
Guido van Rossum9464a7d2001-01-14 14:08:40 +000031def filterwarnings(action, message="", category=Warning, module="", lineno=0,
32 append=0):
Guido van Rossum2a862c62000-12-15 21:59:53 +000033 """Insert an entry into the list of warnings filters (at the front).
34
35 Use assertions to check that all arguments have the right type."""
Skip Montanarod8f21202003-05-14 17:33:53 +000036 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +000037 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000038 "once"), "invalid action: %r" % (action,)
Guido van Rossum3172c5d2007-10-16 18:12:55 +000039 assert isinstance(message, str), "message must be a string"
Guido van Rossum13257902007-06-07 23:15:56 +000040 assert isinstance(category, type), "category must be a class"
Guido van Rossum2a862c62000-12-15 21:59:53 +000041 assert issubclass(category, Warning), "category must be a Warning subclass"
Guido van Rossum3172c5d2007-10-16 18:12:55 +000042 assert isinstance(module, str), "module must be a string"
Walter Dörwald65230a22002-06-03 15:58:32 +000043 assert isinstance(lineno, int) and lineno >= 0, \
Guido van Rossum2a862c62000-12-15 21:59:53 +000044 "lineno must be an int >= 0"
Guido van Rossum9464a7d2001-01-14 14:08:40 +000045 item = (action, re.compile(message, re.I), category,
46 re.compile(module), lineno)
47 if append:
48 filters.append(item)
49 else:
50 filters.insert(0, item)
Guido van Rossum2a862c62000-12-15 21:59:53 +000051
Jeremy Hylton85014662003-07-11 15:37:59 +000052def simplefilter(action, category=Warning, lineno=0, append=0):
53 """Insert a simple entry into the list of warnings filters (at the front).
54
55 A simple filter matches all modules and messages.
56 """
57 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000058 "once"), "invalid action: %r" % (action,)
Jeremy Hylton85014662003-07-11 15:37:59 +000059 assert isinstance(lineno, int) and lineno >= 0, \
60 "lineno must be an int >= 0"
61 item = (action, None, category, None, lineno)
62 if append:
63 filters.append(item)
64 else:
65 filters.insert(0, item)
66
Guido van Rossum2a862c62000-12-15 21:59:53 +000067def resetwarnings():
Tim Petersd0cc4f02002-04-16 01:51:25 +000068 """Clear the list of warning filters, so that no filters are active."""
Guido van Rossum2a862c62000-12-15 21:59:53 +000069 filters[:] = []
70
71class _OptionError(Exception):
72 """Exception used by option processing helpers."""
73 pass
74
75# Helper to process -W options passed via sys.warnoptions
76def _processoptions(args):
77 for arg in args:
78 try:
79 _setoption(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +000080 except _OptionError as msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000081 print("Invalid -W option ignored:", msg, file=sys.stderr)
Guido van Rossum2a862c62000-12-15 21:59:53 +000082
83# Helper for _processoptions()
84def _setoption(arg):
Skip Montanarod8f21202003-05-14 17:33:53 +000085 import re
Tim Peterse1190062001-01-15 03:34:38 +000086 parts = arg.split(':')
87 if len(parts) > 5:
Walter Dörwald70a6b492004-02-12 17:35:32 +000088 raise _OptionError("too many fields (max 5): %r" % (arg,))
Tim Peterse1190062001-01-15 03:34:38 +000089 while len(parts) < 5:
90 parts.append('')
91 action, message, category, module, lineno = [s.strip()
92 for s in parts]
93 action = _getaction(action)
94 message = re.escape(message)
95 category = _getcategory(category)
96 module = re.escape(module)
97 if module:
98 module = module + '$'
99 if lineno:
100 try:
101 lineno = int(lineno)
102 if lineno < 0:
103 raise ValueError
104 except (ValueError, OverflowError):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000105 raise _OptionError("invalid lineno %r" % (lineno,))
Tim Peterse1190062001-01-15 03:34:38 +0000106 else:
107 lineno = 0
108 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000109
110# Helper for _setoption()
111def _getaction(action):
112 if not action:
113 return "default"
114 if action == "all": return "always" # Alias
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000115 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000116 if a.startswith(action):
117 return a
Walter Dörwald70a6b492004-02-12 17:35:32 +0000118 raise _OptionError("invalid action: %r" % (action,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000119
120# Helper for _setoption()
121def _getcategory(category):
Skip Montanarod8f21202003-05-14 17:33:53 +0000122 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000123 if not category:
124 return Warning
125 if re.match("^[a-zA-Z0-9_]+$", category):
126 try:
127 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000128 except NameError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000129 raise _OptionError("unknown warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000130 else:
131 i = category.rfind(".")
132 module = category[:i]
133 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000134 try:
135 m = __import__(module, None, None, [klass])
136 except ImportError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000137 raise _OptionError("invalid module name: %r" % (module,))
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000138 try:
139 cat = getattr(m, klass)
140 except AttributeError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000141 raise _OptionError("unknown warning category: %r" % (category,))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000142 if not issubclass(cat, Warning):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000143 raise _OptionError("invalid warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000144 return cat
145
Christian Heimes33fe8092008-04-13 13:53:33 +0000146
147# Code typically replaced by _warnings
148def warn(message, category=None, stacklevel=1):
149 """Issue a warning, or maybe ignore it or raise an exception."""
150 # Check if message is already a Warning object
151 if isinstance(message, Warning):
152 category = message.__class__
153 # Check category argument
154 if category is None:
155 category = UserWarning
156 assert issubclass(category, Warning)
157 # Get context information
158 try:
159 caller = sys._getframe(stacklevel)
160 except ValueError:
161 globals = sys.__dict__
162 lineno = 1
163 else:
164 globals = caller.f_globals
165 lineno = caller.f_lineno
166 if '__name__' in globals:
167 module = globals['__name__']
168 else:
169 module = "<string>"
170 filename = globals.get('__file__')
171 if filename:
172 fnl = filename.lower()
173 if fnl.endswith((".pyc", ".pyo")):
174 filename = filename[:-1]
175 else:
176 if module == "__main__":
177 try:
178 filename = sys.argv[0]
179 except AttributeError:
180 # embedded interpreters don't have sys.argv, see bug #839151
181 filename = '__main__'
182 if not filename:
183 filename = module
184 registry = globals.setdefault("__warningregistry__", {})
185 warn_explicit(message, category, filename, lineno, module, registry,
186 globals)
187
188def warn_explicit(message, category, filename, lineno,
189 module=None, registry=None, module_globals=None):
Brett Cannondb734912008-06-27 00:52:15 +0000190 lineno = int(lineno)
Christian Heimes33fe8092008-04-13 13:53:33 +0000191 if module is None:
192 module = filename or "<unknown>"
193 if module[-3:].lower() == ".py":
194 module = module[:-3] # XXX What about leading pathname?
195 if registry is None:
196 registry = {}
197 if isinstance(message, Warning):
198 text = str(message)
199 category = message.__class__
200 else:
201 text = message
202 message = category(message)
203 key = (text, category, lineno)
204 # Quick test for common case
205 if registry.get(key):
206 return
207 # Search the filters
208 for item in filters:
209 action, msg, cat, mod, ln = item
210 if ((msg is None or msg.match(text)) and
211 issubclass(category, cat) and
212 (mod is None or mod.match(module)) and
213 (ln == 0 or lineno == ln)):
214 break
215 else:
216 action = defaultaction
217 # Early exit actions
218 if action == "ignore":
219 registry[key] = 1
220 return
221
222 # Prime the linecache for formatting, in case the
223 # "file" is actually in a zipfile or something.
224 linecache.getlines(filename, module_globals)
225
226 if action == "error":
227 raise message
228 # Other actions
229 if action == "once":
230 registry[key] = 1
231 oncekey = (text, category)
232 if onceregistry.get(oncekey):
233 return
234 onceregistry[oncekey] = 1
235 elif action == "always":
236 pass
237 elif action == "module":
238 registry[key] = 1
239 altkey = (text, category, 0)
240 if registry.get(altkey):
241 return
242 registry[altkey] = 1
243 elif action == "default":
244 registry[key] = 1
245 else:
246 # Unrecognized actions are errors
247 raise RuntimeError(
248 "Unrecognized action (%r) in warnings.filters:\n %s" %
249 (action, item))
Christian Heimes8dc226f2008-05-06 23:45:46 +0000250 if not hasattr(showwarning, "__call__"):
251 raise TypeError("warnings.showwarning() must be set to a "
252 "function or method")
Christian Heimes33fe8092008-04-13 13:53:33 +0000253 # Print message and context
254 showwarning(message, category, filename, lineno)
255
256
Brett Cannonec92e182008-09-02 02:46:59 +0000257class WarningMessage(object):
258
259 """Holds the result of a single showwarning() call."""
260
261 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
262 "line")
263
264 def __init__(self, message, category, filename, lineno, file=None,
265 line=None):
266 local_values = locals()
267 for attr in self._WARNING_DETAILS:
268 setattr(self, attr, local_values[attr])
269 self._category_name = category.__name__ if category else None
270
271 def __str__(self):
272 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
273 "line : %r}" % (self.message, self._category_name,
274 self.filename, self.lineno, self.line))
275
276
Brett Cannonec92e182008-09-02 02:46:59 +0000277class catch_warnings(object):
278
Brett Cannon1cd02472008-09-09 01:52:27 +0000279 """A context manager that copies and restores the warnings filter upon
280 exiting the context.
Brett Cannonec92e182008-09-02 02:46:59 +0000281
Brett Cannon1cd02472008-09-09 01:52:27 +0000282 The 'record' argument specifies whether warnings should be captured by a
283 custom implementation of warnings.showwarning() and be appended to a list
284 returned by the context manager. Otherwise None is returned by the context
285 manager. The objects appended to the list are arguments whose attributes
286 mirror the arguments to showwarning().
287
288 The 'module' argument is to specify an alternative module to the module
289 named 'warnings' and imported under that name. This argument is only useful
290 when testing the warnings module itself.
Brett Cannonec92e182008-09-02 02:46:59 +0000291
292 """
293
294 def __init__(self, *, record=False, module=None):
295 """Specify whether to record warnings and if an alternative module
296 should be used other than sys.modules['warnings'].
297
298 For compatibility with Python 3.0, please consider all arguments to be
299 keyword-only.
300
301 """
Brett Cannon1cd02472008-09-09 01:52:27 +0000302 self._record = record
Brett Cannonec92e182008-09-02 02:46:59 +0000303 self._module = sys.modules['warnings'] if module is None else module
304
305 def __enter__(self):
306 self._filters = self._module.filters
307 self._module.filters = self._filters[:]
308 self._showwarning = self._module.showwarning
Brett Cannon1cd02472008-09-09 01:52:27 +0000309 if self._record:
310 log = []
311 def showwarning(*args, **kwargs):
312 log.append(WarningMessage(*args, **kwargs))
313 self._module.showwarning = showwarning
314 return log
315 else:
316 return None
Brett Cannonec92e182008-09-02 02:46:59 +0000317
318 def __exit__(self, *exc_info):
319 self._module.filters = self._filters
320 self._module.showwarning = self._showwarning
321
322
Christian Heimes33fe8092008-04-13 13:53:33 +0000323# filters contains a sequence of filter 5-tuples
324# The components of the 5-tuple are:
325# - an action: error, ignore, always, default, module, or once
326# - a compiled regex that must match the warning message
327# - a class representing the warning category
328# - a compiled regex that must match the module that is being warned
329# - a line number for the line being warning, or 0 to mean any line
330# If either if the compiled regexs are None, match anything.
331_warnings_defaults = False
332try:
333 from _warnings import (filters, default_action, once_registry,
334 warn, warn_explicit)
335 defaultaction = default_action
336 onceregistry = once_registry
337 _warnings_defaults = True
338except ImportError:
339 filters = []
340 defaultaction = "default"
341 onceregistry = {}
342
343
Guido van Rossum2a862c62000-12-15 21:59:53 +0000344# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000345_processoptions(sys.warnoptions)
Christian Heimes33fe8092008-04-13 13:53:33 +0000346if not _warnings_defaults:
347 simplefilter("ignore", category=PendingDeprecationWarning, append=1)
348 simplefilter("ignore", category=ImportWarning, append=1)
349 bytes_warning = sys.flags.bytes_warning
350 if bytes_warning > 1:
351 bytes_action = "error"
352 elif bytes_warning:
353 bytes_action = "default"
354 else:
355 bytes_action = "ignore"
356 simplefilter(bytes_action, category=BytesWarning, append=1)
357del _warnings_defaults