PageRenderTime 194ms CodeModel.GetById 101ms app.highlight 17ms RepoModel.GetById 73ms app.codeStats 1ms

/rpython/tool/error.py

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