"""Python part of the warnings subsystem."""
# Note: function level imports should *not* be used
# in this module as it may cause import lock deadlock.
__all__
= ["warn", "showwarning", "formatwarning", "filterwarnings",
# filters contains a sequence of filter 5-tuples
# The components of the 5-tuple are:
# - an action: error, ignore, always, default, module, or once
# - a compiled regex that must match the warning message
# - a class representing the warning category
# - a compiled regex that must match the module that is being warned
# - a line number for the line being warning, or 0 to mean any line
# If either if the compiled regexs are None, match anything.
defaultaction
= "default"
def warn(message
, category
=None, stacklevel
=1):
"""Issue a warning, or maybe ignore it or raise an exception."""
# Check if message is already a Warning object
if isinstance(message
, Warning):
category
= message
.__class
__
# Check category argument
assert issubclass(category
, Warning)
# Get context information
caller
= sys
._getframe
(stacklevel
)
globals = caller
.f_globals
if '__name__' in globals:
module
= globals['__name__']
filename
= globals.get('__file__')
if fnl
.endswith(".pyc") or fnl
.endswith(".pyo"):
# embedded interpreters don't have sys.argv, see bug #839151
registry
= globals.setdefault("__warningregistry__", {})
warn_explicit(message
, category
, filename
, lineno
, module
, registry
)
def warn_explicit(message
, category
, filename
, lineno
,
module
=None, registry
=None):
if module
[-3:].lower() == ".py":
module
= module
[:-3] # XXX What about leading pathname?
if isinstance(message
, Warning):
category
= message
.__class
__
message
= category(message
)
key
= (text
, category
, lineno
)
# Quick test for common case
action
, msg
, cat
, mod
, ln
= item
if ((msg
is None or msg
.match(text
)) and
issubclass(category
, cat
) and
(mod
is None or mod
.match(module
)) and
(ln
== 0 or lineno
== ln
)):
oncekey
= (text
, category
)
if onceregistry
.get(oncekey
):
onceregistry
[oncekey
] = 1
altkey
= (text
, category
, 0)
elif action
== "default":
# Unrecognized actions are errors
"Unrecognized action (%r) in warnings.filters:\n %s" %
# Print message and context
showwarning(message
, category
, filename
, lineno
)
def showwarning(message
, category
, filename
, lineno
, file=None):
"""Hook to write a warning to a file; replace if you like."""
file.write(formatwarning(message
, category
, filename
, lineno
))
pass # the file (probably stderr) is invalid - this warning gets lost.
def formatwarning(message
, category
, filename
, lineno
):
"""Function to format a warning the standard way."""
s
= "%s:%s: %s: %s\n" % (filename
, lineno
, category
.__name
__, message
)
line
= linecache
.getline(filename
, lineno
).strip()
s
= s
+ " " + line
+ "\n"
def filterwarnings(action
, message
="", category
=Warning, module
="", lineno
=0,
"""Insert an entry into the list of warnings filters (at the front).
Use assertions to check that all arguments have the right type."""
assert action
in ("error", "ignore", "always", "default", "module",
"once"), "invalid action: %r" % (action
,)
assert isinstance(message
, basestring
), "message must be a string"
assert isinstance(category
, types
.ClassType
), "category must be a class"
assert issubclass(category
, Warning), "category must be a Warning subclass"
assert isinstance(module
, basestring
), "module must be a string"
assert isinstance(lineno
, int) and lineno
>= 0, \
"lineno must be an int >= 0"
item
= (action
, re
.compile(message
, re
.I
), category
,
re
.compile(module
), lineno
)
def simplefilter(action
, category
=Warning, lineno
=0, append
=0):
"""Insert a simple entry into the list of warnings filters (at the front).
A simple filter matches all modules and messages.
assert action
in ("error", "ignore", "always", "default", "module",
"once"), "invalid action: %r" % (action
,)
assert isinstance(lineno
, int) and lineno
>= 0, \
"lineno must be an int >= 0"
item
= (action
, None, category
, None, lineno
)
"""Clear the list of warning filters, so that no filters are active."""
class _OptionError(Exception):
"""Exception used by option processing helpers."""
# Helper to process -W options passed via sys.warnoptions
def _processoptions(args
):
except _OptionError
, msg
:
print >>sys
.stderr
, "Invalid -W option ignored:", msg
# Helper for _processoptions()
raise _OptionError("too many fields (max 5): %r" % (arg
,))
action
, message
, category
, module
, lineno
= [s
.strip()
action
= _getaction(action
)
message
= re
.escape(message
)
category
= _getcategory(category
)
module
= re
.escape(module
)
except (ValueError, OverflowError):
raise _OptionError("invalid lineno %r" % (lineno
,))
filterwarnings(action
, message
, category
, module
, lineno
)
# Helper for _setoption()
if action
== "all": return "always" # Alias
for a
in ['default', 'always', 'ignore', 'module', 'once', 'error']:
raise _OptionError("invalid action: %r" % (action
,))
# Helper for _setoption()
def _getcategory(category
):
if re
.match("^[a-zA-Z0-9_]+$", category
):
raise _OptionError("unknown warning category: %r" % (category
,))
m
= __import__(module
, None, None, [klass
])
raise _OptionError("invalid module name: %r" % (module
,))
raise _OptionError("unknown warning category: %r" % (category
,))
if (not isinstance(cat
, types
.ClassType
) or
not issubclass(cat
, Warning)):
raise _OptionError("invalid warning category: %r" % (category
,))
_processoptions(sys
.warnoptions
)
# XXX OverflowWarning should go away for Python 2.5.
simplefilter("ignore", category
=OverflowWarning, append
=1)
simplefilter("ignore", category
=PendingDeprecationWarning
, append
=1)