[pypy-commit] pypy reflowing: hg merge default

rlamy pypy.commits at gmail.com
Thu Nov 24 13:19:57 EST 2016


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: reflowing
Changeset: r88645:9b3564c820ef
Date: 2016-11-24 06:07 +0000
http://bitbucket.org/pypy/pypy/changeset/9b3564c820ef/

Log:	hg merge default

diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -111,7 +111,9 @@
                 self.keywords = self.keywords + keywords
                 self.keywords_w = self.keywords_w + values_w
             return
+        is_dict = False
         if space.isinstance_w(w_starstararg, space.w_dict):
+            is_dict = True
             keys_w = space.unpackiterable(w_starstararg)
         else:
             try:
@@ -125,7 +127,9 @@
             keys_w = space.unpackiterable(w_keys)
         keywords_w = [None] * len(keys_w)
         keywords = [None] * len(keys_w)
-        _do_combine_starstarargs_wrapped(space, keys_w, w_starstararg, keywords, keywords_w, self.keywords)
+        _do_combine_starstarargs_wrapped(
+            space, keys_w, w_starstararg, keywords, keywords_w, self.keywords,
+            is_dict)
         self.keyword_names_w = keys_w
         if self.keywords is None:
             self.keywords = keywords
@@ -355,7 +359,7 @@
                             key)
 
 def _do_combine_starstarargs_wrapped(space, keys_w, w_starstararg, keywords,
-        keywords_w, existingkeywords):
+        keywords_w, existingkeywords, is_dict):
     i = 0
     for w_key in keys_w:
         try:
@@ -374,7 +378,16 @@
                             "got multiple values for keyword argument '%s'",
                             key)
         keywords[i] = key
-        keywords_w[i] = space.getitem(w_starstararg, w_key)
+        if is_dict:
+            # issue 2435: bug-to-bug compatibility with cpython. for a subclass of
+            # dict, just ignore the __getitem__ and access the underlying dict
+            # directly
+            from pypy.objspace.descroperation import dict_getitem
+            w_descr = dict_getitem(space)
+            w_value = space.get_and_call_function(w_descr, w_starstararg, w_key)
+        else:
+            w_value = space.getitem(w_starstararg, w_key)
+        keywords_w[i] = w_value
         i += 1
 
 @jit.look_inside_iff(
diff --git a/pypy/interpreter/test/test_argument.py b/pypy/interpreter/test/test_argument.py
--- a/pypy/interpreter/test/test_argument.py
+++ b/pypy/interpreter/test/test_argument.py
@@ -120,6 +120,12 @@
             raise OperationError(AttributeError, name)
         return method(*args)
 
+    def lookup_in_type_where(self, cls, name):
+        return 'hopefully not needed', getattr(cls, name)
+
+    def get_and_call_function(self, w_descr, w_obj, *args):
+        return w_descr.__get__(w_obj)(*args)
+
     def type(self, obj):
         class Type:
             def getname(self, space):
@@ -805,3 +811,19 @@
             assert str(e) == "myerror"
         else:
             assert False, "Expected TypeError"
+
+    def test_dict_subclass_with_weird_getitem(self):
+        # issue 2435: bug-to-bug compatibility with cpython. for a subclass of
+        # dict, just ignore the __getitem__ and behave like ext_do_call in ceval.c
+        # which just uses the underlying dict
+        class d(dict):
+            def __getitem__(self, key):
+                return key
+
+        for key in ["foo", u"foo"]:
+            q = d()
+            q[key] = "bar"
+
+            def test(**kwargs):
+                return kwargs
+            assert test(**q) == {"foo": "bar"}
diff --git a/pypy/module/_file/interp_file.py b/pypy/module/_file/interp_file.py
--- a/pypy/module/_file/interp_file.py
+++ b/pypy/module/_file/interp_file.py
@@ -495,11 +495,10 @@
             if space.isinstance_w(w_data, space.w_unicode):
                 # note: "encode" is called before we acquire the lock
                 # for this file, which is done in file_write_str().
-                # Direct access to unicodeobject because we don't want
+                # Use a specific space method because we don't want
                 # to call user-defined "encode" methods here.
-                from pypy.objspace.std.unicodeobject import encode_object
-                w_data = encode_object(space, w_data, self.encoding,
-                                       self.errors)
+                w_data = space.encode_unicode_object(w_data,
+                     self.encoding, self.errors)
             data = space.charbuf_w(w_data)
         self.file_write_str(data)
 
diff --git a/pypy/module/bz2/interp_bz2.py b/pypy/module/bz2/interp_bz2.py
--- a/pypy/module/bz2/interp_bz2.py
+++ b/pypy/module/bz2/interp_bz2.py
@@ -293,7 +293,7 @@
 same_attributes_as_in_file.remove('__init__')
 same_attributes_as_in_file.extend([
     'name', 'mode', 'encoding', 'closed', 'newlines', 'softspace',
-    'writelines', '__exit__', '__weakref__'])
+    'writelines', '__exit__', '__weakref__', 'write'])
 
 W_BZ2File.typedef = TypeDef(
     "BZ2File",
diff --git a/pypy/module/cpyext/dictobject.py b/pypy/module/cpyext/dictobject.py
--- a/pypy/module/cpyext/dictobject.py
+++ b/pypy/module/cpyext/dictobject.py
@@ -137,8 +137,7 @@
     """This is the same as PyDict_Merge(a, b, 1) in C, or a.update(b) in
     Python.  Return 0 on success or -1 if an exception was raised.
     """
-    space.call_method(space.w_dict, "update", w_obj, w_other)
-    return 0
+    return PyDict_Merge(space, w_obj, w_other, 1)
 
 @cpython_api([PyObject], PyObject)
 def PyDict_Keys(space, w_obj):
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -252,7 +252,10 @@
 def PyObject_Format(space, w_obj, w_format_spec):
     if w_format_spec is None:
         w_format_spec = space.wrap('')
-    return space.call_method(w_obj, '__format__', w_format_spec)
+    w_ret = space.call_method(w_obj, '__format__', w_format_spec)
+    if space.isinstance_w(w_format_spec, space.w_unicode):
+        return space.unicode_from_object(w_ret)
+    return w_ret
 
 @cpython_api([PyObject], PyObject)
 def PyObject_Unicode(space, w_obj):
diff --git a/pypy/module/cpyext/test/test_dictobject.py b/pypy/module/cpyext/test/test_dictobject.py
--- a/pypy/module/cpyext/test/test_dictobject.py
+++ b/pypy/module/cpyext/test/test_dictobject.py
@@ -103,6 +103,17 @@
         api.PyDict_Update(w_d, w_d2)
         assert space.unwrap(w_d) == dict(a='b', c='d', e='f')
 
+    def test_update_doesnt_accept_list_of_tuples(self, space, api):
+        w_d = space.newdict()
+        space.setitem(w_d, space.wrap("a"), space.wrap("b"))
+
+        w_d2 = space.wrap([("c", "d"), ("e", "f")])
+
+        api.PyDict_Update(w_d, w_d2)
+        assert api.PyErr_Occurred() is space.w_AttributeError
+        api.PyErr_Clear()
+        assert space.unwrap(w_d) == dict(a='b') # unchanged
+
     def test_iter(self, space, api):
         w_dict = space.sys.getdict(space)
         py_dict = make_ref(space, w_dict)
@@ -199,3 +210,18 @@
              """),
             ])
         assert module.dict_proxy({'a': 1, 'b': 2}) == 2
+
+    def test_update(self):
+        module = self.import_extension('foo', [
+            ("update", "METH_VARARGS",
+             '''
+             if (PyDict_Update(PyTuple_GetItem(args, 0), PyTuple_GetItem(args, 1)))
+                return NULL;
+             Py_RETURN_NONE;
+             ''')])
+        d = {"a": 1}
+        module.update(d, {"c": 2})
+        assert d == dict(a=1, c=2)
+        d = {"a": 1}
+        raises(AttributeError, module.update, d, [("c", 2)])
+
diff --git a/pypy/module/cpyext/test/test_object.py b/pypy/module/cpyext/test/test_object.py
--- a/pypy/module/cpyext/test/test_object.py
+++ b/pypy/module/cpyext/test/test_object.py
@@ -312,6 +312,16 @@
         assert isinstance(dict(), collections.Mapping)
         assert module.ismapping(dict())
 
+    def test_format_returns_unicode(self):
+        module = self.import_extension('foo', [
+            ("empty_format", "METH_O",
+            """
+                PyObject* empty_unicode = PyUnicode_FromStringAndSize("", 0);
+                PyObject* obj = PyObject_Format(args, empty_unicode);
+                return obj;
+            """)])
+        a = module.empty_format('hello')
+        assert isinstance(a, unicode)
 
 class AppTestPyBuffer_FillInfo(AppTestCpythonExtensionBase):
     """
diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -331,12 +331,34 @@
                  PyHeapTypeObject *heaptype = (PyHeapTypeObject *)args;
                  Py_INCREF(heaptype->ht_name);
                  return heaptype->ht_name;
+             '''),
+            ("setattr", "METH_O",
              '''
-             )
+                int ret;
+                PyObject* name = PyString_FromString("mymodule");
+                PyObject *obj = PyType_Type.tp_alloc(&PyType_Type, 0);
+                PyHeapTypeObject *type = (PyHeapTypeObject*)obj;
+                if ((type->ht_type.tp_flags & Py_TPFLAGS_HEAPTYPE) == 0)
+                {
+                    PyErr_SetString(PyExc_ValueError,
+                                    "Py_TPFLAGS_HEAPTYPE not set");
+                    return NULL;
+                }
+                type->ht_type.tp_name = ((PyTypeObject*)args)->tp_name;
+                PyType_Ready(&type->ht_type);
+                ret = PyObject_SetAttrString((PyObject*)&type->ht_type,
+                                    "__module__", name);
+                Py_DECREF(name);
+                if (ret < 0)
+                    return NULL;
+                return PyLong_FromLong(ret);
+             '''),
             ])
         class C(object):
             pass
         assert module.name_by_heaptype(C) == "C"
+        assert module.setattr(C) == 0
+
 
     def test_type_dict(self):
         foo = self.import_module("foo")
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -469,7 +469,7 @@
         W_TypeObject.__init__(self, space, name,
             bases_w or [space.w_object], dict_w, force_new_layout=new_layout)
         self.flag_cpytype = True
-        self.flag_heaptype = False
+        self.flag_heaptype = pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE
         # if a sequence or a mapping, then set the flag to force it
         if pto.c_tp_as_sequence and pto.c_tp_as_sequence.c_sq_item:
             self.flag_map_or_seq = 'S'
@@ -852,14 +852,14 @@
     w_obj = space.allocate_instance(W_PyCTypeObject, w_metatype)
     track_reference(space, py_obj, w_obj)
     # __init__ wraps all slotdefs functions from py_type via add_operators
-    w_obj.__init__(space, py_type) 
+    w_obj.__init__(space, py_type)
     w_obj.ready()
 
     finish_type_2(space, py_type, w_obj)
     base = py_type.c_tp_base
     if base:
         # XXX refactor - parts of this are done in finish_type_2 -> inherit_slots
-        if not py_type.c_tp_as_number: 
+        if not py_type.c_tp_as_number:
             py_type.c_tp_as_number = base.c_tp_as_number
             py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_CHECKTYPES
             py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS
diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -61,16 +61,24 @@
 @specialize.memo()
 def str_getitem(space):
     "Utility that returns the app-level descriptor str.__getitem__."
-    w_src, w_iter = space.lookup_in_type_where(space.w_str,
-                                               '__getitem__')
-    return w_iter
+    w_src, w_getitem = space.lookup_in_type_where(space.w_str,
+                                                  '__getitem__')
+    return w_getitem
 
 @specialize.memo()
 def unicode_getitem(space):
     "Utility that returns the app-level descriptor unicode.__getitem__."
-    w_src, w_iter = space.lookup_in_type_where(space.w_unicode,
-                                               '__getitem__')
-    return w_iter
+    w_src, w_getitem = space.lookup_in_type_where(space.w_unicode,
+                                                  '__getitem__')
+    return w_getitem
+
+ at specialize.memo()
+def dict_getitem(space):
+    "Utility that returns the app-level descriptor dict.__getitem__."
+    w_src, w_getitem = space.lookup_in_type_where(space.w_dict,
+                                                  '__getitem__')
+    return w_getitem
+
 
 def raiseattrerror(space, w_obj, name, w_descr=None):
     if w_descr is None:
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -330,6 +330,9 @@
     def unicode_from_object(self, w_obj):
         return w_some_obj()
 
+    def encode_unicode_object(self, w_unicode, encoding, errors):
+        return w_some_obj()
+
     def _try_fetch_pycode(self, w_func):
         return None
 
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -626,6 +626,10 @@
         from pypy.objspace.std.unicodeobject import unicode_from_object
         return unicode_from_object(self, w_obj)
 
+    def encode_unicode_object(self, w_unicode, encoding, errors):
+        from pypy.objspace.std.unicodeobject import encode_object
+        return encode_object(self, w_unicode, encoding, errors)
+
     def call_method(self, w_obj, methname, *arg_w):
         return callmethod.call_method_opt(self, w_obj, methname, *arg_w)
 
diff --git a/rpython/annotator/annrpython.py b/rpython/annotator/annrpython.py
--- a/rpython/annotator/annrpython.py
+++ b/rpython/annotator/annrpython.py
@@ -22,7 +22,8 @@
     """Block annotator for RPython.
     See description in doc/translation.txt."""
 
-    def __init__(self, translator=None, policy=None, bookkeeper=None):
+    def __init__(self, translator=None, policy=None, bookkeeper=None,
+            keepgoing=False):
         import rpython.rtyper.extfuncregistry # has side effects
 
         if translator is None:
@@ -51,6 +52,9 @@
         if bookkeeper is None:
             bookkeeper = Bookkeeper(self)
         self.bookkeeper = bookkeeper
+        self.keepgoing = keepgoing
+        self.failed_blocks = set()
+        self.errors = []
 
     def __getstate__(self):
         attrs = """translator pendingblocks annotated links_followed
@@ -203,6 +207,12 @@
         else:
             newgraphs = self.translator.graphs  #all of them
             got_blocked_blocks = False in self.annotated.values()
+        if self.failed_blocks:
+            text = ('Annotation failed, %s errors were recorded:' %
+                    len(self.errors))
+            text += '\n-----'.join(str(e) for e in self.errors)
+            raise annmodel.AnnotatorError(text)
+
         if got_blocked_blocks:
             for graph in self.blocked_graphs.values():
                 self.blocked_graphs[graph] = True
@@ -358,6 +368,8 @@
 
         #print '* processblock', block, cells
         self.annotated[block] = graph
+        if block in self.failed_blocks:
+            return
         if block in self.blocked_blocks:
             del self.blocked_blocks[block]
         try:
@@ -402,6 +414,10 @@
         except annmodel.UnionError as e:
             # Add source code to the UnionError
             e.source = '\n'.join(source_lines(graph, block, None, long=True))
+            if self.keepgoing:
+                self.errors.append(e)
+                self.failed_blocks.add(block)
+                return
             raise
         # if the merged cells changed, we must redo the analysis
         if unions != oldcells:
@@ -492,6 +508,10 @@
 
         except annmodel.AnnotatorError as e: # note that UnionError is a subclass
             e.source = gather_error(self, graph, block, i)
+            if self.keepgoing:
+                self.errors.append(e)
+                self.failed_blocks.add(block)
+                return
             raise
 
         else:
diff --git a/rpython/annotator/test/test_model.py b/rpython/annotator/test/test_model.py
--- a/rpython/annotator/test/test_model.py
+++ b/rpython/annotator/test/test_model.py
@@ -192,6 +192,20 @@
     assert union(union(s1, s2), s3) == union(s1, union(s2, s3))
 
 
+ at pytest.mark.xfail
+ at given(st_annotation, st_annotation)
+def test_generalize_isinstance(annotator, s1, s2):
+    try:
+        s_12 = union(s1, s2)
+    except UnionError:
+        assume(False)
+    assume(s1 != s_ImpossibleValue)
+    from rpython.annotator.unaryop import s_isinstance
+    s_int = annotator.bookkeeper.immutablevalue(int)
+    s_res_12 = s_isinstance(annotator, s_12, s_int, [])
+    s_res_1 = s_isinstance(annotator, s1, s_int, [])
+    assert s_res_12.contains(s_res_1)
+
 def compile_function(function, annotation=[]):
     t = TranslationContext()
     t.buildannotator().build_types(function, annotation)
diff --git a/rpython/config/translationoption.py b/rpython/config/translationoption.py
--- a/rpython/config/translationoption.py
+++ b/rpython/config/translationoption.py
@@ -188,6 +188,10 @@
                "When true, enable the use of tagged pointers. "
                "If false, use normal boxing",
                default=False),
+    BoolOption("keepgoing",
+               "Continue annotating when errors are encountered, and report "
+               "them all at the end of the annotation phase",
+               default=False, cmdline="--keepgoing"),
     BoolOption("lldebug",
                "If true, makes an lldebug build", default=False,
                cmdline="--lldebug"),
diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py b/rpython/jit/metainterp/optimizeopt/intbounds.py
--- a/rpython/jit/metainterp/optimizeopt/intbounds.py
+++ b/rpython/jit/metainterp/optimizeopt/intbounds.py
@@ -399,9 +399,9 @@
 
     def optimize_INT_EQ(self, op):
         arg0 = self.get_box_replacement(op.getarg(0))
+        b1 = self.getintbound(arg0)
         arg1 = self.get_box_replacement(op.getarg(1))
-        b1 = self.getintbound(op.getarg(0))
-        b2 = self.getintbound(op.getarg(1))
+        b2 = self.getintbound(arg1)
         if b1.known_gt(b2):
             self.make_constant_int(op, 0)
         elif b1.known_lt(b2):
diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py
--- a/rpython/rlib/objectmodel.py
+++ b/rpython/rlib/objectmodel.py
@@ -323,6 +323,8 @@
 def register_replacement_for(replaced_function, sandboxed_name=None):
     def wrap(func):
         from rpython.rtyper.extregistry import ExtRegistryEntry
+        # to support calling func directly
+        func._sandbox_external_name = sandboxed_name
         class ExtRegistry(ExtRegistryEntry):
             _about_ = replaced_function
             def compute_annotation(self):
diff --git a/rpython/rlib/rfloat.py b/rpython/rlib/rfloat.py
--- a/rpython/rlib/rfloat.py
+++ b/rpython/rlib/rfloat.py
@@ -1,6 +1,7 @@
 """Float constants"""
 
 import math, struct
+from math import isinf, isnan, copysign, acosh, asinh, atanh, log1p, expm1
 
 from rpython.annotator.model import SomeString, SomeChar
 from rpython.rlib import objectmodel, unroll
@@ -184,104 +185,6 @@
 INFINITY = 1e200 * 1e200
 NAN = abs(INFINITY / INFINITY)    # bah, INF/INF gives us -NAN?
 
-try:
-    # Try to get math functions added in 2.6.
-    from math import isinf, isnan, copysign, acosh, asinh, atanh, log1p
-except ImportError:
-    @not_rpython
-    def isinf(x):
-        return x == INFINITY or x == -INFINITY
-
-    @not_rpython
-    def isnan(v):
-        return v != v
-
-    @not_rpython
-    def copysign(x, y):
-        """Return x with the sign of y"""
-        if x < 0.:
-            x = -x
-        if y > 0. or (y == 0. and math.atan2(y, -1.) > 0.):
-            return x
-        else:
-            return -x
-
-    _2_to_m28 = 3.7252902984619141E-09; # 2**-28
-    _2_to_p28 = 268435456.0; # 2**28
-    _ln2 = 6.93147180559945286227E-01
-
-    @not_rpython
-    def acosh(x):
-        if isnan(x):
-            return NAN
-        if x < 1.:
-            raise ValueError("math domain error")
-        if x >= _2_to_p28:
-            if isinf(x):
-                return x
-            else:
-                return math.log(x) + _ln2
-        if x == 1.:
-            return 0.
-        if x >= 2.:
-            t = x * x
-            return math.log(2. * x - 1. / (x + math.sqrt(t - 1.0)))
-        t = x - 1.0
-        return log1p(t + math.sqrt(2. * t + t * t))
-
-    @not_rpython
-    def asinh(x):
-        absx = abs(x)
-        if not isfinite(x):
-            return x
-        if absx < _2_to_m28:
-            return x
-        if absx > _2_to_p28:
-            w = math.log(absx) + _ln2
-        elif absx > 2.:
-            w = math.log(2. * absx + 1. / (math.sqrt(x * x + 1.) + absx))
-        else:
-            t = x * x
-            w = log1p(absx + t / (1. + math.sqrt(1. + t)))
-        return copysign(w, x)
-
-    @not_rpython
-    def atanh(x):
-        if isnan(x):
-            return x
-        absx = abs(x)
-        if absx >= 1.:
-            raise ValueError("math domain error")
-        if absx < _2_to_m28:
-            return x
-        if absx < .5:
-            t = absx + absx
-            t = .5 * log1p(t + t * absx / (1. - absx))
-        else:
-            t = .5 * log1p((absx + absx) / (1. - absx))
-        return copysign(t, x)
-
-    @not_rpython
-    def log1p(x):
-        if abs(x) < DBL_EPSILON // 2.:
-            return x
-        elif -.5 <= x <= 1.:
-            y = 1. + x
-            return math.log(y) - ((y - 1.) - x) / y
-        else:
-            return math.log(1. + x)
-
-try:
-    from math import expm1 # Added in Python 2.7.
-except ImportError:
-    @not_rpython
-    def expm1(x):
-        if abs(x) < .7:
-            u = math.exp(x)
-            if u == 1.:
-                return x
-            return (u - 1.) * x / math.log(u)
-        return math.exp(x) - 1.
 
 def log2(x):
     # Uses an algorithm that should:
diff --git a/rpython/translator/sandbox/test/test_sandbox.py b/rpython/translator/sandbox/test/test_sandbox.py
--- a/rpython/translator/sandbox/test/test_sandbox.py
+++ b/rpython/translator/sandbox/test/test_sandbox.py
@@ -65,6 +65,24 @@
     f.close()
     assert tail == ""
 
+def test_open_dup_rposix():
+    from rpython.rlib import rposix
+    def entry_point(argv):
+        fd = rposix.open("/tmp/foobar", os.O_RDONLY, 0777)
+        assert fd == 77
+        fd2 = rposix.dup(fd)
+        assert fd2 == 78
+        return 0
+
+    exe = compile(entry_point)
+    g, f = run_in_subprocess(exe)
+    expect(f, g, "ll_os.ll_os_open", ("/tmp/foobar", os.O_RDONLY, 0777), 77)
+    expect(f, g, "ll_os.ll_os_dup",  (77, True), 78)
+    g.close()
+    tail = f.read()
+    f.close()
+    assert tail == ""
+
 def test_read_write():
     def entry_point(argv):
         fd = os.open("/tmp/foobar", os.O_RDONLY, 0777)
diff --git a/rpython/translator/translator.py b/rpython/translator/translator.py
--- a/rpython/translator/translator.py
+++ b/rpython/translator/translator.py
@@ -67,7 +67,8 @@
         if self.annotator is not None:
             raise ValueError("we already have an annotator")
         from rpython.annotator.annrpython import RPythonAnnotator
-        self.annotator = RPythonAnnotator(self, policy=policy)
+        self.annotator = RPythonAnnotator(
+            self, policy=policy, keepgoing=self.config.translation.keepgoing)
         return self.annotator
 
     def buildrtyper(self):


More information about the pypy-commit mailing list