blob: cefa961b06e3dbf7c8c6d449d93f467594e90f96 [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.
Brett Cannon8a232cc2008-05-05 05:32:07 +00006import inspect
Mark Hammonda43fd0c2003-02-19 00:33:33 +00007import linecache
Brett Cannone9746892008-04-12 23:44:07 +00008import sys
9import types
Guido van Rossum2a862c62000-12-15 21:59:53 +000010
Skip Montanaro40fc1602001-03-01 04:27:19 +000011__all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
12 "resetwarnings"]
13
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.
Brett Cannon8a232cc2008-05-05 05:32:07 +000033# Keep a worrking version around in case the deprecation of the old API is
34# 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
50 Use assertions to check that all arguments have the right type."""
Skip Montanarod8f21202003-05-14 17:33:53 +000051 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +000052 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000053 "once"), "invalid action: %r" % (action,)
Martin v. Löwisff9284bc22002-10-14 21:06:02 +000054 assert isinstance(message, basestring), "message must be a string"
Brett Cannonbf364092006-03-01 04:25:17 +000055 assert isinstance(category, (type, types.ClassType)), \
56 "category must be a class"
Guido van Rossum2a862c62000-12-15 21:59:53 +000057 assert issubclass(category, Warning), "category must be a Warning subclass"
Martin v. Löwisff9284bc22002-10-14 21:06:02 +000058 assert isinstance(module, basestring), "module must be a string"
Walter Dörwald65230a22002-06-03 15:58:32 +000059 assert isinstance(lineno, int) and lineno >= 0, \
Guido van Rossum2a862c62000-12-15 21:59:53 +000060 "lineno must be an int >= 0"
Guido van Rossum9464a7d2001-01-14 14:08:40 +000061 item = (action, re.compile(message, re.I), category,
62 re.compile(module), lineno)
63 if append:
64 filters.append(item)
65 else:
66 filters.insert(0, item)
Guido van Rossum2a862c62000-12-15 21:59:53 +000067
Jeremy Hylton85014662003-07-11 15:37:59 +000068def simplefilter(action, category=Warning, lineno=0, append=0):
69 """Insert a simple entry into the list of warnings filters (at the front).
70
71 A simple filter matches all modules and messages.
72 """
73 assert action in ("error", "ignore", "always", "default", "module",
Walter Dörwald70a6b492004-02-12 17:35:32 +000074 "once"), "invalid action: %r" % (action,)
Jeremy Hylton85014662003-07-11 15:37:59 +000075 assert isinstance(lineno, int) and lineno >= 0, \
76 "lineno must be an int >= 0"
77 item = (action, None, category, None, lineno)
78 if append:
79 filters.append(item)
80 else:
81 filters.insert(0, item)
82
Guido van Rossum2a862c62000-12-15 21:59:53 +000083def resetwarnings():
Tim Petersd0cc4f02002-04-16 01:51:25 +000084 """Clear the list of warning filters, so that no filters are active."""
Guido van Rossum2a862c62000-12-15 21:59:53 +000085 filters[:] = []
86
87class _OptionError(Exception):
88 """Exception used by option processing helpers."""
89 pass
90
91# Helper to process -W options passed via sys.warnoptions
92def _processoptions(args):
93 for arg in args:
94 try:
95 _setoption(arg)
96 except _OptionError, msg:
97 print >>sys.stderr, "Invalid -W option ignored:", msg
98
99# Helper for _processoptions()
100def _setoption(arg):
Skip Montanarod8f21202003-05-14 17:33:53 +0000101 import re
Tim Peterse1190062001-01-15 03:34:38 +0000102 parts = arg.split(':')
103 if len(parts) > 5:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000104 raise _OptionError("too many fields (max 5): %r" % (arg,))
Tim Peterse1190062001-01-15 03:34:38 +0000105 while len(parts) < 5:
106 parts.append('')
107 action, message, category, module, lineno = [s.strip()
108 for s in parts]
109 action = _getaction(action)
110 message = re.escape(message)
111 category = _getcategory(category)
112 module = re.escape(module)
113 if module:
114 module = module + '$'
115 if lineno:
116 try:
117 lineno = int(lineno)
118 if lineno < 0:
119 raise ValueError
120 except (ValueError, OverflowError):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000121 raise _OptionError("invalid lineno %r" % (lineno,))
Tim Peterse1190062001-01-15 03:34:38 +0000122 else:
123 lineno = 0
124 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000125
126# Helper for _setoption()
127def _getaction(action):
128 if not action:
129 return "default"
130 if action == "all": return "always" # Alias
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000131 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000132 if a.startswith(action):
133 return a
Walter Dörwald70a6b492004-02-12 17:35:32 +0000134 raise _OptionError("invalid action: %r" % (action,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000135
136# Helper for _setoption()
137def _getcategory(category):
Skip Montanarod8f21202003-05-14 17:33:53 +0000138 import re
Guido van Rossum2a862c62000-12-15 21:59:53 +0000139 if not category:
140 return Warning
141 if re.match("^[a-zA-Z0-9_]+$", category):
142 try:
143 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000144 except NameError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000145 raise _OptionError("unknown warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000146 else:
147 i = category.rfind(".")
148 module = category[:i]
149 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000150 try:
151 m = __import__(module, None, None, [klass])
152 except ImportError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000153 raise _OptionError("invalid module name: %r" % (module,))
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000154 try:
155 cat = getattr(m, klass)
156 except AttributeError:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000157 raise _OptionError("unknown warning category: %r" % (category,))
Brett Cannon53ab5b72006-06-22 16:49:14 +0000158 if not issubclass(cat, Warning):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000159 raise _OptionError("invalid warning category: %r" % (category,))
Guido van Rossum2a862c62000-12-15 21:59:53 +0000160 return cat
161
Brett Cannone9746892008-04-12 23:44:07 +0000162
163# Code typically replaced by _warnings
164def warn(message, category=None, stacklevel=1):
165 """Issue a warning, or maybe ignore it or raise an exception."""
166 # Check if message is already a Warning object
167 if isinstance(message, Warning):
168 category = message.__class__
169 # Check category argument
170 if category is None:
171 category = UserWarning
172 assert issubclass(category, Warning)
173 # Get context information
174 try:
175 caller = sys._getframe(stacklevel)
176 except ValueError:
177 globals = sys.__dict__
178 lineno = 1
179 else:
180 globals = caller.f_globals
181 lineno = caller.f_lineno
182 if '__name__' in globals:
183 module = globals['__name__']
184 else:
185 module = "<string>"
186 filename = globals.get('__file__')
187 if filename:
188 fnl = filename.lower()
189 if fnl.endswith((".pyc", ".pyo")):
190 filename = filename[:-1]
191 else:
192 if module == "__main__":
193 try:
194 filename = sys.argv[0]
195 except AttributeError:
196 # embedded interpreters don't have sys.argv, see bug #839151
197 filename = '__main__'
198 if not filename:
199 filename = module
200 registry = globals.setdefault("__warningregistry__", {})
201 warn_explicit(message, category, filename, lineno, module, registry,
202 globals)
203
204def warn_explicit(message, category, filename, lineno,
205 module=None, registry=None, module_globals=None):
206 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))
265 # Print message and context
Brett Cannon8a232cc2008-05-05 05:32:07 +0000266 if inspect.isfunction(showwarning):
267 arg_spec = inspect.getargspec(showwarning)
268 if 'line' not in arg_spec.args:
269 showwarning_msg = ("functions overriding warnings.showwarning() "
270 "must support the 'line' argument")
271 if message == showwarning_msg:
272 _show_warning(message, category, filename, lineno)
273 else:
274 warn(showwarning_msg, DeprecationWarning)
Brett Cannone9746892008-04-12 23:44:07 +0000275 showwarning(message, category, filename, lineno)
276
277
278# filters contains a sequence of filter 5-tuples
279# The components of the 5-tuple are:
280# - an action: error, ignore, always, default, module, or once
281# - a compiled regex that must match the warning message
282# - a class representing the warning category
283# - a compiled regex that must match the module that is being warned
284# - a line number for the line being warning, or 0 to mean any line
285# If either if the compiled regexs are None, match anything.
286_warnings_defaults = False
287try:
288 from _warnings import (filters, default_action, once_registry,
289 warn, warn_explicit)
290 defaultaction = default_action
291 onceregistry = once_registry
292 _warnings_defaults = True
293except ImportError:
294 filters = []
295 defaultaction = "default"
296 onceregistry = {}
297
298
Guido van Rossum2a862c62000-12-15 21:59:53 +0000299# Module initialization
Tim Peters66025202004-03-21 17:06:20 +0000300_processoptions(sys.warnoptions)
Brett Cannone9746892008-04-12 23:44:07 +0000301if not _warnings_defaults:
302 simplefilter("ignore", category=PendingDeprecationWarning, append=1)
303 simplefilter("ignore", category=ImportWarning, append=1)
304 bytes_warning = sys.flags.bytes_warning
305 if bytes_warning > 1:
306 bytes_action = "error"
307 elif bytes_warning:
308 bytes_action = "default"
309 else:
310 bytes_action = "ignore"
311 simplefilter(bytes_action, category=BytesWarning, append=1)
312del _warnings_defaults