PageRenderTime 53ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/rpython/tool/error.py

https://bitbucket.org/kkris/pypy
Python | 173 lines | 166 code | 5 blank | 2 comment | 15 complexity | e77d71ae622f80e3d3dac979cdeff2d4 MD5 | raw file
  1. """ error handling features, just a way of displaying errors
  2. """
  3. from rpython.tool.ansi_print import ansi_log
  4. from rpython.flowspace.model import 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. def source_lines1(graph, block, operindex=None, offset=None, long=False, \
  13. show_lines_of_code=SHOW_DEFAULT_LINES_OF_CODE):
  14. if block is not None:
  15. if block is graph.returnblock:
  16. return ['<return block>']
  17. try:
  18. source = graph.source
  19. except AttributeError:
  20. return ['no source!']
  21. else:
  22. graph_lines = source.split("\n")
  23. if offset is not None:
  24. linestart = offset2lineno(graph.func.func_code, offset)
  25. linerange = (linestart, linestart)
  26. here = None
  27. else:
  28. if block is None or not block.operations:
  29. return []
  30. def toline(operindex):
  31. return offset2lineno(graph.func.func_code, block.operations[operindex].offset)
  32. if operindex is None:
  33. linerange = (toline(0), toline(-1))
  34. if not long:
  35. return ['?']
  36. here = None
  37. else:
  38. operline = toline(operindex)
  39. if long:
  40. linerange = (toline(0), toline(-1))
  41. here = operline
  42. else:
  43. linerange = (operline, operline)
  44. here = None
  45. lines = ["Happened at file %s line %d" % (graph.filename, here or linerange[0]), ""]
  46. for n in range(max(0, linerange[0]-show_lines_of_code), \
  47. min(linerange[1]+1+show_lines_of_code, len(graph_lines)+graph.startline)):
  48. if n == here:
  49. prefix = '==> '
  50. else:
  51. prefix = ' '
  52. lines.append(prefix + graph_lines[n-graph.startline])
  53. lines.append("")
  54. return lines
  55. def source_lines(graph, *args, **kwds):
  56. lines = source_lines1(graph, *args, **kwds)
  57. return ['In %r:' % (graph,)] + lines
  58. class AnnotatorError(Exception):
  59. pass
  60. class NoSuchAttrError(Exception):
  61. pass
  62. class ErrorWrapper(object):
  63. def __init__(self, msg):
  64. self.msg = msg
  65. def __repr__(self):
  66. return '<%s>' % (self.msg,)
  67. def gather_error(annotator, graph, block, operindex):
  68. msg = [""]
  69. if operindex is not None:
  70. oper = block.operations[operindex]
  71. if oper.opname == 'simple_call':
  72. format_simple_call(annotator, oper, msg)
  73. else:
  74. oper = None
  75. msg.append(" " + str(oper))
  76. msg += source_lines(graph, block, operindex, long=True)
  77. if oper is not None:
  78. if SHOW_ANNOTATIONS:
  79. msg.append("Known variable annotations:")
  80. for arg in oper.args + [oper.result]:
  81. if isinstance(arg, Variable):
  82. try:
  83. msg.append(" " + str(arg) + " = " + str(annotator.binding(arg)))
  84. except KeyError:
  85. pass
  86. return "\n".join(msg)
  87. def format_blocked_annotation_error(annotator, blocked_blocks):
  88. text = []
  89. for block, (graph, index) in blocked_blocks.items():
  90. text.append('-+' * 30)
  91. text.append("Blocked block -- operation cannot succeed")
  92. text.append(gather_error(annotator, graph, block, index))
  93. return '\n'.join(text)
  94. def format_simple_call(annotator, oper, msg):
  95. msg.append("Occurred processing the following simple_call:")
  96. try:
  97. descs = annotator.bindings[oper.args[0]].descriptions
  98. except (KeyError, AttributeError), e:
  99. msg.append(" (%s getting at the binding!)" % (
  100. e.__class__.__name__,))
  101. return
  102. for desc in list(descs):
  103. func = desc.pyobj
  104. if func is None:
  105. r = repr(desc)
  106. else:
  107. try:
  108. if isinstance(func, type):
  109. func_name = "%s.__init__" % func.__name__
  110. func = func.__init__.im_func
  111. else:
  112. func_name = func.func_name
  113. r = "function %s <%s, line %s>" % (func_name,
  114. func.func_code.co_filename, func.func_code.co_firstlineno)
  115. except (AttributeError, TypeError):
  116. r = repr(desc)
  117. msg.append(" %s returning" % (r,))
  118. msg.append("")
  119. def debug(drv, use_pdb=True):
  120. # XXX unify some code with rpython.translator.goal.translate
  121. from rpython.translator.tool.pdbplus import PdbPlusShow
  122. from rpython.translator.driver import log
  123. t = drv.translator
  124. class options:
  125. huge = 100
  126. tb = None
  127. import traceback
  128. errmsg = ["Error:\n"]
  129. exc, val, tb = sys.exc_info()
  130. errmsg.extend([" %s" % line for line in traceback.format_exception(exc, val, [])])
  131. block = getattr(val, '__annotator_block', None)
  132. if block:
  133. class FileLike:
  134. def write(self, s):
  135. errmsg.append(" %s" % s)
  136. errmsg.append("Processing block:\n")
  137. t.about(block, FileLike())
  138. log.ERROR(''.join(errmsg))
  139. log.event("start debugger...")
  140. if use_pdb:
  141. pdb_plus_show = PdbPlusShow(t)
  142. pdb_plus_show.start(tb)
  143. def offset2lineno(c, stopat):
  144. tab = c.co_lnotab
  145. line = c.co_firstlineno
  146. addr = 0
  147. for i in range(0, len(tab), 2):
  148. addr = addr + ord(tab[i])
  149. if addr > stopat:
  150. break
  151. line = line + ord(tab[i+1])
  152. return line