/pypy/tool/error.py
Python | 214 lines | 206 code | 6 blank | 2 comment | 16 complexity | e3d96a2f41f9254c9fb89e20cb3dfda0 MD5 | raw file
- """ error handling features, just a way of displaying errors
- """
- from pypy.tool.ansi_print import ansi_log, raise_nicer_exception
- from pypy.objspace.flow.model import Constant, Variable
- import sys
- import py
- log = py.log.Producer("error")
- py.log.setconsumer("error", ansi_log)
- SHOW_TRACEBACK = False
- SHOW_ANNOTATIONS = True
- SHOW_DEFAULT_LINES_OF_CODE = 0
- from pypy.interpreter.pytraceback import offset2lineno
- import traceback
- def source_lines1(graph, block, operindex=None, offset=None, long=False, \
- show_lines_of_code=SHOW_DEFAULT_LINES_OF_CODE):
- if block is not None:
- if block is graph.returnblock:
- return ['<return block>']
- try:
- source = graph.source
- except AttributeError:
- return ['no source!']
- else:
- graph_lines = source.split("\n")
- if offset is not None:
- linestart = offset2lineno(graph.func.func_code, offset)
- linerange = (linestart, linestart)
- here = None
- else:
- if block is None or not block.operations:
- return []
- def toline(operindex):
- return offset2lineno(graph.func.func_code, block.operations[operindex].offset)
- if operindex is None:
- linerange = (toline(0), toline(-1))
- if not long:
- return ['?']
- here = None
- else:
- operline = toline(operindex)
- if long:
- linerange = (toline(0), toline(-1))
- here = operline
- else:
- linerange = (operline, operline)
- here = None
- lines = ["Happened at file %s line %d" % (graph.filename, here or linerange[0]), ""]
- for n in range(max(0, linerange[0]-show_lines_of_code), \
- min(linerange[1]+1+show_lines_of_code, len(graph_lines)+graph.startline)):
- if n == here:
- prefix = '==> '
- else:
- prefix = ' '
- lines.append(prefix + graph_lines[n-graph.startline])
- lines.append("")
- return lines
- def source_lines(graph, *args, **kwds):
- lines = source_lines1(graph, *args, **kwds)
- return ['In %r:' % (graph,)] + lines
- class FlowingError(Exception):
- pass
- class AnnotatorError(Exception):
- pass
- class NoSuchAttrError(Exception):
- pass
- def gather_error(annotator, block, graph):
- msg = [""]
- msg.append('-+' * 30)
- from pypy.annotation import model
- msg.append("Blocked block -- operation cannot succeed")
- if model.DEBUG:
- _, _, operindex = annotator.why_not_annotated[block][1].break_at
- else:
- # guess the blocked operation by the fact that its return value is
- # not annotated
- for operindex in range(len(block.operations)):
- if block.operations[operindex].result not in annotator.bindings:
- break
- else:
- operindex = None
- if operindex is not None:
- oper = block.operations[operindex]
- msg.append(" " + str(oper))
- else:
- oper = None
- msg.append(" (inconsistency - the block is fully annotated??)")
- msg += source_lines(graph, block, operindex, long=True)
- if oper is not None:
- if SHOW_ANNOTATIONS:
- msg.append("Known variable annotations:")
- for arg in oper.args + [oper.result]:
- if isinstance(arg, Variable):
- try:
- msg.append(" " + str(arg) + " = " + str(annotator.binding(arg)))
- except KeyError:
- pass
- if model.DEBUG and SHOW_TRACEBACK:
- msg.extend(traceback.format_exception(*annotator.why_not_annotated[block]))
- return "\n".join(msg)
- def format_blocked_annotation_error(annotator, blocked_blocks):
- text = []
- for block, graph in blocked_blocks.items():
- text.append(gather_error(annotator, block, graph))
- return '\n'.join(text)
- def format_simple_call(annotator, oper, what, msg):
- msg.append("Simple call of incompatible family:")
- try:
- descs = annotator.bindings[oper.args[0]].descriptions
- except (KeyError, AttributeError), e:
- msg.append(" (%s getting at the binding!)" % (
- e.__class__.__name__,))
- return
- for desc in list(descs):
- func = desc.pyobj
- if func is None:
- r = repr(desc)
- else:
- try:
- if isinstance(func, type):
- func_name = "%s.__init__" % func.__name__
- func = func.__init__.im_func
- else:
- func_name = func.func_name
- r = "function %s <%s, line %s>" % (func_name,
- func.func_code.co_filename, func.func_code.co_firstlineno)
- except (AttributeError, TypeError):
- r = repr(desc)
- msg.append(" %s returning" % (r,))
- if hasattr(desc, 'getuniquegraph'):
- graph = desc.getuniquegraph()
- r = annotator.binding(graph.returnblock.inputargs[0],
- "(no annotation)")
- else:
- r = '?'
- msg.append(" %s" % (r,))
- msg.append("")
- def format_someobject_error(annotator, position_key, what, s_value, called_from_graph, binding=""):
- #block = getattr(annotator, 'flowin_block', None) or block
- msg = ["annotation of %r degenerated to SomeObject()" % (what,)]
- if position_key is not None:
- graph, block, operindex = position_key
- if operindex is not None:
- oper = block.operations[operindex]
- if oper.opname == 'simple_call':
- format_simple_call(annotator, oper, what, msg)
- else:
- msg.append(str(oper))
- else:
- msg.append("at the start of the block with input arguments:")
- for v in block.inputargs:
- s_v = annotator.binding(v, "(no annotation)")
- msg.append("%8s: %s" % (v, s_v))
- msg.append('')
- msg += source_lines(graph, block, operindex, long=True)
- if called_from_graph is not None:
- msg.append(".. called from %r" % (called_from_graph,))
- if s_value.origin is not None:
- msg.append(".. SomeObject() origin: %s" % (
- annotator.whereami(s_value.origin),))
- msg.append("Previous annotation:")
- msg.append(" " + str(binding))
- return "\n".join(msg)
- def format_global_error(graph, offset, message):
- msg = []
- msg.append('-+' * 30)
- msg.append(message)
- msg += source_lines(graph, None, offset=offset)
- return "\n".join(msg)
- def debug(drv, use_pdb=True):
- # XXX unify some code with pypy.translator.goal.translate
- from pypy.translator.tool.pdbplus import PdbPlusShow
- from pypy.translator.driver import log
- t = drv.translator
- class options:
- huge = 100
- tb = None
- import traceback
- errmsg = ["Error:\n"]
- exc, val, tb = sys.exc_info()
- errmsg.extend([" %s" % line for line in traceback.format_exception(exc, val, [])])
- block = getattr(val, '__annotator_block', None)
- if block:
- class FileLike:
- def write(self, s):
- errmsg.append(" %s" % s)
- errmsg.append("Processing block:\n")
- t.about(block, FileLike())
- log.ERROR(''.join(errmsg))
- log.event("start debugger...")
- if use_pdb:
- pdb_plus_show = PdbPlusShow(t)
- pdb_plus_show.start(tb)