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, long)) and lineno >= 0, \ 88 "lineno must be an int >= 0" 89 item = (action, re.compile(message, re.I), category, 90 re.compile(module), int(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, long)) and lineno >= 0, \ 109 "lineno must be an int >= 0" 110 item = (action, None, category, None, int(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 self.message = message 313 self.category = category 314 self.filename = filename 315 self.lineno = lineno 316 self.file = file 317 self.line = line 318 self._category_name = category.__name__ if category else None 319 320 def __str__(self): 321 return ("{message : %r, category : %r, filename : %r, lineno : %s, " 322 "line : %r}" % (self.message, self._category_name, 323 self.filename, self.lineno, self.line)) 324 325 326class catch_warnings(object): 327 328 """A context manager that copies and restores the warnings filter upon 329 exiting the context. 330 331 The 'record' argument specifies whether warnings should be captured by a 332 custom implementation of warnings.showwarning() and be appended to a list 333 returned by the context manager. Otherwise None is returned by the context 334 manager. The objects appended to the list are arguments whose attributes 335 mirror the arguments to showwarning(). 336 337 The 'module' argument is to specify an alternative module to the module 338 named 'warnings' and imported under that name. This argument is only useful 339 when testing the warnings module itself. 340 341 """ 342 343 def __init__(self, record=False, module=None): 344 """Specify whether to record warnings and if an alternative module 345 should be used other than sys.modules['warnings']. 346 347 For compatibility with Python 3.0, please consider all arguments to be 348 keyword-only. 349 350 """ 351 self._record = record 352 self._module = sys.modules['warnings'] if module is None else module 353 self._entered = False 354 355 def __repr__(self): 356 args = [] 357 if self._record: 358 args.append("record=True") 359 if self._module is not sys.modules['warnings']: 360 args.append("module=%r" % self._module) 361 name = type(self).__name__ 362 return "%s(%s)" % (name, ", ".join(args)) 363 364 def __enter__(self): 365 if self._entered: 366 raise RuntimeError("Cannot enter %r twice" % self) 367 self._entered = True 368 self._filters = self._module.filters 369 self._module.filters = self._filters[:] 370 self._showwarning = self._module.showwarning 371 if self._record: 372 log = [] 373 def showwarning(*args, **kwargs): 374 log.append(WarningMessage(*args, **kwargs)) 375 self._module.showwarning = showwarning 376 return log 377 else: 378 return None 379 380 def __exit__(self, *exc_info): 381 if not self._entered: 382 raise RuntimeError("Cannot exit %r without entering first" % self) 383 self._module.filters = self._filters 384 self._module.showwarning = self._showwarning 385 386 387# filters contains a sequence of filter 5-tuples 388# The components of the 5-tuple are: 389# - an action: error, ignore, always, default, module, or once 390# - a compiled regex that must match the warning message 391# - a class representing the warning category 392# - a compiled regex that must match the module that is being warned 393# - a line number for the line being warning, or 0 to mean any line 394# If either if the compiled regexs are None, match anything. 395_warnings_defaults = False 396try: 397 from _warnings import (filters, default_action, once_registry, 398 warn, warn_explicit) 399 defaultaction = default_action 400 onceregistry = once_registry 401 _warnings_defaults = True 402except ImportError: 403 filters = [] 404 defaultaction = "default" 405 onceregistry = {} 406 407 408# Module initialization 409_processoptions(sys.warnoptions) 410if not _warnings_defaults: 411 silence = [ImportWarning, PendingDeprecationWarning] 412 # Don't silence DeprecationWarning if -3 or -Q was used. 413 if not sys.py3kwarning and not sys.flags.division_warning: 414 silence.append(DeprecationWarning) 415 for cls in silence: 416 simplefilter("ignore", category=cls) 417 bytes_warning = sys.flags.bytes_warning 418 if bytes_warning > 1: 419 bytes_action = "error" 420 elif bytes_warning: 421 bytes_action = "default" 422 else: 423 bytes_action = "ignore" 424 simplefilter(bytes_action, category=BytesWarning, append=1) 425del _warnings_defaults 426