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", "warn_explicit", "showwarning",
11 "formatwarning", "filterwarnings", "simplefilter",
12 "resetwarnings", "catch_warnings"]
15 def warnpy3k(message
, category
=None, stacklevel
=1):
16 """Issue a deprecation warning for Python 3.x related changes.
18 Warnings are omitted unless Python is started with the -3 option.
22 category
= DeprecationWarning
23 warn(message
, category
, stacklevel
+1)
25 def _show_warning(message
, category
, filename
, lineno
, file=None, line
=None):
26 """Hook to write a warning to a file; replace if you like."""
30 # sys.stderr is None - warnings get lost
33 file.write(formatwarning(message
, category
, filename
, lineno
, line
))
35 pass # the file (probably stderr) is invalid - this warning gets lost.
36 # Keep a working version around in case the deprecation of the old API is
38 showwarning
= _show_warning
40 def formatwarning(message
, category
, filename
, lineno
, line
=None):
41 """Function to format a warning the standard way."""
42 s
= "%s:%s: %s: %s\n" % (filename
, lineno
, category
.__name
__, message
)
43 line
= linecache
.getline(filename
, lineno
) if line
is None else line
49 def filterwarnings(action
, message
="", category
=Warning, module
="", lineno
=0,
51 """Insert an entry into the list of warnings filters (at the front).
53 'action' -- one of "error", "ignore", "always", "default", "module",
55 'message' -- a regex that the warning message must match
56 'category' -- a class that the warning must be a subclass of
57 'module' -- a regex that the module name must match
58 'lineno' -- an integer line number, 0 matches all warnings
59 'append' -- if true, append to the list of filters
62 assert action
in ("error", "ignore", "always", "default", "module",
63 "once"), "invalid action: %r" % (action
,)
64 assert isinstance(message
, basestring
), "message must be a string"
65 assert isinstance(category
, (type, types
.ClassType
)), \
66 "category must be a class"
67 assert issubclass(category
, Warning), "category must be a Warning subclass"
68 assert isinstance(module
, basestring
), "module must be a string"
69 assert isinstance(lineno
, int) and lineno
>= 0, \
70 "lineno must be an int >= 0"
71 item
= (action
, re
.compile(message
, re
.I
), category
,
72 re
.compile(module
), lineno
)
76 filters
.insert(0, item
)
78 def simplefilter(action
, category
=Warning, lineno
=0, append
=0):
79 """Insert a simple entry into the list of warnings filters (at the front).
81 A simple filter matches all modules and messages.
82 'action' -- one of "error", "ignore", "always", "default", "module",
84 'category' -- a class that the warning must be a subclass of
85 'lineno' -- an integer line number, 0 matches all warnings
86 'append' -- if true, append to the list of filters
88 assert action
in ("error", "ignore", "always", "default", "module",
89 "once"), "invalid action: %r" % (action
,)
90 assert isinstance(lineno
, int) and lineno
>= 0, \
91 "lineno must be an int >= 0"
92 item
= (action
, None, category
, None, lineno
)
96 filters
.insert(0, item
)
99 """Clear the list of warning filters, so that no filters are active."""
102 class _OptionError(Exception):
103 """Exception used by option processing helpers."""
106 # Helper to process -W options passed via sys.warnoptions
107 def _processoptions(args
):
111 except _OptionError
, msg
:
112 print >>sys
.stderr
, "Invalid -W option ignored:", msg
114 # Helper for _processoptions()
117 parts
= arg
.split(':')
119 raise _OptionError("too many fields (max 5): %r" % (arg
,))
120 while len(parts
) < 5:
122 action
, message
, category
, module
, lineno
= [s
.strip()
124 action
= _getaction(action
)
125 message
= re
.escape(message
)
126 category
= _getcategory(category
)
127 module
= re
.escape(module
)
129 module
= module
+ '$'
135 except (ValueError, OverflowError):
136 raise _OptionError("invalid lineno %r" % (lineno
,))
139 filterwarnings(action
, message
, category
, module
, lineno
)
141 # Helper for _setoption()
142 def _getaction(action
):
145 if action
== "all": return "always" # Alias
146 for a
in ('default', 'always', 'ignore', 'module', 'once', 'error'):
147 if a
.startswith(action
):
149 raise _OptionError("invalid action: %r" % (action
,))
151 # Helper for _setoption()
152 def _getcategory(category
):
156 if re
.match("^[a-zA-Z0-9_]+$", category
):
160 raise _OptionError("unknown warning category: %r" % (category
,))
162 i
= category
.rfind(".")
163 module
= category
[:i
]
164 klass
= category
[i
+1:]
166 m
= __import__(module
, None, None, [klass
])
168 raise _OptionError("invalid module name: %r" % (module
,))
170 cat
= getattr(m
, klass
)
171 except AttributeError:
172 raise _OptionError("unknown warning category: %r" % (category
,))
173 if not issubclass(cat
, Warning):
174 raise _OptionError("invalid warning category: %r" % (category
,))
178 # Code typically replaced by _warnings
179 def warn(message
, category
=None, stacklevel
=1):
180 """Issue a warning, or maybe ignore it or raise an exception."""
181 # Check if message is already a Warning object
182 if isinstance(message
, Warning):
183 category
= message
.__class
__
184 # Check category argument
186 category
= UserWarning
187 assert issubclass(category
, Warning)
188 # Get context information
190 caller
= sys
._getframe
(stacklevel
)
192 globals = sys
.__dict
__
195 globals = caller
.f_globals
196 lineno
= caller
.f_lineno
197 if '__name__' in globals:
198 module
= globals['__name__']
201 filename
= globals.get('__file__')
203 fnl
= filename
.lower()
204 if fnl
.endswith((".pyc", ".pyo")):
205 filename
= filename
[:-1]
207 if module
== "__main__":
209 filename
= sys
.argv
[0]
210 except AttributeError:
211 # embedded interpreters don't have sys.argv, see bug #839151
212 filename
= '__main__'
215 registry
= globals.setdefault("__warningregistry__", {})
216 warn_explicit(message
, category
, filename
, lineno
, module
, registry
,
219 def warn_explicit(message
, category
, filename
, lineno
,
220 module
=None, registry
=None, module_globals
=None):
223 module
= filename
or "<unknown>"
224 if module
[-3:].lower() == ".py":
225 module
= module
[:-3] # XXX What about leading pathname?
228 if isinstance(message
, Warning):
230 category
= message
.__class
__
233 message
= category(message
)
234 key
= (text
, category
, lineno
)
235 # Quick test for common case
236 if registry
.get(key
):
240 action
, msg
, cat
, mod
, ln
= item
241 if ((msg
is None or msg
.match(text
)) and
242 issubclass(category
, cat
) and
243 (mod
is None or mod
.match(module
)) and
244 (ln
== 0 or lineno
== ln
)):
247 action
= defaultaction
249 if action
== "ignore":
253 # Prime the linecache for formatting, in case the
254 # "file" is actually in a zipfile or something.
255 linecache
.getlines(filename
, module_globals
)
257 if action
== "error":
262 oncekey
= (text
, category
)
263 if onceregistry
.get(oncekey
):
265 onceregistry
[oncekey
] = 1
266 elif action
== "always":
268 elif action
== "module":
270 altkey
= (text
, category
, 0)
271 if registry
.get(altkey
):
274 elif action
== "default":
277 # Unrecognized actions are errors
279 "Unrecognized action (%r) in warnings.filters:\n %s" %
281 # Print message and context
282 showwarning(message
, category
, filename
, lineno
)
285 class WarningMessage(object):
287 """Holds the result of a single showwarning() call."""
289 _WARNING_DETAILS
= ("message", "category", "filename", "lineno", "file",
292 def __init__(self
, message
, category
, filename
, lineno
, file=None,
294 local_values
= locals()
295 for attr
in self
._WARNING
_DETAILS
:
296 setattr(self
, attr
, local_values
[attr
])
297 self
._category
_name
= category
.__name
__ if category
else None
300 return ("{message : %r, category : %r, filename : %r, lineno : %s, "
301 "line : %r}" % (self
.message
, self
._category
_name
,
302 self
.filename
, self
.lineno
, self
.line
))
305 class catch_warnings(object):
307 """A context manager that copies and restores the warnings filter upon
310 The 'record' argument specifies whether warnings should be captured by a
311 custom implementation of warnings.showwarning() and be appended to a list
312 returned by the context manager. Otherwise None is returned by the context
313 manager. The objects appended to the list are arguments whose attributes
314 mirror the arguments to showwarning().
316 The 'module' argument is to specify an alternative module to the module
317 named 'warnings' and imported under that name. This argument is only useful
318 when testing the warnings module itself.
322 def __init__(self
, record
=False, module
=None):
323 """Specify whether to record warnings and if an alternative module
324 should be used other than sys.modules['warnings'].
326 For compatibility with Python 3.0, please consider all arguments to be
330 self
._record
= record
331 self
._module
= sys
.modules
['warnings'] if module
is None else module
332 self
._entered
= False
337 args
.append("record=True")
338 if self
._module
is not sys
.modules
['warnings']:
339 args
.append("module=%r" % self
._module
)
340 name
= type(self
).__name
__
341 return "%s(%s)" % (name
, ", ".join(args
))
345 raise RuntimeError("Cannot enter %r twice" % self
)
347 self
._filters
= self
._module
.filters
348 self
._module
.filters
= self
._filters
[:]
349 self
._showwarning
= self
._module
.showwarning
352 def showwarning(*args
, **kwargs
):
353 log
.append(WarningMessage(*args
, **kwargs
))
354 self
._module
.showwarning
= showwarning
359 def __exit__(self
, *exc_info
):
360 if not self
._entered
:
361 raise RuntimeError("Cannot exit %r without entering first" % self
)
362 self
._module
.filters
= self
._filters
363 self
._module
.showwarning
= self
._showwarning
366 # filters contains a sequence of filter 5-tuples
367 # The components of the 5-tuple are:
368 # - an action: error, ignore, always, default, module, or once
369 # - a compiled regex that must match the warning message
370 # - a class representing the warning category
371 # - a compiled regex that must match the module that is being warned
372 # - a line number for the line being warning, or 0 to mean any line
373 # If either if the compiled regexs are None, match anything.
374 _warnings_defaults
= False
376 from _warnings
import (filters
, default_action
, once_registry
,
378 defaultaction
= default_action
379 onceregistry
= once_registry
380 _warnings_defaults
= True
383 defaultaction
= "default"
387 # Module initialization
388 _processoptions(sys
.warnoptions
)
389 if not _warnings_defaults
:
390 silence
= [ImportWarning
, PendingDeprecationWarning
]
391 # Don't silence DeprecationWarning if -3 or -Q was used.
392 if not sys
.py3kwarning
and not sys
.flags
.division_warning
:
393 silence
.append(DeprecationWarning)
395 simplefilter("ignore", category
=cls
)
396 bytes_warning
= sys
.flags
.bytes_warning
397 if bytes_warning
> 1:
398 bytes_action
= "error"
400 bytes_action
= "default"
402 bytes_action
= "ignore"
403 simplefilter(bytes_action
, category
=BytesWarning
, append
=1)
404 del _warnings_defaults