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.
10 __all__
= ["warn", "showwarning", "formatwarning", "filterwarnings",
11 "resetwarnings", "catch_warnings"]
14 def warnpy3k(message
, category
=None, stacklevel
=1):
15 """Issue a deprecation warning for Python 3.x related changes.
17 Warnings are omitted unless Python is started with the -3 option.
21 category
= DeprecationWarning
22 warn(message
, category
, stacklevel
+1)
24 def _show_warning(message
, category
, filename
, lineno
, file=None, line
=None):
25 """Hook to write a warning to a file; replace if you like."""
29 file.write(formatwarning(message
, category
, filename
, lineno
, line
))
31 pass # the file (probably stderr) is invalid - this warning gets lost.
32 # Keep a working version around in case the deprecation of the old API is
34 showwarning
= _show_warning
36 def formatwarning(message
, category
, filename
, lineno
, line
=None):
37 """Function to format a warning the standard way."""
38 s
= "%s:%s: %s: %s\n" % (filename
, lineno
, category
.__name
__, message
)
39 line
= linecache
.getline(filename
, lineno
) if line
is None else line
45 def filterwarnings(action
, message
="", category
=Warning, module
="", lineno
=0,
47 """Insert an entry into the list of warnings filters (at the front).
49 'action' -- one of "error", "ignore", "always", "default", "module",
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
58 assert action
in ("error", "ignore", "always", "default", "module",
59 "once"), "invalid action: %r" % (action
,)
60 assert isinstance(message
, basestring
), "message must be a string"
61 assert isinstance(category
, (type, types
.ClassType
)), \
62 "category must be a class"
63 assert issubclass(category
, Warning), "category must be a Warning subclass"
64 assert isinstance(module
, basestring
), "module must be a string"
65 assert isinstance(lineno
, int) and lineno
>= 0, \
66 "lineno must be an int >= 0"
67 item
= (action
, re
.compile(message
, re
.I
), category
,
68 re
.compile(module
), lineno
)
72 filters
.insert(0, item
)
74 def simplefilter(action
, category
=Warning, lineno
=0, append
=0):
75 """Insert a simple entry into the list of warnings filters (at the front).
77 A simple filter matches all modules and messages.
78 'action' -- one of "error", "ignore", "always", "default", "module",
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
84 assert action
in ("error", "ignore", "always", "default", "module",
85 "once"), "invalid action: %r" % (action
,)
86 assert isinstance(lineno
, int) and lineno
>= 0, \
87 "lineno must be an int >= 0"
88 item
= (action
, None, category
, None, lineno
)
92 filters
.insert(0, item
)
95 """Clear the list of warning filters, so that no filters are active."""
98 class _OptionError(Exception):
99 """Exception used by option processing helpers."""
102 # Helper to process -W options passed via sys.warnoptions
103 def _processoptions(args
):
107 except _OptionError
, msg
:
108 print >>sys
.stderr
, "Invalid -W option ignored:", msg
110 # Helper for _processoptions()
113 parts
= arg
.split(':')
115 raise _OptionError("too many fields (max 5): %r" % (arg
,))
116 while len(parts
) < 5:
118 action
, message
, category
, module
, lineno
= [s
.strip()
120 action
= _getaction(action
)
121 message
= re
.escape(message
)
122 category
= _getcategory(category
)
123 module
= re
.escape(module
)
125 module
= module
+ '$'
131 except (ValueError, OverflowError):
132 raise _OptionError("invalid lineno %r" % (lineno
,))
135 filterwarnings(action
, message
, category
, module
, lineno
)
137 # Helper for _setoption()
138 def _getaction(action
):
141 if action
== "all": return "always" # Alias
142 for a
in ('default', 'always', 'ignore', 'module', 'once', 'error'):
143 if a
.startswith(action
):
145 raise _OptionError("invalid action: %r" % (action
,))
147 # Helper for _setoption()
148 def _getcategory(category
):
152 if re
.match("^[a-zA-Z0-9_]+$", category
):
156 raise _OptionError("unknown warning category: %r" % (category
,))
158 i
= category
.rfind(".")
159 module
= category
[:i
]
160 klass
= category
[i
+1:]
162 m
= __import__(module
, None, None, [klass
])
164 raise _OptionError("invalid module name: %r" % (module
,))
166 cat
= getattr(m
, klass
)
167 except AttributeError:
168 raise _OptionError("unknown warning category: %r" % (category
,))
169 if not issubclass(cat
, Warning):
170 raise _OptionError("invalid warning category: %r" % (category
,))
174 # Code typically replaced by _warnings
175 def 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
182 category
= UserWarning
183 assert issubclass(category
, Warning)
184 # Get context information
186 caller
= sys
._getframe
(stacklevel
)
188 globals = sys
.__dict
__
191 globals = caller
.f_globals
192 lineno
= caller
.f_lineno
193 if '__name__' in globals:
194 module
= globals['__name__']
197 filename
= globals.get('__file__')
199 fnl
= filename
.lower()
200 if fnl
.endswith((".pyc", ".pyo")):
201 filename
= filename
[:-1]
203 if module
== "__main__":
205 filename
= sys
.argv
[0]
206 except AttributeError:
207 # embedded interpreters don't have sys.argv, see bug #839151
208 filename
= '__main__'
211 registry
= globals.setdefault("__warningregistry__", {})
212 warn_explicit(message
, category
, filename
, lineno
, module
, registry
,
215 def warn_explicit(message
, category
, filename
, lineno
,
216 module
=None, registry
=None, module_globals
=None):
219 module
= filename
or "<unknown>"
220 if module
[-3:].lower() == ".py":
221 module
= module
[:-3] # XXX What about leading pathname?
224 if isinstance(message
, Warning):
226 category
= message
.__class
__
229 message
= category(message
)
230 key
= (text
, category
, lineno
)
231 # Quick test for common case
232 if registry
.get(key
):
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
)):
243 action
= defaultaction
245 if action
== "ignore":
249 # Prime the linecache for formatting, in case the
250 # "file" is actually in a zipfile or something.
251 linecache
.getlines(filename
, module_globals
)
253 if action
== "error":
258 oncekey
= (text
, category
)
259 if onceregistry
.get(oncekey
):
261 onceregistry
[oncekey
] = 1
262 elif action
== "always":
264 elif action
== "module":
266 altkey
= (text
, category
, 0)
267 if registry
.get(altkey
):
270 elif action
== "default":
273 # Unrecognized actions are errors
275 "Unrecognized action (%r) in warnings.filters:\n %s" %
277 # Print message and context
278 showwarning(message
, category
, filename
, lineno
)
281 class WarningMessage(object):
283 """Holds the result of a single showwarning() call."""
285 _WARNING_DETAILS
= ("message", "category", "filename", "lineno", "file",
288 def __init__(self
, message
, category
, filename
, lineno
, file=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
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
))
301 class catch_warnings(object):
303 """A context manager that copies and restores the warnings filter upon
306 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().
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.
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'].
322 For compatibility with Python 3.0, please consider all arguments to be
326 self
._record
= record
327 self
._module
= sys
.modules
['warnings'] if module
is None else module
328 self
._entered
= False
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
))
341 raise RuntimeError("Cannot enter %r twice" % self
)
343 self
._filters
= self
._module
.filters
344 self
._module
.filters
= self
._filters
[:]
345 self
._showwarning
= self
._module
.showwarning
348 def showwarning(*args
, **kwargs
):
349 log
.append(WarningMessage(*args
, **kwargs
))
350 self
._module
.showwarning
= showwarning
355 def __exit__(self
, *exc_info
):
356 if not self
._entered
:
357 raise RuntimeError("Cannot exit %r without entering first" % self
)
358 self
._module
.filters
= self
._filters
359 self
._module
.showwarning
= self
._showwarning
362 # 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
372 from _warnings
import (filters
, default_action
, once_registry
,
374 defaultaction
= default_action
375 onceregistry
= once_registry
376 _warnings_defaults
= True
379 defaultaction
= "default"
383 # Module initialization
384 _processoptions(sys
.warnoptions
)
385 if not _warnings_defaults
:
386 silence
= [ImportWarning
, PendingDeprecationWarning
]
387 # Don't silence DeprecationWarning if -3 or -Q was used.
388 if not sys
.py3kwarning
and not sys
.flags
.division_warning
:
389 silence
.append(DeprecationWarning)
391 simplefilter("ignore", category
=cls
)
392 bytes_warning
= sys
.flags
.bytes_warning
393 if bytes_warning
> 1:
394 bytes_action
= "error"
396 bytes_action
= "default"
398 bytes_action
= "ignore"
399 simplefilter(bytes_action
, category
=BytesWarning
, append
=1)
400 del _warnings_defaults