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