[pypy-commit] pypy ppc-vsx-support: merge default

plan_rich pypy.commits at gmail.com
Tue Aug 23 05:09:09 EDT 2016


Author: Richard Plangger <planrichi at gmail.com>
Branch: ppc-vsx-support
Changeset: r86438:a39f3886c9ac
Date: 2016-08-23 09:39 +0200
http://bitbucket.org/pypy/pypy/changeset/a39f3886c9ac/

Log:	merge default

diff too long, truncating to 2000 out of 5493 lines

diff --git a/include/PyPy.h b/include/PyPy.h
--- a/include/PyPy.h
+++ b/include/PyPy.h
@@ -2,7 +2,11 @@
 #define _PYPY_H_
 
 /* This header is meant to be included in programs that use PyPy as an
-   embedded library. */
+   embedded library.
+
+   NOTE: this is deprecated.  Instead, use cffi's embedding support:
+   http://cffi.readthedocs.org/en/latest/embedding.html
+*/
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: cffi
-Version: 1.7.0
+Version: 1.8.0
 Summary: Foreign Function Interface for Python calling C code.
 Home-page: http://cffi.readthedocs.org
 Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@
 from .api import FFI, CDefError, FFIError
 from .ffiplatform import VerificationError, VerificationMissing
 
-__version__ = "1.7.0"
-__version_info__ = (1, 7, 0)
+__version__ = "1.8.0"
+__version_info__ = (1, 8, 0)
 
 # The verifier module file names are based on the CRC32 of a string that
 # contains the following version number.  It may be older than __version__
diff --git a/lib_pypy/cffi/_cffi_include.h b/lib_pypy/cffi/_cffi_include.h
--- a/lib_pypy/cffi/_cffi_include.h
+++ b/lib_pypy/cffi/_cffi_include.h
@@ -42,7 +42,9 @@
 #  include <stdint.h>
 # endif
 # if _MSC_VER < 1800   /* MSVC < 2013 */
-   typedef unsigned char _Bool;
+#  ifndef __cplusplus
+    typedef unsigned char _Bool;
+#  endif
 # endif
 #else
 # include <stdint.h>
@@ -59,7 +61,7 @@
 
 #ifdef __cplusplus
 # ifndef _Bool
-#  define _Bool bool   /* semi-hackish: C++ has no _Bool; bool is builtin */
+   typedef bool _Bool;   /* semi-hackish: C++ has no _Bool; bool is builtin */
 # endif
 #endif
 
@@ -196,20 +198,6 @@
     return NULL;
 }
 
-_CFFI_UNUSED_FN
-static PyObject **_cffi_unpack_args(PyObject *args_tuple, Py_ssize_t expected,
-                                    const char *fnname)
-{
-    if (PyTuple_GET_SIZE(args_tuple) != expected) {
-        PyErr_Format(PyExc_TypeError,
-                     "%.150s() takes exactly %zd arguments (%zd given)",
-                     fnname, expected, PyTuple_GET_SIZE(args_tuple));
-        return NULL;
-    }
-    return &PyTuple_GET_ITEM(args_tuple, 0);   /* pointer to the first item,
-                                                  the others follow */
-}
-
 /**********  end CPython-specific section  **********/
 #else
 _CFFI_UNUSED_FN
diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -233,7 +233,7 @@
         f = PySys_GetObject((char *)"stderr");
         if (f != NULL && f != Py_None) {
             PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
-                               "\ncompiled with cffi version: 1.7.0"
+                               "\ncompiled with cffi version: 1.8.0"
                                "\n_cffi_backend module: ", f);
             modules = PyImport_GetModuleDict();
             mod = PyDict_GetItemString(modules, "_cffi_backend");
diff --git a/lib_pypy/cffi/model.py b/lib_pypy/cffi/model.py
--- a/lib_pypy/cffi/model.py
+++ b/lib_pypy/cffi/model.py
@@ -519,12 +519,10 @@
             smallest_value = min(self.enumvalues)
             largest_value = max(self.enumvalues)
         else:
-            import warnings
-            warnings.warn("%r has no values explicitly defined; next version "
-                          "will refuse to guess which integer type it is "
-                          "meant to be (unsigned/signed, int/long)"
-                          % self._get_c_name())
-            smallest_value = largest_value = 0
+            raise api.CDefError("%r has no values explicitly defined: "
+                                "refusing to guess which integer type it is "
+                                "meant to be (unsigned/signed, int/long)"
+                % self._get_c_name())
         if smallest_value < 0:   # needs a signed type
             sign = 1
             candidate1 = PrimitiveType("int")
diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py
--- a/lib_pypy/cffi/recompiler.py
+++ b/lib_pypy/cffi/recompiler.py
@@ -275,6 +275,8 @@
     def write_c_source_to_f(self, f, preamble):
         self._f = f
         prnt = self._prnt
+        if self.ffi._embedding is None:
+            prnt('#define Py_LIMITED_API')
         #
         # first the '#include' (actually done by inlining the file's content)
         lines = self._rel_readlines('_cffi_include.h')
@@ -513,7 +515,7 @@
                                                     tovar, errcode)
             return
         #
-        elif isinstance(tp, (model.StructOrUnion, model.EnumType)):
+        elif isinstance(tp, model.StructOrUnionOrEnum):
             # a struct (not a struct pointer) as a function argument
             self._prnt('  if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)'
                       % (tovar, self._gettypenum(tp), fromvar))
@@ -570,7 +572,7 @@
         elif isinstance(tp, model.ArrayType):
             return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % (
                 var, self._gettypenum(model.PointerType(tp.item)))
-        elif isinstance(tp, model.StructType):
+        elif isinstance(tp, model.StructOrUnion):
             if tp.fldnames is None:
                 raise TypeError("'%s' is used as %s, but is opaque" % (
                     tp._get_c_name(), context))
@@ -683,13 +685,11 @@
             rng = range(len(tp.args))
             for i in rng:
                 prnt('  PyObject *arg%d;' % i)
-            prnt('  PyObject **aa;')
             prnt()
-            prnt('  aa = _cffi_unpack_args(args, %d, "%s");' % (len(rng), name))
-            prnt('  if (aa == NULL)')
+            prnt('  if (!PyArg_UnpackTuple(args, "%s", %d, %d, %s))' % (
+                name, len(rng), len(rng),
+                ', '.join(['&arg%d' % i for i in rng])))
             prnt('    return NULL;')
-            for i in rng:
-                prnt('  arg%d = aa[%d];' % (i, i))
         prnt()
         #
         for i, type in enumerate(tp.args):
@@ -862,6 +862,8 @@
             enumfields = list(tp.enumfields())
             for fldname, fldtype, fbitsize, fqual in enumfields:
                 fldtype = self._field_type(tp, fldname, fldtype)
+                self._check_not_opaque(fldtype,
+                                       "field '%s.%s'" % (tp.name, fldname))
                 # cname is None for _add_missing_struct_unions() only
                 op = OP_NOOP
                 if fbitsize >= 0:
@@ -911,6 +913,13 @@
                             first_field_index, c_fields))
         self._seen_struct_unions.add(tp)
 
+    def _check_not_opaque(self, tp, location):
+        while isinstance(tp, model.ArrayType):
+            tp = tp.item
+        if isinstance(tp, model.StructOrUnion) and tp.fldtypes is None:
+            raise TypeError(
+                "%s is of an opaque type (not declared in cdef())" % location)
+
     def _add_missing_struct_unions(self):
         # not very nice, but some struct declarations might be missing
         # because they don't have any known C name.  Check that they are
diff --git a/lib_pypy/cffi/vengine_cpy.py b/lib_pypy/cffi/vengine_cpy.py
--- a/lib_pypy/cffi/vengine_cpy.py
+++ b/lib_pypy/cffi/vengine_cpy.py
@@ -308,7 +308,7 @@
         elif isinstance(tp, model.ArrayType):
             return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % (
                 var, self._gettypenum(model.PointerType(tp.item)))
-        elif isinstance(tp, model.StructType):
+        elif isinstance(tp, model.StructOrUnion):
             if tp.fldnames is None:
                 raise TypeError("'%s' is used as %s, but is opaque" % (
                     tp._get_c_name(), context))
diff --git a/lib_pypy/resource.py b/lib_pypy/resource.py
--- a/lib_pypy/resource.py
+++ b/lib_pypy/resource.py
@@ -86,7 +86,11 @@
     if len(limits) != 2:
         raise ValueError("expected a tuple of 2 integers")
 
-    if lib.my_setrlimit(resource, limits[0], limits[1]) == -1:
+    # accept and round down floats, like CPython does
+    limit0 = int(limits[0])
+    limit1 = int(limits[1])
+
+    if lib.my_setrlimit(resource, limit0, limit1) == -1:
         if ffi.errno == EINVAL:
             raise ValueError("current limit exceeds maximum limit")
         elif ffi.errno == EPERM:
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -99,17 +99,24 @@
 
 The garbage collectors used or implemented by PyPy are not based on
 reference counting, so the objects are not freed instantly when they are no
-longer reachable.  The most obvious effect of this is that files are not
+longer reachable.  The most obvious effect of this is that files (and sockets, etc) are not
 promptly closed when they go out of scope.  For files that are opened for
 writing, data can be left sitting in their output buffers for a while, making
 the on-disk file appear empty or truncated.  Moreover, you might reach your
 OS's limit on the number of concurrently opened files.
 
-Fixing this is essentially impossible without forcing a
+If you are debugging a case where a file in your program is not closed
+properly, you can use the ``-X track-resources`` command line option. If it is
+given, a ``ResourceWarning`` is produced for every file and socket that the
+garbage collector closes. The warning will contain the stack trace of the
+position where the file or socket was created, to make it easier to see which
+parts of the program don't close files explicitly.
+
+Fixing this difference to CPython is essentially impossible without forcing a
 reference-counting approach to garbage collection.  The effect that you
 get in CPython has clearly been described as a side-effect of the
 implementation and not a language design decision: programs relying on
-this are basically bogus.  It would anyway be insane to try to enforce
+this are basically bogus.  It would be a too strong restriction to try to enforce
 CPython's behavior in a language spec, given that it has no chance to be
 adopted by Jython or IronPython (or any other port of Python to Java or
 .NET).
@@ -134,7 +141,7 @@
 
 Here are some more technical details.  This issue affects the precise
 time at which ``__del__`` methods are called, which
-is not reliable in PyPy (nor Jython nor IronPython).  It also means that
+is not reliable or timely in PyPy (nor Jython nor IronPython).  It also means that
 **weak references** may stay alive for a bit longer than expected.  This
 makes "weak proxies" (as returned by ``weakref.proxy()``) somewhat less
 useful: they will appear to stay alive for a bit longer in PyPy, and
diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst
--- a/pypy/doc/faq.rst
+++ b/pypy/doc/faq.rst
@@ -356,6 +356,11 @@
 that a C-level traceback is usually of no help at all in PyPy.
 Debugging PyPy can be annoying.
 
+`This is a clear and useful bug report.`__  (Admittedly, sometimes
+the problem is really hard to reproduce, but please try to.)
+
+.. __: https://bitbucket.org/pypy/pypy/issues/2363/segfault-in-gc-pinned-object-in
+
 In more details:
 
 * First, please give the exact PyPy version, and the OS.
diff --git a/pypy/doc/gc_info.rst b/pypy/doc/gc_info.rst
--- a/pypy/doc/gc_info.rst
+++ b/pypy/doc/gc_info.rst
@@ -14,10 +14,9 @@
     Defaults to 1/2 of your cache or ``4M``.
     Small values (like 1 or 1KB) are useful for debugging.
 
-``PYPY_GC_NURSERY_CLEANUP``
-    The interval at which nursery is cleaned up. Must
-    be smaller than the nursery size and bigger than the
-    biggest object we can allotate in the nursery.
+``PYPY_GC_NURSERY_DEBUG``
+    If set to non-zero, will fill nursery with garbage, to help
+    debugging.
 
 ``PYPY_GC_INCREMENT_STEP``
     The size of memory marked during the marking step.  Default is size of
@@ -62,3 +61,8 @@
     use.
     Values are ``0`` (off), ``1`` (on major collections) or ``2`` (also
     on minor collections).
+
+``PYPY_GC_MAX_PINNED``
+    The maximal number of pinned objects at any point in time.  Defaults
+    to a conservative value depending on nursery size and maximum object
+    size inside the nursery.  Useful for debugging by setting it to 0.
diff --git a/pypy/doc/man/pypy.1.rst b/pypy/doc/man/pypy.1.rst
--- a/pypy/doc/man/pypy.1.rst
+++ b/pypy/doc/man/pypy.1.rst
@@ -2,6 +2,9 @@
  pypy
 ======
 
+.. note: this is turned into a regular man page "pypy.1" by
+   doing "make man" in pypy/doc/
+
 SYNOPSIS
 ========
 
@@ -48,6 +51,10 @@
 -B
     Disable writing bytecode (``.pyc``) files.
 
+-X track-resources
+    Produce a ``ResourceWarning`` whenever a file or socket is closed by the
+    garbage collector.
+
 --version
     Print the PyPy version.
 
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
@@ -119,3 +119,34 @@
 ``ffi.from_buffer(string)`` in CFFI.  Additionally, and most
 importantly, CFFI calls that take directly a string as argument don't
 copy the string any more---this is like CFFI on CPython.
+
+.. branch: resource_warning
+
+Add a new command line option -X track-resources which will produce
+ResourceWarnings when the GC closes unclosed files and sockets.
+
+.. branch: cpyext-realloc
+
+Implement PyObject_Realloc
+
+.. branch: inline-blocks
+
+Improve a little bit the readability of the generated C code
+
+.. branch: improve-vmprof-testing
+
+Improved vmprof support: now tries hard to not miss any Python-level
+frame in the captured stacks, even if there is the metainterp or
+blackhole interp involved.  Also fix the stacklet (greenlet) support.
+
+.. branch: py2-mappingproxy
+
+``type.__dict__`` now returns a ``dict_proxy`` object, like on CPython.
+Previously it returned what looked like a regular dict object (but it
+was already read-only).
+
+
+.. branch: const-fold-we-are-jitted
+
+Reduce the size of the generated C code by constant-folding ``we_are_jitted``
+in non-jitcode.
diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py
--- a/pypy/interpreter/app_main.py
+++ b/pypy/interpreter/app_main.py
@@ -24,11 +24,15 @@
 -V     : print the Python version number and exit (also --version)
 -W arg : warning control; arg is action:message:category:module:lineno
          also PYTHONWARNINGS=arg
+-X arg : set implementation-specific option
 file   : program read from script file
 -      : program read from stdin (default; interactive mode if a tty)
 arg ...: arguments passed to program in sys.argv[1:]
+
 PyPy options and arguments:
 --info : print translation information about this PyPy executable
+-X track-resources : track the creation of files and sockets and display
+                     a warning if they are not closed explicitly
 """
 # Missing vs CPython: PYTHONHOME, PYTHONCASEOK
 USAGE2 = """
@@ -229,6 +233,14 @@
         import pypyjit
         pypyjit.set_param(jitparam)
 
+def set_runtime_options(options, Xparam, *args):
+    if Xparam == 'track-resources':
+        sys.pypy_set_track_resources(True)
+    else:
+        print >> sys.stderr, 'usage: %s -X [options]' % (get_sys_executable(),)
+        print >> sys.stderr, '[options] can be: track-resources'
+        raise SystemExit
+
 class CommandLineError(Exception):
     pass
 
@@ -404,6 +416,7 @@
     '--info':    (print_info,      None),
     '--jit':     (set_jit_option,  Ellipsis),
     '-funroll-loops': (funroll_loops, None),
+    '-X':        (set_runtime_options, Ellipsis),
     '--':        (end_options,     None),
     }
 
diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -387,7 +387,8 @@
     def _stacksize(self, blocks):
         """Compute co_stacksize."""
         for block in blocks:
-            block.initial_depth = 0
+            block.initial_depth = -99
+        blocks[0].initial_depth = 0
         # Assumes that it is sufficient to walk the blocks in 'post-order'.
         # This means we ignore all back-edges, but apart from that, we only
         # look into a block when all the previous blocks have been done.
@@ -406,8 +407,11 @@
 
     def _do_stack_depth_walk(self, block):
         depth = block.initial_depth
+        if depth == -99:     # this block is never reached, skip
+             return 0
         for instr in block.instructions:
             depth += _opcode_stack_effect(instr.opcode, instr.arg)
+            assert depth >= 0
             if depth >= self._max_depth:
                 self._max_depth = depth
             jump_op = instr.opcode
diff --git a/pypy/interpreter/astcompiler/optimize.py b/pypy/interpreter/astcompiler/optimize.py
--- a/pypy/interpreter/astcompiler/optimize.py
+++ b/pypy/interpreter/astcompiler/optimize.py
@@ -108,8 +108,15 @@
         return getattr(space, name)(operand)
     return do_fold
 
-def _fold_pow(space, left, right):
-    return space.pow(left, right, space.w_None)
+def _fold_pow(space, w_left, w_right):
+    # don't constant-fold if "w_left" and "w_right" are integers and
+    # the estimated bit length of the power is unreasonably large
+    space.appexec([w_left, w_right], """(left, right):
+        if isinstance(left, (int, long)) and isinstance(right, (int, long)):
+            if left.bit_length() * right > 5000:
+                raise OverflowError
+    """)
+    return space.pow(w_left, w_right, space.w_None)
 
 def _fold_not(space, operand):
     return space.wrap(not space.is_true(operand))
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -1156,3 +1156,22 @@
             counts = self.count_instructions(source)
             assert ops.BUILD_SET not in counts
             assert ops.LOAD_CONST in counts
+
+    def test_dont_fold_huge_powers(self):
+        for source in (
+            "2 ** 3000",         # not constant-folded: too big
+            "(-2) ** 3000",
+            ):
+            source = 'def f(): %s' % source
+            counts = self.count_instructions(source)
+            assert ops.BINARY_POWER in counts
+
+        for source in (
+            "2 ** 2000",         # constant-folded
+            "2 ** -3000",
+            "1.001 ** 3000",
+            "1 ** 3000.0",
+            ):
+            source = 'def f(): %s' % source
+            counts = self.count_instructions(source)
+            assert ops.BINARY_POWER not in counts
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1703,6 +1703,23 @@
                 "Python int too large for C unsigned short")
         return value
 
+    def c_uid_t_w(self, w_obj):
+        # xxx assumes that uid_t and gid_t are a C unsigned int.
+        # Equivalent to space.c_uint_w(), with the exception that
+        # it also accepts -1 and converts that to UINT_MAX, which
+        # is (uid_t)-1.  And values smaller than -1 raise
+        # OverflowError, not ValueError.
+        try:
+            return self.c_uint_w(w_obj)
+        except OperationError as e:
+            if e.match(self, self.w_ValueError):
+                # ValueError: cannot convert negative integer to unsigned
+                if self.int_w(w_obj) == -1:
+                    return UINT_MAX
+                raise oefmt(self.w_OverflowError,
+                            "user/group id smaller than minimum (-1)")
+            raise
+
     def truncatedint_w(self, w_obj, allow_conversion=True):
         # Like space.gateway_int_w(), but return the integer truncated
         # instead of raising OverflowError.  For obscure cases only.
@@ -1764,6 +1781,40 @@
             _warnings.warn(msg, warningcls, stacklevel=stacklevel)
         """)
 
+    def resource_warning(self, w_msg, w_tb):
+        self.appexec([w_msg, w_tb],
+                     """(msg, tb):
+            import sys
+            print >> sys.stderr, msg
+            if tb:
+                print >> sys.stderr, "Created at (most recent call last):"
+                print >> sys.stderr, tb
+        """)
+
+    def format_traceback(self):
+        # we need to disable track_resources before calling the traceback
+        # module. Else, it tries to open more files to format the traceback,
+        # the file constructor will call space.format_traceback etc., in an
+        # inifite recursion
+        flag = self.sys.track_resources
+        self.sys.track_resources = False
+        try:
+            return self.appexec([],
+                         """():
+                import sys, traceback
+                # the "1" is because we don't want to show THIS code
+                # object in the traceback
+                try:
+                    f = sys._getframe(1)
+                except ValueError:
+                    # this happens if you call format_traceback at the very beginning
+                    # of startup, when there is no bottom code object
+                    return '<no stacktrace available>'
+                return "".join(traceback.format_stack(f))
+            """)
+        finally:
+            self.sys.track_resources = flag
+
 
 class AppExecCache(SpaceCache):
     def build(cache, source):
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -167,6 +167,9 @@
     def visit_c_ushort(self, el, app_sig):
         self.checked_space_method(el, app_sig)
 
+    def visit_c_uid_t(self, el, app_sig):
+        self.checked_space_method(el, app_sig)
+
     def visit_truncatedint_w(self, el, app_sig):
         self.checked_space_method(el, app_sig)
 
@@ -294,6 +297,9 @@
     def visit_c_ushort(self, typ):
         self.run_args.append("space.c_ushort_w(%s)" % (self.scopenext(),))
 
+    def visit_c_uid_t(self, typ):
+        self.run_args.append("space.c_uid_t_w(%s)" % (self.scopenext(),))
+
     def visit_truncatedint_w(self, typ):
         self.run_args.append("space.truncatedint_w(%s)" % (self.scopenext(),))
 
@@ -440,6 +446,9 @@
     def visit_c_ushort(self, typ):
         self.unwrap.append("space.c_ushort_w(%s)" % (self.nextarg(),))
 
+    def visit_c_uid_t(self, typ):
+        self.unwrap.append("space.c_uid_t_w(%s)" % (self.nextarg(),))
+
     def visit_truncatedint_w(self, typ):
         self.unwrap.append("space.truncatedint_w(%s)" % (self.nextarg(),))
 
@@ -587,7 +596,10 @@
 
         # First extract the signature from the (CPython-level) code object
         from pypy.interpreter import pycode
-        argnames, varargname, kwargname = pycode.cpython_code_signature(func.func_code)
+        sig = pycode.cpython_code_signature(func.func_code)
+        argnames = sig.argnames
+        varargname = sig.varargname
+        kwargname = sig.kwargname
         self._argnames = argnames
 
         if unwrap_spec is None:
@@ -611,7 +623,9 @@
         app_sig = SignatureBuilder(func)
 
         UnwrapSpec_Check(orig_sig).apply_over(unwrap_spec, app_sig)
-        self.sig = argnames, varargname, kwargname = app_sig.signature()
+        self.sig = app_sig.signature()
+        argnames = self.sig.argnames
+        varargname = self.sig.varargname
 
         self.minargs = len(argnames)
         if varargname:
@@ -942,7 +956,7 @@
                 defs_w.append(space.wrap(defaultval))
         if self._code._unwrap_spec:
             UNDEFINED = object()
-            alldefs_w = [UNDEFINED] * len(self._code.sig[0])
+            alldefs_w = [UNDEFINED] * len(self._code.sig.argnames)
             if defs_w:
                 alldefs_w[-len(defs_w):] = defs_w
             code = self._code
@@ -959,7 +973,7 @@
                     assert isinstance(w_default, W_Root)
                     assert argname.startswith('w_')
                     argname = argname[2:]
-                    j = self._code.sig[0].index(argname)
+                    j = self._code.sig.argnames.index(argname)
                     assert alldefs_w[j] in (UNDEFINED, None)
                     alldefs_w[j] = w_default
             first_defined = 0
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -37,7 +37,7 @@
 
 # cpython_code_signature helper
 def cpython_code_signature(code):
-    "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)."
+    """Return a Signature instance."""
     argcount = code.co_argcount
     varnames = code.co_varnames
     assert argcount >= 0     # annotator hint
diff --git a/pypy/interpreter/signature.py b/pypy/interpreter/signature.py
--- a/pypy/interpreter/signature.py
+++ b/pypy/interpreter/signature.py
@@ -55,18 +55,3 @@
         if not isinstance(other, Signature):
             return NotImplemented
         return not self == other
-
-
-    # make it look tuply for its use in the annotator
-
-    def __len__(self):
-        return 3
-
-    def __getitem__(self, i):
-        if i == 0:
-            return self.argnames
-        if i == 1:
-            return self.varargname
-        if i == 2:
-            return self.kwargname
-        raise IndexError
\ No newline at end of file
diff --git a/pypy/interpreter/test/test_app_main.py b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -220,6 +220,13 @@
         expected = {"no_user_site": True}
         self.check(['-c', 'pass'], {}, sys_argv=['-c'], run_command='pass', **expected)
 
+    def test_track_resources(self, monkeypatch):
+        myflag = [False]
+        def pypy_set_track_resources(flag):
+            myflag[0] = flag
+        monkeypatch.setattr(sys, 'pypy_set_track_resources', pypy_set_track_resources, raising=False)
+        self.check(['-X', 'track-resources'], {}, sys_argv=[''], run_stdin=True)
+        assert myflag[0] == True
 
 class TestInteraction:
     """
@@ -1074,4 +1081,3 @@
             # assert it did not crash
         finally:
             sys.path[:] = old_sys_path
-
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
@@ -46,13 +46,6 @@
         assert sig.find_argname("c") == 2
         assert sig.find_argname("d") == -1
 
-    def test_tuply(self):
-        sig = Signature(["a", "b", "c"], "d", "e")
-        x, y, z = sig
-        assert x == ["a", "b", "c"]
-        assert y == "d"
-        assert z == "e"
-
 class dummy_wrapped_dict(dict):
     def __nonzero__(self):
         raise NotImplementedError
diff --git a/pypy/interpreter/test/test_objspace.py b/pypy/interpreter/test/test_objspace.py
--- a/pypy/interpreter/test/test_objspace.py
+++ b/pypy/interpreter/test/test_objspace.py
@@ -427,3 +427,28 @@
         space.finish()
         # assert that we reach this point without getting interrupted
         # by the OperationError(NameError)
+
+    def test_format_traceback(self):
+        from pypy.tool.pytest.objspace import maketestobjspace
+        from pypy.interpreter.gateway import interp2app
+        #
+        def format_traceback(space):
+            return space.format_traceback()
+        #
+        space = maketestobjspace()
+        w_format_traceback = space.wrap(interp2app(format_traceback))
+        w_tb = space.appexec([w_format_traceback], """(format_traceback):
+            def foo():
+                return bar()
+            def bar():
+                return format_traceback()
+            return foo()
+        """)
+        tb = space.str_w(w_tb)
+        expected = '\n'.join([
+            '  File "?", line 6, in anonymous',  # this is the appexec code object
+            '  File "?", line 3, in foo',
+            '  File "?", line 5, in bar',
+            ''
+        ])
+        assert tb == expected
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -203,7 +203,8 @@
     name = func.__name__
     extra = ', '.join(extraargs)
     from pypy.interpreter import pycode
-    argnames, _, _ = pycode.cpython_code_signature(func.func_code)
+    sig = pycode.cpython_code_signature(func.func_code)
+    argnames = sig.argnames
     if use_closure:
         if argnames[1] == 'space':
             args = "closure, space, obj"
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -3,7 +3,7 @@
 from rpython.rlib import rdynload, clibffi, entrypoint
 from rpython.rtyper.lltypesystem import rffi
 
-VERSION = "1.7.0"
+VERSION = "1.8.0"
 
 FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
 try:
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
@@ -310,11 +310,15 @@
                             self.ctype.name, ct.name)
             #
             itemsize = ct.ctitem.size
-            if itemsize <= 0:
-                itemsize = 1
             with self as ptr1, w_other as ptr2:
                 diff = (rffi.cast(lltype.Signed, ptr1) -
-                        rffi.cast(lltype.Signed, ptr2)) // itemsize
+                        rffi.cast(lltype.Signed, ptr2))
+            if itemsize > 1:
+                if diff % itemsize:
+                    raise oefmt(space.w_ValueError,
+                        "pointer subtraction: the distance between the two "
+                        "pointers is not a multiple of the item size")
+                diff //= itemsize
             return space.wrap(diff)
         #
         return self._add_or_sub(w_other, -1)
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
@@ -253,6 +253,7 @@
     sandboxsafe=True)
 
 # split here for JIT backends that don't support floats/longlongs/etc.
+ at jit.dont_look_inside
 def is_nonnull_longdouble(cdata):
     return _is_nonnull_longdouble(read_raw_longdouble_data(cdata))
 def is_nonnull_float(cdata, size):
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
@@ -1,7 +1,7 @@
 # ____________________________________________________________
 
 import sys
-assert __version__ == "1.7.0", ("This test_c.py file is for testing a version"
+assert __version__ == "1.8.0", ("This test_c.py file is for testing a version"
                                 " of cffi that differs from the one that we"
                                 " get from 'import _cffi_backend'")
 if sys.version_info < (3,):
@@ -576,6 +576,19 @@
     e = py.test.raises(TypeError, "q - a")
     assert str(e.value) == "cannot subtract cdata 'short *' and cdata 'int *'"
 
+def test_ptr_sub_unaligned():
+    BInt = new_primitive_type("int")
+    BIntPtr = new_pointer_type(BInt)
+    a = cast(BIntPtr, 1240)
+    for bi in range(1430, 1438):
+        b = cast(BIntPtr, bi)
+        if ((bi - 1240) % size_of_int()) == 0:
+            assert b - a == (bi - 1240) // size_of_int()
+            assert a - b == (1240 - bi) // size_of_int()
+        else:
+            py.test.raises(ValueError, "b - a")
+            py.test.raises(ValueError, "a - b")
+
 def test_cast_primitive_from_cdata():
     p = new_primitive_type("int")
     n = cast(p, cast(p, -42))
diff --git a/pypy/module/_cffi_backend/test/test_re_python.py b/pypy/module/_cffi_backend/test/test_re_python.py
--- a/pypy/module/_cffi_backend/test/test_re_python.py
+++ b/pypy/module/_cffi_backend/test/test_re_python.py
@@ -69,10 +69,13 @@
         sub_ffi.set_source('re_py_subsrc', None)
         sub_ffi.emit_python_code(str(tmpdir.join('re_py_subsrc.py')))
         #
-        space.appexec([space.wrap(str(tmpdir))], """(path):
-            import _cffi_backend     # force it to be initialized
-            import sys
-            sys.path.insert(0, path)
+        cls.w_fix_path = space.appexec([space.wrap(str(tmpdir))], """(path):
+            def fix_path(ignored=None):
+                import _cffi_backend     # force it to be initialized
+                import sys
+                if path not in sys.path:
+                    sys.path.insert(0, path)
+            return fix_path
         """)
 
     def teardown_method(self, meth):
@@ -86,17 +89,20 @@
 
 
     def test_constant_1(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         assert ffi.integer_const('FOOBAR') == -42
         assert ffi.integer_const('FOOBAZ') == -43
 
     def test_large_constant(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         assert ffi.integer_const('BIGPOS') == 420000000000
         assert ffi.integer_const('BIGNEG') == -420000000000
 
     def test_function(self):
         import _cffi_backend
+        self.fix_path()
         from re_python_pysrc import ffi
         lib = ffi.dlopen(self.extmod)
         assert lib.add42(-10) == 32
@@ -104,6 +110,7 @@
 
     def test_dlclose(self):
         import _cffi_backend
+        self.fix_path()
         from re_python_pysrc import ffi
         lib = ffi.dlopen(self.extmod)
         ffi.dlclose(lib)
@@ -115,17 +122,20 @@
             "library '%s' has been closed" % (self.extmod,))
 
     def test_constant_via_lib(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         lib = ffi.dlopen(self.extmod)
         assert lib.FOOBAR == -42
         assert lib.FOOBAZ == -43
 
     def test_opaque_struct(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         ffi.cast("struct foo_s *", 0)
         raises(TypeError, ffi.new, "struct foo_s *")
 
     def test_nonopaque_struct(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         for p in [ffi.new("struct bar_s *", [5, b"foobar"]),
                   ffi.new("bar_t *", [5, b"foobar"])]:
@@ -134,12 +144,14 @@
             assert p.a[5] == ord('r')
 
     def test_enum(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         assert ffi.integer_const("BB") == 1
         e = ffi.cast("enum foo_e", 2)
         assert ffi.string(e) == "CC"
 
     def test_include_1(self):
+        self.fix_path()
         from re_py_subsrc import ffi
         assert ffi.integer_const('FOOBAR') == -42
         assert ffi.integer_const('FOOBAZ') == -43
@@ -153,6 +165,7 @@
         assert p.a[4] == ord('a')
 
     def test_global_var(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         lib = ffi.dlopen(self.extmod)
         assert lib.globalvar42 == 1234
@@ -163,24 +176,28 @@
         assert lib.globalvar42 == 1238
 
     def test_global_const_int(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         lib = ffi.dlopen(self.extmod)
         assert lib.globalconst42 == 4321
         raises(AttributeError, ffi.addressof, lib, 'globalconst42')
 
     def test_global_const_nonint(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         lib = ffi.dlopen(self.extmod)
         assert ffi.string(lib.globalconsthello, 8) == "hello"
         raises(AttributeError, ffi.addressof, lib, 'globalconsthello')
 
     def test_rtld_constants(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         ffi.RTLD_NOW    # check that we have the attributes
         ffi.RTLD_LAZY
         ffi.RTLD_GLOBAL
 
     def test_no_such_function_or_global_var(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         lib = ffi.dlopen(self.extmod)
         e = raises(ffi.error, getattr, lib, 'no_such_function')
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
@@ -38,23 +38,33 @@
     errors   = None
     fd       = -1
     cffi_fileobj = None    # pypy/module/_cffi_backend
+    w_tb     = None  # String representation of the traceback at creation time
 
     newlines = 0     # Updated when the stream is closed
 
     def __init__(self, space):
         self.space = space
         self.register_finalizer(space)
+        if self.space.sys.track_resources:
+            self.w_tb = self.space.format_traceback()
 
     def _finalize_(self):
         # assume that the file and stream objects are only visible in the
         # thread that runs _finalize_, so no race condition should be
         # possible and no locking is done here.
-        if self.stream is not None:
-            try:
-                self.direct_close()
-            except StreamErrors as e:
-                operr = wrap_streamerror(self.space, e, self.w_name)
-                raise operr
+        if self.stream is None:
+            return
+        if self.space.sys.track_resources:
+            w_repr = self.space.repr(self)
+            str_repr = self.space.str_w(w_repr)
+            w_msg = self.space.wrap("WARNING: unclosed file: " + str_repr)
+            self.space.resource_warning(w_msg, self.w_tb)
+        #
+        try:
+            self.direct_close()
+        except StreamErrors as e:
+            operr = wrap_streamerror(self.space, e, self.w_name)
+            raise operr
 
     def fdopenstream(self, stream, fd, mode, w_name=None):
         self.fd = fd
diff --git a/pypy/module/_file/test/test_file.py b/pypy/module/_file/test/test_file.py
--- a/pypy/module/_file/test/test_file.py
+++ b/pypy/module/_file/test/test_file.py
@@ -1,5 +1,6 @@
 from __future__ import with_statement
-import py, os, errno
+import pytest, os, errno
+from pypy.interpreter.gateway import interp2app, unwrap_spec
 
 def getfile(space):
     return space.appexec([], """():
@@ -10,13 +11,24 @@
             return file
     """)
 
+# the following function is used e.g. in test_resource_warning
+ at unwrap_spec(regex=str, s=str)
+def regex_search(space, regex, s):
+    import re
+    import textwrap
+    regex = textwrap.dedent(regex).strip()
+    m = re.search(regex, s)
+    m = bool(m)
+    return space.wrap(m)
+
 class AppTestFile(object):
     spaceconfig = dict(usemodules=("_file",))
 
     def setup_class(cls):
         cls.w_temppath = cls.space.wrap(
-            str(py.test.ensuretemp("fileimpl").join("foo.txt")))
+            str(pytest.ensuretemp("fileimpl").join("foo.txt")))
         cls.w_file = getfile(cls.space)
+        cls.w_regex_search = cls.space.wrap(interp2app(regex_search))
 
     def test_simple(self):
         f = self.file(self.temppath, "w")
@@ -206,6 +218,9 @@
         assert exc.value.filename == os.curdir
 
     def test_encoding_errors(self):
+        import sys
+        if '__pypy__' not in sys.builtin_module_names:
+            pytest.skip("pypy only test")
         import _file
 
         with self.file(self.temppath, "w") as f:
@@ -254,6 +269,71 @@
         if '__pypy__' in sys.builtin_module_names:
             assert repr(self.temppath) in g.getvalue()
 
+    @pytest.mark.skipif("config.option.runappdirect")
+    def test_track_resources(self):
+        import os, gc, sys, cStringIO
+        if '__pypy__' not in sys.builtin_module_names:
+            skip("pypy specific test")
+        def fn(flag1, flag2, do_close=False):
+            sys.pypy_set_track_resources(flag1)
+            f = self.file(self.temppath, 'w')
+            sys.pypy_set_track_resources(flag2)
+            buf = cStringIO.StringIO()
+            preverr = sys.stderr
+            try:
+                sys.stderr = buf
+                if do_close:
+                    f.close()
+                del f
+                gc.collect() # force __del__ to be called
+            finally:
+                sys.stderr = preverr
+                sys.pypy_set_track_resources(False)
+            return buf.getvalue()
+
+        # check with track_resources disabled
+        assert fn(False, False) == ""
+        #
+        # check that we don't get the warning if we actually close the file
+        assert fn(False, False, do_close=True) == ""
+        #
+        # check with track_resources enabled
+        msg = fn(True, True)
+        assert self.regex_search(r"""
+        WARNING: unclosed file: <open file .*>
+        Created at \(most recent call last\):
+          File ".*", line .*, in test_track_resources
+          File ".*", line .*, in fn
+        """, msg)
+        #
+        # check with track_resources enabled in the destructor BUT with a
+        # file which was created when track_resources was disabled
+        msg = fn(False, True)
+        assert self.regex_search("WARNING: unclosed file: <open file .*>", msg)
+        assert "Created at" not in msg
+
+    @pytest.mark.skipif("config.option.runappdirect")
+    def test_track_resources_dont_crash(self):
+        import os, gc, sys, cStringIO
+        if '__pypy__' not in sys.builtin_module_names:
+            skip("pypy specific test")
+        #
+        # try hard to create a code object whose co_filename points to an
+        # EXISTING file, so that traceback.py tries to open it when formatting
+        # the stacktrace
+        f = open(self.temppath, 'w')
+        f.close()
+        co = compile('open("%s")' % self.temppath, self.temppath, 'exec')
+        sys.pypy_set_track_resources(True)
+        try:
+            # this exec used to fail, because space.format_traceback tried to
+            # recurively open a file, causing an infinite recursion. For the
+            # purpose of this test, it is enough that it actually finishes
+            # without errors
+            exec co
+        finally:
+            sys.pypy_set_track_resources(False)
+
     def test_truncate(self):
         f = self.file(self.temppath, "w")
         f.write("foo")
@@ -313,7 +393,7 @@
         cls.old_read = os.read
 
         if cls.runappdirect:
-            py.test.skip("works with internals of _file impl on py.py")
+            pytest.skip("works with internals of _file impl on py.py")
         def read(fd, n=None):
             if fd != 424242:
                 return cls.old_read(fd, n)
@@ -352,9 +432,9 @@
 
     def setup_class(cls):
         if not cls.runappdirect:
-            py.test.skip("likely to deadlock when interpreted by py.py")
+            pytest.skip("likely to deadlock when interpreted by py.py")
         cls.w_temppath = cls.space.wrap(
-            str(py.test.ensuretemp("fileimpl").join("concurrency.txt")))
+            str(pytest.ensuretemp("fileimpl").join("concurrency.txt")))
         cls.w_file = getfile(cls.space)
 
     def test_concurrent_writes(self):
@@ -465,7 +545,7 @@
 
     def setup_class(cls):
         cls.w_temppath = cls.space.wrap(
-            str(py.test.ensuretemp("fileimpl").join("foo.txt")))
+            str(pytest.ensuretemp("fileimpl").join("foo.txt")))
         cls.w_file = getfile(cls.space)
 
     def test___enter__(self):
diff --git a/pypy/module/_jitlog/test/test__jitlog.py b/pypy/module/_jitlog/test/test__jitlog.py
--- a/pypy/module/_jitlog/test/test__jitlog.py
+++ b/pypy/module/_jitlog/test/test__jitlog.py
@@ -10,10 +10,10 @@
 
     def setup_class(cls):
         cls.w_tmpfilename = cls.space.wrap(str(udir.join('test__jitlog.1')))
-        cls.w_mark_header = cls.space.wrap(jl.MARK_JITLOG_HEADER)
-        cls.w_version = cls.space.wrap(jl.JITLOG_VERSION_16BIT_LE)
+        cls.w_mark_header = cls.space.newbytes(jl.MARK_JITLOG_HEADER)
+        cls.w_version = cls.space.newbytes(jl.JITLOG_VERSION_16BIT_LE)
         cls.w_is_32bit = cls.space.wrap(sys.maxint == 2**31-1)
-        cls.w_machine = cls.space.wrap(platform.machine())
+        cls.w_machine = cls.space.newbytes(platform.machine())
         cls.w_resops = cls.space.newdict()
         space = cls.space
         for key, value in opname.items():
@@ -48,5 +48,3 @@
                 assert opnum in self.resops
                 # the name must equal
                 assert self.resops[opnum] == opname
-
-
diff --git a/pypy/module/_multibytecodec/src/cjkcodecs/cjkcodecs.h b/pypy/module/_multibytecodec/src/cjkcodecs/cjkcodecs.h
--- a/pypy/module/_multibytecodec/src/cjkcodecs/cjkcodecs.h
+++ b/pypy/module/_multibytecodec/src/cjkcodecs/cjkcodecs.h
@@ -268,22 +268,26 @@
     min = 0;
     max = haystacksize;
 
-    for (pos = haystacksize >> 1; min != max; pos = (min + max) >> 1)
+    for (pos = haystacksize >> 1; min != max; pos = (min + max) >> 1) {
         if (value < haystack[pos].uniseq) {
-            if (max == pos) break;
-            else max = pos;
+            if (max != pos) {
+                max = pos;
+                continue;
+            }
         }
         else if (value > haystack[pos].uniseq) {
-            if (min == pos) break;
-            else min = pos;
+            if (min != pos) {
+                min = pos;
+                continue;
+            }
         }
-        else
-            break;
+        break;
+    }
 
-        if (value == haystack[pos].uniseq)
-            return haystack[pos].code;
-        else
-            return DBCINV;
+    if (value == haystack[pos].uniseq) {
+        return haystack[pos].code;
+    }
+    return DBCINV;
 }
 #endif
 
diff --git a/pypy/module/_socket/interp_socket.py b/pypy/module/_socket/interp_socket.py
--- a/pypy/module/_socket/interp_socket.py
+++ b/pypy/module/_socket/interp_socket.py
@@ -151,9 +151,23 @@
 
 
 class W_Socket(W_Root):
+    w_tb = None  # String representation of the traceback at creation time
+
     def __init__(self, space, sock):
+        self.space = space
         self.sock = sock
         register_socket(space, sock)
+        if self.space.sys.track_resources:
+            self.w_tb = self.space.format_traceback()
+            self.register_finalizer(space)
+
+    def _finalize_(self):
+        is_open = self.sock.fd >= 0
+        if is_open and self.space.sys.track_resources:
+            w_repr = self.space.repr(self)
+            str_repr = self.space.str_w(w_repr)
+            w_msg = self.space.wrap("WARNING: unclosed " + str_repr)
+            self.space.resource_warning(w_msg, self.w_tb)
 
     def get_type_w(self, space):
         return space.wrap(self.sock.type)
diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py
--- a/pypy/module/_socket/test/test_sock_app.py
+++ b/pypy/module/_socket/test/test_sock_app.py
@@ -1,6 +1,8 @@
 import sys, os
-import py
+import pytest
 from pypy.tool.pytest.objspace import gettestobjspace
+from pypy.interpreter.gateway import interp2app
+from pypy.module._file.test.test_file import regex_search
 from rpython.tool.udir import udir
 from rpython.rlib import rsocket
 from rpython.rtyper.lltypesystem import lltype, rffi
@@ -12,8 +14,6 @@
     mod.w_socket = space.appexec([], "(): import _socket as m; return m")
     mod.path = udir.join('fd')
     mod.path.write('fo')
-    mod.raises = py.test.raises # make raises available from app-level tests
-    mod.skip = py.test.skip
 
 def test_gethostname():
     host = space.appexec([w_socket], "(_socket): return _socket.gethostname()")
@@ -41,7 +41,7 @@
     for host in ["localhost", "127.0.0.1", "::1"]:
         if host == "::1" and not ipv6:
             from pypy.interpreter.error import OperationError
-            with py.test.raises(OperationError):
+            with pytest.raises(OperationError):
                 space.appexec([w_socket, space.wrap(host)],
                               "(_socket, host): return _socket.gethostbyaddr(host)")
             continue
@@ -57,14 +57,14 @@
     assert space.unwrap(port) == 25
     # 1 arg version
     if sys.version_info < (2, 4):
-        py.test.skip("getservbyname second argument is not optional before python 2.4")
+        pytest.skip("getservbyname second argument is not optional before python 2.4")
     port = space.appexec([w_socket, space.wrap(name)],
                         "(_socket, name): return _socket.getservbyname(name)")
     assert space.unwrap(port) == 25
 
 def test_getservbyport():
     if sys.version_info < (2, 4):
-        py.test.skip("getservbyport does not exist before python 2.4")
+        pytest.skip("getservbyport does not exist before python 2.4")
     port = 25
     # 2 args version
     name = space.appexec([w_socket, space.wrap(port)],
@@ -97,7 +97,7 @@
 def test_fromfd():
     # XXX review
     if not hasattr(socket, 'fromfd'):
-        py.test.skip("No socket.fromfd on this platform")
+        pytest.skip("No socket.fromfd on this platform")
     orig_fd = path.open()
     fd = space.appexec([w_socket, space.wrap(orig_fd.fileno()),
             space.wrap(socket.AF_INET), space.wrap(socket.SOCK_STREAM),
@@ -157,7 +157,7 @@
 
 def test_pton_ntop_ipv4():
     if not hasattr(socket, 'inet_pton'):
-        py.test.skip('No socket.inet_pton on this platform')
+        pytest.skip('No socket.inet_pton on this platform')
     tests = [
         ("123.45.67.89", "\x7b\x2d\x43\x59"),
         ("0.0.0.0", "\x00" * 4),
@@ -173,9 +173,9 @@
 
 def test_ntop_ipv6():
     if not hasattr(socket, 'inet_pton'):
-        py.test.skip('No socket.inet_pton on this platform')
+        pytest.skip('No socket.inet_pton on this platform')
     if not socket.has_ipv6:
-        py.test.skip("No IPv6 on this platform")
+        pytest.skip("No IPv6 on this platform")
     tests = [
         ("\x00" * 16, "::"),
         ("\x01" * 16, ":".join(["101"] * 8)),
@@ -194,9 +194,9 @@
 
 def test_pton_ipv6():
     if not hasattr(socket, 'inet_pton'):
-        py.test.skip('No socket.inet_pton on this platform')
+        pytest.skip('No socket.inet_pton on this platform')
     if not socket.has_ipv6:
-        py.test.skip("No IPv6 on this platform")
+        pytest.skip("No IPv6 on this platform")
     tests = [
         ("\x00" * 16, "::"),
         ("\x01" * 16, ":".join(["101"] * 8)),
@@ -215,7 +215,7 @@
         assert space.unwrap(w_packed) == packed
 
 def test_has_ipv6():
-    py.test.skip("has_ipv6 is always True on PyPy for now")
+    pytest.skip("has_ipv6 is always True on PyPy for now")
     res = space.appexec([w_socket], "(_socket): return _socket.has_ipv6")
     assert space.unwrap(res) == socket.has_ipv6
 
@@ -229,7 +229,7 @@
     w_l = space.appexec([w_socket, space.wrap(host), space.wrap(port)],
                         "(_socket, host, port): return _socket.getaddrinfo(host, long(port))")
     assert space.unwrap(w_l) == info
-    py.test.skip("Unicode conversion is too slow")
+    pytest.skip("Unicode conversion is too slow")
     w_l = space.appexec([w_socket, space.wrap(unicode(host)), space.wrap(port)],
                         "(_socket, host, port): return _socket.getaddrinfo(host, port)")
     assert space.unwrap(w_l) == info
@@ -250,7 +250,7 @@
 def test_addr_raw_packet():
     from pypy.module._socket.interp_socket import addr_as_object
     if not hasattr(rsocket._c, 'sockaddr_ll'):
-        py.test.skip("posix specific test")
+        pytest.skip("posix specific test")
     # HACK: To get the correct interface number of lo, which in most cases is 1,
     # but can be anything (i.e. 39), we need to call the libc function
     # if_nametoindex to get the correct index
@@ -314,6 +314,7 @@
     def setup_class(cls):
         cls.space = space
         cls.w_udir = space.wrap(str(udir))
+        cls.w_regex_search = space.wrap(interp2app(regex_search))
 
     def teardown_class(cls):
         if not cls.runappdirect:
@@ -402,6 +403,64 @@
         if os.name != 'nt':
             raises(OSError, os.close, fileno)
 
+    def test_socket_track_resources(self):
+        import _socket, os, gc, sys, cStringIO
+        s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0)
+        fileno = s.fileno()
+        assert s.fileno() >= 0
+        s.close()
+        assert s.fileno() < 0
+        s.close()
+        if os.name != 'nt':
+            raises(OSError, os.close, fileno)
+
+    @pytest.mark.skipif("config.option.runappdirect")
+    def test_track_resources(self):
+        import os, gc, sys, cStringIO
+        import _socket
+        if '__pypy__' not in sys.builtin_module_names:
+            skip("pypy specific test")
+        #
+        def fn(flag1, flag2, do_close=False):
+            sys.pypy_set_track_resources(flag1)
+            mysock = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0)
+            sys.pypy_set_track_resources(flag2)
+            buf = cStringIO.StringIO()
+            preverr = sys.stderr
+            try:
+                sys.stderr = buf
+                if do_close:
+                    mysock.close()
+                del mysock
+                gc.collect() # force __del__ to be called
+            finally:
+                sys.stderr = preverr
+                sys.pypy_set_track_resources(False)
+            return buf.getvalue()
+
+        # check with track_resources disabled
+        assert fn(False, False) == ""
+        #
+        # check that we don't get the warning if we actually closed the socket
+        msg = fn(True, True, do_close=True)
+        assert msg == ''
+        #
+        # check with track_resources enabled
+        msg = fn(True, True)
+        assert self.regex_search(r"""
+        WARNING: unclosed <socket object, .*>
+        Created at \(most recent call last\):
+          File ".*", line .*, in test_track_resources
+          File ".*", line .*, in fn
+        """, msg)
+        #
+        # track_resources is enabled after the construction of the socket. in
+        # this case, the socket is not registered for finalization at all, so
+        # we don't see a message
+        msg = fn(False, True)
+        assert msg == ''
+
+
     def test_socket_close_error(self):
         import _socket, os
         if os.name == 'nt':
@@ -630,11 +689,11 @@
 class AppTestNetlink:
     def setup_class(cls):
         if not hasattr(os, 'getpid'):
-            py.test.skip("AF_NETLINK needs os.getpid()")
+            pytest.skip("AF_NETLINK needs os.getpid()")
         w_ok = space.appexec([], "(): import _socket; " +
                                  "return hasattr(_socket, 'AF_NETLINK')")
         if not space.is_true(w_ok):
-            py.test.skip("no AF_NETLINK on this platform")
+            pytest.skip("no AF_NETLINK on this platform")
         cls.space = space
 
     def test_connect_to_kernel_netlink_routing_socket(self):
@@ -650,11 +709,11 @@
 class AppTestPacket:
     def setup_class(cls):
         if not hasattr(os, 'getuid') or os.getuid() != 0:
-            py.test.skip("AF_PACKET needs to be root for testing")
+            pytest.skip("AF_PACKET needs to be root for testing")
         w_ok = space.appexec([], "(): import _socket; " +
                                  "return hasattr(_socket, 'AF_PACKET')")
         if not space.is_true(w_ok):
-            py.test.skip("no AF_PACKET on this platform")
+            pytest.skip("no AF_PACKET on this platform")
         cls.space = space
 
     def test_convert_between_tuple_and_sockaddr_ll(self):
diff --git a/pypy/module/cppyy/pythonify.py b/pypy/module/cppyy/pythonify.py
--- a/pypy/module/cppyy/pythonify.py
+++ b/pypy/module/cppyy/pythonify.py
@@ -175,7 +175,7 @@
          "__new__"      : make_new(class_name),
          }
     pycppclass = metacpp(class_name, _drop_cycles(bases), d)
- 
+
     # cache result early so that the class methods can find the class itself
     setattr(scope, final_class_name, pycppclass)
 
@@ -192,13 +192,10 @@
     for dm_name in cppclass.get_datamember_names():
         cppdm = cppclass.get_datamember(dm_name)
 
-        # here, setattr() can not be used, because a data member can shadow one in
-        # its base class, resulting in the __set__() of its base class being called
-        # by setattr(); so, store directly on the dictionary
-        pycppclass.__dict__[dm_name] = cppdm
+        setattr(pycppclass, dm_name, cppdm)
         import cppyy
         if cppyy._is_static(cppdm):     # TODO: make this a method of cppdm
-            metacpp.__dict__[dm_name] = cppdm
+            setattr(metacpp, dm_name, cppdm)
 
     # the call to register will add back-end specific pythonizations and thus
     # needs to run first, so that the generic pythonizations can use them
@@ -413,7 +410,7 @@
         lib = cppyy._load_dictionary(name)
         _loaded_dictionaries[name] = lib
         return lib
-    
+
 def _init_pythonify():
     # cppyy should not be loaded at the module level, as that will trigger a
     # call to space.getbuiltinmodule(), which will cause cppyy to be loaded
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -11,6 +11,9 @@
 from rpython.rtyper.annlowlevel import llhelper
 from rpython.rlib.objectmodel import we_are_translated, keepalive_until_here
 from rpython.rlib.objectmodel import dont_inline
+from rpython.rlib.rfile import (FILEP, c_fread, c_fclose, c_fwrite,
+        c_fdopen, c_fileno,
+        c_fopen)# for tests
 from rpython.translator import cdir
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 from rpython.translator.gensupp import NameManager
@@ -85,44 +88,32 @@
 assert CONST_WSTRING == rffi.CWCHARP
 
 # FILE* interface
-FILEP = rffi.COpaquePtr('FILE')
 
 if sys.platform == 'win32':
     dash = '_'
 else:
     dash = ''
-fileno = rffi.llexternal(dash + 'fileno', [FILEP], rffi.INT)
-fopen = rffi.llexternal('fopen', [CONST_STRING, CONST_STRING], FILEP)
-fdopen = rffi.llexternal(dash + 'fdopen', [rffi.INT, CONST_STRING],
-                  FILEP, save_err=rffi.RFFI_SAVE_ERRNO)
 
-_fclose = rffi.llexternal('fclose', [FILEP], rffi.INT)
 def fclose(fp):
-    if not is_valid_fd(fileno(fp)):
+    if not is_valid_fd(c_fileno(fp)):
         return -1
-    return _fclose(fp)
+    return c_fclose(fp)
 
-_fwrite = rffi.llexternal('fwrite',
-                         [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, FILEP],
-                         rffi.SIZE_T)
 def fwrite(buf, sz, n, fp):
-    validate_fd(fileno(fp))
-    return _fwrite(buf, sz, n, fp)
+    validate_fd(c_fileno(fp))
+    return c_fwrite(buf, sz, n, fp)
 
-_fread = rffi.llexternal('fread',
-                        [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, FILEP],
-                        rffi.SIZE_T)
 def fread(buf, sz, n, fp):
-    validate_fd(fileno(fp))
-    return _fread(buf, sz, n, fp)
+    validate_fd(c_fileno(fp))
+    return c_fread(buf, sz, n, fp)
 
 _feof = rffi.llexternal('feof', [FILEP], rffi.INT)
 def feof(fp):
-    validate_fd(fileno(fp))
+    validate_fd(c_fileno(fp))
     return _feof(fp)
 
 def is_valid_fp(fp):
-    return is_valid_fd(fileno(fp))
+    return is_valid_fd(c_fileno(fp))
 
 pypy_decl = 'pypy_decl.h'
 
@@ -268,14 +259,14 @@
 
         # extract the signature from the (CPython-level) code object
         from pypy.interpreter import pycode
-        argnames, varargname, kwargname = pycode.cpython_code_signature(callable.func_code)
+        sig = pycode.cpython_code_signature(callable.func_code)
+        assert sig.argnames[0] == 'space'
+        self.argnames = sig.argnames[1:]
+        if gil == 'pygilstate_ensure':
+            assert self.argnames[-1] == 'previous_state'
+            del self.argnames[-1]
+        assert len(self.argnames) == len(self.argtypes)
 
-        assert argnames[0] == 'space'
-        if gil == 'pygilstate_ensure':
-            assert argnames[-1] == 'previous_state'
-            del argnames[-1]
-        self.argnames = argnames[1:]
-        assert len(self.argnames) == len(self.argtypes)
         self.gil = gil
         self.result_borrowed = result_borrowed
         self.result_is_ll = result_is_ll
diff --git a/pypy/module/cpyext/c-api.txt b/pypy/module/cpyext/c-api.txt
deleted file mode 100644
--- a/pypy/module/cpyext/c-api.txt
+++ /dev/null
@@ -1,71 +0,0 @@
-Reference Count
-===============
-
-XXX
-
-Borrowed References
-===================
-
-XXX
-
-PyStringObject support
-======================
-
-The problem
------------
-
-PyString_AsString() returns a (non-movable) pointer to the underlying
-buffer, whereas pypy strings are movable.  C code may temporarily
-store this address and use it, as long as it owns a reference to the
-PyObject.  There is no "release" function to specify that the pointer
-is not needed any more.
-
-Note that the pointer may be used to fill the initial value of
-string. This is valid only when the string was just allocated, and is
-not used elsewhere.
-
-Proposed solution
------------------
-
-Our emulation of the PyStringObject contains an additional member: a
-pointer to a char buffer; it may be NULL.
-
-- A string allocated by pypy will be converted into a PyStringObject
-  with a NULL buffer.  When PyString_AsString() is called, memory is
-  allocated (with flavor='raw') and content is copied.
-
-- A string allocated with PyString_FromStringAndSize(NULL, size) will
-  allocate a buffer with the specified size, but the reference won't
-  be stored in the global map py_objects_r2w; there won't be a
-  corresponding object in pypy.  When from_ref() or Py_INCREF() is
-  called, the pypy string is created, and added in py_objects_r2w.
-  The buffer is then supposed to be immutable.
-
-- _PyString_Resize works only on not-yet-pypy'd strings, and returns a
-  similar object.
-
-- PyString_Size don't need to force the object. (in this case, another
-  "size" member is needed)
-
-- There could be an (expensive!) check in from_ref() that the buffer
-  still corresponds to the pypy gc-managed string.
-
-PySequence_Fast support
-======================
-There are five functions for fast sequence access offered by the CPython API:
-
-PyObject* PySequence_Fast(PyObject *o, const char *m)
-
-PyObject* PySequence_Fast_GET_ITEM(	PyObject *o, int i)
-
-PyObject** PySequence_Fast_ITEMS(	PyObject *o)
-
-PyObject* PySequence_ITEM(	PyObject *o, int i)
-
-int PySequence_Fast_GET_SIZE(	PyObject *o)
-
-PyPy supports four of these, but does not support PySequence_Fast_ITEMS.
-(Various ways to support PySequence_Fast_ITEMS were considered. They all had
-two things in common: they would have taken a lot of work, and they would have
-resulted in incomplete semantics or in poor performance. We decided that a slow
-implementation of PySequence_Fast_ITEMS was not very useful.)
diff --git a/pypy/module/cpyext/include/Python.h b/pypy/module/cpyext/include/Python.h
--- a/pypy/module/cpyext/include/Python.h
+++ b/pypy/module/cpyext/include/Python.h
@@ -2,6 +2,9 @@
 #define Py_PYTHON_H
 
 /* Compat stuff */
+#ifdef __GNUC__
+#define _GNU_SOURCE 1
+#endif
 #ifndef _WIN32
 # include <inttypes.h>
 # include <stdint.h>
@@ -52,7 +55,6 @@
 #ifndef DL_IMPORT
 #       define DL_IMPORT(RTYPE) RTYPE
 #endif
-
 #include <stdlib.h>
 
 #ifndef _WIN32
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
@@ -21,6 +21,8 @@
                          flavor='raw',
                          add_memory_pressure=True)
 
+realloc = rffi.llexternal('realloc', [rffi.VOIDP, rffi.SIZE_T], rffi.VOIDP)
+
 @cpython_api([rffi.VOIDP, size_t], rffi.VOIDP)
 def PyObject_Realloc(space, ptr, size):
     if not lltype.cast_ptr_to_int(ptr):
@@ -28,7 +30,7 @@
                          flavor='raw',
                          add_memory_pressure=True)
     # XXX FIXME
-    return lltype.nullptr(rffi.VOIDP.TO)
+    return realloc(ptr, size)
 
 @cpython_api([rffi.VOIDP], lltype.Void)
 def PyObject_Free(space, ptr):
diff --git a/pypy/module/cpyext/pyfile.py b/pypy/module/cpyext/pyfile.py
--- a/pypy/module/cpyext/pyfile.py
+++ b/pypy/module/cpyext/pyfile.py
@@ -1,6 +1,7 @@
 from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rlib.rfile import c_setvbuf, _IONBF
 from pypy.module.cpyext.api import (
-    cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, build_type_checkers, fdopen)
+    cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, build_type_checkers, c_fdopen)
 from pypy.module.cpyext.pyobject import PyObject
 from pypy.module.cpyext.object import Py_PRINT_RAW
 from pypy.interpreter.error import (OperationError, oefmt, 
@@ -64,11 +65,12 @@
     if (fd < 0 or not mode or mode[0] not in ['r', 'w', 'a', 'U'] or
         ('U' in mode and ('w' in mode or 'a' in mode))):
         raise oefmt(space.w_IOError, 'invalid fileno or mode') 
-    ret = fdopen(fd, mode)
+    ret = c_fdopen(fd, mode)
     if not ret:
         raise exception_from_saved_errno(space, space.w_IOError)
+    # XXX fix this once use-file-star-for-file lands
+    c_setvbuf(ret, lltype.nullptr(rffi.CCHARP.TO), _IONBF, 0)
     return ret
-        
 
 @cpython_api([FILEP, CONST_STRING, CONST_STRING, rffi.VOIDP], PyObject)
 def PyFile_FromFile(space, fp, name, mode, close):
diff --git a/pypy/module/cpyext/sequence.py b/pypy/module/cpyext/sequence.py
--- a/pypy/module/cpyext/sequence.py
+++ b/pypy/module/cpyext/sequence.py
@@ -10,7 +10,7 @@
 from pypy.objspace.std import tupleobject
 
 from pypy.module.cpyext.tupleobject import PyTuple_Check, PyTuple_SetItem
-from pypy.module.cpyext.object import Py_IncRef, Py_DecRef
+from pypy.module.cpyext.pyobject import decref
 
 from pypy.module.cpyext.dictobject import PyDict_Check
 
@@ -252,7 +252,7 @@
     def setitem(self, w_list, index, w_obj):
         storage = self.unerase(w_list.lstorage)
         index = self._check_index(index, storage._length)
-        Py_DecRef(w_list.space, storage._elems[index])
+        decref(w_list.space, storage._elems[index])
         storage._elems[index] = make_ref(w_list.space, w_obj)
 
     def length(self, w_list):
@@ -264,9 +264,8 @@
         return storage._elems
 
     def getslice(self, w_list, start, stop, step, length):
-        #storage = self.unerase(w_list.lstorage)
-        raise oefmt(w_list.space.w_NotImplementedError,
-                    "settting a slice of a PySequence_Fast is not supported")
+        w_list.switch_to_object_strategy()
+        return w_list.strategy.getslice(w_list, start, stop, step, length)
 
     def getitems(self, w_list):
         # called when switching list strategy, so convert storage
@@ -389,5 +388,5 @@
 
     def __del__(self):
         for i in range(self._length):
-            Py_DecRef(self.space, self._elems[i])
+            decref(self.space, self._elems[i])
         lltype.free(self._elems, flavor='raw')
diff --git a/pypy/module/cpyext/test/test_eval.py b/pypy/module/cpyext/test/test_eval.py
--- a/pypy/module/cpyext/test/test_eval.py
+++ b/pypy/module/cpyext/test/test_eval.py
@@ -3,7 +3,7 @@
 from pypy.module.cpyext.test.test_api import BaseApiTest
 from pypy.module.cpyext.eval import (
     Py_single_input, Py_file_input, Py_eval_input, PyCompilerFlags)
-from pypy.module.cpyext.api import fopen, fclose, fileno, Py_ssize_tP
+from pypy.module.cpyext.api import c_fopen, c_fclose, c_fileno, Py_ssize_tP
 from pypy.interpreter.gateway import interp2app
 from pypy.interpreter.astcompiler import consts
 from rpython.tool.udir import udir
@@ -130,19 +130,19 @@
     def test_run_file(self, space, api):
         filepath = udir / "cpyext_test_runfile.py"
         filepath.write("raise ZeroDivisionError")
-        fp = fopen(str(filepath), "rb")
+        fp = c_fopen(str(filepath), "rb")
         filename = rffi.str2charp(str(filepath))
         w_globals = w_locals = space.newdict()
         api.PyRun_File(fp, filename, Py_file_input, w_globals, w_locals)
-        fclose(fp)
+        c_fclose(fp)
         assert api.PyErr_Occurred() is space.w_ZeroDivisionError
         api.PyErr_Clear()
 
         # try again, but with a closed file
-        fp = fopen(str(filepath), "rb")
-        os.close(fileno(fp))
+        fp = c_fopen(str(filepath), "rb")
+        os.close(c_fileno(fp))
         api.PyRun_File(fp, filename, Py_file_input, w_globals, w_locals)
-        fclose(fp)
+        c_fclose(fp)
         assert api.PyErr_Occurred() is space.w_IOError
         api.PyErr_Clear()
 
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
@@ -235,8 +235,9 @@
         assert type(x) is int
         assert x == -424344
 
-    @pytest.mark.skipif(True, reason='realloc not fully implemented')
     def test_object_realloc(self):
+        if not self.runappdirect:
+            skip('no untranslated support for realloc')
         module = self.import_extension('foo', [
             ("realloctest", "METH_NOARGS",
              """
@@ -244,12 +245,11 @@
                  char *copy, *orig = PyObject_MALLOC(12);
                  memcpy(orig, "hello world", 12);
                  copy = PyObject_REALLOC(orig, 15);
+                 /* realloc() takes care of freeing orig, if changed */
                  if (copy == NULL)
                      Py_RETURN_NONE;
                  ret = PyString_FromStringAndSize(copy, 12);
-                 if (copy != orig)
-                     PyObject_Free(copy);
-                 PyObject_Free(orig);
+                 PyObject_Free(copy);
                  return ret;
              """)])
         x = module.realloctest()
diff --git a/pypy/module/cpyext/test/test_pyfile.py b/pypy/module/cpyext/test/test_pyfile.py
--- a/pypy/module/cpyext/test/test_pyfile.py
+++ b/pypy/module/cpyext/test/test_pyfile.py
@@ -1,5 +1,4 @@
 from pypy.conftest import option
-from pypy.module.cpyext.api import fopen, fclose, fwrite
 from pypy.module.cpyext.test.test_api import BaseApiTest
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 from pypy.module.cpyext.object import Py_PRINT_RAW
@@ -133,6 +132,15 @@
                     return PyLong_FromLong(0);
                 return PyLong_FromLong(ftell(fp));
              """),
+            ("read_10", "METH_O",
+             """
+                char s[10];
+                FILE * fp = PyFile_AsFile(args);
+                if (fp == NULL)
+                    return PyLong_FromLong(0);
+                fread(s, 1, 10, fp);
+                return PyLong_FromLong(ftell(fp));
+             """),
             ])
         filename = self.udir + "/_test_file"
         with open(filename, 'w') as fid:
@@ -142,5 +150,12 @@
             t_py = fid.tell()
             assert t_py == 80
             t_c = module.get_c_tell(fid)
-        assert t_c == t_py
+            assert t_c == t_py
+            print '-------- tell ',t_c
+            t_c = module.read_10(fid)
+            assert t_c == t_py + 10
+            print '-------- tell ',t_c
+            t_py = fid.tell()
+            assert t_c == t_py, 'after a fread, c level ftell(fp) %d but PyFile.tell() %d' % (t_c, t_py)
 
+
diff --git a/pypy/module/cpyext/test/test_sequence.py b/pypy/module/cpyext/test/test_sequence.py
--- a/pypy/module/cpyext/test/test_sequence.py
+++ b/pypy/module/cpyext/test/test_sequence.py
@@ -78,6 +78,17 @@
         assert api.PySequence_SetSlice(w_t, 1, 1, space.wrap((3,))) == 0
         assert space.eq_w(w_t, space.wrap([1, 3, 5]))
 
+    def test_get_slice_fast(self, space, api):
+        w_t = space.wrap([1, 2, 3, 4, 5])
+        api.PySequence_Fast(w_t, "foo") # converts
+        assert space.unwrap(api.PySequence_GetSlice(w_t, 2, 4)) == [3, 4]
+        assert space.unwrap(api.PySequence_GetSlice(w_t, 1, -1)) == [2, 3, 4]
+
+        assert api.PySequence_DelSlice(w_t, 1, 4) == 0
+        assert space.eq_w(w_t, space.wrap([1, 5]))
+        assert api.PySequence_SetSlice(w_t, 1, 1, space.wrap((3,))) == 0
+        assert space.eq_w(w_t, space.wrap([1, 3, 5]))
+
     def test_iter(self, space, api):
         w_t = space.wrap((1, 2))
         w_iter = api.PySeqIter_New(w_t)
@@ -226,18 +237,33 @@
         assert space.int_w(space.len(w_l)) == 10
 
 
-class XAppTestSequenceObject(AppTestCpythonExtensionBase):
-    def test_sequenceobject(self):
+class AppTestSequenceObject(AppTestCpythonExtensionBase):
+    def test_fast(self):
         module = self.import_extension('foo', [
             ("test_fast_sequence", "METH_VARARGS",
              """
-                PyObject * o = PyTuple_GetItem(args, 0);
+                int size, i;
+                PyTypeObject * common_type;
+                PyObject *foo, **objects;
+                PyObject * seq = PyTuple_GetItem(args, 0);
                 /* XXX assert it is a tuple */
-                PyObject *foo = PySequence_Fast(o, "some string");
-                PyObject ** res = PySequence_Fast_ITEMS(foo);
-                /* XXX do some kind of test on res */
-                /* XXX now what? who manages res's refcount? */
+                if (seq == NULL)
+                    Py_RETURN_NONE;
+                foo = PySequence_Fast(seq, "some string");
+                objects = PySequence_Fast_ITEMS(foo);
+                size = PySequence_Fast_GET_SIZE(seq);
+                common_type = size > 0 ? Py_TYPE(objects[0]) : NULL;
+                for (i = 1; i < size; ++i) {
+                    if (Py_TYPE(objects[i]) != common_type) {
+                        common_type = NULL;
+                        break;
+                    }
+                }
+                Py_DECREF(foo);
+                Py_DECREF(common_type);
                 return PyBool_FromLong(1);
              """)])
-        assert module.test_fast_sequence([1, 2, 3, 4])
+        s = [1, 2, 3, 4]
+        assert module.test_fast_sequence(s[0:-1])
+        assert module.test_fast_sequence(s[::-1])
 
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
@@ -282,11 +282,41 @@
                      args->ob_type->tp_dict, "copy");
                  Py_INCREF(method);
                  return method;
+             '''),
+            ("get_type_dict", "METH_O",
              '''
-             )
+                PyObject* value = args->ob_type->tp_dict;
+                if (value == NULL) value = Py_None;
+                Py_INCREF(value);
+                return value;
+             '''),
             ])
         obj = foo.new()
         assert module.read_tp_dict(obj) == foo.fooType.copy
+        d = module.get_type_dict(obj)
+        assert type(d) is dict
+        d["_some_attribute"] = 1
+        assert type(obj)._some_attribute == 1
+        del d["_some_attribute"]
+
+        class A(object):
+            pass
+        obj = A()
+        d = module.get_type_dict(obj)
+        assert type(d) is dict
+        d["_some_attribute"] = 1
+        assert type(obj)._some_attribute == 1
+        del d["_some_attribute"]
+
+        d = module.get_type_dict(1)
+        assert type(d) is dict
+        try:
+            d["_some_attribute"] = 1
+        except TypeError:  # on PyPy, int.__dict__ is really immutable
+            pass
+        else:
+            assert int._some_attribute == 1
+            del d["_some_attribute"]
 
     def test_custom_allocation(self):
         foo = self.import_module("foo")
@@ -355,6 +385,21 @@
 
         api.Py_DecRef(ref)
 
+    def test_type_dict(self, space, api):
+        w_class = space.appexec([], """():
+            class A(object):
+                pass
+            return A
+            """)
+        ref = make_ref(space, w_class)
+
+        py_type = rffi.cast(PyTypeObjectPtr, ref)
+        w_dict = from_ref(space, py_type.c_tp_dict)
+        w_name = space.wrap('a')
+        space.setitem(w_dict, w_name, space.wrap(1))
+        assert space.int_w(space.getattr(w_class, w_name)) == 1
+        space.delitem(w_dict, w_name)
+
     def test_multiple_inheritance(self, space, api):
         w_class = space.appexec([], """():
             class A(object):
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
@@ -272,12 +272,12 @@
         if len(slot_names) == 1:
             if not getattr(pto, slot_names[0]):
                 setattr(pto, slot_names[0], slot_func_helper)
-        elif (w_type.getname(space) in ('list', 'tuple') and 
+        elif (w_type.getname(space) in ('list', 'tuple') and
               slot_names[0] == 'c_tp_as_number'):
             # XXX hack - hwo can we generalize this? The problem is method
             # names like __mul__ map to more than one slot, and we have no
             # convenient way to indicate which slots CPython have filled
-            # 
+            #
             # We need at least this special case since Numpy checks that
             # (list, tuple) do __not__ fill tp_as_number
             pass
@@ -860,8 +860,8 @@
 


More information about the pypy-commit mailing list