diff -r ddcf09a348ca Doc/library/warnings.rst --- a/Doc/library/warnings.rst Wed Nov 28 19:24:44 2012 +0200 +++ b/Doc/library/warnings.rst Thu Nov 29 05:12:04 2012 +0100 @@ -382,6 +382,31 @@ and calls to :func:`simplefilter`. +.. function:: process_option(option) + + Parse a comma-separated filter definition, as described for command line + option :option:`-W`, and insert the filter. If the filter definition is + malformed, a :exc:`warnings.WarningsOptParsingException` is raised.Along + with :mod:`argparse`, it is useful to control warnings from the command line + of a program.:: + + import argparse, warnings + + parser = argparse.ArgumentParser(description='Mimic python -W behaviour.') + parser.add_argument('-W', dest='warnings', action='append', metavar='arg', + help='warning control; arg is action:message:category:module:lineno') + + args = parser.parse_args() + + if args.warnings: + for arg in args.warnings: + try: + warnings.process_option(arg) + except WarningsOptParseError as msg: + print("Invalid -W option ignored:", msg, file=sys.stderr) + + + Available Context Managers -------------------------- diff -r ddcf09a348ca Lib/test/test_warnings.py --- a/Lib/test/test_warnings.py Wed Nov 28 19:24:44 2012 +0200 +++ b/Lib/test/test_warnings.py Thu Nov 29 05:12:04 2012 +0100 @@ -384,12 +384,13 @@ def test_improper_input(self): # Uses the private _setoption() function to test the parsing # of command-line warning arguments + self.module.resetwarnings() with original_warnings.catch_warnings(module=self.module): - self.assertRaises(self.module._OptionError, + self.assertRaises(self.module.WarningsOptParsingError, self.module._setoption, '1:2:3:4:5:6') - self.assertRaises(self.module._OptionError, + self.assertRaises(self.module.WarningsOptParsingError, self.module._setoption, 'bogus::Warning') - self.assertRaises(self.module._OptionError, + self.assertRaises(self.module.WarningsOptParsingError, self.module._setoption, 'ignore:2::4:-5') self.module._setoption('error::Warning::0') self.assertRaises(UserWarning, self.module.warn, 'convert to error') @@ -410,6 +411,19 @@ self.assertFalse(out.strip()) self.assertNotIn(b'RuntimeWarning', err) + def test_cmd_line_API(self): + # check if the opt args are properly parsed + self.module.resetwarnings() + with original_warnings.catch_warnings(module=self.module): + self.assertRaises(self.module.WarningsOptParsingError, + self.module.process_option, '1:2:3:4:5:6') + self.assertRaises(self.module.WarningsOptParsingError, + self.module.process_option, 'bogus::Warning') + self.assertRaises(self.module.WarningsOptParsingError, + self.module.process_option, 'ignore:2::4:-5') + self.module.process_option('error::Warning::0') + self.assertRaises(UserWarning, self.module.warn, 'convert to error') + class CWCmdLineTests(BaseTest, WCmdLineTests): module = c_warnings diff -r ddcf09a348ca Lib/warnings.py --- a/Lib/warnings.py Wed Nov 28 19:24:44 2012 +0200 +++ b/Lib/warnings.py Thu Nov 29 05:12:04 2012 +0100 @@ -81,15 +81,29 @@ filters[:] = [] class _OptionError(Exception): + """Exception used by option processing helpers. + Kept for compatibility""" + pass + + +class WarningsOptParsingError(_OptionError): """Exception used by option processing helpers.""" pass + +def process_option(opt): + """Parse a comma separated warning filter defintion and insert it. + The filter definition must match python -W option format + """ + # let the exceptions rise to the user + _setoption(opt) + # Helper to process -W options passed via sys.warnoptions def _processoptions(args): for arg in args: try: _setoption(arg) - except _OptionError as msg: + except WarningsOptParsingError as msg: print("Invalid -W option ignored:", msg, file=sys.stderr) # Helper for _processoptions() @@ -97,7 +111,7 @@ import re parts = arg.split(':') if len(parts) > 5: - raise _OptionError("too many fields (max 5): %r" % (arg,)) + raise WarningsOptParsingError("too many fields (max 5): %r" % (arg,)) while len(parts) < 5: parts.append('') action, message, category, module, lineno = [s.strip() @@ -114,7 +128,7 @@ if lineno < 0: raise ValueError except (ValueError, OverflowError): - raise _OptionError("invalid lineno %r" % (lineno,)) + raise WarningsOptParsingError("invalid lineno %r" % (lineno,)) else: lineno = 0 filterwarnings(action, message, category, module, lineno) @@ -127,7 +141,7 @@ for a in ('default', 'always', 'ignore', 'module', 'once', 'error'): if a.startswith(action): return a - raise _OptionError("invalid action: %r" % (action,)) + raise WarningsOptParsingError("invalid action: %r" % (action,)) # Helper for _setoption() def _getcategory(category): @@ -138,7 +152,8 @@ try: cat = eval(category) except NameError: - raise _OptionError("unknown warning category: %r" % (category,)) + raise WarningsOptParsingError("unknown warning category: %r" % + (category,)) else: i = category.rfind(".") module = category[:i] @@ -146,13 +161,15 @@ try: m = __import__(module, None, None, [klass]) except ImportError: - raise _OptionError("invalid module name: %r" % (module,)) + raise WarningsOptParsingError("invalid module name: %r" % (module,)) try: cat = getattr(m, klass) except AttributeError: - raise _OptionError("unknown warning category: %r" % (category,)) + raise WarningsOptParsingError("unknown warning category: %r" % + (category,)) if not issubclass(cat, Warning): - raise _OptionError("invalid warning category: %r" % (category,)) + raise WarningsOptParsingError("invalid warning category: %r" % + (category,)) return cat