PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/tool/error.py

https://bitbucket.org/chence/pypy
Python | 204 lines | 196 code | 6 blank | 2 comment | 16 complexity | aa671f7999a6398ea480d1e28f29177b 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 AnnotatorError(Exception):
  61. pass
  62. class NoSuchAttrError(Exception):
  63. pass
  64. def gather_error(annotator, block, graph):
  65. msg = [""]
  66. msg.append('-+' * 30)
  67. from pypy.annotation import model
  68. msg.append("Blocked block -- operation cannot succeed")
  69. if model.DEBUG:
  70. _, _, operindex = annotator.why_not_annotated[block][1].break_at
  71. else:
  72. # guess the blocked operation by the fact that its return value is
  73. # not annotated
  74. for operindex in range(len(block.operations)):
  75. if block.operations[operindex].result not in annotator.bindings:
  76. break
  77. else:
  78. operindex = None
  79. if operindex is not None:
  80. oper = block.operations[operindex]
  81. msg.append(" " + str(oper))
  82. else:
  83. oper = None
  84. msg.append(" (inconsistency - the block is fully annotated??)")
  85. msg += source_lines(graph, block, operindex, long=True)
  86. if oper is not None:
  87. if SHOW_ANNOTATIONS:
  88. msg.append("Known variable annotations:")
  89. for arg in oper.args + [oper.result]:
  90. if isinstance(arg, Variable):
  91. try:
  92. msg.append(" " + str(arg) + " = " + str(annotator.binding(arg)))
  93. except KeyError:
  94. pass
  95. if model.DEBUG and SHOW_TRACEBACK:
  96. msg.extend(traceback.format_exception(*annotator.why_not_annotated[block]))
  97. return "\n".join(msg)
  98. def format_blocked_annotation_error(annotator, blocked_blocks):
  99. text = []
  100. for block, graph in blocked_blocks.items():
  101. text.append(gather_error(annotator, block, graph))
  102. return '\n'.join(text)
  103. def format_simple_call(annotator, oper, what, msg):
  104. msg.append("Simple call of incompatible family:")
  105. try:
  106. descs = annotator.bindings[oper.args[0]].descriptions
  107. except (KeyError, AttributeError), e:
  108. msg.append(" (%s getting at the binding!)" % (
  109. e.__class__.__name__,))
  110. return
  111. for desc in list(descs):
  112. func = desc.pyobj
  113. if func is None:
  114. r = repr(desc)
  115. else:
  116. try:
  117. if isinstance(func, type):
  118. func_name = "%s.__init__" % func.__name__
  119. func = func.__init__.im_func
  120. else:
  121. func_name = func.func_name
  122. r = "function %s <%s, line %s>" % (func_name,
  123. func.func_code.co_filename, func.func_code.co_firstlineno)
  124. except (AttributeError, TypeError):
  125. r = repr(desc)
  126. msg.append(" %s returning" % (r,))
  127. if hasattr(desc, 'getuniquegraph'):
  128. graph = desc.getuniquegraph()
  129. r = annotator.binding(graph.returnblock.inputargs[0],
  130. "(no annotation)")
  131. else:
  132. r = '?'
  133. msg.append(" %s" % (r,))
  134. msg.append("")
  135. def format_someobject_error(annotator, position_key, what, s_value, called_from_graph, binding=""):
  136. #block = getattr(annotator, 'flowin_block', None) or block
  137. msg = ["annotation of %r degenerated to SomeObject()" % (what,)]
  138. if position_key is not None:
  139. graph, block, operindex = position_key
  140. if operindex is not None:
  141. oper = block.operations[operindex]
  142. if oper.opname == 'simple_call':
  143. format_simple_call(annotator, oper, what, msg)
  144. else:
  145. msg.append(str(oper))
  146. else:
  147. msg.append("at the start of the block with input arguments:")
  148. for v in block.inputargs:
  149. s_v = annotator.binding(v, "(no annotation)")
  150. msg.append("%8s: %s" % (v, s_v))
  151. msg.append('')
  152. msg += source_lines(graph, block, operindex, long=True)
  153. if called_from_graph is not None:
  154. msg.append(".. called from %r" % (called_from_graph,))
  155. if s_value.origin is not None:
  156. msg.append(".. SomeObject() origin: %s" % (
  157. annotator.whereami(s_value.origin),))
  158. msg.append("Previous annotation:")
  159. msg.append(" " + str(binding))
  160. return "\n".join(msg)
  161. def debug(drv, use_pdb=True):
  162. # XXX unify some code with pypy.translator.goal.translate
  163. from pypy.translator.tool.pdbplus import PdbPlusShow
  164. from pypy.translator.driver import log
  165. t = drv.translator
  166. class options:
  167. huge = 100
  168. tb = None
  169. import traceback
  170. errmsg = ["Error:\n"]
  171. exc, val, tb = sys.exc_info()
  172. errmsg.extend([" %s" % line for line in traceback.format_exception(exc, val, [])])
  173. block = getattr(val, '__annotator_block', None)
  174. if block:
  175. class FileLike:
  176. def write(self, s):
  177. errmsg.append(" %s" % s)
  178. errmsg.append("Processing block:\n")
  179. t.about(block, FileLike())
  180. log.ERROR(''.join(errmsg))
  181. log.event("start debugger...")
  182. if use_pdb:
  183. pdb_plus_show = PdbPlusShow(t)
  184. pdb_plus_show.start(tb)