version becomes 3.1.2
[python/dscho.git] / Lib / warnings.py
blob9de2c6737ba2e1d49598b1c2bcb1dadf9ef46819
1 """Python part of the warnings subsystem."""
3 # Note: function level imports should *not* be used
4 # in this module as it may cause import lock deadlock.
5 # See bug 683658.
6 import linecache
7 import sys
9 __all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
10 "resetwarnings", "catch_warnings"]
13 def showwarning(message, category, filename, lineno, file=None, line=None):
14 """Hook to write a warning to a file; replace if you like."""
15 if file is None:
16 file = sys.stderr
17 try:
18 file.write(formatwarning(message, category, filename, lineno, line))
19 except IOError:
20 pass # the file (probably stderr) is invalid - this warning gets lost.
22 def formatwarning(message, category, filename, lineno, line=None):
23 """Function to format a warning the standard way."""
24 s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
25 line = linecache.getline(filename, lineno) if line is None else line
26 if line:
27 line = line.strip()
28 s += " %s\n" % line
29 return s
31 def filterwarnings(action, message="", category=Warning, module="", lineno=0,
32 append=False):
33 """Insert an entry into the list of warnings filters (at the front).
35 'action' -- one of "error", "ignore", "always", "default", "module",
36 or "once"
37 'message' -- a regex that the warning message must match
38 'category' -- a class that the warning must be a subclass of
39 'module' -- a regex that the module name must match
40 'lineno' -- an integer line number, 0 matches all warnings
41 'append' -- if true, append to the list of filters
42 """
43 import re
44 assert action in ("error", "ignore", "always", "default", "module",
45 "once"), "invalid action: %r" % (action,)
46 assert isinstance(message, str), "message must be a string"
47 assert isinstance(category, type), "category must be a class"
48 assert issubclass(category, Warning), "category must be a Warning subclass"
49 assert isinstance(module, str), "module must be a string"
50 assert isinstance(lineno, int) and lineno >= 0, \
51 "lineno must be an int >= 0"
52 item = (action, re.compile(message, re.I), category,
53 re.compile(module), lineno)
54 if append:
55 filters.append(item)
56 else:
57 filters.insert(0, item)
59 def simplefilter(action, category=Warning, lineno=0, append=False):
60 """Insert a simple entry into the list of warnings filters (at the front).
62 A simple filter matches all modules and messages.
63 'action' -- one of "error", "ignore", "always", "default", "module",
64 or "once"
65 'category' -- a class that the warning must be a subclass of
66 'lineno' -- an integer line number, 0 matches all warnings
67 'append' -- if true, append to the list of filters
68 """
69 assert action in ("error", "ignore", "always", "default", "module",
70 "once"), "invalid action: %r" % (action,)
71 assert isinstance(lineno, int) and lineno >= 0, \
72 "lineno must be an int >= 0"
73 item = (action, None, category, None, lineno)
74 if append:
75 filters.append(item)
76 else:
77 filters.insert(0, item)
79 def resetwarnings():
80 """Clear the list of warning filters, so that no filters are active."""
81 filters[:] = []
83 class _OptionError(Exception):
84 """Exception used by option processing helpers."""
85 pass
87 # Helper to process -W options passed via sys.warnoptions
88 def _processoptions(args):
89 for arg in args:
90 try:
91 _setoption(arg)
92 except _OptionError as msg:
93 print("Invalid -W option ignored:", msg, file=sys.stderr)
95 # Helper for _processoptions()
96 def _setoption(arg):
97 import re
98 parts = arg.split(':')
99 if len(parts) > 5:
100 raise _OptionError("too many fields (max 5): %r" % (arg,))
101 while len(parts) < 5:
102 parts.append('')
103 action, message, category, module, lineno = [s.strip()
104 for s in parts]
105 action = _getaction(action)
106 message = re.escape(message)
107 category = _getcategory(category)
108 module = re.escape(module)
109 if module:
110 module = module + '$'
111 if lineno:
112 try:
113 lineno = int(lineno)
114 if lineno < 0:
115 raise ValueError
116 except (ValueError, OverflowError):
117 raise _OptionError("invalid lineno %r" % (lineno,))
118 else:
119 lineno = 0
120 filterwarnings(action, message, category, module, lineno)
122 # Helper for _setoption()
123 def _getaction(action):
124 if not action:
125 return "default"
126 if action == "all": return "always" # Alias
127 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
128 if a.startswith(action):
129 return a
130 raise _OptionError("invalid action: %r" % (action,))
132 # Helper for _setoption()
133 def _getcategory(category):
134 import re
135 if not category:
136 return Warning
137 if re.match("^[a-zA-Z0-9_]+$", category):
138 try:
139 cat = eval(category)
140 except NameError:
141 raise _OptionError("unknown warning category: %r" % (category,))
142 else:
143 i = category.rfind(".")
144 module = category[:i]
145 klass = category[i+1:]
146 try:
147 m = __import__(module, None, None, [klass])
148 except ImportError:
149 raise _OptionError("invalid module name: %r" % (module,))
150 try:
151 cat = getattr(m, klass)
152 except AttributeError:
153 raise _OptionError("unknown warning category: %r" % (category,))
154 if not issubclass(cat, Warning):
155 raise _OptionError("invalid warning category: %r" % (category,))
156 return cat
159 # Code typically replaced by _warnings
160 def warn(message, category=None, stacklevel=1):
161 """Issue a warning, or maybe ignore it or raise an exception."""
162 # Check if message is already a Warning object
163 if isinstance(message, Warning):
164 category = message.__class__
165 # Check category argument
166 if category is None:
167 category = UserWarning
168 assert issubclass(category, Warning)
169 # Get context information
170 try:
171 caller = sys._getframe(stacklevel)
172 except ValueError:
173 globals = sys.__dict__
174 lineno = 1
175 else:
176 globals = caller.f_globals
177 lineno = caller.f_lineno
178 if '__name__' in globals:
179 module = globals['__name__']
180 else:
181 module = "<string>"
182 filename = globals.get('__file__')
183 if filename:
184 fnl = filename.lower()
185 if fnl.endswith((".pyc", ".pyo")):
186 filename = filename[:-1]
187 else:
188 if module == "__main__":
189 try:
190 filename = sys.argv[0]
191 except AttributeError:
192 # embedded interpreters don't have sys.argv, see bug #839151
193 filename = '__main__'
194 if not filename:
195 filename = module
196 registry = globals.setdefault("__warningregistry__", {})
197 warn_explicit(message, category, filename, lineno, module, registry,
198 globals)
200 def warn_explicit(message, category, filename, lineno,
201 module=None, registry=None, module_globals=None):
202 lineno = int(lineno)
203 if module is None:
204 module = filename or "<unknown>"
205 if module[-3:].lower() == ".py":
206 module = module[:-3] # XXX What about leading pathname?
207 if registry is None:
208 registry = {}
209 if isinstance(message, Warning):
210 text = str(message)
211 category = message.__class__
212 else:
213 text = message
214 message = category(message)
215 key = (text, category, lineno)
216 # Quick test for common case
217 if registry.get(key):
218 return
219 # Search the filters
220 for item in filters:
221 action, msg, cat, mod, ln = item
222 if ((msg is None or msg.match(text)) and
223 issubclass(category, cat) and
224 (mod is None or mod.match(module)) and
225 (ln == 0 or lineno == ln)):
226 break
227 else:
228 action = defaultaction
229 # Early exit actions
230 if action == "ignore":
231 registry[key] = 1
232 return
234 # Prime the linecache for formatting, in case the
235 # "file" is actually in a zipfile or something.
236 linecache.getlines(filename, module_globals)
238 if action == "error":
239 raise message
240 # Other actions
241 if action == "once":
242 registry[key] = 1
243 oncekey = (text, category)
244 if onceregistry.get(oncekey):
245 return
246 onceregistry[oncekey] = 1
247 elif action == "always":
248 pass
249 elif action == "module":
250 registry[key] = 1
251 altkey = (text, category, 0)
252 if registry.get(altkey):
253 return
254 registry[altkey] = 1
255 elif action == "default":
256 registry[key] = 1
257 else:
258 # Unrecognized actions are errors
259 raise RuntimeError(
260 "Unrecognized action (%r) in warnings.filters:\n %s" %
261 (action, item))
262 if not hasattr(showwarning, "__call__"):
263 raise TypeError("warnings.showwarning() must be set to a "
264 "function or method")
265 # Print message and context
266 showwarning(message, category, filename, lineno)
269 class WarningMessage(object):
271 """Holds the result of a single showwarning() call."""
273 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
274 "line")
276 def __init__(self, message, category, filename, lineno, file=None,
277 line=None):
278 local_values = locals()
279 for attr in self._WARNING_DETAILS:
280 setattr(self, attr, local_values[attr])
281 self._category_name = category.__name__ if category else None
283 def __str__(self):
284 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
285 "line : %r}" % (self.message, self._category_name,
286 self.filename, self.lineno, self.line))
289 class catch_warnings(object):
291 """A context manager that copies and restores the warnings filter upon
292 exiting the context.
294 The 'record' argument specifies whether warnings should be captured by a
295 custom implementation of warnings.showwarning() and be appended to a list
296 returned by the context manager. Otherwise None is returned by the context
297 manager. The objects appended to the list are arguments whose attributes
298 mirror the arguments to showwarning().
300 The 'module' argument is to specify an alternative module to the module
301 named 'warnings' and imported under that name. This argument is only useful
302 when testing the warnings module itself.
306 def __init__(self, *, record=False, module=None):
307 """Specify whether to record warnings and if an alternative module
308 should be used other than sys.modules['warnings'].
310 For compatibility with Python 3.0, please consider all arguments to be
311 keyword-only.
314 self._record = record
315 self._module = sys.modules['warnings'] if module is None else module
316 self._entered = False
318 def __repr__(self):
319 args = []
320 if self._record:
321 args.append("record=True")
322 if self._module is not sys.modules['warnings']:
323 args.append("module=%r" % self._module)
324 name = type(self).__name__
325 return "%s(%s)" % (name, ", ".join(args))
327 def __enter__(self):
328 if self._entered:
329 raise RuntimeError("Cannot enter %r twice" % self)
330 self._entered = True
331 self._filters = self._module.filters
332 self._module.filters = self._filters[:]
333 self._showwarning = self._module.showwarning
334 if self._record:
335 log = []
336 def showwarning(*args, **kwargs):
337 log.append(WarningMessage(*args, **kwargs))
338 self._module.showwarning = showwarning
339 return log
340 else:
341 return None
343 def __exit__(self, *exc_info):
344 if not self._entered:
345 raise RuntimeError("Cannot exit %r without entering first" % self)
346 self._module.filters = self._filters
347 self._module.showwarning = self._showwarning
350 # filters contains a sequence of filter 5-tuples
351 # The components of the 5-tuple are:
352 # - an action: error, ignore, always, default, module, or once
353 # - a compiled regex that must match the warning message
354 # - a class representing the warning category
355 # - a compiled regex that must match the module that is being warned
356 # - a line number for the line being warning, or 0 to mean any line
357 # If either if the compiled regexs are None, match anything.
358 _warnings_defaults = False
359 try:
360 from _warnings import (filters, default_action, once_registry,
361 warn, warn_explicit)
362 defaultaction = default_action
363 onceregistry = once_registry
364 _warnings_defaults = True
365 except ImportError:
366 filters = []
367 defaultaction = "default"
368 onceregistry = {}
371 # Module initialization
372 _processoptions(sys.warnoptions)
373 if not _warnings_defaults:
374 simplefilter("ignore", category=PendingDeprecationWarning, append=1)
375 simplefilter("ignore", category=ImportWarning, append=1)
376 bytes_warning = sys.flags.bytes_warning
377 if bytes_warning > 1:
378 bytes_action = "error"
379 elif bytes_warning:
380 bytes_action = "default"
381 else:
382 bytes_action = "ignore"
383 simplefilter(bytes_action, category=BytesWarning, append=1)
384 del _warnings_defaults