PageRenderTime 41ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/Python/system/warnings.py

https://bitbucket.org/cwalther/moulscript-dlanor
Python | 259 lines | 227 code | 8 blank | 24 comment | 38 complexity | 5ae223c405b8f51e1bfe609f9b32d76b MD5 | raw file
Possible License(s): AGPL-1.0, GPL-3.0
  1. """Python part of the warnings subsystem."""
  2. # Note: function level imports should *not* be used
  3. # in this module as it may cause import lock deadlock.
  4. # See bug 683658.
  5. import sys, types
  6. import linecache
  7. __all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
  8. "resetwarnings"]
  9. # filters contains a sequence of filter 5-tuples
  10. # The components of the 5-tuple are:
  11. # - an action: error, ignore, always, default, module, or once
  12. # - a compiled regex that must match the warning message
  13. # - a class representing the warning category
  14. # - a compiled regex that must match the module that is being warned
  15. # - a line number for the line being warning, or 0 to mean any line
  16. # If either if the compiled regexs are None, match anything.
  17. filters = []
  18. defaultaction = "default"
  19. onceregistry = {}
  20. def warn(message, category=None, stacklevel=1):
  21. """Issue a warning, or maybe ignore it or raise an exception."""
  22. # Check if message is already a Warning object
  23. if isinstance(message, Warning):
  24. category = message.__class__
  25. # Check category argument
  26. if category is None:
  27. category = UserWarning
  28. assert issubclass(category, Warning)
  29. # Get context information
  30. try:
  31. caller = sys._getframe(stacklevel)
  32. except ValueError:
  33. globals = sys.__dict__
  34. lineno = 1
  35. else:
  36. globals = caller.f_globals
  37. lineno = caller.f_lineno
  38. if '__name__' in globals:
  39. module = globals['__name__']
  40. else:
  41. module = "<string>"
  42. filename = globals.get('__file__')
  43. if filename:
  44. fnl = filename.lower()
  45. if fnl.endswith(".pyc") or fnl.endswith(".pyo"):
  46. filename = filename[:-1]
  47. else:
  48. if module == "__main__":
  49. filename = sys.argv[0]
  50. if not filename:
  51. filename = module
  52. registry = globals.setdefault("__warningregistry__", {})
  53. warn_explicit(message, category, filename, lineno, module, registry)
  54. def warn_explicit(message, category, filename, lineno,
  55. module=None, registry=None):
  56. if module is None:
  57. module = filename
  58. if module[-3:].lower() == ".py":
  59. module = module[:-3] # XXX What about leading pathname?
  60. if registry is None:
  61. registry = {}
  62. if isinstance(message, Warning):
  63. text = str(message)
  64. category = message.__class__
  65. else:
  66. text = message
  67. message = category(message)
  68. key = (text, category, lineno)
  69. # Quick test for common case
  70. if registry.get(key):
  71. return
  72. # Search the filters
  73. for item in filters:
  74. action, msg, cat, mod, ln = item
  75. if ((msg is None or msg.match(text)) and
  76. issubclass(category, cat) and
  77. (msg is None or mod.match(module)) and
  78. (ln == 0 or lineno == ln)):
  79. break
  80. else:
  81. action = defaultaction
  82. # Early exit actions
  83. if action == "ignore":
  84. registry[key] = 1
  85. return
  86. if action == "error":
  87. raise message
  88. # Other actions
  89. if action == "once":
  90. registry[key] = 1
  91. oncekey = (text, category)
  92. if onceregistry.get(oncekey):
  93. return
  94. onceregistry[oncekey] = 1
  95. elif action == "always":
  96. pass
  97. elif action == "module":
  98. registry[key] = 1
  99. altkey = (text, category, 0)
  100. if registry.get(altkey):
  101. return
  102. registry[altkey] = 1
  103. elif action == "default":
  104. registry[key] = 1
  105. else:
  106. # Unrecognized actions are errors
  107. raise RuntimeError(
  108. "Unrecognized action (%s) in warnings.filters:\n %s" %
  109. (`action`, str(item)))
  110. # Print message and context
  111. showwarning(message, category, filename, lineno)
  112. def showwarning(message, category, filename, lineno, file=None):
  113. """Hook to write a warning to a file; replace if you like."""
  114. if file is None:
  115. file = sys.stderr
  116. try:
  117. file.write(formatwarning(message, category, filename, lineno))
  118. except IOError:
  119. pass # the file (probably stderr) is invalid - this warning gets lost.
  120. def formatwarning(message, category, filename, lineno):
  121. """Function to format a warning the standard way."""
  122. s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
  123. line = linecache.getline(filename, lineno).strip()
  124. if line:
  125. s = s + " " + line + "\n"
  126. return s
  127. def filterwarnings(action, message="", category=Warning, module="", lineno=0,
  128. append=0):
  129. """Insert an entry into the list of warnings filters (at the front).
  130. Use assertions to check that all arguments have the right type."""
  131. import re
  132. assert action in ("error", "ignore", "always", "default", "module",
  133. "once"), "invalid action: %s" % `action`
  134. assert isinstance(message, basestring), "message must be a string"
  135. assert isinstance(category, types.ClassType), "category must be a class"
  136. assert issubclass(category, Warning), "category must be a Warning subclass"
  137. assert isinstance(module, basestring), "module must be a string"
  138. assert isinstance(lineno, int) and lineno >= 0, \
  139. "lineno must be an int >= 0"
  140. item = (action, re.compile(message, re.I), category,
  141. re.compile(module), lineno)
  142. if append:
  143. filters.append(item)
  144. else:
  145. filters.insert(0, item)
  146. def simplefilter(action, category=Warning, lineno=0, append=0):
  147. """Insert a simple entry into the list of warnings filters (at the front).
  148. A simple filter matches all modules and messages.
  149. """
  150. assert action in ("error", "ignore", "always", "default", "module",
  151. "once"), "invalid action: %s" % `action`
  152. assert isinstance(lineno, int) and lineno >= 0, \
  153. "lineno must be an int >= 0"
  154. item = (action, None, category, None, lineno)
  155. if append:
  156. filters.append(item)
  157. else:
  158. filters.insert(0, item)
  159. def resetwarnings():
  160. """Clear the list of warning filters, so that no filters are active."""
  161. filters[:] = []
  162. class _OptionError(Exception):
  163. """Exception used by option processing helpers."""
  164. pass
  165. # Helper to process -W options passed via sys.warnoptions
  166. def _processoptions(args):
  167. for arg in args:
  168. try:
  169. _setoption(arg)
  170. except _OptionError, msg:
  171. print >>sys.stderr, "Invalid -W option ignored:", msg
  172. # Helper for _processoptions()
  173. def _setoption(arg):
  174. import re
  175. parts = arg.split(':')
  176. if len(parts) > 5:
  177. raise _OptionError("too many fields (max 5): %s" % `arg`)
  178. while len(parts) < 5:
  179. parts.append('')
  180. action, message, category, module, lineno = [s.strip()
  181. for s in parts]
  182. action = _getaction(action)
  183. message = re.escape(message)
  184. category = _getcategory(category)
  185. module = re.escape(module)
  186. if module:
  187. module = module + '$'
  188. if lineno:
  189. try:
  190. lineno = int(lineno)
  191. if lineno < 0:
  192. raise ValueError
  193. except (ValueError, OverflowError):
  194. raise _OptionError("invalid lineno %s" % `lineno`)
  195. else:
  196. lineno = 0
  197. filterwarnings(action, message, category, module, lineno)
  198. # Helper for _setoption()
  199. def _getaction(action):
  200. if not action:
  201. return "default"
  202. if action == "all": return "always" # Alias
  203. for a in ['default', 'always', 'ignore', 'module', 'once', 'error']:
  204. if a.startswith(action):
  205. return a
  206. raise _OptionError("invalid action: %s" % `action`)
  207. # Helper for _setoption()
  208. def _getcategory(category):
  209. import re
  210. if not category:
  211. return Warning
  212. if re.match("^[a-zA-Z0-9_]+$", category):
  213. try:
  214. cat = eval(category)
  215. except NameError:
  216. raise _OptionError("unknown warning category: %s" % `category`)
  217. else:
  218. i = category.rfind(".")
  219. module = category[:i]
  220. klass = category[i+1:]
  221. try:
  222. m = __import__(module, None, None, [klass])
  223. except ImportError:
  224. raise _OptionError("invalid module name: %s" % `module`)
  225. try:
  226. cat = getattr(m, klass)
  227. except AttributeError:
  228. raise _OptionError("unknown warning category: %s" % `category`)
  229. if (not isinstance(cat, types.ClassType) or
  230. not issubclass(cat, Warning)):
  231. raise _OptionError("invalid warning category: %s" % `category`)
  232. return cat
  233. # Module initialization
  234. if __name__ == "__main__":
  235. import __main__
  236. sys.modules['warnings'] = __main__
  237. _test()
  238. else:
  239. _processoptions(sys.warnoptions)
  240. simplefilter("ignore", category=OverflowWarning, append=1)
  241. simplefilter("ignore", category=PendingDeprecationWarning, append=1)