Author: Armin Rigo <ar...@tunes.org>
Branch: use-gc-del-3
Changeset: r84324:7b8178ec0f5b
Date: 2016-05-09 10:29 +0200
http://bitbucket.org/pypy/pypy/changeset/7b8178ec0f5b/

Log:    hg merge default

diff --git a/dotviewer/graphserver.py b/dotviewer/graphserver.py
--- a/dotviewer/graphserver.py
+++ b/dotviewer/graphserver.py
@@ -143,6 +143,11 @@
 
 if __name__ == '__main__':
     if len(sys.argv) != 2:
+        if len(sys.argv) == 1:
+            # start locally
+            import sshgraphserver
+            sshgraphserver.ssh_graph_server(['LOCAL'])
+            sys.exit(0)
         print >> sys.stderr, __doc__
         sys.exit(2)
     if sys.argv[1] == '--stdio':
diff --git a/dotviewer/sshgraphserver.py b/dotviewer/sshgraphserver.py
--- a/dotviewer/sshgraphserver.py
+++ b/dotviewer/sshgraphserver.py
@@ -4,11 +4,14 @@
 
 Usage:
     sshgraphserver.py  hostname  [more args for ssh...]
+    sshgraphserver.py  LOCAL
 
 This logs in to 'hostname' by passing the arguments on the command-line
 to ssh.  No further configuration is required: it works for all programs
 using the dotviewer library as long as they run on 'hostname' under the
 same username as the one sshgraphserver logs as.
+
+If 'hostname' is the string 'LOCAL', then it starts locally without ssh.
 """
 
 import graphserver, socket, subprocess, random
@@ -18,12 +21,19 @@
     s1 = socket.socket()
     s1.bind(('127.0.0.1', socket.INADDR_ANY))
     localhost, localport = s1.getsockname()
-    remoteport = random.randrange(10000, 20000)
-    #  ^^^ and just hope there is no conflict
 
-    args = ['ssh', '-S', 'none', '-C', '-R%d:127.0.0.1:%d' % (remoteport, 
localport)]
-    args = args + sshargs + ['python -u -c "exec input()"']
-    print ' '.join(args[:-1])
+    if sshargs[0] != 'LOCAL':
+        remoteport = random.randrange(10000, 20000)
+        #  ^^^ and just hope there is no conflict
+
+        args = ['ssh', '-S', 'none', '-C', '-R%d:127.0.0.1:%d' % (
+            remoteport, localport)]
+        args = args + sshargs + ['python -u -c "exec input()"']
+    else:
+        remoteport = localport
+        args = ['python', '-u', '-c', 'exec input()']
+
+    print ' '.join(args)
     p = subprocess.Popen(args, bufsize=0,
                          stdin=subprocess.PIPE,
                          stdout=subprocess.PIPE)
diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -397,20 +397,7 @@
         data.  Later, when this new cdata object is garbage-collected,
         'destructor(old_cdata_object)' will be called.
         """
-        try:
-            gcp = self._backend.gcp
-        except AttributeError:
-            pass
-        else:
-            return gcp(cdata, destructor)
-        #
-        with self._lock:
-            try:
-                gc_weakrefs = self.gc_weakrefs
-            except AttributeError:
-                from .gc_weakref import GcWeakrefs
-                gc_weakrefs = self.gc_weakrefs = GcWeakrefs(self)
-            return gc_weakrefs.build(cdata, destructor)
+        return self._backend.gcp(cdata, destructor)
 
     def _get_cached_btype(self, type):
         assert self._lock.acquire(False) is False
diff --git a/lib_pypy/cffi/backend_ctypes.py b/lib_pypy/cffi/backend_ctypes.py
--- a/lib_pypy/cffi/backend_ctypes.py
+++ b/lib_pypy/cffi/backend_ctypes.py
@@ -460,6 +460,11 @@
                         return x._value
                     raise TypeError("character expected, got %s" %
                                     type(x).__name__)
+                def __nonzero__(self):
+                    return ord(self._value) != 0
+            else:
+                def __nonzero__(self):
+                    return self._value != 0
 
             if kind == 'float':
                 @staticmethod
@@ -993,6 +998,31 @@
         assert onerror is None   # XXX not implemented
         return BType(source, error)
 
+    def gcp(self, cdata, destructor):
+        BType = self.typeof(cdata)
+
+        if destructor is None:
+            if not (hasattr(BType, '_gcp_type') and
+                    BType._gcp_type is BType):
+                raise TypeError("Can remove destructor only on a object "
+                                "previously returned by ffi.gc()")
+            cdata._destructor = None
+            return None
+
+        try:
+            gcp_type = BType._gcp_type
+        except AttributeError:
+            class CTypesDataGcp(BType):
+                __slots__ = ['_orig', '_destructor']
+                def __del__(self):
+                    if self._destructor is not None:
+                        self._destructor(self._orig)
+            gcp_type = BType._gcp_type = CTypesDataGcp
+        new_cdata = self.cast(gcp_type, cdata)
+        new_cdata._orig = cdata
+        new_cdata._destructor = destructor
+        return new_cdata
+
     typeof = type
 
     def getcname(self, BType, replace_with):
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -68,3 +68,19 @@
 CPython).
 
 .. branch: oefmt
+
+.. branch: cpyext-werror
+
+Compile c snippets with -Werror in cpyext
+
+.. branch: gc-del-3
+
+Add rgc.FinalizerQueue, documented in pypy/doc/discussion/finalizer-order.rst.
+It is a more flexible way to make RPython finalizers.
+
+.. branch: unpacking-cpython-shortcut
+
+.. branch: cleanups
+
+.. branch: cpyext-more-slots
+
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
@@ -688,3 +688,21 @@
         def f(x): pass
         e = raises(TypeError, "f(**{u'&#252;' : 19})")
         assert "?" in str(e.value)
+
+    def test_starstarargs_dict_subclass(self):
+        def f(**kwargs):
+            return kwargs
+        class DictSubclass(dict):
+            def __iter__(self):
+                yield 'x'
+        # CPython, as an optimization, looks directly into dict internals when
+        # passing one via **kwargs.
+        x =DictSubclass()
+        assert f(**x) == {}
+        x['a'] = 1
+        assert f(**x) == {'a': 1}
+
+    def test_starstarargs_module_dict(self):
+        def f(**kwargs):
+            return kwargs
+        assert f(**globals()) == globals()
diff --git a/pypy/module/_cffi_backend/cdataobj.py 
b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -71,7 +71,7 @@
 
     def nonzero(self):
         with self as ptr:
-            nonzero = bool(ptr)
+            nonzero = self.ctype.nonzero(ptr)
         return self.space.wrap(nonzero)
 
     def int(self, space):
@@ -365,8 +365,16 @@
         return self.ctype.size
 
     def with_gc(self, w_destructor):
+        space = self.space
+        if space.is_none(w_destructor):
+            if isinstance(self, W_CDataGCP):
+                self.w_destructor = None
+                return space.w_None
+            raise oefmt(space.w_TypeError,
+                        "Can remove destructor only on a object "
+                        "previously returned by ffi.gc()")
         with self as ptr:
-            return W_CDataGCP(self.space, ptr, self.ctype, self, w_destructor)
+            return W_CDataGCP(space, ptr, self.ctype, self, w_destructor)
 
     def unpack(self, length):
         from pypy.module._cffi_backend.ctypeptr import W_CTypePtrOrArray
@@ -527,7 +535,7 @@
 class W_CDataGCP(W_CData):
     """For ffi.gc()."""
     _attrs_ = ['w_original_cdata', 'w_destructor']
-    _immutable_fields_ = ['w_original_cdata', 'w_destructor']
+    _immutable_fields_ = ['w_original_cdata']
 
     def __init__(self, space, cdata, ctype, w_original_cdata, w_destructor):
         W_CData.__init__(self, space, cdata, ctype)
@@ -536,7 +544,10 @@
         self.register_finalizer(space)
 
     def _finalize_(self):
-        self.space.call_function(self.w_destructor, self.w_original_cdata)
+        w_destructor = self.w_destructor
+        if w_destructor is not None:
+            self.w_destructor = None
+            self.space.call_function(w_destructor, self.w_original_cdata)
 
 
 W_CData.typedef = TypeDef(
diff --git a/pypy/module/_cffi_backend/ctypeobj.py 
b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -147,6 +147,9 @@
         raise oefmt(space.w_TypeError, "cannot add a cdata '%s' and a number",
                     self.name)
 
+    def nonzero(self, cdata):
+        return bool(cdata)
+
     def insert_name(self, extra, extra_position):
         name = '%s%s%s' % (self.name[:self.name_position],
                            extra,
diff --git a/pypy/module/_cffi_backend/ctypeprim.py 
b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -93,6 +93,18 @@
             return self.space.newlist_int(result)
         return W_CType.unpack_ptr(self, w_ctypeptr, ptr, length)
 
+    def nonzero(self, cdata):
+        if self.size <= rffi.sizeof(lltype.Signed):
+            value = misc.read_raw_long_data(cdata, self.size)
+            return value != 0
+        else:
+            return self._nonzero_longlong(cdata)
+
+    def _nonzero_longlong(self, cdata):
+        # in its own function: LONGLONG may make the whole function jit-opaque
+        value = misc.read_raw_signed_data(cdata, self.size)
+        return bool(value)
+
 
 class W_CTypePrimitiveCharOrUniChar(W_CTypePrimitive):
     _attrs_ = []
@@ -435,6 +447,9 @@
             return self.space.newlist_float(result)
         return W_CType.unpack_ptr(self, w_ctypeptr, ptr, length)
 
+    def nonzero(self, cdata):
+        return misc.is_nonnull_float(cdata, self.size)
+
 
 class W_CTypePrimitiveLongDouble(W_CTypePrimitiveFloat):
     _attrs_ = []
@@ -501,3 +516,7 @@
                                              rffi.LONGDOUBLE, rffi.LONGDOUBLEP)
             return True
         return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob)
+
+    @jit.dont_look_inside
+    def nonzero(self, cdata):
+        return misc.is_nonnull_longdouble(cdata)
diff --git a/pypy/module/_cffi_backend/misc.py 
b/pypy/module/_cffi_backend/misc.py
--- a/pypy/module/_cffi_backend/misc.py
+++ b/pypy/module/_cffi_backend/misc.py
@@ -256,7 +256,7 @@
 def is_nonnull_longdouble(cdata):
     return _is_nonnull_longdouble(read_raw_longdouble_data(cdata))
 def is_nonnull_float(cdata, size):
-    return read_raw_float_data(cdata, size) != 0.0
+    return read_raw_float_data(cdata, size) != 0.0    # note: True if a NaN
 
 def object_as_bool(space, w_ob):
     # convert and cast a Python object to a boolean.  Accept an integer
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py 
b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -141,9 +141,13 @@
     INF = 1E200 * 1E200
     for name in ["float", "double"]:
         p = new_primitive_type(name)
-        assert bool(cast(p, 0))
+        assert bool(cast(p, 0)) is False      # since 1.7
+        assert bool(cast(p, -0.0)) is False   # since 1.7
+        assert bool(cast(p, 1e-42)) is True
+        assert bool(cast(p, -1e-42)) is True
         assert bool(cast(p, INF))
         assert bool(cast(p, -INF))
+        assert bool(cast(p, float("nan")))
         assert int(cast(p, -150)) == -150
         assert int(cast(p, 61.91)) == 61
         assert long(cast(p, 61.91)) == 61
@@ -202,7 +206,8 @@
 
 def test_character_type():
     p = new_primitive_type("char")
-    assert bool(cast(p, '\x00'))
+    assert bool(cast(p, 'A')) is True
+    assert bool(cast(p, '\x00')) is False    # since 1.7
     assert cast(p, '\x00') != cast(p, -17*256)
     assert int(cast(p, 'A')) == 65
     assert long(cast(p, 'A')) == 65
@@ -2558,7 +2563,8 @@
     BBoolP = new_pointer_type(BBool)
     assert int(cast(BBool, False)) == 0
     assert int(cast(BBool, True)) == 1
-    assert bool(cast(BBool, False)) is True    # warning!
+    assert bool(cast(BBool, False)) is False    # since 1.7
+    assert bool(cast(BBool, True)) is True
     assert int(cast(BBool, 3)) == 1
     assert int(cast(BBool, long(3))) == 1
     assert int(cast(BBool, long(10)**4000)) == 1
diff --git a/pypy/module/_cffi_backend/test/test_ffi_obj.py 
b/pypy/module/_cffi_backend/test/test_ffi_obj.py
--- a/pypy/module/_cffi_backend/test/test_ffi_obj.py
+++ b/pypy/module/_cffi_backend/test/test_ffi_obj.py
@@ -331,6 +331,25 @@
             gc.collect()
         assert seen == [1]
 
+    def test_ffi_gc_disable(self):
+        import _cffi_backend as _cffi1_backend
+        ffi = _cffi1_backend.FFI()
+        p = ffi.new("int *", 123)
+        raises(TypeError, ffi.gc, p, None)
+        seen = []
+        q1 = ffi.gc(p, lambda p: seen.append(1))
+        q2 = ffi.gc(q1, lambda p: seen.append(2))
+        import gc; gc.collect()
+        assert seen == []
+        assert ffi.gc(q1, None) is None
+        del q1, q2
+        for i in range(5):
+            if seen:
+                break
+            import gc
+            gc.collect()
+        assert seen == [2]
+
     def test_ffi_new_allocator_1(self):
         import _cffi_backend as _cffi1_backend
         ffi = _cffi1_backend.FFI()
diff --git a/pypy/module/_multibytecodec/app_multibytecodec.py 
b/pypy/module/_multibytecodec/app_multibytecodec.py
--- a/pypy/module/_multibytecodec/app_multibytecodec.py
+++ b/pypy/module/_multibytecodec/app_multibytecodec.py
@@ -44,8 +44,10 @@
                 self, data))
 
     def reset(self):
-        self.stream.write(MultibyteIncrementalEncoder.encode(
-                self, '', final=True))
+        data = MultibyteIncrementalEncoder.encode(
+            self, '', final=True)
+        if len(data) > 0:
+            self.stream.write(data)
         MultibyteIncrementalEncoder.reset(self)
 
     def writelines(self, lines):
diff --git a/pypy/module/_multibytecodec/test/test_app_stream.py 
b/pypy/module/_multibytecodec/test/test_app_stream.py
--- a/pypy/module/_multibytecodec/test/test_app_stream.py
+++ b/pypy/module/_multibytecodec/test/test_app_stream.py
@@ -90,3 +90,15 @@
         w.write(u'\u304b')
         w.write(u'\u309a')
         assert w.stream.output == ['\x83m', '', '\x82\xf5']
+
+    def test_writer_seek_no_empty_write(self):
+        # issue #2293: codecs.py will sometimes issue a reset()
+        # on a StreamWriter attached to a file that is not opened
+        # for writing at all.  We must not emit a "write('')"!
+        class FakeFile:
+            def write(self, data):
+                raise IOError("can't write!")
+        #
+        w = self.ShiftJisx0213StreamWriter(FakeFile())
+        w.reset()
+        # assert did not crash
diff --git a/pypy/module/cpyext/ndarrayobject.py 
b/pypy/module/cpyext/ndarrayobject.py
--- a/pypy/module/cpyext/ndarrayobject.py
+++ b/pypy/module/cpyext/ndarrayobject.py
@@ -248,7 +248,7 @@
     w_signature = rffi.charp2str(signature)
     return do_ufunc(space, funcs, data, types, ntypes, nin, nout, identity, 
name, doc,
              check_return, w_signature)
-            
+
 
 def do_ufunc(space, funcs, data, types, ntypes, nin, nout, identity, name, doc,
              check_return, w_signature):
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -374,7 +374,75 @@
     header = pypy_decl
     if mangle_name('', typedef.name) is None:
         header = None
-    if name == 'tp_setattro':
+    handled = False
+    # unary functions
+    for tp_name, attr in [('tp_as_number.c_nb_int', '__int__'),
+                          ('tp_as_number.c_nb_long', '__long__'),
+                          ('tp_as_number.c_nb_float', '__float__'),
+                          ('tp_as_number.c_nb_negative', '__neg__'),
+                          ('tp_as_number.c_nb_positive', '__pos__'),
+                          ('tp_as_number.c_nb_absolute', '__abs__'),
+                          ('tp_as_number.c_nb_invert', '__invert__'),
+                          ('tp_as_number.c_nb_index', '__index__'),
+                          ('tp_str', '__str__'),
+                          ('tp_repr', '__repr__'),
+                          ('tp_iter', '__iter__'),
+                          ]:
+        if name == tp_name:
+            slot_fn = w_type.getdictvalue(space, attr)
+            if slot_fn is None:
+                return
+
+            @cpython_api([PyObject], PyObject, header=header)
+            @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), 
typedef.name))
+            def slot_func(space, w_self):
+                return space.call_function(slot_fn, w_self)
+            api_func = slot_func.api_func
+            handled = True
+
+    # binary functions
+    for tp_name, attr in [('tp_as_number.c_nb_add', '__add__'),
+                          ('tp_as_number.c_nb_subtract', '__subtract__'),
+                          ('tp_as_number.c_nb_multiply', '__mul__'),
+                          ('tp_as_number.c_nb_divide', '__div__'),
+                          ('tp_as_number.c_nb_remainder', '__mod__'),
+                          ('tp_as_number.c_nb_divmod', '__divmod__'),
+                          ('tp_as_number.c_nb_lshift', '__lshift__'),
+                          ('tp_as_number.c_nb_rshift', '__rshift__'),
+                          ('tp_as_number.c_nb_and', '__and__'),
+                          ('tp_as_number.c_nb_xor', '__xor__'),
+                          ('tp_as_number.c_nb_or', '__or__'),
+                          ]:
+        if name == tp_name:
+            slot_fn = w_type.getdictvalue(space, attr)
+            if slot_fn is None:
+                return
+
+            @cpython_api([PyObject, PyObject], PyObject, header=header)
+            @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), 
typedef.name))
+            def slot_func(space, w_self, w_arg):
+                return space.call_function(slot_fn, w_self, w_arg)
+            api_func = slot_func.api_func
+            handled = True
+
+    # ternary functions
+    for tp_name, attr in [('tp_as_number.c_nb_power', ''),
+                          ]:
+        if name == tp_name:
+            slot_fn = w_type.getdictvalue(space, attr)
+            if slot_fn is None:
+                return
+
+            @cpython_api([PyObject, PyObject, PyObject], PyObject, 
header=header)
+            @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), 
typedef.name))
+            def slot_func(space, w_self, w_arg1, w_arg2):
+                return space.call_function(slot_fn, w_self, w_arg1, w_arg2)
+            api_func = slot_func.api_func
+            handled = True
+
+    if handled:
+        pass
+    elif name == 'tp_setattro':
         setattr_fn = w_type.getdictvalue(space, '__setattr__')
         delattr_fn = w_type.getdictvalue(space, '__delattr__')
         if setattr_fn is None:
@@ -401,28 +469,6 @@
             return space.call_function(getattr_fn, w_self, w_name)
         api_func = slot_tp_getattro.api_func
 
-    elif name == 'tp_as_number.c_nb_int':
-        int_fn = w_type.getdictvalue(space, '__int__')
-        if int_fn is None:
-            return
-
-        @cpython_api([PyObject], PyObject, header=header)
-        @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
-        def slot_nb_int(space, w_self):
-            return space.call_function(int_fn, w_self)
-        api_func = slot_nb_int.api_func
-
-    elif name == 'tp_as_number.c_nb_float':
-        float_fn = w_type.getdictvalue(space, '__float__')
-        if float_fn is None:
-            return
-
-        @cpython_api([PyObject], PyObject, header=header)
-        @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
-        def slot_nb_float(space, w_self):
-            return space.call_function(float_fn, w_self)
-        api_func = slot_nb_float.api_func
-
     elif name == 'tp_call':
         call_fn = w_type.getdictvalue(space, '__call__')
         if call_fn is None:
@@ -436,28 +482,6 @@
             return space.call_args(call_fn, args)
         api_func = slot_tp_call.api_func
 
-    elif name == 'tp_str':
-        str_fn = w_type.getdictvalue(space, '__str__')
-        if str_fn is None:
-            return
-
-        @cpython_api([PyObject], PyObject, header=header)
-        @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
-        def slot_tp_str(space, w_self):
-            return space.call_function(str_fn, w_self)
-        api_func = slot_tp_str.api_func
-
-    elif name == 'tp_iter':
-        iter_fn = w_type.getdictvalue(space, '__iter__')
-        if iter_fn is None:
-            return
-
-        @cpython_api([PyObject], PyObject, header=header)
-        @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
-        def slot_tp_iter(space, w_self):
-            return space.call_function(iter_fn, w_self)
-        api_func = slot_tp_iter.api_func
-
     elif name == 'tp_iternext':
         iternext_fn = w_type.getdictvalue(space, 'next')
         if iternext_fn is None:
@@ -501,6 +525,7 @@
             return space.call_args(space.get(new_fn, w_self), args)
         api_func = slot_tp_new.api_func
     else:
+        # missing: tp_as_number.nb_nonzero, tp_as_number.nb_coerce
         return
 
     return lambda: llhelper(api_func.functype, api_func.get_wrapper(space))
diff --git a/pypy/module/cpyext/test/test_api.py 
b/pypy/module/cpyext/test/test_api.py
--- a/pypy/module/cpyext/test/test_api.py
+++ b/pypy/module/cpyext/test/test_api.py
@@ -1,4 +1,4 @@
-import py
+import py, pytest
 from rpython.rtyper.lltypesystem import rffi, lltype
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.module.cpyext.state import State
@@ -100,7 +100,8 @@
         PyPy_TypedefTest2(space, ppos)
         lltype.free(ppos, flavor='raw')
 
-
+@pytest.mark.skipif(os.environ.get('USER')=='root', 
+                    reason='root can write to all files')
 def test_copy_header_files(tmpdir):
     api.copy_header_files(tmpdir, True)
     def check(name):
diff --git a/pypy/module/cpyext/test/test_borrow.py 
b/pypy/module/cpyext/test/test_borrow.py
--- a/pypy/module/cpyext/test/test_borrow.py
+++ b/pypy/module/cpyext/test/test_borrow.py
@@ -12,13 +12,13 @@
                 PyObject *t = PyTuple_New(1);
                 PyObject *f = PyFloat_FromDouble(42.0);
                 PyObject *g = NULL;
-                printf("Refcnt1: %i\\n", f->ob_refcnt);
+                printf("Refcnt1: %zd\\n", f->ob_refcnt);
                 PyTuple_SetItem(t, 0, f); // steals reference
-                printf("Refcnt2: %i\\n", f->ob_refcnt);
+                printf("Refcnt2: %zd\\n", f->ob_refcnt);
                 f = PyTuple_GetItem(t, 0); // borrows reference
-                printf("Refcnt3: %i\\n", f->ob_refcnt);
+                printf("Refcnt3: %zd\\n", f->ob_refcnt);
                 g = PyTuple_GetItem(t, 0); // borrows reference again
-                printf("Refcnt4: %i\\n", f->ob_refcnt);
+                printf("Refcnt4: %zd\\n", f->ob_refcnt);
                 printf("COMPARE: %i\\n", f == g);
                 fflush(stdout);
                 Py_DECREF(t);
diff --git a/pypy/module/cpyext/test/test_bytesobject.py 
b/pypy/module/cpyext/test/test_bytesobject.py
--- a/pypy/module/cpyext/test/test_bytesobject.py
+++ b/pypy/module/cpyext/test/test_bytesobject.py
@@ -40,7 +40,7 @@
                  #endif
                  if(s->ob_type->tp_basicsize != expected_size)
                  {
-                     printf("tp_basicsize==%ld\\n", s->ob_type->tp_basicsize); 
+                     printf("tp_basicsize==%zd\\n", s->ob_type->tp_basicsize); 
                      result = 0;
                  }
                  Py_DECREF(s);
@@ -162,7 +162,10 @@
         module = self.import_extension('foo', [
             ("string_None", "METH_VARARGS",
              '''
-             return PyString_AsString(Py_None);
+             if (PyString_AsString(Py_None)) {
+                Py_RETURN_NONE;
+             }
+             return NULL;
              '''
             )])
         raises(TypeError, module.string_None)
diff --git a/pypy/module/cpyext/test/test_classobject.py 
b/pypy/module/cpyext/test/test_classobject.py
--- a/pypy/module/cpyext/test/test_classobject.py
+++ b/pypy/module/cpyext/test/test_classobject.py
@@ -29,7 +29,6 @@
         assert space.unwrap(space.getattr(w_instance, space.wrap('x'))) == 1
         assert space.unwrap(space.getattr(w_instance, space.wrap('y'))) == 2
         assert space.unwrap(space.getattr(w_instance, space.wrap('args'))) == 
(3,)
-        
 
     def test_lookup(self, space, api):
         w_instance = space.appexec([], """():
@@ -68,7 +67,7 @@
             ("get_classtype", "METH_NOARGS",
              """
                  Py_INCREF(&PyClass_Type);
-                 return &PyClass_Type;
+                 return (PyObject*)&PyClass_Type;
              """)])
         class C: pass
         assert module.get_classtype() is type(C)
diff --git a/pypy/module/cpyext/test/test_cpyext.py 
b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -72,8 +72,7 @@
     else:
         kwds["link_files"] = [str(api_library + '.so')]
         if sys.platform.startswith('linux'):
-            kwds["compile_extra"]=["-Werror=implicit-function-declaration",
-                                   "-g", "-O0"]
+            kwds["compile_extra"]=["-Werror", "-g", "-O0"]
             kwds["link_extra"]=["-g"]
 
     modname = modname.split('.')[-1]
@@ -747,7 +746,7 @@
             refcnt_after = true_obj->ob_refcnt;
             Py_DECREF(true_obj);
             Py_DECREF(true_obj);
-            fprintf(stderr, "REFCNT %i %i\\n", refcnt, refcnt_after);
+            fprintf(stderr, "REFCNT %zd %zd\\n", refcnt, refcnt_after);
             return PyBool_FromLong(refcnt_after == refcnt + 2);
         }
         static PyObject* foo_bar(PyObject* self, PyObject *args)
@@ -763,7 +762,7 @@
                 return NULL;
             refcnt_after = true_obj->ob_refcnt;
             Py_DECREF(tup);
-            fprintf(stderr, "REFCNT2 %i %i %i\\n", refcnt, refcnt_after,
+            fprintf(stderr, "REFCNT2 %zd %zd %zd\\n", refcnt, refcnt_after,
                     true_obj->ob_refcnt);
             return PyBool_FromLong(refcnt_after == refcnt + 1 &&
                                    refcnt == true_obj->ob_refcnt);
diff --git a/pypy/module/cpyext/test/test_longobject.py 
b/pypy/module/cpyext/test/test_longobject.py
--- a/pypy/module/cpyext/test/test_longobject.py
+++ b/pypy/module/cpyext/test/test_longobject.py
@@ -171,7 +171,7 @@
                  int little_endian, is_signed;
                  if (!PyArg_ParseTuple(args, "ii", &little_endian, &is_signed))
                      return NULL;
-                 return _PyLong_FromByteArray("\x9A\xBC", 2,
+                 return _PyLong_FromByteArray((unsigned char*)"\x9A\xBC", 2,
                                               little_endian, is_signed);
              """),
             ])
@@ -187,7 +187,7 @@
                  int little_endian, is_signed;
                  if (!PyArg_ParseTuple(args, "ii", &little_endian, &is_signed))
                      return NULL;
-                 return _PyLong_FromByteArray("\x9A\xBC\x41", 3,
+                 return _PyLong_FromByteArray((unsigned char*)"\x9A\xBC\x41", 
3,
                                               little_endian, is_signed);
              """),
             ])
diff --git a/pypy/module/cpyext/test/test_pyerrors.py 
b/pypy/module/cpyext/test/test_pyerrors.py
--- a/pypy/module/cpyext/test/test_pyerrors.py
+++ b/pypy/module/cpyext/test/test_pyerrors.py
@@ -168,14 +168,14 @@
              PyErr_NormalizeException(&type, &val, &tb);
              if (type != PyExc_TypeError)
                  Py_RETURN_FALSE;
-             if (val->ob_type != PyExc_TypeError)
+             if ((PyObject*)Py_TYPE(val) != PyExc_TypeError)
                  Py_RETURN_FALSE;
 
              /* Normalize again */
              PyErr_NormalizeException(&type, &val, &tb);
              if (type != PyExc_TypeError)
                  Py_RETURN_FALSE;
-             if (val->ob_type != PyExc_TypeError)
+             if ((PyObject*)Py_TYPE(val) != PyExc_TypeError)
                  Py_RETURN_FALSE;
 
              PyErr_Restore(type, val, tb);
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
@@ -437,14 +437,14 @@
             ("test_tp_getattro", "METH_VARARGS",
              '''
                  PyObject *name, *obj = PyTuple_GET_ITEM(args, 0);
-                 PyIntObject *attr, *value = PyTuple_GET_ITEM(args, 1);
+                 PyIntObject *attr, *value = (PyIntObject*) 
PyTuple_GET_ITEM(args, 1);
                  if (!obj->ob_type->tp_getattro)
                  {
                      PyErr_SetString(PyExc_ValueError, "missing tp_getattro");
                      return NULL;
                  }
                  name = PyString_FromString("attr1");
-                 attr = obj->ob_type->tp_getattro(obj, name);
+                 attr = (PyIntObject*) obj->ob_type->tp_getattro(obj, name);
                  if (attr->ob_ival != value->ob_ival)
                  {
                      PyErr_SetString(PyExc_ValueError,
@@ -454,7 +454,7 @@
                  Py_DECREF(name);
                  Py_DECREF(attr);
                  name = PyString_FromString("attr2");
-                 attr = obj->ob_type->tp_getattro(obj, name);
+                 attr = (PyIntObject*) obj->ob_type->tp_getattro(obj, name);
                  if (attr == NULL && 
PyErr_ExceptionMatches(PyExc_AttributeError))
                  {
                      PyErr_Clear();
@@ -758,8 +758,9 @@
             } IntLikeObject;
 
             static int
-            intlike_nb_nonzero(IntLikeObject *v)
+            intlike_nb_nonzero(PyObject *o)
             {
+                IntLikeObject *v = (IntLikeObject*)o;
                 if (v->value == -42) {
                     PyErr_SetNone(PyExc_ValueError);
                     return -1;
@@ -920,3 +921,59 @@
                           '    multiple bases have instance lay-out conflict')
         else:
             raise AssertionError("did not get TypeError!")
+
+    def test_call_tp_dealloc_when_created_from_python(self):
+        module = self.import_extension('foo', [
+            ("fetchFooType", "METH_VARARGS",
+             """
+                PyObject *o;
+                Foo_Type.tp_dealloc = &dealloc_foo;
+                Foo_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
+                Foo_Type.tp_new = &new_foo;
+                Foo_Type.tp_free = &PyObject_Del;
+                if (PyType_Ready(&Foo_Type) < 0) return NULL;
+
+                o = PyObject_New(PyObject, &Foo_Type);
+                Py_DECREF(o);   /* calls dealloc_foo immediately */
+
+                Py_INCREF(&Foo_Type);
+                return (PyObject *)&Foo_Type;
+             """),
+            ("getCounter", "METH_VARARGS",
+             """
+                return PyInt_FromLong(foo_counter);
+             """)], prologue=
+            """
+            static int foo_counter = 1000;
+            static void dealloc_foo(PyObject *foo) {
+                foo_counter += 10;
+            }
+            static PyObject *new_foo(PyTypeObject *t, PyObject *a, PyObject *k)
+            {
+                foo_counter += 1000;
+                return t->tp_alloc(t, 0);
+            }
+            static PyTypeObject Foo_Type = {
+                PyVarObject_HEAD_INIT(NULL, 0)
+                "foo.foo",
+            };
+            """)
+        Foo = module.fetchFooType()
+        assert module.getCounter() == 1010
+        Foo(); Foo()
+        for i in range(10):
+            if module.getCounter() >= 3030:
+                break
+            # NB. use self.debug_collect() instead of gc.collect(),
+            # otherwise rawrefcount's dealloc callback doesn't trigger
+            self.debug_collect()
+        assert module.getCounter() == 3030
+        #
+        class Bar(Foo):
+            pass
+        Bar(); Bar()
+        for i in range(10):
+            if module.getCounter() >= 5050:
+                break
+            self.debug_collect()
+        assert module.getCounter() == 5050
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
@@ -556,7 +556,14 @@
     typedescr = get_typedescr(w_type.layout.typedef)
 
     # dealloc
-    pto.c_tp_dealloc = typedescr.get_dealloc(space)
+    if space.gettypeobject(w_type.layout.typedef) is w_type:
+        # only for the exact type, like 'space.w_tuple' or 'space.w_list'
+        pto.c_tp_dealloc = typedescr.get_dealloc(space)
+    else:
+        # for all subtypes, use subtype_dealloc()
+        pto.c_tp_dealloc = llhelper(
+            subtype_dealloc.api_func.functype,
+            subtype_dealloc.api_func.get_wrapper(space))
     # buffer protocol
     if space.is_w(w_type, space.w_str):
         setup_string_buffer_procs(space, pto)
diff --git a/pypy/module/micronumpy/concrete.py 
b/pypy/module/micronumpy/concrete.py
--- a/pypy/module/micronumpy/concrete.py
+++ b/pypy/module/micronumpy/concrete.py
@@ -258,7 +258,6 @@
         elif space.is_w(w_idx, space.w_None):
             return [NewAxisChunk(), EllipsisChunk()]
         result = []
-        i = 0
         has_ellipsis = False
         has_filter = False
         for w_item in space.fixedview(w_idx):
@@ -274,7 +273,6 @@
                 result.append(NewAxisChunk())
             elif space.isinstance_w(w_item, space.w_slice):
                 result.append(SliceChunk(w_item))
-                i += 1
             elif isinstance(w_item, W_NDimArray) and 
w_item.get_dtype().is_bool():
                 if has_filter:
                     # in CNumPy, the support for this is incomplete
@@ -287,7 +285,6 @@
                 result.append(IntegerChunk(w_item.descr_int(space)))
             else:
                 result.append(IntegerChunk(w_item))
-                i += 1
         if not has_ellipsis:
             result.append(EllipsisChunk())
         return result
diff --git a/pypy/module/micronumpy/loop.py b/pypy/module/micronumpy/loop.py
--- a/pypy/module/micronumpy/loop.py
+++ b/pypy/module/micronumpy/loop.py
@@ -199,7 +199,7 @@
     reds='auto')
 
 def call_many_to_many(space, shape, func, in_dtypes, out_dtypes, in_args, 
out_args):
-    # out must hav been built. func needs no calc_type, is usually an
+    # out must have been built. func needs no calc_type, is usually an
     # external ufunc
     nin = len(in_args)
     in_iters = [None] * nin
@@ -806,7 +806,6 @@
     indexlen = len(indexes_w)
     dtype = arr.get_dtype()
     iter = PureShapeIter(iter_shape, indexes_w)
-    indexlen = len(indexes_w)
     while not iter.done():
         getitem_int_driver.jit_merge_point(shapelen=shapelen, 
indexlen=indexlen,
                                            dtype=dtype, prefixlen=prefixlen)
diff --git a/pypy/module/micronumpy/ndarray.py 
b/pypy/module/micronumpy/ndarray.py
--- a/pypy/module/micronumpy/ndarray.py
+++ b/pypy/module/micronumpy/ndarray.py
@@ -231,11 +231,11 @@
                     dim = i
                     idx = c.w_idx
                     chunks.pop(i)
-                    chunks.insert(0, SliceChunk(space.newslice(space.wrap(0), 
+                    chunks.insert(0, SliceChunk(space.newslice(space.wrap(0),
                                  space.w_None, space.w_None)))
                     break
             if dim > 0:
-                view = self.implementation.swapaxes(space, self, 0, dim) 
+                view = self.implementation.swapaxes(space, self, 0, dim)
             if dim >= 0:
                 view = new_view(space, self, chunks)
                 view.setitem_filter(space, idx, val_arr)
@@ -563,7 +563,7 @@
         l_w = []
         for i in range(self.get_shape()[0]):
             item_w = self.descr_getitem(space, space.wrap(i))
-            if (isinstance(item_w, W_NDimArray) or 
+            if (isinstance(item_w, W_NDimArray) or
                     isinstance(item_w, boxes.W_GenericBox)):
                 l_w.append(space.call_method(item_w, "tolist"))
             else:
@@ -740,7 +740,7 @@
                         space.str_w(self.get_dtype().descr_repr(space)),
                         space.str_w(new_dtype.descr_repr(space)), casting)
         order  = order_converter(space, space.wrap(order), self.get_order())
-        if (not copy and new_dtype == self.get_dtype() 
+        if (not copy and new_dtype == self.get_dtype()
                 and (order in (NPY.KEEPORDER, NPY.ANYORDER) or order == 
self.get_order())
                 and (subok or type(self) is W_NDimArray)):
             return self
diff --git a/pypy/module/micronumpy/strides.py 
b/pypy/module/micronumpy/strides.py
--- a/pypy/module/micronumpy/strides.py
+++ b/pypy/module/micronumpy/strides.py
@@ -1,14 +1,13 @@
 from pypy.interpreter.error import oefmt
 from rpython.rlib import jit
-from pypy.module.micronumpy import support, constants as NPY
+from pypy.module.micronumpy import constants as NPY
 from pypy.module.micronumpy.base import W_NDimArray
 
 
 # structures to describe slicing
 
 class BaseChunk(object):
-    _attrs_ = ['step','out_dim']
-    pass
+    _attrs_ = ['step', 'out_dim']
 
 
 class Chunk(BaseChunk):
@@ -36,6 +35,7 @@
 class IntegerChunk(BaseChunk):
     input_dim = 1
     out_dim = 0
+
     def __init__(self, w_idx):
         self.w_idx = w_idx
 
@@ -70,6 +70,7 @@
 class EllipsisChunk(BaseChunk):
     input_dim = 0
     out_dim = 0
+
     def __init__(self):
         pass
 
@@ -80,6 +81,7 @@
 class BooleanChunk(BaseChunk):
     input_dim = 1
     out_dim = 1
+
     def __init__(self, w_idx):
         self.w_idx = w_idx
 
diff --git a/pypy/module/micronumpy/ufuncs.py b/pypy/module/micronumpy/ufuncs.py
--- a/pypy/module/micronumpy/ufuncs.py
+++ b/pypy/module/micronumpy/ufuncs.py
@@ -1521,7 +1521,7 @@
 # Instantiated in cpyext/ndarrayobject. It is here since ufunc calls
 # set_dims_and_steps, otherwise ufunc, ndarrayobject would have circular
 # imports
-npy_intpp = rffi.LONGP
+npy_intpp = rffi.INTPTR_T
 LONG_SIZE = LONG_BIT / 8
 CCHARP_SIZE = _get_bitsize('P') / 8
 
diff --git a/pypy/module/select/interp_epoll.py 
b/pypy/module/select/interp_epoll.py
--- a/pypy/module/select/interp_epoll.py
+++ b/pypy/module/select/interp_epoll.py
@@ -53,6 +53,10 @@
 EPOLL_CTL_MOD = cconfig["EPOLL_CTL_MOD"]
 EPOLL_CTL_DEL = cconfig["EPOLL_CTL_DEL"]
 
+DEF_REGISTER_EVENTMASK = (public_symbols["EPOLLIN"] |
+                          public_symbols["EPOLLOUT"] |
+                          public_symbols["EPOLLPRI"])
+
 epoll_create = rffi.llexternal(
     "epoll_create", [rffi.INT], rffi.INT, compilation_info=eci,
     save_err=rffi.RFFI_SAVE_ERRNO
@@ -133,7 +137,7 @@
         self.close()
 
     @unwrap_spec(eventmask=int)
-    def descr_register(self, space, w_fd, eventmask=-1):
+    def descr_register(self, space, w_fd, eventmask=DEF_REGISTER_EVENTMASK):
         self.check_closed(space)
         self.epoll_ctl(space, EPOLL_CTL_ADD, w_fd, eventmask)
 
@@ -142,7 +146,7 @@
         self.epoll_ctl(space, EPOLL_CTL_DEL, w_fd, 0, ignore_ebadf=True)
 
     @unwrap_spec(eventmask=int)
-    def descr_modify(self, space, w_fd, eventmask=-1):
+    def descr_modify(self, space, w_fd, eventmask):
         self.check_closed(space)
         self.epoll_ctl(space, EPOLL_CTL_MOD, w_fd, eventmask)
 
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
@@ -56,7 +56,7 @@
         max = int(max)
         p = ffi.cast(c_decl, min)
         assert p != min       # no __eq__(int)
-        assert bool(p) is True
+        assert bool(p) is bool(min)
         assert int(p) == min
         p = ffi.cast(c_decl, max)
         assert int(p) == max
@@ -285,7 +285,9 @@
         assert ffi.new("char*", b"\xff")[0] == b'\xff'
         assert ffi.new("char*")[0] == b'\x00'
         assert int(ffi.cast("char", 300)) == 300 - 256
-        assert bool(ffi.cast("char", 0))
+        assert not bool(ffi.cast("char", 0))
+        assert bool(ffi.cast("char", 1))
+        assert bool(ffi.cast("char", 255))
         py.test.raises(TypeError, ffi.new, "char*", 32)
         py.test.raises(TypeError, ffi.new, "char*", u+"x")
         py.test.raises(TypeError, ffi.new, "char*", b"foo")
@@ -326,7 +328,11 @@
             py.test.raises(TypeError, ffi.new, "wchar_t*", u+'\U00012345')
         assert ffi.new("wchar_t*")[0] == u+'\x00'
         assert int(ffi.cast("wchar_t", 300)) == 300
-        assert bool(ffi.cast("wchar_t", 0))
+        assert not bool(ffi.cast("wchar_t", 0))
+        assert bool(ffi.cast("wchar_t", 1))
+        assert bool(ffi.cast("wchar_t", 65535))
+        if SIZE_OF_WCHAR > 2:
+            assert bool(ffi.cast("wchar_t", 65536))
         py.test.raises(TypeError, ffi.new, "wchar_t*", 32)
         py.test.raises(TypeError, ffi.new, "wchar_t*", "foo")
         #
@@ -1523,21 +1529,30 @@
         import gc; gc.collect(); gc.collect(); gc.collect()
         assert seen == [3]
 
+    def test_gc_disable(self):
+        ffi = FFI(backend=self.Backend())
+        p = ffi.new("int *", 123)
+        py.test.raises(TypeError, ffi.gc, p, None)
+        seen = []
+        q1 = ffi.gc(p, lambda p: seen.append(1))
+        q2 = ffi.gc(q1, lambda p: seen.append(2))
+        import gc; gc.collect()
+        assert seen == []
+        assert ffi.gc(q1, None) is None
+        del q1, q2
+        import gc; gc.collect(); gc.collect(); gc.collect()
+        assert seen == [2]
+
     def test_gc_finite_list(self):
         ffi = FFI(backend=self.Backend())
-        public = not hasattr(ffi._backend, 'gcp')
         p = ffi.new("int *", 123)
         keepalive = []
         for i in range(10):
             keepalive.append(ffi.gc(p, lambda p: None))
-            if public:
-                assert len(ffi.gc_weakrefs.data) == i + 1
         del keepalive[:]
         import gc; gc.collect(); gc.collect()
         for i in range(10):
             keepalive.append(ffi.gc(p, lambda p: None))
-        if public:
-            assert len(ffi.gc_weakrefs.data) == 10
 
     def test_CData_CType(self):
         ffi = FFI(backend=self.Backend())
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py
@@ -467,12 +467,12 @@
 
     def test_introspect_order(self):
         ffi = FFI()
-        ffi.cdef("union aaa { int a; }; typedef struct ccc { int a; } b;")
-        ffi.cdef("union g   { int a; }; typedef struct cc  { int a; } bbb;")
-        ffi.cdef("union aa  { int a; }; typedef struct a   { int a; } bb;")
-        assert ffi.list_types() == (['b', 'bb', 'bbb'],
-                                    ['a', 'cc', 'ccc'],
-                                    ['aa', 'aaa', 'g'])
+        ffi.cdef("union CFFIaaa { int a; }; typedef struct CFFIccc { int a; } 
CFFIb;")
+        ffi.cdef("union CFFIg   { int a; }; typedef struct CFFIcc  { int a; } 
CFFIbbb;")
+        ffi.cdef("union CFFIaa  { int a; }; typedef struct CFFIa   { int a; } 
CFFIbb;")
+        assert ffi.list_types() == (['CFFIb', 'CFFIbb', 'CFFIbbb'],
+                                    ['CFFIa', 'CFFIcc', 'CFFIccc'],
+                                    ['CFFIaa', 'CFFIaaa', 'CFFIg'])
 
     def test_unpack(self):
         ffi = FFI()
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py
@@ -139,7 +139,7 @@
         max = int(max)
         p = ffi.cast(c_decl, min)
         assert p != min       # no __eq__(int)
-        assert bool(p) is True
+        assert bool(p) is bool(min)
         assert int(p) == min
         p = ffi.cast(c_decl, max)
         assert int(p) == max
@@ -351,7 +351,9 @@
         assert ffi.new("char*", b"\xff")[0] == b'\xff'
         assert ffi.new("char*")[0] == b'\x00'
         assert int(ffi.cast("char", 300)) == 300 - 256
-        assert bool(ffi.cast("char", 0))
+        assert not bool(ffi.cast("char", 0))
+        assert bool(ffi.cast("char", 1))
+        assert bool(ffi.cast("char", 255))
         py.test.raises(TypeError, ffi.new, "char*", 32)
         py.test.raises(TypeError, ffi.new, "char*", u+"x")
         py.test.raises(TypeError, ffi.new, "char*", b"foo")
@@ -391,7 +393,11 @@
             py.test.raises(TypeError, ffi.new, "wchar_t*", u+'\U00012345')
         assert ffi.new("wchar_t*")[0] == u+'\x00'
         assert int(ffi.cast("wchar_t", 300)) == 300
-        assert bool(ffi.cast("wchar_t", 0))
+        assert not bool(ffi.cast("wchar_t", 0))
+        assert bool(ffi.cast("wchar_t", 1))
+        assert bool(ffi.cast("wchar_t", 65535))
+        if SIZE_OF_WCHAR > 2:
+            assert bool(ffi.cast("wchar_t", 65536))
         py.test.raises(TypeError, ffi.new, "wchar_t*", 32)
         py.test.raises(TypeError, ffi.new, "wchar_t*", "foo")
         #
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
@@ -1898,14 +1898,14 @@
 
 def test_introspect_order():
     ffi = FFI()
-    ffi.cdef("union aaa { int a; }; typedef struct ccc { int a; } b;")
-    ffi.cdef("union g   { int a; }; typedef struct cc  { int a; } bbb;")
-    ffi.cdef("union aa  { int a; }; typedef struct a   { int a; } bb;")
+    ffi.cdef("union CFFIaaa { int a; }; typedef struct CFFIccc { int a; } 
CFFIb;")
+    ffi.cdef("union CFFIg   { int a; }; typedef struct CFFIcc  { int a; } 
CFFIbbb;")
+    ffi.cdef("union CFFIaa  { int a; }; typedef struct CFFIa   { int a; } 
CFFIbb;")
     verify(ffi, "test_introspect_order", """
-        union aaa { int a; }; typedef struct ccc { int a; } b;
-        union g   { int a; }; typedef struct cc  { int a; } bbb;
-        union aa  { int a; }; typedef struct a   { int a; } bb;
+        union CFFIaaa { int a; }; typedef struct CFFIccc { int a; } CFFIb;
+        union CFFIg   { int a; }; typedef struct CFFIcc  { int a; } CFFIbbb;
+        union CFFIaa  { int a; }; typedef struct CFFIa   { int a; } CFFIbb;
     """)
-    assert ffi.list_types() == (['b', 'bb', 'bbb'],
-                                    ['a', 'cc', 'ccc'],
-                                    ['aa', 'aaa', 'g'])
+    assert ffi.list_types() == (['CFFIb', 'CFFIbb', 'CFFIbbb'],
+                                ['CFFIa', 'CFFIcc', 'CFFIccc'],
+                                ['CFFIaa', 'CFFIaaa', 'CFFIg'])
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
@@ -280,6 +280,14 @@
             pass
         with open("setup.py", "w") as f:
             f.write("""if 1:
+                # https://bugs.python.org/issue23246
+                import sys
+                if sys.platform == 'win32':
+                    try:
+                        import setuptools
+                    except ImportError:
+                        pass
+
                 import cffi
                 ffi = cffi.FFI()
                 ffi.set_source("pack1.mymod", "/*code would be here*/")
diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py 
b/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py
--- a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py
@@ -80,8 +80,21 @@
             # find a solution to that: we could hack sys.path inside the
             # script run here, but we can't hack it in the same way in
             # execute().
-            output = self._run([sys.executable,
-                                os.path.join(local_dir, filename)])
+            pathname = os.path.join(path, filename)
+            with open(pathname, 'w') as g:
+                g.write('''
+# https://bugs.python.org/issue23246
+import sys
+if sys.platform == 'win32':
+    try:
+        import setuptools
+    except ImportError:
+        pass
+''')
+                with open(os.path.join(local_dir, filename), 'r') as f:
+                    g.write(f.read())
+
+            output = self._run([sys.executable, pathname])
             match = re.compile(r"\bFILENAME: (.+)").search(output)
             assert match
             dynamic_lib_name = match.group(1)
diff --git a/pypy/module/test_lib_pypy/cffi_tests/udir.py 
b/pypy/module/test_lib_pypy/cffi_tests/udir.py
--- a/pypy/module/test_lib_pypy/cffi_tests/udir.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/udir.py
@@ -1,4 +1,14 @@
 # Generated by pypy/tool/import_cffi.py
 import py
+import sys
 
 udir = py.path.local.make_numbered_dir(prefix = 'ffi-')
+
+
+# Windows-only workaround for some configurations: see
+# https://bugs.python.org/issue23246 (Python 2.7.9)
+if sys.platform == 'win32':
+    try:
+        import setuptools
+    except ImportError:
+        pass
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
@@ -484,7 +484,12 @@
         return None
 
     def view_as_kwargs(self, w_dict):
-        if type(w_dict) is W_DictObject:
+        # Tries to return (keys_list, values_list), or (None, None) if
+        # it fails.  It can fail on some dict implementations, so don't
+        # rely on it.  For dict subclasses, though, it never fails;
+        # this emulates CPython's behavior which often won't call
+        # custom __iter__() or keys() methods in dict subclasses.
+        if isinstance(w_dict, W_DictObject):
             return w_dict.view_as_kwargs()
         return (None, None)
 
diff --git a/pypy/tool/release/repackage.sh b/pypy/tool/release/repackage.sh
--- a/pypy/tool/release/repackage.sh
+++ b/pypy/tool/release/repackage.sh
@@ -3,7 +3,7 @@
 min=1
 rev=1
 branchname=release-$maj.x  # ==OR== release-$maj.$min.x
-tagname=release-$maj.$min  # ==OR== release-$maj.$min.$rev
+tagname=release-$maj.$min.$rev  # ==OR== release-$maj.$min
 
 hg log -r $branchname || exit 1
 hg log -r $tagname || exit 1
diff --git a/rpython/jit/metainterp/optimizeopt/intutils.py 
b/rpython/jit/metainterp/optimizeopt/intutils.py
--- a/rpython/jit/metainterp/optimizeopt/intutils.py
+++ b/rpython/jit/metainterp/optimizeopt/intutils.py
@@ -1,5 +1,8 @@
+import sys
 from rpython.rlib.rarithmetic import ovfcheck, LONG_BIT, maxint, is_valid_int
 from rpython.rlib.objectmodel import we_are_translated
+from rpython.rtyper.lltypesystem import lltype
+from rpython.rtyper.lltypesystem.lloperation import llop
 from rpython.jit.metainterp.resoperation import rop, ResOperation
 from rpython.jit.metainterp.optimizeopt.info import AbstractInfo, 
INFO_NONNULL,\
      INFO_UNKNOWN, INFO_NULL
@@ -174,15 +177,13 @@
     def div_bound(self, other):
         if self.has_upper and self.has_lower and \
            other.has_upper and other.has_lower and \
-           not other.contains(0):
-            try:
-                vals = (ovfcheck(self.upper / other.upper),
-                        ovfcheck(self.upper / other.lower),
-                        ovfcheck(self.lower / other.upper),
-                        ovfcheck(self.lower / other.lower))
-                return IntBound(min4(vals), max4(vals))
-            except OverflowError:
-                return IntUnbounded()
+           not other.contains(0) and self.lower > (-sys.maxint-1):
+            vals = (
+                llop.int_floordiv(lltype.Signed, self.upper, other.upper),
+                llop.int_floordiv(lltype.Signed, self.upper, other.lower),
+                llop.int_floordiv(lltype.Signed, self.lower, other.upper),
+                llop.int_floordiv(lltype.Signed, self.lower, other.lower))
+            return IntBound(min4(vals), max4(vals))
         else:
             return IntUnbounded()
 
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py 
b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
@@ -240,6 +240,8 @@
 
 
 def test_div_bound():
+    from rpython.rtyper.lltypesystem import lltype
+    from rpython.rtyper.lltypesystem.lloperation import llop
     for _, _, b1 in some_bounds():
         for _, _, b2 in some_bounds():
             b3 = b1.div_bound(b2)
@@ -247,7 +249,8 @@
                 for n2 in nbr:
                     if b1.contains(n1) and b2.contains(n2):
                         if n2 != 0:
-                            assert b3.contains(n1 / n2)
+                            assert b3.contains(
+                                llop.int_floordiv(lltype.Signed, n1, n2))
 
     a=bound(2, 4).div_bound(bound(1, 2))
     assert not a.contains(0)
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py 
b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -5529,6 +5529,27 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_division_bound_bug(self):
+        ops = """
+        [i4]
+        i1 = int_ge(i4, -50)
+        guard_true(i1) []
+        i2 = int_le(i4, -40)
+        guard_true(i2) []
+        # here, -50 <= i4 <= -40
+
+        i5 = int_floordiv(i4, 30)
+        # here, we know that that i5 == -1  (C-style handling of negatives!)
+        escape_n(i5)
+        jump(i4)
+        """
+        expected = """
+        [i4, i5]
+        escape_n(-1)
+        jump(i4, -1)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_subsub_ovf(self):
         ops = """
         [i0]
diff --git a/rpython/rlib/runicode.py b/rpython/rlib/runicode.py
--- a/rpython/rlib/runicode.py
+++ b/rpython/rlib/runicode.py
@@ -989,8 +989,6 @@
     return result.build(), pos
 
 
-# Specialize on the errorhandler when it's a constant
-@specialize.arg_or_var(4)
 def str_decode_ascii(s, size, errors, final=False,
                      errorhandler=None):
     if errorhandler is None:
@@ -1020,8 +1018,6 @@
     return result.build()
 
 
-# Specialize on the errorhandler when it's a constant
-@specialize.arg_or_var(3)
 def unicode_encode_ucs1_helper(p, size, errors,
                                errorhandler=None, limit=256):
     if errorhandler is None:
@@ -1064,12 +1060,10 @@
 
     return result.build()
 
-@specialize.arg_or_var(3)
 def unicode_encode_latin_1(p, size, errors, errorhandler=None):
     res = unicode_encode_ucs1_helper(p, size, errors, errorhandler, 256)
     return res
 
-@specialize.arg_or_var(3)
 def unicode_encode_ascii(p, size, errors, errorhandler=None):
     res = unicode_encode_ucs1_helper(p, size, errors, errorhandler, 128)
     return res
@@ -1194,8 +1188,6 @@
                 builder.append(res)
     return pos
 
-# Specialize on the errorhandler when it's a constant
-@specialize.arg_or_var(4)
 def str_decode_unicode_escape(s, size, errors, final=False,
                               errorhandler=None,
                               unicodedata_handler=None):
diff --git a/rpython/translator/driver.py b/rpython/translator/driver.py
--- a/rpython/translator/driver.py
+++ b/rpython/translator/driver.py
@@ -552,16 +552,16 @@
         self.log.info('usession directory: %s' % (udir,))
         return result
 
-    @staticmethod
-    def from_targetspec(targetspec_dic, config=None, args=None,
+    @classmethod
+    def from_targetspec(cls, targetspec_dic, config=None, args=None,
                         empty_translator=None,
                         disable=[],
                         default_goal=None):
         if args is None:
             args = []
 
-        driver = TranslationDriver(config=config, default_goal=default_goal,
-                                   disable=disable)
+        driver = cls(config=config, default_goal=default_goal,
+                     disable=disable)
         target = targetspec_dic['target']
         spec = target(driver, args)
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to