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.
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."""
18 file.write(formatwarning(message
, category
, filename
, lineno
, line
))
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
31 def filterwarnings(action
, message
="", category
=Warning, module
="", lineno
=0,
33 """Insert an entry into the list of warnings filters (at the front).
35 Use assertions to check that all arguments have the right type."""
37 assert action
in ("error", "ignore", "always", "default", "module",
38 "once"), "invalid action: %r" % (action
,)
39 assert isinstance(message
, str), "message must be a string"
40 assert isinstance(category
, type), "category must be a class"
41 assert issubclass(category
, Warning), "category must be a Warning subclass"
42 assert isinstance(module
, str), "module must be a string"
43 assert isinstance(lineno
, int) and lineno
>= 0, \
44 "lineno must be an int >= 0"
45 item
= (action
, re
.compile(message
, re
.I
), category
,
46 re
.compile(module
), lineno
)
50 filters
.insert(0, item
)
52 def simplefilter(action
, category
=Warning, lineno
=0, append
=0):
53 """Insert a simple entry into the list of warnings filters (at the front).
55 A simple filter matches all modules and messages.
57 assert action
in ("error", "ignore", "always", "default", "module",
58 "once"), "invalid action: %r" % (action
,)
59 assert isinstance(lineno
, int) and lineno
>= 0, \
60 "lineno must be an int >= 0"
61 item
= (action
, None, category
, None, lineno
)
65 filters
.insert(0, item
)
68 """Clear the list of warning filters, so that no filters are active."""
71 class _OptionError(Exception):
72 """Exception used by option processing helpers."""
75 # Helper to process -W options passed via sys.warnoptions
76 def _processoptions(args
):
80 except _OptionError
as msg
:
81 print("Invalid -W option ignored:", msg
, file=sys
.stderr
)
83 # Helper for _processoptions()
86 parts
= arg
.split(':')
88 raise _OptionError("too many fields (max 5): %r" % (arg
,))
91 action
, message
, category
, module
, lineno
= [s
.strip()
93 action
= _getaction(action
)
94 message
= re
.escape(message
)
95 category
= _getcategory(category
)
96 module
= re
.escape(module
)
104 except (ValueError, OverflowError):
105 raise _OptionError("invalid lineno %r" % (lineno
,))
108 filterwarnings(action
, message
, category
, module
, lineno
)
110 # Helper for _setoption()
111 def _getaction(action
):
114 if action
== "all": return "always" # Alias
115 for a
in ('default', 'always', 'ignore', 'module', 'once', 'error'):
116 if a
.startswith(action
):
118 raise _OptionError("invalid action: %r" % (action
,))
120 # Helper for _setoption()
121 def _getcategory(category
):
125 if re
.match("^[a-zA-Z0-9_]+$", category
):
129 raise _OptionError("unknown warning category: %r" % (category
,))
131 i
= category
.rfind(".")
132 module
= category
[:i
]
133 klass
= category
[i
+1:]
135 m
= __import__(module
, None, None, [klass
])
137 raise _OptionError("invalid module name: %r" % (module
,))
139 cat
= getattr(m
, klass
)
140 except AttributeError:
141 raise _OptionError("unknown warning category: %r" % (category
,))
142 if not issubclass(cat
, Warning):
143 raise _OptionError("invalid warning category: %r" % (category
,))
147 # Code typically replaced by _warnings
148 def 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
155 category
= UserWarning
156 assert issubclass(category
, Warning)
157 # Get context information
159 caller
= sys
._getframe
(stacklevel
)
161 globals = sys
.__dict
__
164 globals = caller
.f_globals
165 lineno
= caller
.f_lineno
166 if '__name__' in globals:
167 module
= globals['__name__']
170 filename
= globals.get('__file__')
172 fnl
= filename
.lower()
173 if fnl
.endswith((".pyc", ".pyo")):
174 filename
= filename
[:-1]
176 if module
== "__main__":
178 filename
= sys
.argv
[0]
179 except AttributeError:
180 # embedded interpreters don't have sys.argv, see bug #839151
181 filename
= '__main__'
184 registry
= globals.setdefault("__warningregistry__", {})
185 warn_explicit(message
, category
, filename
, lineno
, module
, registry
,
188 def warn_explicit(message
, category
, filename
, lineno
,
189 module
=None, registry
=None, module_globals
=None):
192 module
= filename
or "<unknown>"
193 if module
[-3:].lower() == ".py":
194 module
= module
[:-3] # XXX What about leading pathname?
197 if isinstance(message
, Warning):
199 category
= message
.__class
__
202 message
= category(message
)
203 key
= (text
, category
, lineno
)
204 # Quick test for common case
205 if registry
.get(key
):
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
)):
216 action
= defaultaction
218 if action
== "ignore":
222 # Prime the linecache for formatting, in case the
223 # "file" is actually in a zipfile or something.
224 linecache
.getlines(filename
, module_globals
)
226 if action
== "error":
231 oncekey
= (text
, category
)
232 if onceregistry
.get(oncekey
):
234 onceregistry
[oncekey
] = 1
235 elif action
== "always":
237 elif action
== "module":
239 altkey
= (text
, category
, 0)
240 if registry
.get(altkey
):
243 elif action
== "default":
246 # Unrecognized actions are errors
248 "Unrecognized action (%r) in warnings.filters:\n %s" %
250 if not hasattr(showwarning
, "__call__"):
251 raise TypeError("warnings.showwarning() must be set to a "
252 "function or method")
253 # Print message and context
254 showwarning(message
, category
, filename
, lineno
)
257 class WarningMessage(object):
259 """Holds the result of a single showwarning() call."""
261 _WARNING_DETAILS
= ("message", "category", "filename", "lineno", "file",
264 def __init__(self
, message
, category
, filename
, lineno
, file=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
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
))
277 class catch_warnings(object):
279 """A context manager that copies and restores the warnings filter upon
282 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().
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.
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'].
298 For compatibility with Python 3.0, please consider all arguments to be
302 self
._record
= record
303 self
._module
= sys
.modules
['warnings'] if module
is None else module
304 self
._entered
= False
309 args
.append("record=True")
310 if self
._module
is not sys
.modules
['warnings']:
311 args
.append("module=%r" % self
._module
)
312 name
= type(self
).__name
__
313 return "%s(%s)" % (name
, ", ".join(args
))
317 raise RuntimeError("Cannot enter %r twice" % self
)
319 self
._filters
= self
._module
.filters
320 self
._module
.filters
= self
._filters
[:]
321 self
._showwarning
= self
._module
.showwarning
324 def showwarning(*args
, **kwargs
):
325 log
.append(WarningMessage(*args
, **kwargs
))
326 self
._module
.showwarning
= showwarning
331 def __exit__(self
, *exc_info
):
332 if not self
._entered
:
333 raise RuntimeError("Cannot exit %r without entering first" % self
)
334 self
._module
.filters
= self
._filters
335 self
._module
.showwarning
= self
._showwarning
338 # filters contains a sequence of filter 5-tuples
339 # The components of the 5-tuple are:
340 # - an action: error, ignore, always, default, module, or once
341 # - a compiled regex that must match the warning message
342 # - a class representing the warning category
343 # - a compiled regex that must match the module that is being warned
344 # - a line number for the line being warning, or 0 to mean any line
345 # If either if the compiled regexs are None, match anything.
346 _warnings_defaults
= False
348 from _warnings
import (filters
, default_action
, once_registry
,
350 defaultaction
= default_action
351 onceregistry
= once_registry
352 _warnings_defaults
= True
355 defaultaction
= "default"
359 # Module initialization
360 _processoptions(sys
.warnoptions
)
361 if not _warnings_defaults
:
362 simplefilter("ignore", category
=PendingDeprecationWarning
, append
=1)
363 simplefilter("ignore", category
=ImportWarning
, append
=1)
364 bytes_warning
= sys
.flags
.bytes_warning
365 if bytes_warning
> 1:
366 bytes_action
= "error"
368 bytes_action
= "default"
370 bytes_action
= "ignore"
371 simplefilter(bytes_action
, category
=BytesWarning
, append
=1)
372 del _warnings_defaults