[pypy-commit] pypy kill-someobject: fix test_error, a bit by improving error messages

fijal noreply at buildbot.pypy.org
Tue Oct 9 17:58:07 CEST 2012


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: kill-someobject
Changeset: r57954:01e86a93b033
Date: 2012-10-09 17:56 +0200
http://bitbucket.org/pypy/pypy/changeset/01e86a93b033/

Log:	fix test_error, a bit by improving error messages

diff --git a/pypy/annotation/annrpython.py b/pypy/annotation/annrpython.py
--- a/pypy/annotation/annrpython.py
+++ b/pypy/annotation/annrpython.py
@@ -1,9 +1,8 @@
-import sys
 import types
-from pypy.tool.ansi_print import ansi_log, raise_nicer_exception
+from pypy.tool.ansi_print import ansi_log
 from pypy.tool.pairtype import pair
 from pypy.tool.error import (format_blocked_annotation_error,
-                             format_someobject_error, AnnotatorError)
+                             AnnotatorError, gather_error)
 from pypy.objspace.flow.model import (Variable, Constant, FunctionGraph,
                                       c_last_exception, checkgraph)
 from pypy.translator import simplify, transform
@@ -38,7 +37,7 @@
         self.links_followed = {} # set of links that have ever been followed
         self.notify = {}        # {block: {positions-to-reflow-from-when-done}}
         self.fixed_graphs = {}  # set of graphs not to annotate again
-        self.blocked_blocks = {} # set of {blocked_block: graph}
+        self.blocked_blocks = {} # set of {blocked_block: (graph, index)}
         # --- the following information is recorded for debugging ---
         self.blocked_graphs = {} # set of graphs that have blocked blocks
         # --- end of debugging information ---
@@ -341,7 +340,7 @@
             self.flowin(graph, block)
         except BlockedInference, e:
             self.annotated[block] = False   # failed, hopefully temporarily
-            self.blocked_blocks[block] = graph
+            self.blocked_blocks[block] = (graph, e.opindex)
         except Exception, e:
             # hack for debug tools only
             if not hasattr(e, '__annotator_block'):
@@ -360,7 +359,7 @@
         self.pendingblocks[block] = graph
         assert block in self.annotated
         self.annotated[block] = False  # must re-flow
-        self.blocked_blocks[block] = graph
+        self.blocked_blocks[block] = (graph, None)
 
     def bindinputargs(self, graph, block, inputcells):
         # Create the initial bindings for the input args of a block.
@@ -368,7 +367,7 @@
         for a, cell in zip(block.inputargs, inputcells):
             self.setbinding(a, cell)
         self.annotated[block] = False  # must flowin.
-        self.blocked_blocks[block] = graph
+        self.blocked_blocks[block] = (graph, None)
 
     def mergeinputargs(self, graph, block, inputcells):
         # Merge the new 'cells' with each of the block's existing input
@@ -397,7 +396,7 @@
             for i in range(len(block.operations)):
                 try:
                     self.bookkeeper.enter((graph, block, i))
-                    self.consider_op(block.operations[i])
+                    self.consider_op(block, i)
                 finally:
                     self.bookkeeper.leave()
 
@@ -573,7 +572,8 @@
 
     #___ creating the annotations based on operations ______
 
-    def consider_op(self, op):
+    def consider_op(self, block, opindex):
+        op = block.operations[opindex]
         argcells = [self.binding(a) for a in op.args]
         consider_meth = getattr(self,'consider_op_'+op.opname,
                                 None)
@@ -588,16 +588,17 @@
         # boom -- in the assert of setbinding()
         for arg in argcells:
             if isinstance(arg, annmodel.SomeImpossibleValue):
-                raise BlockedInference(self, op)
+                raise BlockedInference(self, op, opindex)
         try:
             resultcell = consider_meth(*argcells)
-        except Exception:
+        except Exception, e:
             graph = self.bookkeeper.position_key[0]
-            raise_nicer_exception(op, str(graph))
+            e.args = e.args + (gather_error(self, graph, block, opindex),)
+            raise
         if resultcell is None:
             resultcell = self.noreturnvalue(op)
         elif resultcell == annmodel.s_ImpossibleValue:
-            raise BlockedInference(self, op) # the operation cannot succeed
+            raise BlockedInference(self, op, opindex) # the operation cannot succeed
         assert isinstance(resultcell, annmodel.SomeObject)
         assert isinstance(op.result, Variable)
         self.setbinding(op.result, resultcell)  # bind resultcell to op.result
@@ -648,13 +649,14 @@
     """This exception signals the type inference engine that the situation
     is currently blocked, and that it should try to progress elsewhere."""
 
-    def __init__(self, annotator, op):
+    def __init__(self, annotator, op, opindex):
         self.annotator = annotator
         try:
             self.break_at = annotator.bookkeeper.position_key
         except AttributeError:
             self.break_at = None
         self.op = op
+        self.opindex = opindex
 
     def __repr__(self):
         if not self.break_at:
diff --git a/pypy/tool/ansi_print.py b/pypy/tool/ansi_print.py
--- a/pypy/tool/ansi_print.py
+++ b/pypy/tool/ansi_print.py
@@ -72,23 +72,3 @@
                        file=self.file, newline=newline, flush=flush)
 
 ansi_log = AnsiLog()
-
-# ____________________________________________________________
-# Nice helper
-
-def raise_nicer_exception(*extraargs):
-    cls, e, tb = sys.exc_info()
-    str_e = str(e)
-    class ExcSubclass(cls):
-        def __str__(self):
-            lines = [str_e]
-            for extra in extraargs:
-                lines.append('\t.. %r' % (extra,))
-            return '\n'.join(lines)
-    ExcSubclass.__name__ = cls.__name__ + "'"
-    ExcSubclass.__module__ = cls.__module__
-    try:
-        e.__class__ = ExcSubclass
-    except TypeError:   # doesn't work any more on 2.5 :-(
-        pass
-    raise ExcSubclass, e, tb
diff --git a/pypy/tool/error.py b/pypy/tool/error.py
--- a/pypy/tool/error.py
+++ b/pypy/tool/error.py
@@ -2,8 +2,8 @@
 """ 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
+from pypy.tool.ansi_print import ansi_log
+from pypy.objspace.flow.model import Variable
 import sys
 
 import py
@@ -15,7 +15,6 @@
 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):
@@ -71,29 +70,16 @@
 class NoSuchAttrError(Exception):
     pass
 
-def gather_error(annotator, block, graph):
-    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+def gather_error(annotator, graph, block, operindex):
     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))
+        if oper.opname == 'simple_call':
+            format_simple_call(annotator, oper, msg)
     else:
         oper = None
-        msg.append(" (inconsistency - the block is fully annotated??)")
+    msg.append(" " + str(oper))
     msg += source_lines(graph, block, operindex, long=True)
     if oper is not None:
         if SHOW_ANNOTATIONS:
@@ -104,17 +90,17 @@
                         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))
+    for block, (graph, index) in blocked_blocks.items():
+        text.append('-+' * 30)
+        text.append("Blocked block -- operation cannot succeed")
+        text.append(gather_error(annotator, graph, block, index))
     return '\n'.join(text)
 
-def format_simple_call(annotator, oper, what, msg):
+def format_simple_call(annotator, oper, msg):
     msg.append("Simple call of incompatible family:")
     try:
         descs = annotator.bindings[oper.args[0]].descriptions
@@ -147,32 +133,6 @@
         msg.append("      %s" % (r,))
         msg.append("")
 
-def format_someobject_error(annotator, position_key, what, s_value, called_from_graph, binding=""):
-    XXXXXXXXXXXXXXXXXXXXXX
-    #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,))
-    msg.append("Previous annotation:")
-    msg.append("  " + str(binding))
-    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
diff --git a/pypy/tool/test/test_error.py b/pypy/tool/test/test_error.py
--- a/pypy/tool/test/test_error.py
+++ b/pypy/tool/test/test_error.py
@@ -4,6 +4,7 @@
 
 from pypy.translator.translator import TranslationContext
 from pypy.tool.error import AnnotatorError
+from pypy.annotation.model import UnionError
 
 import py
 
@@ -37,7 +38,7 @@
             a = 9
         return a
 
-    py.test.raises(AnnotatorError, compile_function, someobject_degeneration, [int])
+    py.test.raises(UnionError, compile_function, someobject_degeneration, [int])
 
 def test_someobject2():
     def someobject_deg(n):
@@ -47,12 +48,12 @@
             return AAA()
         return a
 
-    py.test.raises(AnnotatorError, compile_function, someobject_deg, [int])
+    py.test.raises(UnionError, compile_function, someobject_deg, [int])
 
 def test_eval_someobject():
     exec("def f(n):\n if n == 2:\n  return 'a'\n else:\n  return 3")
 
-    py.test.raises(AnnotatorError, compile_function, f, [int])
+    py.test.raises(UnionError, compile_function, f, [int])
 
 def test_someobject_from_call():
     def one(x):
@@ -70,6 +71,6 @@
 
     try:
         compile_function(fn, [int])
-    except AnnotatorError, e:
-        assert 'function one' in e.args[0]
-        assert 'function two' in e.args[0]
+    except UnionError, e:
+        assert 'function one' in e.args[2]
+        assert 'function two' in e.args[2]


More information about the pypy-commit mailing list