home *** CD-ROM | disk | FTP | other *** search
- """Python part of the warnings subsystem."""
-
- import sys, re, types
-
- __all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
- "resetwarnings"]
-
- defaultaction = "default"
- filters = []
- onceregistry = {}
-
- def warn(message, category=None, stacklevel=1):
- """Issue a warning, or maybe ignore it or raise an exception."""
- # Check category argument
- if category is None:
- category = UserWarning
- assert issubclass(category, Warning)
- # Get context information
- try:
- caller = sys._getframe(stacklevel)
- except ValueError:
- globals = sys.__dict__
- lineno = 1
- else:
- globals = caller.f_globals
- lineno = caller.f_lineno
- if globals.has_key('__name__'):
- module = globals['__name__']
- else:
- module = "<string>"
- filename = globals.get('__file__')
- if filename:
- fnl = filename.lower()
- if fnl.endswith(".pyc") or fnl.endswith(".pyo"):
- filename = filename[:-1]
- else:
- if module == "__main__":
- filename = sys.argv[0]
- if not filename:
- filename = module
- 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 is None:
- module = filename
- if module[-3:].lower() == ".py":
- module = module[:-3] # XXX What about leading pathname?
- if registry is None:
- registry = {}
- key = (message, category, lineno)
- # Quick test for common case
- if registry.get(key):
- return
- # Search the filters
- for item in filters:
- action, msg, cat, mod, ln = item
- if (msg.match(message) and
- issubclass(category, cat) and
- mod.match(module) and
- (ln == 0 or lineno == ln)):
- break
- else:
- action = defaultaction
- # Early exit actions
- if action == "ignore":
- registry[key] = 1
- return
- if action == "error":
- raise category(message)
- # Other actions
- if action == "once":
- registry[key] = 1
- oncekey = (message, category)
- if onceregistry.get(oncekey):
- return
- onceregistry[oncekey] = 1
- elif action == "always":
- pass
- elif action == "module":
- registry[key] = 1
- altkey = (message, category, 0)
- if registry.get(altkey):
- return
- registry[altkey] = 1
- elif action == "default":
- registry[key] = 1
- else:
- # Unrecognized actions are errors
- raise RuntimeError(
- "Unrecognized action (%s) in warnings.filters:\n %s" %
- (`action`, str(item)))
- # 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."""
- if file is None:
- file = sys.stderr
- file.write(formatwarning(message, category, filename, lineno))
-
- def formatwarning(message, category, filename, lineno):
- """Function to format a warning the standard way."""
- import linecache
- s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
- line = linecache.getline(filename, lineno).strip()
- if line:
- s = s + " " + line + "\n"
- return s
-
- def filterwarnings(action, message="", category=Warning, module="", lineno=0,
- append=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: %s" % `action`
- assert isinstance(message, types.StringType), "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 type(module) is types.StringType, "module must be a string"
- assert type(lineno) is types.IntType and lineno >= 0, \
- "lineno must be an int >= 0"
- item = (action, re.compile(message, re.I), category,
- re.compile(module), lineno)
- if append:
- filters.append(item)
- else:
- filters.insert(0, item)
-
- def resetwarnings():
- """Reset the list of warnings filters to its default state."""
- filters[:] = []
-
- class _OptionError(Exception):
- """Exception used by option processing helpers."""
- pass
-
- # Helper to process -W options passed via sys.warnoptions
- def _processoptions(args):
- for arg in args:
- try:
- _setoption(arg)
- except _OptionError, msg:
- print >>sys.stderr, "Invalid -W option ignored:", msg
-
- # Helper for _processoptions()
- def _setoption(arg):
- parts = arg.split(':')
- if len(parts) > 5:
- raise _OptionError("too many fields (max 5): %s" % `arg`)
- while len(parts) < 5:
- parts.append('')
- action, message, category, module, lineno = [s.strip()
- for s in parts]
- action = _getaction(action)
- message = re.escape(message)
- category = _getcategory(category)
- module = re.escape(module)
- if module:
- module = module + '$'
- if lineno:
- try:
- lineno = int(lineno)
- if lineno < 0:
- raise ValueError
- except (ValueError, OverflowError):
- raise _OptionError("invalid lineno %s" % `lineno`)
- else:
- lineno = 0
- filterwarnings(action, message, category, module, lineno)
-
- # Helper for _setoption()
- def _getaction(action):
- if not action:
- return "default"
- if action == "all": return "always" # Alias
- for a in ['default', 'always', 'ignore', 'module', 'once', 'error']:
- if a.startswith(action):
- return a
- raise _OptionError("invalid action: %s" % `action`)
-
- # Helper for _setoption()
- def _getcategory(category):
- if not category:
- return Warning
- if re.match("^[a-zA-Z0-9_]+$", category):
- try:
- cat = eval(category)
- except NameError:
- raise _OptionError("unknown warning category: %s" % `category`)
- else:
- i = category.rfind(".")
- module = category[:i]
- klass = category[i+1:]
- try:
- m = __import__(module, None, None, [klass])
- except ImportError:
- raise _OptionError("invalid module name: %s" % `module`)
- try:
- cat = getattr(m, klass)
- except AttributeError:
- raise _OptionError("unknown warning category: %s" % `category`)
- if (not isinstance(cat, types.ClassType) or
- not issubclass(cat, Warning)):
- raise _OptionError("invalid warning category: %s" % `category`)
- return cat
-
- # Self-test
- def _test():
- import getopt
- testoptions = []
- try:
- opts, args = getopt.getopt(sys.argv[1:], "W:")
- except getopt.error, msg:
- print >>sys.stderr, msg
- return
- for o, a in opts:
- testoptions.append(a)
- try:
- _processoptions(testoptions)
- except _OptionError, msg:
- print >>sys.stderr, msg
- return
- for item in filters: print item
- hello = "hello world"
- warn(hello); warn(hello); warn(hello); warn(hello)
- warn(hello, UserWarning)
- warn(hello, DeprecationWarning)
- for i in range(3):
- warn(hello)
- filterwarnings("error", "", Warning, "", 0)
- try:
- warn(hello)
- except Exception, msg:
- print "Caught", msg.__class__.__name__ + ":", msg
- else:
- print "No exception"
- resetwarnings()
- try:
- filterwarnings("booh", "", Warning, "", 0)
- except Exception, msg:
- print "Caught", msg.__class__.__name__ + ":", msg
- else:
- print "No exception"
-
- # Module initialization
- if __name__ == "__main__":
- import __main__
- sys.modules['warnings'] = __main__
- _test()
- else:
- _processoptions(sys.warnoptions)
- filterwarnings("ignore", category=OverflowWarning, append=1)
-