PageRenderTime 103ms CodeModel.GetById 40ms app.highlight 18ms RepoModel.GetById 42ms app.codeStats 1ms

/pypy/tool/error.py

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