Author: Armin Rigo <[email protected]>
Branch: py3.5-marshal3
Changeset: r86615:e75acfc7d246
Date: 2016-08-27 19:15 +0200
http://bitbucket.org/pypy/pypy/changeset/e75acfc7d246/

Log:    hg merge py3.5

diff too long, truncating to 2000 out of 2720 lines

diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py
--- a/lib_pypy/_curses.py
+++ b/lib_pypy/_curses.py
@@ -554,6 +554,9 @@
     def putwin(self, filep):
         # filestar = ffi.new("FILE *", filep)
         return _check_ERR(lib.putwin(self._win, filep), "putwin")
+        # XXX CPython 3.5 says: We have to simulate this by writing to
+        # a temporary FILE*, then reading back, then writing to the
+        # argument stream.
 
     def redrawln(self, beg, num):
         return _check_ERR(lib.wredrawln(self._win, beg, num), "redrawln")
@@ -704,6 +707,7 @@
 
 
 def getwin(filep):
+    # XXX CPython 3.5: there's logic to use a temp file instead
     return Window(_check_NULL(lib.getwin(filep)))
 
 
diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py
--- a/pypy/doc/conf.py
+++ b/pypy/doc/conf.py
@@ -58,16 +58,16 @@
 
 # General information about the project.
 project = u'PyPy'
-copyright = u'2015, The PyPy Project'
+copyright = u'2016, The PyPy Project'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
 # The short X.Y version.
-version = '4.0'
+version = '5.4'
 # The full version, including alpha/beta/rc tags.
-release = '4.0.0'
+release = '5.4.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/pypy/doc/index-of-release-notes.rst 
b/pypy/doc/index-of-release-notes.rst
--- a/pypy/doc/index-of-release-notes.rst
+++ b/pypy/doc/index-of-release-notes.rst
@@ -6,6 +6,7 @@
 
 .. toctree::
 
+   release-pypy2.7-v5.4.0.rst
    release-pypy2.7-v5.3.1.rst
    release-pypy2.7-v5.3.0.rst
    release-5.1.1.rst
diff --git a/pypy/doc/index-of-whatsnew.rst b/pypy/doc/index-of-whatsnew.rst
--- a/pypy/doc/index-of-whatsnew.rst
+++ b/pypy/doc/index-of-whatsnew.rst
@@ -7,6 +7,7 @@
 .. toctree::
 
    whatsnew-head.rst
+   whatsnew-pypy2-5.4.0.rst
    whatsnew-pypy2-5.3.1.rst
    whatsnew-pypy2-5.3.0.rst
    whatsnew-5.1.0.rst
diff --git a/pypy/doc/project-ideas.rst b/pypy/doc/project-ideas.rst
--- a/pypy/doc/project-ideas.rst
+++ b/pypy/doc/project-ideas.rst
@@ -57,7 +57,7 @@
 --------------
 
 Our cpyext C-API compatiblity layer can now run upstream NumPy unmodified.
-Release PyPy2.7-v5.3 still fails about 200 of the ~6000 test in the NumPy
+Release PyPy2.7-v5.4 still fails about 60 of the ~6000 test in the NumPy
 test suite. We could use help analyzing the failures and fixing them either
 as patches to upstream NumPy, or as fixes to PyPy.
 
diff --git a/pypy/doc/release-pypy2.7-v5.4.0.rst 
b/pypy/doc/release-pypy2.7-v5.4.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-pypy2.7-v5.4.0.rst
@@ -0,0 +1,219 @@
+============
+PyPy2.7 v5.4
+============
+
+We have released PyPy2.7 v5.4, a little under two months after PyPy2.7 v5.3.
+This new PyPy2.7 release includes further improvements to our C-API 
compatability layer (cpyext), enabling us to pass over 99% of the upstream
+numpy `test suite`_. We updated built-in cffi_ support to version 1.8,
+which now supports the "limited API" mode for c-extensions on 
+CPython >=3.2.
+
+We improved tooling for the PyPy JIT_, and expanded VMProf
+support to OpenBSD and Dragon Fly BSD
+
+As always, this release fixed many issues and bugs raised by the
+growing community of PyPy users. 
+
+XXXXX MORE ???
+
+You can download the PyPy2.7 v5.4 release here:
+
+    http://pypy.org/download.html
+
+We would like to thank our donors for the continued support of the PyPy
+project.
+
+We would also like to thank our contributors and
+encourage new people to join the project. PyPy has many
+layers and we need help with all of them: `PyPy`_ and `RPython`_ documentation
+improvements, tweaking popular `modules`_ to run on pypy, or general `help`_
+with making RPython's JIT even better.
+
+.. _`test suite`: 
https://bitbucket.org/pypy/pypy/wiki/Adventures%20in%20cpyext%20compatibility
+.. _cffi: https://cffi.readthedocs.org
+.. _JIT: 
https://morepypy.blogspot.com.au/2016/08/pypy-tooling-upgrade-jitviewer-and.html
+.. _`PyPy`: http://doc.pypy.org
+.. _`RPython`: https://rpython.readthedocs.org
+.. _`modules`: 
http://doc.pypy.org/en/latest/project-ideas.html#make-more-python-modules-pypy-friendly
+.. _`help`: http://doc.pypy.org/en/latest/project-ideas.html
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`PyPy and CPython 2.7.x`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+We also welcome developers of other `dynamic languages`_ to see what RPython
+can do for them.
+
+This release supports: 
+
+  * **x86** machines on most common operating systems
+    (Linux 32/64 bits, Mac OS X 64 bits, Windows 32 bits, OpenBSD, FreeBSD)
+  
+  * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux,
+  
+  * big- and little-endian variants of **PPC64** running Linux,
+
+  * **s390x** running Linux
+
+.. _`PyPy and CPython 2.7.x`: http://speed.pypy.org
+.. _`dynamic languages`: http://pypyjs.org
+
+Other Highlights (since 5.3 released in June 2016)
+=========================================================
+
+* New features:
+
+  * Add `sys.{get,set}dlopenflags`
+
+  * Improve CPython compatibility of 'is' for small and empty strings
+
+  * Support for rgc.FinalizerQueue in the Boehm garbage collector
+
+  * (RPython) support spawnv() if it is called in C `_spawnv` on windows
+
+  * Fill in more slots when creating a PyTypeObject from a W_TypeObject,
+    like `__hex__`, `__sub__`, `__pow__`
+
+  * Copy CPython's logic more closely for `isinstance()` and
+    `issubclass()` as well as `type.__instancecheck__()` and
+    `type.__subclasscheck__()`
+
+  * Expose the name of CDLL objects
+
+  * Rewrite the win32 dependencies of `subprocess` to use cffi
+    instead of ctypes
+
+  * Improve the `JIT logging`_ facitilities
+
+  * (RPython) make int * string work
+
+  * Allocate all RPython strings with one extra byte, normally
+    unused. This now allows `ffi.from_buffer(string)` in CFFI with
+    no copy
+
+  * Adds a new commandline option `-X track-resources` that will
+    produce a `ResourceWarning` when the GC closes a file or socket.
+    The traceback for the place where the file or socket was allocated
+    is given as well, which aids finding places where `close()` is
+    missing
+
+  * Add missing `PyObject_Realloc`, `PySequence_GetSlice`
+
+  * `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)
+
+  * (RPython) add `rposix.{get,set}_inheritable()`, needed by Python 3.5
+
+  * (RPython) add `rposix_scandir` portably, needed for Python 3.5
+
+  * Support for memoryview attributes (format, itemsize, ...) which also
+    adds support for `PyMemoryView_FromObject`
+
+* Bug Fixes
+
+  * Reject `mkdir()` in read-only sandbox filesystems
+
+  * Add include guards to pymem.h to enable c++ compilation
+
+  * Fix build breakage on OpenBSD and FreeBSD
+
+  * Support OpenBSD, Dragon Fly BSD in VMProf
+
+  * Fix for `bytearray('').replace('a', 'ab')` for empty strings
+
+  * Sync internal state before calling `PyFile_AsFile()`
+
+  * Allow writing to a char* from `PyString_AsString()` until it is
+    forced, also refactor `PyStringObject` to look like CPython's
+    and allow subclassing `PyString_Type` and `PyUnicode_Type`
+
+  * Rpython rffi's socket(2) wrapper did not preserve errno
+
+  * Refactor `PyTupleObject` to look like CPython's and allow
+    subclassing `PyTuple_Type`
+
+  * Allow c-level assignment to a function pointer in a C-API
+    user-defined type after calling PyTypeReady by retrieving
+    a pointer to the function via offsets
+    rather than storing the function pointer itself
+
+  * Use `madvise(MADV_FREE)`, or if that doesn't exist
+    `MADV_DONTNEED` on freed arenas to release memory back to the
+    OS for resource monitoring
+
+  * Fix overflow detection in conversion of float to 64-bit integer
+    in timeout argument to various thread/threading primitives
+
+  * Fix win32 outputting `\r\r\n` in some cases
+
+  * Make `hash(-1)` return -2, as CPython does, and fix all the
+    ancilary places this matters
+
+  * Issues reported with our previous release were resolved_ after
+    reports from users on our issue tracker at
+    https://bitbucket.org/pypy/pypy/issues or on IRC at #pypy
+
+  * Fix `PyNumber_Check()` to behave more like CPython
+
+  * (VMProf) Try hard to not miss any Python-level frame in the
+    captured stacks, even if there is metainterp or blackhole interp
+    involved.  Also fix the stacklet (greenlet) support
+
+  * Fix a critical JIT bug where `raw_malloc` -equivalent functions
+    lost the additional flags
+
+  * Fix the mapdict cache for subclasses of builtin types that
+    provide a dict
+
+* Performance improvements:
+
+  * Add a before_call()-like equivalent before a few operations like
+   `malloc_nursery`, to move values from registers into other registers
+    instead of to the stack.
+
+  * More tightly pack the stack when calling with `release gil`
+
+  * Support `int_floordiv()`, `int_mod()` in the JIT more efficiently
+    and add `rarithmetic.int_c_div()`, `rarithmetic.int_c_mod()` as
+    explicit interfaces. Clarify that `int_floordiv()` does python-style
+    rounding, unlike `llop.int_floordiv()`.
+
+  * Use `ll_assert` (more often) in incminimark
+
+  * (Testing) Simplify handling of interp-level tests and make it
+    more forward-compatible. Don't use interp-level RPython
+    machinery to test building app-level extensions in cpyext
+
+  * Constant-fold `ffi.offsetof("structname", "fieldname")` in cffi
+    backend
+
+  * Avoid a case in the JIT, where successive guard failures in
+    the same Python function end up as successive levels of
+    RPython functions, eventually exhausting the stack, while at
+    app-level the traceback is very short
+
+  * Check for NULL returns from calls to the raw-malloc and raise,
+    rather than a guard
+
+  * Improve `socket.recvfrom()` so that it copies less if possible
+
+  * When generating C code, inline `goto` to blocks with only one
+    predecessor, generating less lines of code
+
+  * When running the final backend-optimization phase before emitting
+    C code, constant-fold calls to we_are_jitted to return False. This
+    makes the generated C code a few percent smaller
+
+  * Refactor the `uid_t/gid_t` handling in `rlib.rposix` and in
+    `interp_posix.py`, based on the clean-up of CPython 2.7.x 
+
+.. _`JIT logging`: 
https://morepypy.blogspot.com/2016/08/pypy-tooling-upgrade-jitviewer-and.html
+.. _resolved: http://doc.pypy.org/en/latest/whatsnew-5.4.0.html
+
+Please update, and continue to help us make PyPy better.
+
+Cheers
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
@@ -1,157 +1,8 @@
-=========================
-What's new in PyPy2.7 5.3+
-=========================
+==========================
+What's new in PyPy2.7 5.4+
+==========================
 
-.. this is a revision shortly after release-pypy2.7-v5.3
-.. startrev: 873218a739f1
+.. this is a revision shortly after release-pypy2.7-v5.4
+.. startrev: 4176c6f63109
 
-.. 418b05f95db5
-Improve CPython compatibility for ``is``. Now code like ``if x is ():``
-works the same way as it does on CPython.  See 
http://pypy.readthedocs.io/en/latest/cpython_differences.html#object-identity-of-primitive-values-is-and-id
 .
 
-.. pull request #455
-Add sys.{get,set}dlopenflags, for cpyext extensions.
-
-.. branch: fix-gen-dfa
-
-Resolves an issue with the generator script to build the dfa for Python syntax.
-
-.. branch: z196-support
-
-Fixes a critical issue in the register allocator and extends support on s390x.
-PyPy runs and translates on the s390x revisions z10 (released February 2008, 
experimental)
-and z196 (released August 2010) in addition to zEC12 and z13.
-To target e.g. z196 on a zEC12 machine supply CFLAGS="-march=z196" to your 
shell environment.
-
-.. branch: s390x-5.3-catchup
-
-Implement the backend related changes for s390x.
-
-.. branch: incminimark-ll_assert
-.. branch: vmprof-openbsd
-
-.. branch: testing-cleanup
-
-Simplify handling of interp-level tests and make it more forward-
-compatible.
-
-.. branch: pyfile-tell
-Sync w_file with the c-level FILE* before returning FILE* in PyFile_AsFile
-
-.. branch: rw-PyString_AS_STRING
-Allow rw access to the char* returned from PyString_AS_STRING, also refactor
-PyStringObject to look like cpython's and allow subclassing PyString_Type and
-PyUnicode_Type
-
-.. branch: save_socket_errno
-
-Bug fix: if ``socket.socket()`` failed, the ``socket.error`` did not show
-the errno of the failing system call, but instead some random previous
-errno.
-
-.. branch: PyTuple_Type-subclass
-
-Refactor PyTupleObject to look like cpython's and allow subclassing 
-PyTuple_Type
-
-.. branch: call-via-pyobj
-
-Use offsets from PyTypeObject to find actual c function to call rather than
-fixed functions, allows function override after PyType_Ready is called
-
-.. branch: issue2335
-
-Avoid exhausting the stack in the JIT due to successive guard
-failures in the same Python function ending up as successive levels of
-RPython functions, while at app-level the traceback is very short
-
-.. branch: use-madv-free
-
-Try harder to memory to the OS.  See e.g. issue #2336.  Note that it does
-not show up as a reduction of the VIRT column in ``top``, and the RES
-column might also not show the reduction, particularly on Linux >= 4.5 or
-on OS/X: it uses MADV_FREE, which only marks the pages as returnable to
-the OS if the memory is low.
-
-.. branch: cpyext-slotdefs2
-
-Fill in more slots when creating a PyTypeObject from a W_TypeObject
-More slots are still TBD, like tp_print and richcmp
-
-.. branch: json-surrogates
-
-Align json module decode with the cpython's impl, fixes issue 2345
-
-.. branch: issue2343
-
-Copy CPython's logic more closely for handling of ``__instancecheck__()``
-and ``__subclasscheck__()``.  Fixes issue 2343.
-
-.. branch: msvcrt-cffi
-
-Rewrite the Win32 dependencies of 'subprocess' to use cffi instead
-of ctypes. This avoids importing ctypes in many small programs and
-scripts, which in turn avoids enabling threads (because ctypes
-creates callbacks at import time, and callbacks need threads).
-
-.. branch: new-jit-log
-
-The new logging facility that integrates with and adds features to vmprof.com.
-
-.. branch: jitlog-32bit
-
-Resolve issues to use the new logging facility on a 32bit system
-
-.. branch: ep2016sprint
-
-Trying harder to make hash(-1) return -2, like it does on CPython
-
-.. branch: jitlog-exact-source-lines
-
-Log exact line positions in debug merge points.
-
-.. branch: null_byte_after_str
-
-Allocate all RPython strings with one extra byte, normally unused.
-It is used to hold a final zero in case we need some ``char *``
-representation of the string, together with checks like ``not
-can_move()`` or object pinning. Main new thing that this allows:
-``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.
-
-.. branch: memoryview-attributes
-
-Support for memoryview attributes (format, itemsize, ...).
-Extends the cpyext emulation layer.
diff --git a/pypy/doc/whatsnew-pypy2-5.4.0.rst 
b/pypy/doc/whatsnew-pypy2-5.4.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-pypy2-5.4.0.rst
@@ -0,0 +1,165 @@
+=========================
+What's new in PyPy2.7 5.4
+=========================
+
+.. this is a revision shortly after release-pypy2.7-v5.3
+.. startrev: 873218a739f1
+
+.. 418b05f95db5
+Improve CPython compatibility for ``is``. Now code like ``if x is ():``
+works the same way as it does on CPython.  See 
http://pypy.readthedocs.io/en/latest/cpython_differences.html#object-identity-of-primitive-values-is-and-id
 .
+
+.. pull request #455
+Add sys.{get,set}dlopenflags, for cpyext extensions.
+
+.. branch: fix-gen-dfa
+
+Resolves an issue with the generator script to build the dfa for Python syntax.
+
+.. branch: z196-support
+
+Fixes a critical issue in the register allocator and extends support on s390x.
+PyPy runs and translates on the s390x revisions z10 (released February 2008, 
experimental)
+and z196 (released August 2010) in addition to zEC12 and z13.
+To target e.g. z196 on a zEC12 machine supply CFLAGS="-march=z196" to your 
shell environment.
+
+.. branch: s390x-5.3-catchup
+
+Implement the backend related changes for s390x.
+
+.. branch: incminimark-ll_assert
+.. branch: vmprof-openbsd
+
+.. branch: testing-cleanup
+
+Simplify handling of interp-level tests and make it more forward-
+compatible.
+
+.. branch: pyfile-tell
+Sync w_file with the c-level FILE* before returning FILE* in PyFile_AsFile
+
+.. branch: rw-PyString_AS_STRING
+Allow rw access to the char* returned from PyString_AS_STRING, also refactor
+PyStringObject to look like cpython's and allow subclassing PyString_Type and
+PyUnicode_Type
+
+.. branch: save_socket_errno
+
+Bug fix: if ``socket.socket()`` failed, the ``socket.error`` did not show
+the errno of the failing system call, but instead some random previous
+errno.
+
+.. branch: PyTuple_Type-subclass
+
+Refactor PyTupleObject to look like cpython's and allow subclassing 
+PyTuple_Type
+
+.. branch: call-via-pyobj
+
+Use offsets from PyTypeObject to find actual c function to call rather than
+fixed functions, allows function override after PyType_Ready is called
+
+.. branch: issue2335
+
+Avoid exhausting the stack in the JIT due to successive guard
+failures in the same Python function ending up as successive levels of
+RPython functions, while at app-level the traceback is very short
+
+.. branch: use-madv-free
+
+Try harder to memory to the OS.  See e.g. issue #2336.  Note that it does
+not show up as a reduction of the VIRT column in ``top``, and the RES
+column might also not show the reduction, particularly on Linux >= 4.5 or
+on OS/X: it uses MADV_FREE, which only marks the pages as returnable to
+the OS if the memory is low.
+
+.. branch: cpyext-slotdefs2
+
+Fill in more slots when creating a PyTypeObject from a W_TypeObject
+More slots are still TBD, like tp_print and richcmp
+
+.. branch: json-surrogates
+
+Align json module decode with the cpython's impl, fixes issue 2345
+
+.. branch: issue2343
+
+Copy CPython's logic more closely for handling of ``__instancecheck__()``
+and ``__subclasscheck__()``.  Fixes issue 2343.
+
+.. branch: msvcrt-cffi
+
+Rewrite the Win32 dependencies of 'subprocess' to use cffi instead
+of ctypes. This avoids importing ctypes in many small programs and
+scripts, which in turn avoids enabling threads (because ctypes
+creates callbacks at import time, and callbacks need threads).
+
+.. branch: new-jit-log
+
+The new logging facility that integrates with and adds features to vmprof.com.
+
+.. branch: jitlog-32bit
+
+Resolve issues to use the new logging facility on a 32bit system
+
+.. branch: ep2016sprint
+
+Trying harder to make hash(-1) return -2, like it does on CPython
+
+.. branch: jitlog-exact-source-lines
+
+Log exact line positions in debug merge points.
+
+.. branch: null_byte_after_str
+
+Allocate all RPython strings with one extra byte, normally unused.
+It is used to hold a final zero in case we need some ``char *``
+representation of the string, together with checks like ``not
+can_move()`` or object pinning. Main new thing that this allows:
+``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.
+
+.. branch: memoryview-attributes
+
+Support for memoryview attributes (format, itemsize, ...).
+Extends the cpyext emulation layer.
+
+.. branch: redirect-assembler-jitlog
+
+Log more information to properly rebuild the redirected traces in jitviewer.
+
+.. branch: cpyext-subclass
+
+Copy Py_TPFLAGS_CHECKTYPES, Py_TPFLAGS_HAVE_INPLACEOPS when inheriting
diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py
--- a/pypy/module/_io/interp_fileio.py
+++ b/pypy/module/_io/interp_fileio.py
@@ -4,6 +4,7 @@
     OperationError, oefmt, wrap_oserror, wrap_oserror2)
 from rpython.rlib.rarithmetic import r_longlong
 from rpython.rlib.rstring import StringBuilder
+from rpython.rlib import rposix
 from os import O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_TRUNC, O_EXCL
 import sys, os, stat, errno
 from pypy.module._io.interp_iobase import W_RawIOBase, convert_size
@@ -29,6 +30,7 @@
 
 O_BINARY = getattr(os, "O_BINARY", 0)
 O_APPEND = getattr(os, "O_APPEND", 0)
+_open_inhcache = rposix.SetNonInheritableCache()
 
 def _bad_mode(space):
     raise oefmt(space.w_ValueError,
@@ -139,6 +141,7 @@
 
     @unwrap_spec(mode=str, closefd=int)
     def descr_init(self, space, w_name, mode='r', closefd=True, w_opener=None):
+        self._close(space)
         if space.isinstance_w(w_name, space.w_float):
             raise oefmt(space.w_TypeError,
                         "integer argument expected, got float")
@@ -153,6 +156,8 @@
                 raise oefmt(space.w_ValueError, "negative file descriptor")
 
         self.readable, self.writable, self.created, self.appending, flags = 
decode_mode(space, mode)
+        if rposix.O_CLOEXEC is not None:
+            flags |= rposix.O_CLOEXEC
 
         fd_is_own = False
         try:
@@ -171,8 +176,7 @@
                     raise oefmt(space.w_ValueError,
                                 "Cannot use closefd=False with file name")
 
-                from pypy.module.posix.interp_posix import (
-                    dispatch_filename, rposix)
+                from pypy.module.posix.interp_posix import dispatch_filename
                 try:
                     self.fd = dispatch_filename(rposix.open)(
                         space, w_name, flags, 0666)
@@ -181,6 +185,11 @@
                                         exception_name='w_IOError')
                 finally:
                     fd_is_own = True
+                if not rposix._WIN32:
+                    try:
+                        _open_inhcache.set_non_inheritable(self.fd)
+                    except OSError as e:
+                        raise wrap_oserror2(space, e, w_name)
             else:
                 w_fd = space.call_function(w_opener, w_name, space.wrap(flags))
                 try:
@@ -192,6 +201,11 @@
                                 "expected integer from opener")
                 finally:
                     fd_is_own = True
+                if not rposix._WIN32:
+                    try:
+                        rposix.set_inheritable(self.fd, False)
+                    except OSError as e:
+                        raise wrap_oserror2(space, e, w_name)
 
             self._dircheck(space, w_name)
             space.setattr(self, space.wrap("name"), w_name)
diff --git a/pypy/module/_io/test/test_fileio.py 
b/pypy/module/_io/test/test_fileio.py
--- a/pypy/module/_io/test/test_fileio.py
+++ b/pypy/module/_io/test/test_fileio.py
@@ -246,6 +246,33 @@
             assert f.mode == 'xb'
         raises(FileExistsError, _io.FileIO, filename, 'x')
 
+    def test_non_inheritable(self):
+        import _io, posix
+        f = _io.FileIO(self.tmpfile, 'r')
+        assert posix.get_inheritable(f.fileno()) == False
+        f.close()
+
+    def test_FileIO_fd_does_not_change_inheritable(self):
+        import _io, posix
+        fd1, fd2 = posix.pipe()
+        posix.set_inheritable(fd1, True)
+        posix.set_inheritable(fd2, False)
+        f1 = _io.FileIO(fd1, 'r')
+        f2 = _io.FileIO(fd2, 'w')
+        assert posix.get_inheritable(fd1) == True
+        assert posix.get_inheritable(fd2) == False
+        f1.close()
+        f2.close()
+
+    def test_close_upon_reinit(self):
+        import _io, posix
+        f = _io.FileIO(self.tmpfile, 'r')
+        fd1 = f.fileno()
+        f.__init__(self.tmpfile, 'w')
+        fd2 = f.fileno()
+        if fd1 != fd2:
+            raises(OSError, posix.close, fd1)
+
 
 def test_flush_at_exit():
     from pypy import conftest
diff --git a/pypy/module/_posixsubprocess/_posixsubprocess.c 
b/pypy/module/_posixsubprocess/_posixsubprocess.c
--- a/pypy/module/_posixsubprocess/_posixsubprocess.c
+++ b/pypy/module/_posixsubprocess/_posixsubprocess.c
@@ -106,6 +106,30 @@
 }
 
 
+RPY_EXTERN
+int rpy_set_inheritable(int fd, int inheritable);   /* rposix.py */
+
+static int
+make_inheritable(long *py_fds_to_keep, ssize_t num_fds_to_keep,
+                 int errpipe_write)
+{
+    long i;
+
+    for (i = 0; i < num_fds_to_keep; ++i) {
+        long fd = py_fds_to_keep[i];
+        if (fd == errpipe_write) {
+            /* errpipe_write is part of py_fds_to_keep. It must be closed at
+               exec(), but kept open in the child process until exec() is
+               called. */
+            continue;
+        }
+        if (rpy_set_inheritable((int)fd, 1) < 0)
+            return -1;
+    }
+    return 0;
+}
+
+
 /* Close all file descriptors in the range start_fd inclusive to
  * end_fd exclusive except for those in py_fds_to_keep.  If the
  * range defined by [start_fd, end_fd) is large this will take a
@@ -329,6 +353,9 @@
     /* Buffer large enough to hold a hex integer.  We can't malloc. */
     char hex_errno[sizeof(saved_errno)*2+1];
 
+    if (make_inheritable(py_fds_to_keep, num_fds_to_keep, errpipe_write) < 0)
+        goto error;
+
     /* Close parent's pipe ends. */
     if (p2cwrite != -1) {
         POSIX_CALL(close(p2cwrite));
@@ -352,26 +379,25 @@
        dup2() removes the CLOEXEC flag but we must do it ourselves if dup2()
        would be a no-op (issue #10806). */
     if (p2cread == 0) {
-        int old = fcntl(p2cread, F_GETFD);
-        if (old != -1)
-            fcntl(p2cread, F_SETFD, old & ~FD_CLOEXEC);
-    } else if (p2cread != -1) {
+        if (rpy_set_inheritable(p2cread, 1) < 0)
+            goto error;
+    }
+    else if (p2cread != -1)
         POSIX_CALL(dup2(p2cread, 0));  /* stdin */
+
+    if (c2pwrite == 1) {
+        if (rpy_set_inheritable(c2pwrite, 1) < 0)
+            goto error;
     }
-    if (c2pwrite == 1) {
-        int old = fcntl(c2pwrite, F_GETFD);
-        if (old != -1)
-            fcntl(c2pwrite, F_SETFD, old & ~FD_CLOEXEC);
-    } else if (c2pwrite != -1) {
+    else if (c2pwrite != -1)
         POSIX_CALL(dup2(c2pwrite, 1));  /* stdout */
+
+    if (errwrite == 2) {
+        if (rpy_set_inheritable(errwrite, 1) < 0)
+            goto error;
     }
-    if (errwrite == 2) {
-        int old = fcntl(errwrite, F_GETFD);
-        if (old != -1)
-            fcntl(errwrite, F_SETFD, old & ~FD_CLOEXEC);
-    } else if (errwrite != -1) {
+    else if (errwrite != -1)
         POSIX_CALL(dup2(errwrite, 2));  /* stderr */
-    }
 
     /* Close pipe fds.  Make sure we don't close the same fd more than */
     /* once, or standard fds. */
diff --git a/pypy/module/_posixsubprocess/_posixsubprocess.h 
b/pypy/module/_posixsubprocess/_posixsubprocess.h
--- a/pypy/module/_posixsubprocess/_posixsubprocess.h
+++ b/pypy/module/_posixsubprocess/_posixsubprocess.h
@@ -1,3 +1,4 @@
+#include <unistd.h>    /* for ssize_t */
 #include "src/precommondefs.h"
 
 RPY_EXTERN void
diff --git a/pypy/module/_posixsubprocess/interp_subprocess.py 
b/pypy/module/_posixsubprocess/interp_subprocess.py
--- a/pypy/module/_posixsubprocess/interp_subprocess.py
+++ b/pypy/module/_posixsubprocess/interp_subprocess.py
@@ -5,6 +5,7 @@
 from rpython.rtyper.tool import rffi_platform as platform
 from rpython.translator import cdir
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from rpython.rlib import rposix
 
 from pypy.interpreter.error import (
     OperationError, exception_from_saved_errno, oefmt, wrap_oserror)
@@ -36,6 +37,7 @@
     compile_extra.append("-DHAVE_SETSID")
 
 eci = eci.merge(
+    rposix.eci_inheritable,
     ExternalCompilationInfo(
         compile_extra=compile_extra))
 
diff --git a/pypy/module/_posixsubprocess/test/test_subprocess.py 
b/pypy/module/_posixsubprocess/test/test_subprocess.py
--- a/pypy/module/_posixsubprocess/test/test_subprocess.py
+++ b/pypy/module/_posixsubprocess/test/test_subprocess.py
@@ -75,3 +75,18 @@
         n = 1
         raises(OverflowError, _posixsubprocess.fork_exec,
                1,Z(),3,[1, 2],5,6,7,8,9,10,11,12,13,14,15,16,17)
+
+    def test_pass_fds_make_inheritable(self):
+        import subprocess, posix
+
+        fd1, fd2 = posix.pipe()
+        assert posix.get_inheritable(fd1) is False
+        assert posix.get_inheritable(fd2) is False
+
+        subprocess.check_call(['/usr/bin/env', 'python', '-c',
+                               'import os;os.write(%d,b"K")' % fd2],
+                              close_fds=True, pass_fds=[fd2])
+        res = posix.read(fd1, 1)
+        assert res == b"K"
+        posix.close(fd1)
+        posix.close(fd2)
diff --git a/pypy/module/_socket/interp_func.py 
b/pypy/module/_socket/interp_func.py
--- a/pypy/module/_socket/interp_func.py
+++ b/pypy/module/_socket/interp_func.py
@@ -143,24 +143,11 @@
 @unwrap_spec(fd=int)
 def dup(space, fd):
     try:
-        newfd = rsocket.dup(fd)
+        newfd = rsocket.dup(fd, inheritable=False)
     except SocketError as e:
         raise converted_error(space, e)
     return space.wrap(newfd)
 
-@unwrap_spec(fd=int, family=int, type=int, proto=int)
-def fromfd(space, fd, family, type, proto=0):
-    """fromfd(fd, family, type[, proto]) -> socket object
-
-    Create a socket object from the given file descriptor.
-    The remaining arguments are the same as for socket().
-    """
-    try:
-        sock = rsocket.fromfd(fd, family, type, proto)
-    except SocketError as e:
-        raise converted_error(space, e)
-    return space.wrap(W_Socket(space, sock))
-
 @unwrap_spec(family=int, type=int, proto=int)
 def socketpair(space, family=rsocket.socketpair_default_family,
                       type  =rsocket.SOCK_STREAM,
@@ -173,7 +160,8 @@
     AF_UNIX if defined on the platform; otherwise, the default is AF_INET.
     """
     try:
-        sock1, sock2 = rsocket.socketpair(family, type, proto)
+        sock1, sock2 = rsocket.socketpair(family, type, proto,
+                                          inheritable=False)
     except SocketError as e:
         raise converted_error(space, e)
     return space.newtuple([
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
@@ -177,7 +177,7 @@
                 sock = RSocket(family, type, proto,
                                fd=space.c_filedescriptor_w(w_fileno))
             else:
-                sock = RSocket(family, type, proto)
+                sock = RSocket(family, type, proto, inheritable=False)
             W_Socket.__init__(self, space, sock)
         except SocketError as e:
             raise converted_error(space, e)
@@ -228,7 +228,7 @@
         For IP sockets, the address info is a pair (hostaddr, port).
         """
         try:
-            fd, addr = self.sock.accept()
+            fd, addr = self.sock.accept(inheritable=False)
             return space.newtuple([space.wrap(fd),
                                    addr_as_object(addr, fd, space)])
         except SocketError as e:
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
@@ -546,11 +546,15 @@
         s.ioctl(_socket.SIO_KEEPALIVE_VALS, (1, 100, 100))
 
     def test_dup(self):
-        import _socket as socket
+        import _socket as socket, posix
         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         s.bind(('localhost', 0))
         fd = socket.dup(s.fileno())
         assert s.fileno() != fd
+        assert posix.get_inheritable(s.fileno()) is False
+        assert posix.get_inheritable(fd) is False
+        posix.close(fd)
+        s.close()
 
     def test_dup_error(self):
         import _socket
@@ -652,6 +656,26 @@
         assert len(w) == 1, [str(warning) for warning in w]
         assert r in str(w[0])
 
+    def test_invalid_fd(self):
+        import _socket
+        raises(ValueError, _socket.socket, fileno=-1)
+
+    def test_socket_non_inheritable(self):
+        import _socket, posix
+        s1 = _socket.socket()
+        assert posix.get_inheritable(s1.fileno()) is False
+        s1.close()
+
+    def test_socketpair_non_inheritable(self):
+        import _socket, posix
+        if not hasattr(_socket, 'socketpair'):
+            skip("no socketpair")
+        s1, s2 = _socket.socketpair()
+        assert posix.get_inheritable(s1.fileno()) is False
+        assert posix.get_inheritable(s2.fileno()) is False
+        s1.close()
+        s2.close()
+
 
 class AppTestNetlink:
     def setup_class(cls):
@@ -830,6 +854,16 @@
         assert cli.family == socket.AF_INET
 
 
+    def test_accept_non_inheritable(self):
+        import _socket, posix
+        cli = _socket.socket()
+        cli.connect(self.serv.getsockname())
+        fileno, addr = self.serv._accept()
+        assert posix.get_inheritable(fileno) is False
+        posix.close(fileno)
+        cli.close()
+
+
 class AppTestErrno:
     spaceconfig = {'usemodules': ['_socket']}
 
diff --git a/pypy/module/_winreg/interp_winreg.py 
b/pypy/module/_winreg/interp_winreg.py
--- a/pypy/module/_winreg/interp_winreg.py
+++ b/pypy/module/_winreg/interp_winreg.py
@@ -356,9 +356,15 @@
 
     elif typ == rwinreg.REG_SZ or typ == rwinreg.REG_EXPAND_SZ:
         if not buflen:
-            return space.wrap("")
-        s = rffi.charp2strn(rffi.cast(rffi.CCHARP, buf), buflen)
-        return space.wrap(s)
+            s = ""
+        else:
+            # may or may not have a trailing NULL in the buffer.
+            buf = rffi.cast(rffi.CCHARP, buf)
+            if buf[buflen - 1] == '\x00':
+                buflen -= 1
+            s = rffi.charp2strn(buf, buflen)
+        w_s = space.wrap(s)
+        return space.call_method(w_s, 'decode', space.wrap('mbcs'))
 
     elif typ == rwinreg.REG_MULTI_SZ:
         if not buflen:
@@ -458,7 +464,7 @@
                     return space.newtuple([
                         convert_from_regdata(space, databuf,
                                              length, retType[0]),
-                        space.wrap(retType[0]),
+                        space.wrap(intmask(retType[0])),
                         ])
 
 @unwrap_spec(subkey=str)
@@ -610,7 +616,7 @@
                                 space.wrap(rffi.charp2str(valuebuf)),
                                 convert_from_regdata(space, databuf,
                                                      length, retType[0]),
-                                space.wrap(retType[0]),
+                                space.wrap(intmask(retType[0])),
                                 ])
 
 @unwrap_spec(index=int)
diff --git a/pypy/module/_winreg/test/test_winreg.py 
b/pypy/module/_winreg/test/test_winreg.py
--- a/pypy/module/_winreg/test/test_winreg.py
+++ b/pypy/module/_winreg/test/test_winreg.py
@@ -154,6 +154,7 @@
 
     def test_readValues(self):
         from winreg import OpenKey, EnumValue, QueryValueEx, EnumKey
+        from winreg import REG_SZ, REG_EXPAND_SZ
         key = OpenKey(self.root_key, self.test_key_name)
         sub_key = OpenKey(key, "sub_key")
         index = 0
@@ -167,7 +168,10 @@
         assert index == len(self.test_data)
 
         for name, value, type in self.test_data:
-            assert QueryValueEx(sub_key, name) == (value, type)
+            result = QueryValueEx(sub_key, name)
+            assert result == (value, type)
+            if type == REG_SZ or type == REG_EXPAND_SZ:
+                assert isinstance(result[0], unicode)     # not string
 
         assert EnumKey(key, 0) == "sub_key"
         raises(EnvironmentError, EnumKey, key, 1)
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
@@ -119,7 +119,7 @@
 constant_names = """
 Py_TPFLAGS_READY Py_TPFLAGS_READYING Py_TPFLAGS_HAVE_GETCHARBUFFER
 METH_COEXIST METH_STATIC METH_CLASS Py_TPFLAGS_BASETYPE
-METH_NOARGS METH_VARARGS METH_KEYWORDS METH_O
+METH_NOARGS METH_VARARGS METH_KEYWORDS METH_O Py_TPFLAGS_HAVE_INPLACEOPS
 Py_TPFLAGS_HEAPTYPE Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_HAVE_NEWBUFFER
 Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE Py_TPFLAGS_CHECKTYPES
 Py_CLEANUP_SUPPORTED
@@ -975,13 +975,15 @@
         py_type_ready(space, get_capsule_type())
     INIT_FUNCTIONS.append(init_types)
     from pypy.module.posix.interp_posix import add_fork_hook
-    reinit_tls = rffi.llexternal('%sThread_ReInitTLS' % prefix, [], 
lltype.Void,
-                                 compilation_info=eci)
     global py_fatalerror
     py_fatalerror = rffi.llexternal('%s_FatalError' % prefix,
                                     [CONST_STRING], lltype.Void,
                                     compilation_info=eci)
-    add_fork_hook('child', reinit_tls)
+    _reinit_tls = rffi.llexternal('%sThread_ReInitTLS' % prefix, [], 
+                                  lltype.Void, compilation_info=eci)
+    def reinit_tls(space):
+        _reinit_tls()
+    add_fork_hook('child', _reinit_tls)
 
 def init_function(func):
     INIT_FUNCTIONS.append(func)
diff --git a/pypy/module/cpyext/include/patchlevel.h 
b/pypy/module/cpyext/include/patchlevel.h
--- a/pypy/module/cpyext/include/patchlevel.h
+++ b/pypy/module/cpyext/include/patchlevel.h
@@ -29,8 +29,8 @@
 #define PY_VERSION             "3.3.5"
 
 /* PyPy version as a string */
-#define PYPY_VERSION "5.3.2-alpha0"
-#define PYPY_VERSION_NUM  0x05030200
+#define PYPY_VERSION "5.4.1-alpha0"
+#define PYPY_VERSION_NUM  0x05040100
 
 /* Defined to mean a PyPy where cpyext holds more regular references
    to PyObjects, e.g. staying alive as long as the internal PyPy object
diff --git a/pypy/module/cpyext/test/buffer_test.c 
b/pypy/module/cpyext/test/buffer_test.c
--- a/pypy/module/cpyext/test/buffer_test.c
+++ b/pypy/module/cpyext/test/buffer_test.c
@@ -1,3 +1,6 @@
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_WARNINGS 1
+#endif
 #include <Python.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -10,7 +13,7 @@
 /* Structure defines a 1-dimensional strided array */
 typedef struct{
     int* arr;
-    long length;
+    Py_ssize_t length;
 } MyArray;
 
 /* initialize the array with integers 0...length */
@@ -61,13 +64,13 @@
 static int
 PyMyArray_init(PyMyArray *self, PyObject *args, PyObject *kwds)
 {
+    int length = 0;
+    static char *kwlist[] = {"length", NULL};
     // init may have already been called
     if (self->arr.arr != NULL) {
         deallocate_MyArray(&self->arr);
     }
 
-    int length = 0;
-    static char *kwlist[] = {"length", NULL};
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &length))
         return -1;
 
@@ -103,16 +106,19 @@
 static int
 PyMyArray_getbuffer(PyObject *obj, Py_buffer *view, int flags)
 {
+  PyMyArray* self = (PyMyArray*)obj;
+  fprintf(stdout, "in PyMyArray_getbuffer\n");
   if (view == NULL) {
+    fprintf(stdout, "view is NULL\n");
     PyErr_SetString(PyExc_ValueError, "NULL view in getbuffer");
     return -1;
   }
   if (flags == 0) {
+    fprintf(stdout, "flags is 0\n");
     PyErr_SetString(PyExc_ValueError, "flags == 0 in getbuffer");
     return -1;
   }
 
-  PyMyArray* self = (PyMyArray*)obj;
   view->obj = (PyObject*)self;
   view->buf = (void*)self->arr.arr;
   view->len = self->arr.length * sizeof(int);
@@ -218,7 +224,6 @@
 #ifdef __GNUC__
 extern __attribute__((visibility("default")))
 #else
-extern __declspec(dllexport)
 #endif
 
 PyMODINIT_FUNC
diff --git a/pypy/module/cpyext/test/test_arraymodule.py 
b/pypy/module/cpyext/test/test_arraymodule.py
--- a/pypy/module/cpyext/test/test_arraymodule.py
+++ b/pypy/module/cpyext/test/test_arraymodule.py
@@ -77,4 +77,13 @@
         module.switch_multiply()
         res = [1, 2, 3] * arr
         assert res == [2, 4, 6]
+
+    def test_subclass(self):
+        module = self.import_module(name='array')
+        class Sub(module.array):
+            pass
+
+        arr = Sub('i', [2])
+        res = [1, 2, 3] * arr
+        assert res == [1, 2, 3, 1, 2, 3]
         
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
@@ -18,7 +18,8 @@
     Py_TPFLAGS_HEAPTYPE, METH_VARARGS, METH_KEYWORDS, CANNOT_FAIL,
     Py_TPFLAGS_HAVE_GETCHARBUFFER, build_type_checkers, StaticObjectBuilder,
     PyObjectFields, Py_TPFLAGS_BASETYPE, PyTypeObject, PyTypeObjectPtr,
-    Py_TPFLAGS_HAVE_NEWBUFFER)
+    Py_TPFLAGS_HAVE_NEWBUFFER, Py_TPFLAGS_CHECKTYPES,
+    Py_TPFLAGS_HAVE_INPLACEOPS)
 from pypy.module.cpyext.methodobject import (W_PyCClassMethodObject,
     W_PyCWrapperObject, PyCFunction_NewEx, PyCFunction_typedef, PyMethodDef,
     W_PyCMethodObject, W_PyCFunctionObject)
@@ -386,6 +387,8 @@
         pto.c_tp_basicsize = base_pto.c_tp_basicsize
     if pto.c_tp_itemsize < base_pto.c_tp_itemsize:
         pto.c_tp_itemsize = base_pto.c_tp_itemsize
+    pto.c_tp_flags |= base_pto.c_tp_flags & Py_TPFLAGS_CHECKTYPES
+    pto.c_tp_flags |= base_pto.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS
     flags = rffi.cast(lltype.Signed, pto.c_tp_flags)
     base_object_pyo = make_ref(space, space.w_object)
     base_object_pto = rffi.cast(PyTypeObjectPtr, base_object_pyo)
@@ -721,8 +724,13 @@
     # inheriting tp_as_* slots
     base = py_type.c_tp_base
     if base:
-        if not py_type.c_tp_as_number: py_type.c_tp_as_number = 
base.c_tp_as_number
-        if not py_type.c_tp_as_sequence: py_type.c_tp_as_sequence = 
base.c_tp_as_sequence
+        if not py_type.c_tp_as_number: 
+            py_type.c_tp_as_number = base.c_tp_as_number
+            py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_CHECKTYPES
+            py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS
+        if not py_type.c_tp_as_sequence:
+            py_type.c_tp_as_sequence = base.c_tp_as_sequence
+            py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS
         if not py_type.c_tp_as_mapping: py_type.c_tp_as_mapping = 
base.c_tp_as_mapping
         if not py_type.c_tp_as_buffer: py_type.c_tp_as_buffer = 
base.c_tp_as_buffer
 
diff --git a/pypy/module/fcntl/test/test_fcntl.py 
b/pypy/module/fcntl/test/test_fcntl.py
--- a/pypy/module/fcntl/test/test_fcntl.py
+++ b/pypy/module/fcntl/test/test_fcntl.py
@@ -32,7 +32,7 @@
 
         f = open(self.tmp + "b", "w+")
 
-        fcntl.fcntl(f, 1, 0)
+        original = fcntl.fcntl(f, 1, 0)
         fcntl.fcntl(f, 1)
         fcntl.fcntl(F(int(f.fileno())), 1)
         raises(TypeError, fcntl.fcntl, "foo")
@@ -46,9 +46,16 @@
         raises(ValueError, fcntl.fcntl, -1, 1, 0)
         raises(ValueError, fcntl.fcntl, F(-1), 1, 0)
         raises(ValueError, fcntl.fcntl, F(int(-1)), 1, 0)
-        assert fcntl.fcntl(f, 1, 0) == 0
+        assert fcntl.fcntl(f, 1, 0) == original
         assert fcntl.fcntl(f, 2, "foo") == b"foo"
-        assert fcntl.fcntl(f, 2, memoryview(b"foo")) == b"foo"
+        assert fcntl.fcntl(f, 2, b"foo") == b"foo"
+
+        # This is supposed to work I think, but CPython 3.5 refuses it
+        # for reasons I don't understand:
+        #     >>> _testcapi.getargs_s_hash(memoryview(b"foo"))
+        #     TypeError: must be read-only bytes-like object, not memoryview
+        #
+        # assert fcntl.fcntl(f, 2, memoryview(b"foo")) == b"foo"
 
         try:
             os.O_LARGEFILE
@@ -202,7 +209,7 @@
         raises(TypeError, fcntl.ioctl, "foo")
         raises(TypeError, fcntl.ioctl, 0, "foo")
         #raises(TypeError, fcntl.ioctl, 0, TIOCGPGRP, float(0))
-        raises(TypeError, fcntl.ioctl, 0, TIOCGPGRP, 1, "foo")
+        raises(TypeError, fcntl.ioctl, 0, TIOCGPGRP, 1, "foo", "bar")
 
         child_pid, mfd = pty.fork()
         if child_pid == 0:
@@ -229,13 +236,13 @@
             assert res == 0
             assert buf.tostring() == expected
 
-            exc = raises(TypeError, fcntl.ioctl, mfd, TIOCGPGRP, 
memoryview(b'abc'), False)
-            assert str(exc.value) == "ioctl requires a file or file 
descriptor, an integer and optionally an integer or buffer argument"
+            raises(TypeError, fcntl.ioctl, mfd, TIOCGPGRP, (), False)
 
             res = fcntl.ioctl(mfd, TIOCGPGRP, buf, False)
             assert res == expected
 
-            raises(TypeError, fcntl.ioctl, mfd, TIOCGPGRP, "\x00\x00", True)
+            # xxx this fails on CPython 3.5, that's a minor bug
+            #raises(TypeError, fcntl.ioctl, mfd, TIOCGPGRP, "\x00\x00", True)
 
             res = fcntl.ioctl(mfd, TIOCGPGRP, "\x00\x00\x00\x00")
             assert res == expected
diff --git a/pypy/module/marshal/interp_marshal.py 
b/pypy/module/marshal/interp_marshal.py
--- a/pypy/module/marshal/interp_marshal.py
+++ b/pypy/module/marshal/interp_marshal.py
@@ -200,15 +200,6 @@
 
     def dump_w_obj(self, w_obj):
         space = self.space
-        if space.type(w_obj).is_heaptype():
-            try:
-                buf = space.readbuf_w(w_obj)
-            except OperationError as e:
-                if not e.match(space, space.w_TypeError):
-                    raise
-                self.raise_exc("unmarshallable object")
-            else:
-                w_obj = space.newbuffer(buf)
         try:
             self.put_w_obj(w_obj)
         except rstackovf.StackOverflow:
diff --git a/pypy/module/marshal/test/test_marshal.py 
b/pypy/module/marshal/test/test_marshal.py
--- a/pypy/module/marshal/test/test_marshal.py
+++ b/pypy/module/marshal/test/test_marshal.py
@@ -186,6 +186,8 @@
             assert str(exc.value) == 'unmarshallable object'
             exc = raises(ValueError, marshal.dumps, subtype())
             assert str(exc.value) == 'unmarshallable object'
+            exc = raises(ValueError, marshal.dumps, (subtype(),))
+            assert str(exc.value) == 'unmarshallable object'
 
     def test_valid_subtypes(self):
         import marshal
diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py
--- a/pypy/module/posix/__init__.py
+++ b/pypy/module/posix/__init__.py
@@ -78,6 +78,8 @@
         'get_terminal_size': 'interp_posix.get_terminal_size',
 
         'scandir': 'interp_scandir.scandir',
+        'get_inheritable': 'interp_posix.get_inheritable',
+        'set_inheritable': 'interp_posix.set_inheritable',
     }
 
     if hasattr(os, 'chown'):
@@ -195,6 +197,9 @@
     interpleveldefs['_have_functions'] = (
         'space.newlist([space.wrap(x) for x in interp_posix.have_functions])')
 
+    if rposix.HAVE_PIPE2:
+        interpleveldefs['pipe2'] = 'interp_posix.pipe2'
+
     def startup(self, space):
         from pypy.module.posix import interp_posix
         from pypy.module.imp import importing
diff --git a/pypy/module/posix/interp_posix.py 
b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -211,6 +211,8 @@
             space.w_NotImplementedError,
             "%s: %s unavailable on this platform", funcname, arg)
 
+_open_inhcache = rposix.SetNonInheritableCache()
+
 @unwrap_spec(flags=c_int, mode=c_int, dir_fd=DirFD(rposix.HAVE_OPENAT))
 def open(space, w_path, flags, mode=0777,
          __kwonly__=None, dir_fd=DEFAULT_DIR_FD):
@@ -222,12 +224,15 @@
   and path should be relative; path will then be relative to that directory.
 dir_fd may not be implemented on your platform.
   If it is unavailable, using it will raise a NotImplementedError."""
+    if rposix.O_CLOEXEC is not None:
+        flags |= rposix.O_CLOEXEC
     try:
         if rposix.HAVE_OPENAT and dir_fd != DEFAULT_DIR_FD:
             path = space.fsencode_w(w_path)
             fd = rposix.openat(path, flags, mode, dir_fd)
         else:
             fd = dispatch_filename(rposix.open)(space, w_path, flags, mode)
+        _open_inhcache.set_non_inheritable(fd)
     except OSError as e:
         raise wrap_oserror2(space, e, w_path)
     return space.wrap(fd)
@@ -538,17 +543,17 @@
     """Create a copy of the file descriptor.  Return the new file
 descriptor."""
     try:
-        newfd = os.dup(fd)
+        newfd = rposix.dup(fd, inheritable=False)
     except OSError as e:
         raise wrap_oserror(space, e)
     else:
         return space.wrap(newfd)
 
-@unwrap_spec(old_fd=c_int, new_fd=c_int)
-def dup2(space, old_fd, new_fd):
+@unwrap_spec(old_fd=c_int, new_fd=c_int, inheritable=int)
+def dup2(space, old_fd, new_fd, inheritable=1):
     """Duplicate a file descriptor."""
     try:
-        os.dup2(old_fd, new_fd)
+        rposix.dup2(old_fd, new_fd, inheritable)
     except OSError as e:
         raise wrap_oserror(space, e)
 
@@ -891,15 +896,38 @@
             result_w[i] = space.fsdecode(w_bytes)
     return space.newlist(result_w)
 
+@unwrap_spec(fd=c_int)
+def get_inheritable(space, fd):
+    try:
+        return space.wrap(rposix.get_inheritable(fd))
+    except OSError as e:
+        raise wrap_oserror(space, e)
+
+@unwrap_spec(fd=c_int, inheritable=int)
+def set_inheritable(space, fd, inheritable):
+    try:
+        rposix.set_inheritable(fd, inheritable)
+    except OSError as e:
+        raise wrap_oserror(space, e)
+
+_pipe_inhcache = rposix.SetNonInheritableCache()
+
 def pipe(space):
     "Create a pipe.  Returns (read_end, write_end)."
     try:
-        fd1, fd2 = os.pipe()
+        fd1, fd2 = rposix.pipe(rposix.O_CLOEXEC or 0)
+        _pipe_inhcache.set_non_inheritable(fd1)
+        _pipe_inhcache.set_non_inheritable(fd2)
     except OSError as e:
         raise wrap_oserror(space, e)
-    # XXX later, use rposix.pipe2() if available!
-    rposix.set_inheritable(fd1, False)
-    rposix.set_inheritable(fd2, False)
+    return space.newtuple([space.wrap(fd1), space.wrap(fd2)])
+
+@unwrap_spec(flags=c_int)
+def pipe2(space, flags):
+    try:
+        fd1, fd2 = rposix.pipe2(flags)
+    except OSError as e:
+        raise wrap_oserror(space, e)
     return space.newtuple([space.wrap(fd1), space.wrap(fd2)])
 
 @unwrap_spec(mode=c_int, dir_fd=DirFD(rposix.HAVE_FCHMODAT),
@@ -1238,6 +1266,8 @@
     "Open a pseudo-terminal, returning open fd's for both master and slave 
end."
     try:
         master_fd, slave_fd = os.openpty()
+        rposix.set_inheritable(master_fd, False)
+        rposix.set_inheritable(slave_fd, False)
     except OSError as e:
         raise wrap_oserror(space, e)
     return space.newtuple([space.wrap(master_fd), space.wrap(slave_fd)])
diff --git a/pypy/module/posix/test/test_posix2.py 
b/pypy/module/posix/test/test_posix2.py
--- a/pypy/module/posix/test/test_posix2.py
+++ b/pypy/module/posix/test/test_posix2.py
@@ -106,6 +106,7 @@
         posix = self.posix
         fd = posix.open(path, posix.O_RDONLY, 0o777)
         fd2 = posix.dup(fd)
+        assert posix.get_inheritable(fd2) == False
         assert not posix.isatty(fd2)
         s = posix.read(fd, 1)
         assert s == b't'
@@ -398,6 +399,16 @@
             os.write(slave_fd, b'x\n')
             data = os.read(master_fd, 100)
             assert data.startswith(b'x')
+            os.close(master_fd)
+            os.close(slave_fd)
+
+        def test_openpty_non_inheritable(self):
+            os = self.posix
+            master_fd, slave_fd = os.openpty()
+            assert os.get_inheritable(master_fd) == False
+            assert os.get_inheritable(slave_fd) == False
+            os.close(master_fd)
+            os.close(slave_fd)
 
     if hasattr(__import__(os.name), "forkpty"):
         def test_forkpty(self):
@@ -1077,6 +1088,52 @@
         x = f.read(1)
         assert x == 'e'
 
+    def test_pipe_inheritable(self):
+        fd1, fd2 = self.posix.pipe()
+        assert self.posix.get_inheritable(fd1) == False
+        assert self.posix.get_inheritable(fd2) == False
+        self.posix.close(fd1)
+        self.posix.close(fd2)
+
+    def test_pipe2(self):
+        if not hasattr(self.posix, 'pipe2'):
+            skip("no pipe2")
+        fd1, fd2 = self.posix.pipe2(0)
+        assert self.posix.get_inheritable(fd1) == True
+        assert self.posix.get_inheritable(fd2) == True
+        self.posix.close(fd1)
+        self.posix.close(fd2)
+
+    def test_O_CLOEXEC(self):
+        if not hasattr(self.posix, 'pipe2'):
+            skip("no pipe2")
+        if not hasattr(self.posix, 'O_CLOEXEC'):
+            skip("no O_CLOEXEC")
+        fd1, fd2 = self.posix.pipe2(self.posix.O_CLOEXEC)
+        assert self.posix.get_inheritable(fd1) == False
+        assert self.posix.get_inheritable(fd2) == False
+        self.posix.close(fd1)
+        self.posix.close(fd2)
+
+    def test_dup2_inheritable(self):
+        fd1, fd2 = self.posix.pipe()
+        assert self.posix.get_inheritable(fd2) == False
+        self.posix.dup2(fd1, fd2)
+        assert self.posix.get_inheritable(fd2) == True
+        self.posix.dup2(fd1, fd2, False)
+        assert self.posix.get_inheritable(fd2) == False
+        self.posix.dup2(fd1, fd2, True)
+        assert self.posix.get_inheritable(fd2) == True
+        self.posix.close(fd1)
+        self.posix.close(fd2)
+
+    def test_open_inheritable(self):
+        os = self.posix
+        fd = os.open(self.path2 + 'test_open_inheritable',
+                     os.O_RDWR | os.O_CREAT, 0o666)
+        assert os.get_inheritable(fd) == False
+        os.close(fd)
+
     def test_urandom(self):
         os = self.posix
         s = os.urandom(5)
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
@@ -39,7 +39,8 @@
 for symbol in public_symbols:
     setattr(CConfig, symbol, rffi_platform.DefinedConstantInteger(symbol))
 
-for symbol in ["EPOLL_CTL_ADD", "EPOLL_CTL_MOD", "EPOLL_CTL_DEL"]:
+for symbol in ["EPOLL_CTL_ADD", "EPOLL_CTL_MOD", "EPOLL_CTL_DEL",
+               "EPOLL_CLOEXEC"]:
     setattr(CConfig, symbol, rffi_platform.ConstantInteger(symbol))
 
 cconfig = rffi_platform.configure(CConfig)
@@ -52,13 +53,14 @@
 EPOLL_CTL_ADD = cconfig["EPOLL_CTL_ADD"]
 EPOLL_CTL_MOD = cconfig["EPOLL_CTL_MOD"]
 EPOLL_CTL_DEL = cconfig["EPOLL_CTL_DEL"]
+EPOLL_CLOEXEC = cconfig["EPOLL_CLOEXEC"]
 
 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,
+epoll_create1 = rffi.llexternal(
+    "epoll_create1", [rffi.INT], rffi.INT, compilation_info=eci,
     save_err=rffi.RFFI_SAVE_ERRNO
 )
 epoll_ctl = rffi.llexternal(
@@ -82,14 +84,12 @@
         self.epfd = epfd
         self.register_finalizer(space)
 
-    @unwrap_spec(sizehint=int)
-    def descr__new__(space, w_subtype, sizehint=-1):
-        if sizehint == -1:
-            sizehint = FD_SETSIZE - 1
-        elif sizehint < 0:
+    @unwrap_spec(sizehint=int, flags=int)
+    def descr__new__(space, w_subtype, sizehint=0, flags=0):
+        if sizehint < 0:     # 'sizehint' is otherwise ignored
             raise oefmt(space.w_ValueError,
                         "sizehint must be greater than zero, got %d", sizehint)
-        epfd = epoll_create(sizehint)
+        epfd = epoll_create1(flags | EPOLL_CLOEXEC)
         if epfd < 0:
             raise exception_from_saved_errno(space, space.w_IOError)
 
diff --git a/pypy/module/select/interp_kqueue.py 
b/pypy/module/select/interp_kqueue.py
--- a/pypy/module/select/interp_kqueue.py
+++ b/pypy/module/select/interp_kqueue.py
@@ -1,10 +1,11 @@
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import oefmt
-from pypy.interpreter.error import exception_from_saved_errno
+from pypy.interpreter.error import exception_from_saved_errno, wrap_oserror
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
 from pypy.interpreter.typedef import TypeDef, generic_new_descr, GetSetProperty
 from rpython.rlib._rsocket_rffi import socketclose_no_errno
 from rpython.rlib.rarithmetic import r_uint
+from rpython.rlib import rposix
 from rpython.rtyper.lltypesystem import rffi, lltype
 from rpython.rtyper.tool import rffi_platform
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
@@ -115,6 +116,10 @@
         kqfd = syscall_kqueue()
         if kqfd < 0:
             raise exception_from_saved_errno(space, space.w_IOError)
+        try:
+            rposix.set_inheritable(kqfd, False)
+        except OSError as e:
+            raise wrap_oserror(space, e)
         return space.wrap(W_Kqueue(space, kqfd))
 
     @unwrap_spec(fd=int)
diff --git a/pypy/module/select/test/test_devpoll.py 
b/pypy/module/select/test/test_devpoll.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/select/test/test_devpoll.py
@@ -0,0 +1,4 @@
+# XXX
+
+# devpoll is not implemented, but if we do, make sure we test for
+# non-inheritable file descriptors
diff --git a/pypy/module/select/test/test_epoll.py 
b/pypy/module/select/test/test_epoll.py
--- a/pypy/module/select/test/test_epoll.py
+++ b/pypy/module/select/test/test_epoll.py
@@ -209,3 +209,10 @@
         ep = select.epoll()
         ep.close()
         ep.close()
+
+    def test_non_inheritable(self):
+        import select, posix
+
+        ep = select.epoll()
+        assert posix.get_inheritable(ep.fileno()) == False
+        ep.close()
diff --git a/pypy/module/select/test/test_kqueue.py 
b/pypy/module/select/test/test_kqueue.py
--- a/pypy/module/select/test/test_kqueue.py
+++ b/pypy/module/select/test/test_kqueue.py
@@ -186,3 +186,10 @@
         a.close()
         b.close()
         kq.close()
+
+    def test_non_inheritable(self):
+        import select, posix
+
+        kq = select.kqueue()
+        assert posix.get_inheritable(kq.fileno()) == False
+        kq.close()
diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py
--- a/pypy/module/sys/version.py
+++ b/pypy/module/sys/version.py
@@ -10,7 +10,7 @@
 #XXX # sync CPYTHON_VERSION with patchlevel.h, package.py
 CPYTHON_API_VERSION        = 1013   #XXX # sync with include/modsupport.h
 
-PYPY_VERSION               = (5, 3, 2, "alpha", 0)    #XXX # sync patchlevel.h
+PYPY_VERSION               = (5, 4, 1, "alpha", 0)    #XXX # sync patchlevel.h
 
 
 import pypy
diff --git a/pypy/module/test_lib_pypy/test_gdbm_extra.py 
b/pypy/module/test_lib_pypy/test_gdbm_extra.py
--- a/pypy/module/test_lib_pypy/test_gdbm_extra.py
+++ b/pypy/module/test_lib_pypy/test_gdbm_extra.py
@@ -15,3 +15,7 @@
     assert len(g) == 2
     del g['abc']
     assert len(g) == 1
+
+def test_unicode():
+    path = unicode(udir.join('test_gdm_unicode'))
+    g = gdbm.open(path, 'c')  # does not crash
diff --git a/pypy/module/test_lib_pypy/test_resource.py 
b/pypy/module/test_lib_pypy/test_resource.py
--- a/pypy/module/test_lib_pypy/test_resource.py
+++ b/pypy/module/test_lib_pypy/test_resource.py
@@ -1,4 +1,5 @@
 from __future__ import absolute_import
+import sys
 
 import os
 if os.name != 'posix':
@@ -47,6 +48,9 @@
     # minimal "does not crash" test
     x, y = resource.getrlimit(resource.RLIMIT_CPU)
     resource.setrlimit(resource.RLIMIT_CPU, (x, y))
-    x += 0.2
-    y += 0.3
-    resource.setrlimit(resource.RLIMIT_CPU, (x, y))    # truncated to ints
+    # sometimes, x and y are very large (more than 53 bits).
+    # for these huge values, int(float(x)) > x...
+    xf = x + (0.2 if x >= 0 else -0.2)
+    yf = y + (0.3 if y >= 0 else -0.3)
+    if int(xf) == x and int(yf) == y:
+        resource.setrlimit(resource.RLIMIT_CPU, (x, y))  # truncated to ints
diff --git a/pypy/objspace/std/complexobject.py 
b/pypy/objspace/std/complexobject.py
--- a/pypy/objspace/std/complexobject.py
+++ b/pypy/objspace/std/complexobject.py
@@ -346,9 +346,16 @@
 
     def descr_hash(self, space):
         hashreal = _hash_float(space, self.realval)
-        hashimg = _hash_float(space, self.imagval)
-        combined = intmask(hashreal + HASH_IMAG * hashimg)
-        return space.newint(-2 if combined == -1 else combined)
+        hashimg = _hash_float(space, self.imagval)   # 0 if self.imagval == 0
+        h = intmask(hashreal + HASH_IMAG * hashimg)
+        h -= (h == -1)
+        return space.newint(h)
+
+    def descr_coerce(self, space, w_other):
+        w_other = self._to_complex(space, w_other)
+        if w_other is None:
+            return space.w_NotImplemented
+        return space.newtuple([self, w_other])
 
     def descr_format(self, space, w_format_spec):
         return newformat.run_formatter(space, w_format_spec, "format_complex",
diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -399,7 +399,9 @@
     descr_str = func_with_new_name(descr_repr, 'descr_str')
 
     def descr_hash(self, space):
-        return space.wrap(_hash_float(space, self.floatval))
+        h = _hash_float(space, self.floatval)
+        h -= (h == -1)
+        return space.wrap(h)
 
     def descr_format(self, space, w_spec):
         return newformat.run_formatter(space, w_spec, "format_float", self)
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -991,7 +991,8 @@
             if index != INVALID:
                 attr = map.find_map_attr(attrname, index)
                 if attr is not None:
-                    # Note that if map.terminator is a DevolvedDictTerminator,
+                    # Note that if map.terminator is a DevolvedDictTerminator
+                    # or the class provides its own dict, not using mapdict, 
then:
                     # map.find_map_attr will always return None if index==DICT.
                     _fill_cache(pycode, nameindex, map, version_tag, 
attr.storageindex)
                     return w_obj._mapdict_read_storage(attr.storageindex)
@@ -1013,6 +1014,12 @@
 
 def LOOKUP_METHOD_mapdict_fill_cache_method(space, pycode, name, nameindex,
                                             w_obj, w_type, w_method):
+    # if the layout has a dict itself, then mapdict is not used for normal
+    # attributes. Then the cache won't be able to spot changes to the dict.
+    # Thus we don't cache. see test_bug_builtin_types_callmethod
+    if w_type.layout.typedef.hasdict:
+        return
+
     if w_method is None or isinstance(w_method, MutableCell):
         # don't cache the MutableCell XXX could be fixed
         return
diff --git a/pypy/objspace/std/marshal_impl.py 
b/pypy/objspace/std/marshal_impl.py
--- a/pypy/objspace/std/marshal_impl.py
+++ b/pypy/objspace/std/marshal_impl.py
@@ -95,10 +95,13 @@
 
 def marshal(space, w_obj, m):
     # _marshallers_unroll is defined at the end of the file
-    for type, func in _marshallers_unroll:
-        if isinstance(w_obj, type):
-            func(space, w_obj, m)
-            return
+    # NOTE that if w_obj is a heap type, like an instance of a
+    # user-defined subclass, then we skip that part completely!
+    if not space.type(w_obj).is_heaptype():
+        for type, func in _marshallers_unroll:
+            if isinstance(w_obj, type):
+                func(space, w_obj, m)
+                return
 
     # any unknown object implementing the buffer protocol is
     # accepted and encoded as a plain string
diff --git a/pypy/objspace/std/memoryobject.py 
b/pypy/objspace/std/memoryobject.py
--- a/pypy/objspace/std/memoryobject.py
+++ b/pypy/objspace/std/memoryobject.py
@@ -99,6 +99,8 @@
             buf = SubBuffer(self.buf, start * itemsize, size * itemsize)
             return W_MemoryView(buf, self.format, itemsize)
         else:
+            # XXX needs to return a W_MemoryView with a NonContiguousSubBuffer
+            # maybe?  Need to check the cpyext requirements for that
             raise oefmt(space.w_NotImplementedError,
                         "XXX extended slicing")
 
diff --git a/pypy/objspace/std/test/test_complexobject.py 
b/pypy/objspace/std/test/test_complexobject.py
--- a/pypy/objspace/std/test/test_complexobject.py
+++ b/pypy/objspace/std/test/test_complexobject.py
@@ -671,3 +671,6 @@
         assert sign(z2.real) == -1
         assert sign(z2.real) == -1
         
+    def test_hash_minus_one(self):
+        assert hash(-1.0 + 0j) == -2
+        assert (-1.0 + 0j).__hash__() == -2
diff --git a/pypy/objspace/std/test/test_floatobject.py 
b/pypy/objspace/std/test/test_floatobject.py
--- a/pypy/objspace/std/test/test_floatobject.py
+++ b/pypy/objspace/std/test/test_floatobject.py
@@ -475,6 +475,10 @@
         s = '\U0001D7CF\U0001D7CE.4' # &#120783;&#120782;.4
         assert float(s) == 10.4
 
+    def test_hash_minus_one(self):
+        assert hash(-1.0) == -2
+        assert (-1.0).__hash__() == -2
+
 
 class AppTestFloatHex:
     spaceconfig = {
diff --git a/pypy/objspace/std/test/test_mapdict.py 
b/pypy/objspace/std/test/test_mapdict.py
--- a/pypy/objspace/std/test/test_mapdict.py
+++ b/pypy/objspace/std/test/test_mapdict.py
@@ -1238,6 +1238,42 @@
         got = x.a
         assert got == 'd'
 
+    def test_bug_builtin_types_callmethod(self):
+        import sys
+        class D(type(sys)):
+            def mymethod(self):
+                return "mymethod"
+
+        def foobar():
+            return "foobar"
+
+        d = D('d')
+        res1 = d.mymethod()
+        d.mymethod = foobar
+        res2 = d.mymethod()
+        assert res1 == "mymethod"
+        assert res2 == "foobar"
+
+    def test_bug_builtin_types_load_attr(self):
+        import sys
+        class D(type(sys)):
+            def mymethod(self):
+                return "mymethod"
+
+        def foobar():
+            return "foobar"
+
+        d = D('d')
+        m = d.mymethod
+        res1 = m()
+        d.mymethod = foobar
+        m = d.mymethod
+        res2 = m()
+        assert res1 == "mymethod"
+        assert res2 == "foobar"
+
+
+
 class AppTestGlobalCaching(AppTestWithMapDict):
     spaceconfig = {"objspace.std.withmethodcachecounter": True}
 
diff --git a/pypy/objspace/std/test/test_random_attr.py 
b/pypy/objspace/std/test/test_random_attr.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/test/test_random_attr.py
@@ -0,0 +1,132 @@
+import pytest
+import sys
+from pypy.tool.pytest.objspace import gettestobjspace
+try:
+    import __pypy__
+except ImportError:
+    pass
+else:
+    pytest.skip("makes no sense under pypy!")
+try:
+    from hypothesis import given, strategies, settings
+except ImportError:
+    pytest.skip("requires hypothesis")
+
+base_initargs = strategies.sampled_from([
+    ("object", (), False),
+    ("type(sys)", ("fake", ), True),
+    ("NewBase", (), True),
+    ("OldBase", (), False),
+    ("object, OldBase", (), False),
+    ("type(sys), OldBase", ("fake", ), True),
+    ])
+
+attrnames = strategies.sampled_from(["a", "b", "c"])
+
[email protected]
+def class_attr(draw):
+    what = draw(strategies.sampled_from(["value", "method", "property"]))
+    if what == "value":
+        val = draw(strategies.integers())
+        return val, str(val)
+    if what == "method":
+        val = draw(strategies.integers())
+        return (lambda self, val=val: val,
+                "lambda self: %d" % val)
+    if what == "property":
+        val = draw(strategies.integers())
+        return (property(lambda self, val=val: val,
+                            lambda self, val: None,
+                            lambda self: None),
+                "property(lambda self: %d, lambda self, val: None, lambda 
self: None)" % val)
+
[email protected]
+def make_code(draw):
+    baseclass, initargs, hasdict = draw(base_initargs)
+
+    code = ["import sys", "class OldBase:pass", "class NewBase(object):pass", 
"class A(%s):" % baseclass]
+    dct = {}
+    if draw(strategies.booleans()):
+        slots = draw(strategies.lists(attrnames))
+        if not hasdict and draw(strategies.booleans()):
+            slots.append("__dict__")
+        dct["__slots__"] = slots
+        code.append("    __slots__ = %s" % (slots, ))
+    for name in ["a", "b", "c"]:
+        if not draw(strategies.booleans()):
+            continue
+        dct[name], codeval = draw(class_attr())
+        code.append("    %s = %s" % (name, codeval))
+    class OldBase: pass
+    class NewBase(object): pass
+    evaldct = {'OldBase': OldBase, 'NewBase': NewBase}
+    if baseclass == 'OldBase':
+        metaclass = type(OldBase)
+    else:
+        metaclass = type
+    cls = metaclass("A", eval(baseclass+',', globals(), evaldct), dct)
+    inst = cls(*initargs)
+    code.append("    pass")
+    code.append("a = A(*%s)" % (initargs, ))
+    for attr in draw(strategies.lists(attrnames, min_size=1)):
+        op = draw(strategies.sampled_from(["read", "read", "read",
+                      "write", "writemeth", "writeclass", "writebase",
+                      "del", "delclass"]))
+        if op == "read":
+            try:
+                res = getattr(inst, attr)
+            except AttributeError:
+                code.append("raises(AttributeError, 'a.%s')" % (attr, ))
+            else:
+                if callable(res):
+                    code.append("assert a.%s() == %s" % (attr, res()))
+                else:
+                    code.append("assert a.%s == %s" % (attr, res))
+        elif op == "write":
+            val = draw(strategies.integers())
+            try:
+                setattr(inst, attr, val)
+            except AttributeError:
+                code.append("raises(AttributeError, 'a.%s=%s')" % (attr, val))
+            else:
+                code.append("a.%s = %s" % (attr, val))
+        elif op == "writemeth":
+            val = draw(strategies.integers())
+            try:
+                setattr(inst, attr, lambda val=val: val)
+            except AttributeError:
+                code.append("raises(AttributeError, 'a.%s=0')" % (attr, ))
+            else:
+                code.append("a.%s = lambda : %s" % (attr, val))
+        elif op == "writeclass":
+            val, codeval = draw(class_attr())
+            setattr(cls, attr, val)
+            code.append("A.%s = %s" % (attr, codeval))
+        elif op == "writebase":
+            val, codeval = draw(class_attr())
+            setattr(OldBase, attr, val)
+            setattr(NewBase, attr, val)
+            code.append("OldBase.%s = NewBase.%s = %s" % (attr, attr , 
codeval))
+        elif op == "del":
+            try:
+                delattr(inst, attr)
+            except AttributeError:
+                code.append("raises(AttributeError, 'del a.%s')" % (attr, ))
+            else:
+                code.append("del a.%s" % (attr, ))
+        elif op == "delclass":
+            try:
+                delattr(cls, attr)
+            except AttributeError:
+                code.append("raises(AttributeError, 'del A.%s')" % (attr, ))
+            else:
+                code.append("del A.%s" % (attr, ))
+    return "\n    ".join(code)
+
+
+@given(code=make_code())
+#@settings(max_examples=5000)
+def test_random_attrs(code, space):
+    print code
+    exec "if 1:\n    " + code
+    space.appexec([], "():\n    " + code)
diff --git a/rpython/jit/backend/x86/assembler.py 
b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -1064,6 +1064,8 @@
         else:
             assert mc.get_relative_pos() <= 13
         mc.copy_to_raw_memory(oldadr)
+        # log the redirection of the call_assembler_* operation
+        jl.redirect_assembler(oldlooptoken, newlooptoken, target)
 
     def dump(self, text):
         if not self.verbose:
diff --git a/rpython/rlib/_rsocket_rffi.py b/rpython/rlib/_rsocket_rffi.py
--- a/rpython/rlib/_rsocket_rffi.py
+++ b/rpython/rlib/_rsocket_rffi.py
@@ -176,6 +176,7 @@
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to