PageRenderTime 58ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/tool/error.py

https://bitbucket.org/jpberdel/pypy
Python | 214 lines | 206 code | 6 blank | 2 comment | 16 complexity | e3d96a2f41f9254c9fb89e20cb3dfda0 MD5 | raw file
  1. """ error handling features, just a way of displaying errors
  2. """
  3. from pypy.tool.ansi_print import ansi_log, raise_nicer_exception
  4. from pypy.objspace.flow.model import Constant, Variable
  5. import sys
  6. import py
  7. log = py.log.Producer("error")
  8. py.log.setconsumer("error", ansi_log)
  9. SHOW_TRACEBACK = False
  10. SHOW_ANNOTATIONS = True
  11. SHOW_DEFAULT_LINES_OF_CODE = 0
  12. from pypy.interpreter.pytraceback import offset2lineno
  13. import traceback
  14. def source_lines1(graph, block, operindex=None, offset=None, long=False, \
  15. show_lines_of_code=SHOW_DEFAULT_LINES_OF_CODE):
  16. if block is not None:
  17. if block is graph.returnblock:
  18. return ['<return block>']
  19. try:
  20. source = graph.source
  21. except AttributeError:
  22. return ['no source!']
  23. else:
  24. graph_lines = source.split("\n")
  25. if offset is not None:
  26. linestart = offset2lineno(graph.func.func_code, offset)
  27. linerange = (linestart, linestart)
  28. here = None
  29. else:
  30. if block is None or not block.operations:
  31. return []
  32. def toline(operindex):
  33. return offset2lineno(graph.func.func_code, block.operations[operindex].offset)
  34. if operindex is None:
  35. linerange = (toline(0), toline(-1))
  36. if not long:
  37. return ['?']
  38. here = None
  39. else:
  40. operline = toline(operindex)
  41. if long:
  42. linerange = (toline(0), toline(-1))
  43. here = operline
  44. else:
  45. linerange = (operline, operline)
  46. here = None
  47. lines = ["Happened at file %s line %d" % (graph.filename, here or linerange[0]), ""]
  48. for n in range(max(0, linerange[0]-show_lines_of_code), \
  49. min(linerange[1]+1+show_lines_of_code, len(graph_lines)+graph.startline)):
  50. if n == here:
  51. prefix = '==> '
  52. else:
  53. prefix = ' '
  54. lines.append(prefix + graph_lines[n-graph.startline])
  55. lines.append("")
  56. return lines
  57. def source_lines(graph, *args, **kwds):
  58. lines = source_lines1(graph, *args, **kwds)
  59. return ['In %r:' % (graph,)] + lines
  60. class FlowingError(Exception):
  61. pass
  62. class AnnotatorError(Exception):
  63. pass
  64. class NoSuchAttrError(Exception):
  65. pass
  66. def gather_error(annotator, block, graph):
  67. msg = [""]
  68. msg.append('-+' * 30)
  69. from pypy.annotation import model
  70. msg.append("Blocked block -- operation cannot succeed")
  71. if model.DEBUG:
  72. _, _, operindex = annotator.why_not_annotated[block][1].break_at
  73. else:
  74. # guess the blocked operation by the fact that its return value is
  75. # not annotated
  76. for operindex in range(len(block.operations)):
  77. if block.operations[operindex].result not in annotator.bindings:
  78. break
  79. else:
  80. operindex = None
  81. if operindex is not None:
  82. oper = block.operations[operindex]
  83. msg.append(" " + str(oper))
  84. else:
  85. oper = None
  86. msg.append(" (inconsistency - the block is fully annotated??)")
  87. msg += source_lines(graph, block, operindex, long=True)
  88. if oper is not None:
  89. if SHOW_ANNOTATIONS:
  90. msg.append("Known variable annotations:")
  91. for arg in oper.args + [oper.result]:
  92. if isinstance(arg, Variable):
  93. try:
  94. msg.append(" " + str(arg) + " = " + str(annotator.binding(arg)))
  95. except KeyError:
  96. pass
  97. if model.DEBUG and SHOW_TRACEBACK:
  98. msg.extend(traceback.format_exception(*annotator.why_not_annotated[block]))
  99. return "\n".join(msg)
  100. def format_blocked_annotation_error(annotator, blocked_blocks):
  101. text = []
  102. for block, graph in blocked_blocks.items():
  103. text.append(gather_error(annotator, block, graph))
  104. return '\n'.join(text)
  105. def format_simple_call(annotator, oper, what, msg):
  106. msg.append("Simple call of incompatible family:")
  107. try:
  108. descs = annotator.bindings[oper.args[0]].descriptions
  109. except (KeyError, AttributeError), e:
  110. msg.append(" (%s getting at the binding!)" % (
  111. e.__class__.__name__,))
  112. return
  113. for desc in list(descs):
  114. func = desc.pyobj
  115. if func is None:
  116. r = repr(desc)
  117. else:
  118. try:
  119. if isinstance(func, type):
  120. func_name = "%s.__init__" % func.__name__
  121. func = func.__init__.im_func
  122. else:
  123. func_name = func.func_name
  124. r = "function %s <%s, line %s>" % (func_name,
  125. func.func_code.co_filename, func.func_code.co_firstlineno)
  126. except (AttributeError, TypeError):
  127. r = repr(desc)
  128. msg.append(" %s returning" % (r,))
  129. if hasattr(desc, 'getuniquegraph'):
  130. graph = desc.getuniquegraph()
  131. r = annotator.binding(graph.returnblock.inputargs[0],
  132. "(no annotation)")
  133. else:
  134. r = '?'
  135. msg.append(" %s" % (r,))
  136. msg.append("")
  137. def format_someobject_error(annotator, position_key, what, s_value, called_from_graph, binding=""):
  138. #block = getattr(annotator, 'flowin_block', None) or block
  139. msg = ["annotation of %r degenerated to SomeObject()" % (what,)]
  140. if position_key is not None:
  141. graph, block, operindex = position_key
  142. if operindex is not None:
  143. oper = block.operations[operindex]
  144. if oper.opname == 'simple_call':
  145. format_simple_call(annotator, oper, what, msg)
  146. else:
  147. msg.append(str(oper))
  148. else:
  149. msg.append("at the start of the block with input arguments:")
  150. for v in block.inputargs:
  151. s_v = annotator.binding(v, "(no annotation)")
  152. msg.append("%8s: %s" % (v, s_v))
  153. msg.append('')
  154. msg += source_lines(graph, block, operindex, long=True)
  155. if called_from_graph is not None:
  156. msg.append(".. called from %r" % (called_from_graph,))
  157. if s_value.origin is not None:
  158. msg.append(".. SomeObject() origin: %s" % (
  159. annotator.whereami(s_value.origin),))
  160. msg.append("Previous annotation:")
  161. msg.append(" " + str(binding))
  162. return "\n".join(msg)
  163. def format_global_error(graph, offset, message):
  164. msg = []
  165. msg.append('-+' * 30)
  166. msg.append(message)
  167. msg += source_lines(graph, None, offset=offset)
  168. return "\n".join(msg)
  169. def debug(drv, use_pdb=True):
  170. # XXX unify some code with pypy.translator.goal.translate
  171. from pypy.translator.tool.pdbplus import PdbPlusShow
  172. from pypy.translator.driver import log
  173. t = drv.translator
  174. class options:
  175. huge = 100
  176. tb = None
  177. import traceback
  178. errmsg = ["Error:\n"]
  179. exc, val, tb = sys.exc_info()
  180. errmsg.extend([" %s" % line for line in traceback.format_exception(exc, val, [])])
  181. block = getattr(val, '__annotator_block', None)
  182. if block:
  183. class FileLike:
  184. def write(self, s):
  185. errmsg.append(" %s" % s)
  186. errmsg.append("Processing block:\n")
  187. t.about(block, FileLike())
  188. log.ERROR(''.join(errmsg))
  189. log.event("start debugger...")
  190. if use_pdb:
  191. pdb_plus_show = PdbPlusShow(t)
  192. pdb_plus_show.start(tb)