1"""Python part of the warnings subsystem.""" 2 3# Note: function level imports should *not* be used 4# in this module as it may cause import lock deadlock. 5# See bug 683658. 6import linecache 7import sys 8import types 9 10__all__ = ["warn", "warn_explicit", "showwarning", 11 "formatwarning", "filterwarnings", "simplefilter", 12 "resetwarnings", "catch_warnings"] 13 14 15def warnpy3k(message, category=None, stacklevel=1): 16 """Issue a deprecation warning for Python 3.x related changes. 17 18 Warnings are omitted unless Python is started with the -3 option. 19 """ 20 if sys.py3kwarning: 21 if category is None: 22 category = DeprecationWarning 23 warn(message, category, stacklevel+1) 24 25def _show_warning(message, category, filename, lineno, file=None, line=None): 26 """Hook to write a warning to a file; replace if you like.""" 27 if file is None: 28 file = sys.stderr 29 if file is None: 30 # sys.stderr is None - warnings get lost 31 return 32 try: 33 file.write(formatwarning(message, category, filename, lineno, line)) 34 except (IOError, UnicodeError): 35 pass # the file (probably stderr) is invalid - this warning gets lost. 36# Keep a working version around in case the deprecation of the old API is 37# triggered. 38showwarning = _show_warning 39 40def formatwarning(message, category, filename, lineno, line=None): 41 """Function to format a warning the standard way.""" 42 try: 43 unicodetype = unicode 44 except NameError: 45 unicodetype = () 46 try: 47 message = str(message) 48 except UnicodeEncodeError: 49 pass 50 s = "%s: %s: %s\n" % (lineno, category.__name__, message) 51 line = linecache.getline(filename, lineno) if line is None else line 52 if line: 53 line = line.strip() 54 if isinstance(s, unicodetype) and isinstance(line, str): 55 line = unicode(line, 'latin1') 56 s += " %s\n" % line 57 if isinstance(s, unicodetype) and isinstance(filename, str): 58 enc = sys.getfilesystemencoding() 59 if enc: 60 try: 61 filename = unicode(filename, enc) 62 except UnicodeDecodeError: 63 pass 64 s = "%s:%s" % (filename, s) 65 return s 66 67def filterwarnings(action, message="", category=Warning, module="", lineno=0, 68 append=0): 69 """Insert an entry into the list of warnings filters (at the front). 70 71 'action' -- one of "error", "ignore", "always", "default", "module", 72 or "once" 73 'message' -- a regex that the warning message must match 74 'category' -- a class that the warning must be a subclass of 75 'module' -- a regex that the module name must match 76 'lineno' -- an integer line number, 0 matches all warnings 77 'append' -- if true, append to the list of filters 78 """ 79 import re 80 assert action in ("error", "ignore", "always", "default", "module", 81 "once"), "invalid action: %r" % (action,) 82 assert isinstance(message, basestring), "message must be a string" 83 assert isinstance(category, (type, types.ClassType)), \ 84 "category must be a class" 85 assert issubclass(category, Warning), "category must be a Warning subclass" 86 assert isinstance(module, basestring), "module must be a string" 87 assert isinstance(lineno, int) and lineno >= 0, \ 88 "lineno must be an int >= 0" 89 item = (action, re.compile(message, re.I), category, 90 re.compile(module), lineno) 91 if append: 92 filters.append(item) 93 else: 94 filters.insert(0, item) 95 96def simplefilter(action, category=Warning, lineno=0, append=0): 97 """Insert a simple entry into the list of warnings filters (at the front). 98 99 A simple filter matches all modules and messages. 100 'action' -- one of "error", "ignore", "always", "default", "module", 101 or "once" 102 'category' -- a class that the warning must be a subclass of 103 'lineno' -- an integer line number, 0 matches all warnings 104 'append' -- if true, append to the list of filters 105 """ 106 assert action in ("error", "ignore", "always", "default", "module", 107 "once"), "invalid action: %r" % (action,) 108 assert isinstance(lineno, int) and lineno >= 0, \ 109 "lineno must be an int >= 0" 110 item = (action, None, category, None, lineno) 111 if append: 112 filters.append(item) 113 else: 114 filters.insert(0, item) 115 116def resetwarnings(): 117 """Clear the list of warning filters, so that no filters are active.""" 118 filters[:] = [] 119 120class _OptionError(Exception): 121 """Exception used by option processing helpers.""" 122 pass 123 124# Helper to process -W options passed via sys.warnoptions 125def _processoptions(args): 126 for arg in args: 127 try: 128 _setoption(arg) 129 except _OptionError, msg: 130 print >>sys.stderr, "Invalid -W option ignored:", msg 131 132# Helper for _processoptions() 133def _setoption(arg): 134 import re 135 parts = arg.split(':') 136 if len(parts) > 5: 137 raise _OptionError("too many fields (max 5): %r" % (arg,)) 138 while len(parts) < 5: 139 parts.append('') 140 action, message, category, module, lineno = [s.strip() 141 for s in parts] 142 action = _getaction(action) 143 message = re.escape(message) 144 category = _getcategory(category) 145 module = re.escape(module) 146 if module: 147 module = module + '$' 148 if lineno: 149 try: 150 lineno = int(lineno) 151 if lineno < 0: 152 raise ValueError 153 except (ValueError, OverflowError): 154 raise _OptionError("invalid lineno %r" % (lineno,)) 155 else: 156 lineno = 0 157 filterwarnings(action, message, category, module, lineno) 158 159# Helper for _setoption() 160def _getaction(action): 161 if not action: 162 return "default" 163 if action == "all": return "always" # Alias 164 for a in ('default', 'always', 'ignore', 'module', 'once', 'error'): 165 if a.startswith(action): 166 return a 167 raise _OptionError("invalid action: %r" % (action,)) 168 169# Helper for _setoption() 170def _getcategory(category): 171 import re 172 if not category: 173 return Warning 174 if re.match("^[a-zA-Z0-9_]+$", category): 175 try: 176 cat = eval(category) 177 except NameError: 178 raise _OptionError("unknown warning category: %r" % (category,)) 179 else: 180 i = category.rfind(".") 181 module = category[:i] 182 klass = category[i+1:] 183 try: 184 m = __import__(module, None, None, [klass]) 185 except ImportError: 186 raise _OptionError("invalid module name: %r" % (module,)) 187 try: 188 cat = getattr(m, klass) 189 except AttributeError: 190 raise _OptionError("unknown warning category: %r" % (category,)) 191 if not issubclass(cat, Warning): 192 raise _OptionError("invalid warning category: %r" % (category,)) 193 return cat 194 195 196# Code typically replaced by _warnings 197def warn(message, category=None, stacklevel=1): 198 """Issue a warning, or maybe ignore it or raise an exception.""" 199 # Check if message is already a Warning object 200 if isinstance(message, Warning): 201 category = message.__class__ 202 # Check category argument 203 if category is None: 204 category = UserWarning 205 assert issubclass(category, Warning) 206 # Get context information 207 try: 208 caller = sys._getframe(stacklevel) 209 except ValueError: 210 globals = sys.__dict__ 211 lineno = 1 212 else: 213 globals = caller.f_globals 214 lineno = caller.f_lineno 215 if '__name__' in globals: 216 module = globals['__name__'] 217 else: 218 module = "<string>" 219 filename = globals.get('__file__') 220 if filename: 221 fnl = filename.lower() 222 if fnl.endswith((".pyc", ".pyo")): 223 filename = filename[:-1] 224 else: 225 if module == "__main__": 226 try: 227 filename = sys.argv[0] 228 except AttributeError: 229 # embedded interpreters don't have sys.argv, see bug #839151 230 filename = '__main__' 231 if not filename: 232 filename = module 233 registry = globals.setdefault("__warningregistry__", {}) 234 warn_explicit(message, category, filename, lineno, module, registry, 235 globals) 236 237def warn_explicit(message, category, filename, lineno, 238 module=None, registry=None, module_globals=None): 239 lineno = int(lineno) 240 if module is None: 241 module = filename or "<unknown>" 242 if module[-3:].lower() == ".py": 243 module = module[:-3] # XXX What about leading pathname? 244 if registry is None: 245 registry = {} 246 if isinstance(message, Warning): 247 text = str(message) 248 category = message.__class__ 249 else: 250 text = message 251 message = category(message) 252 key = (text, category, lineno) 253 # Quick test for common case 254 if registry.get(key): 255 return 256 # Search the filters 257 for item in filters: 258 action, msg, cat, mod, ln = item 259 if ((msg is None or msg.match(text)) and 260 issubclass(category, cat) and 261 (mod is None or mod.match(module)) and 262 (ln == 0 or lineno == ln)): 263 break 264 else: 265 action = defaultaction 266 # Early exit actions 267 if action == "ignore": 268 registry[key] = 1 269 return 270 271 # Prime the linecache for formatting, in case the 272 # "file" is actually in a zipfile or something. 273 linecache.getlines(filename, module_globals) 274 275 if action == "error": 276 raise message 277 # Other actions 278 if action == "once": 279 registry[key] = 1 280 oncekey = (text, category) 281 if onceregistry.get(oncekey): 282 return 283 onceregistry[oncekey] = 1 284 elif action == "always": 285 pass 286 elif action == "module": 287 registry[key] = 1 288 altkey = (text, category, 0) 289 if registry.get(altkey): 290 return 291 registry[altkey] = 1 292 elif action == "default": 293 registry[key] = 1 294 else: 295 # Unrecognized actions are errors 296 raise RuntimeError( 297 "Unrecognized action (%r) in warnings.filters:\n %s" % 298 (action, item)) 299 # Print message and context 300 showwarning(message, category, filename, lineno) 301 302 303class WarningMessage(object): 304 305 """Holds the result of a single showwarning() call.""" 306 307 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file", 308 "line") 309 310 def __init__(self, message, category, filename, lineno, file=None, 311 line=None): 312 local_values = locals() 313 for attr in self._WARNING_DETAILS: 314 setattr(self, attr, local_values[attr]) 315 self._category_name = category.__name__ if category else None 316 317 def __str__(self): 318 return ("{message : %r, category : %r, filename : %r, lineno : %s, " 319 "line : %r}" % (self.message, self._category_name, 320 self.filename, self.lineno, self.line)) 321 322 323class catch_warnings(object): 324 325 """A context manager that copies and restores the warnings filter upon 326 exiting the context. 327 328 The 'record' argument specifies whether warnings should be captured by a 329 custom implementation of warnings.showwarning() and be appended to a list 330 returned by the context manager. Otherwise None is returned by the context 331 manager. The objects appended to the list are arguments whose attributes 332 mirror the arguments to showwarning(). 333 334 The 'module' argument is to specify an alternative module to the module 335 named 'warnings' and imported under that name. This argument is only useful 336 when testing the warnings module itself. 337 338 """ 339 340 def __init__(self, record=False, module=None): 341 """Specify whether to record warnings and if an alternative module 342 should be used other than sys.modules['warnings']. 343 344 For compatibility with Python 3.0, please consider all arguments to be 345 keyword-only. 346 347 """ 348 self._record = record 349 self._module = sys.modules['warnings'] if module is None else module 350 self._entered = False 351 352 def __repr__(self): 353 args = [] 354 if self._record: 355 args.append("record=True") 356 if self._module is not sys.modules['warnings']: 357 args.append("module=%r" % self._module) 358 name = type(self).__name__ 359 return "%s(%s)" % (name, ", ".join(args)) 360 361 def __enter__(self): 362 if self._entered: 363 raise RuntimeError("Cannot enter %r twice" % self) 364 self._entered = True 365 self._filters = self._module.filters 366 self._module.filters = self._filters[:] 367 self._showwarning = self._module.showwarning 368 if self._record: 369 log = [] 370 def showwarning(*args, **kwargs): 371 log.append(WarningMessage(*args, **kwargs)) 372 self._module.showwarning = showwarning 373 return log 374 else: 375 return None 376 377 def __exit__(self, *exc_info): 378 if not self._entered: 379 raise RuntimeError("Cannot exit %r without entering first" % self) 380 self._module.filters = self._filters 381 self._module.showwarning = self._showwarning 382 383 384# filters contains a sequence of filter 5-tuples 385# The components of the 5-tuple are: 386# - an action: error, ignore, always, default, module, or once 387# - a compiled regex that must match the warning message 388# - a class representing the warning category 389# - a compiled regex that must match the module that is being warned 390# - a line number for the line being warning, or 0 to mean any line 391# If either if the compiled regexs are None, match anything. 392_warnings_defaults = False 393try: 394 from _warnings import (filters, default_action, once_registry, 395 warn, warn_explicit) 396 defaultaction = default_action 397 onceregistry = once_registry 398 _warnings_defaults = True 399except ImportError: 400 filters = [] 401 defaultaction = "default" 402 onceregistry = {} 403 404 405# Module initialization 406_processoptions(sys.warnoptions) 407if not _warnings_defaults: 408 silence = [ImportWarning, PendingDeprecationWarning] 409 # Don't silence DeprecationWarning if -3 or -Q was used. 410 if not sys.py3kwarning and not sys.flags.division_warning: 411 silence.append(DeprecationWarning) 412 for cls in silence: 413 simplefilter("ignore", category=cls) 414 bytes_warning = sys.flags.bytes_warning 415 if bytes_warning > 1: 416 bytes_action = "error" 417 elif bytes_warning: 418 bytes_action = "default" 419 else: 420 bytes_action = "ignore" 421 simplefilter(bytes_action, category=BytesWarning, append=1) 422del _warnings_defaults 423