Commits

Maciej Fijalkowski committed d2ea3fe Merge

merge

Comments (0)

Files changed (105)

lib-python/2.7/test/test_array.py

         b = array.array(self.badtypecode())
         with self.assertRaises(TypeError):
             a + b
+
         with self.assertRaises(TypeError):
             a + 'bad'
 
         b = array.array(self.badtypecode())
         with self.assertRaises(TypeError):
             a += b
+
         with self.assertRaises(TypeError):
             a += 'bad'
 

lib-python/2.7/test/test_file2k.py

 
     def _create_file(self):
         if self.use_buffering:
-            f = open(self.filename, "w+", buffering=1024*16)
+            self.f = open(self.filename, "w+", buffering=1024*16)
         else:
-            f = open(self.filename, "w+")
-        self.f = f
-        self.all_files.append(f)
+            self.f = open(self.filename, "w+")
+        self.all_files.append(self.f)
         oldf = self.all_files.pop(0)
         if oldf is not None:
             oldf.close()

lib-python/2.7/test/test_itertools.py

 
     @test_support.impl_detail("tuple reuse is specific to CPython")
     def test_combinations_tuple_reuse(self):
-        # Test implementation detail:  tuple re-use
         self.assertEqual(len(set(map(id, combinations('abcde', 3)))), 1)
         self.assertNotEqual(len(set(map(id, list(combinations('abcde', 3))))), 1)
 
 
     @test_support.impl_detail("tuple reuse is specific to CPython")
     def test_combinations_with_replacement_tuple_reuse(self):
-        # Test implementation detail:  tuple re-use
         cwr = combinations_with_replacement
         self.assertEqual(len(set(map(id, cwr('abcde', 3)))), 1)
         self.assertNotEqual(len(set(map(id, list(cwr('abcde', 3))))), 1)
 
     @test_support.impl_detail("tuple reuse is specific to CPython")
     def test_permutations_tuple_reuse(self):
-        # Test implementation detail:  tuple re-use
         self.assertEqual(len(set(map(id, permutations('abcde', 3)))), 1)
         self.assertNotEqual(len(set(map(id, list(permutations('abcde', 3))))), 1)
 

lib-python/2.7/test/test_memoryview.py

         self.assertRaises(TypeError, setitem, (0,), b"a")
         self.assertRaises(TypeError, setitem, "a", b"a")
         # Trying to resize the memory object
-        self.assertRaises((ValueError, TypeError), setitem, 0, b"")
-        self.assertRaises((ValueError, TypeError), setitem, 0, b"ab")
+        self.assertRaises(ValueError, setitem, 0, b"")
+        self.assertRaises(ValueError, setitem, 0, b"ab")
         self.assertRaises(ValueError, setitem, slice(1,1), b"a")
         self.assertRaises(ValueError, setitem, slice(0,2), b"a")
 
             self.assertTrue(m[0:6] == m[:])
             self.assertFalse(m[0:5] == m)
 
-            if test_support.check_impl_detail(cpython=True):
-                # what is supported and what is not supported by memoryview is
-                # very inconsisten on CPython. In PyPy, memoryview supports
-                # the buffer interface, and thus the following comparison
-                # succeeds. See also the comment in
-                # pypy.objspace.std.memoryview.W_MemoryView.descr_buffer
-                #
-                # Comparison with objects which don't support the buffer API
-                self.assertFalse(m == u"abcdef", "%s %s" % (self, tp))
-                self.assertTrue(m != u"abcdef")
-                self.assertFalse(u"abcdef" == m)
-                self.assertTrue(u"abcdef" != m)
+            # Comparison with objects which don't support the buffer API
+            self.assertFalse(m == u"abcdef")
+            self.assertTrue(m != u"abcdef")
+            self.assertFalse(u"abcdef" == m)
+            self.assertTrue(u"abcdef" != m)
 
             # Unordered comparisons are unimplemented, and therefore give
             # arbitrary results (they raise a TypeError in py3k)

lib_pypy/_ctypes_test.py

-import imp, os
+import imp
+import os
 
 try:
     import cpyext
     output_dir = _pypy_testcapi.get_hashed_dir(os.path.join(thisdir, cfile))
     try:
         fp, filename, description = imp.find_module('_ctypes_test', path=[output_dir])
-        imp.load_module('_ctypes_test', fp, filename, description)
+        with fp:
+            imp.load_module('_ctypes_test', fp, filename, description)
     except ImportError:
         print('could not find _ctypes_test in %s' % output_dir)
         _pypy_testcapi.compile_shared('_ctypes_test.c', '_ctypes_test', output_dir)

lib_pypy/_testcapi.py

-import imp, os
+import imp
+import os
 
 try:
     import cpyext
 
 try:
     fp, filename, description = imp.find_module('_testcapi', path=[output_dir])
-    imp.load_module('_testcapi', fp, filename, description)
+    with fp:
+        imp.load_module('_testcapi', fp, filename, description)
 except ImportError:
     _pypy_testcapi.compile_shared(cfile, '_testcapi', output_dir)

pypy/doc/cppyy.rst

   Fixing these bootstrap problems is on the TODO list.
   The global namespace is ``cppyy.gbl``.
 
+* **NULL**: Is represented as ``cppyy.gbl.nullptr``.
+  In C++11, the keyword ``nullptr`` is used to represent ``NULL``.
+  For clarity of intent, it is recommended to use this instead of ``None``
+  (or the integer ``0``, which can serve in some cases), as ``None`` is better
+  understood as ``void`` in C++.
+
 * **operator conversions**: If defined in the C++ class and a python
   equivalent exists (i.e. all builtin integer and floating point types, as well
   as ``bool``), it will map onto that python conversion.
   Special care needs to be taken for global operator overloads in C++: first,
   make sure that they are actually reflected, especially for the global
   overloads for ``operator==`` and ``operator!=`` of STL vector iterators in
-  the case of gcc (note that they are not needed to iterator over a vector).
+  the case of gcc (note that they are not needed to iterate over a vector).
   Second, make sure that reflection info is loaded in the proper order.
   I.e. that these global overloads are available before use.
 

pypy/doc/extending.rst

 Reflex
 ======
 
-This method is still experimental.  It adds the `cppyy`_ module.
-The method works by using the `Reflex package`_ to provide reflection
-information of the C++ code, which is then used to automatically generate
-bindings at runtime.
-From a python standpoint, there is no difference between generating bindings
-at runtime, or having them "statically" generated and available in scripts
-or compiled into extension modules: python classes and functions are always
-runtime structures, created when a script or module loads.
+The builtin `cppyy`_ module uses reflection information, provided by
+`Reflex`_ (which needs to be `installed separately`_), of C/C++ code to
+automatically generate bindings at runtime.
+In Python, classes and functions are always runtime structures, so when they
+are generated matters not for performance.
 However, if the backend itself is capable of dynamic behavior, it is a much
-better functional match to python, allowing tighter integration and more
-natural language mappings.
-Full details are `available here`_.
+better functional match, allowing tighter integration and more natural
+language mappings.
+
+The `cppyy`_ module is written in RPython, thus PyPy's JIT is able to remove
+most cross-language call overhead.
+
+`Full details`_ are `available here`_.
 
 .. _`cppyy`: cppyy.html
-.. _`reflex-support`: cppyy.html
-.. _`Reflex package`: http://root.cern.ch/drupal/content/reflex
+.. _`installed separately`: http://cern.ch/wlav/reflex-2013-08-14.tar.bz2
+.. _`Reflex`: http://root.cern.ch/drupal/content/reflex
+.. _`Full details`: cppyy.html
 .. _`available here`: cppyy.html
 
-Pros
-----
-
-The cppyy module is written in RPython, which makes it possible to keep the
-code execution visible to the JIT all the way to the actual point of call into
-C++, thus allowing for a very fast interface.
-Reflex is currently in use in large software environments in High Energy
-Physics (HEP), across many different projects and packages, and its use can be
-virtually completely automated in a production environment.
-One of its uses in HEP is in providing language bindings for CPython.
-Thus, it is possible to use Reflex to have bound code work on both CPython and
-on PyPy.
-In the medium-term, Reflex will be replaced by `cling`_, which is based on
-`llvm`_.
-This will affect the backend only; the python-side interface is expected to
-remain the same, except that cling adds a lot of dynamic behavior to C++,
-enabling further language integration.
-
-.. _`cling`: http://root.cern.ch/drupal/content/cling
-.. _`llvm`: http://llvm.org/
-
-Cons
-----
-
-C++ is a large language, and cppyy is not yet feature-complete.
-Still, the experience gained in developing the equivalent bindings for CPython
-means that adding missing features is a simple matter of engineering, not a
-question of research.
-The module is written so that currently missing features should do no harm if
-you don't use them, if you do need a particular feature, it may be necessary
-to work around it in python or with a C++ helper function.
-Although Reflex works on various platforms, the bindings with PyPy have only
-been tested on Linux.
-
 
 RPython Mixed Modules
 =====================

pypy/doc/release-2.3.0.rst

+=======================================
+PyPy 2.3 - XXXX TODO
+=======================================
+
+We're pleased to announce PyPy 2.3, which targets version 2.7.6 of the Python
+language. This release updates the stdlib from 2.7.3, jumping directly to 2.7.6.
+
+This release also contains several bugfixes and performance improvements. 
+
+You can download the PyPy 2.3 release here:
+
+    http://pypy.org/download.html
+
+We would like to thank our donors for the continued support of the PyPy
+project. We showed quite a bit of progress on all three projects (see below)
+and we're slowly running out of funds.
+Please consider donating more so we can finish those projects!  The three
+projects are:
+
+* Py3k (supporting Python 3.x): the release PyPy3 2.2 is imminent.
+
+* STM (software transactional memory): a preview will be released very soon,
+  as soon as we fix a few bugs
+
+* NumPy: the work done is included in the PyPy 2.2 release. More details below.
+
+.. _`Raspberry Pi Foundation`: http://www.raspberrypi.org
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`pypy 2.2 and cpython 2.7.2`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+This release supports x86 machines running Linux 32/64, Mac OS X 64, Windows
+32, or ARM (ARMv6 or ARMv7, with VFPv3).
+
+Work on the native Windows 64 is still stalling, we would welcome a volunteer
+to handle that.
+
+.. _`pypy 2.2 and cpython 2.7.2`: http://speed.pypy.org
+
+Highlights
+==========
+
+* Our Garbage Collector is now "incremental".  It should avoid almost
+  all pauses due to a major collection taking place.  Previously, it
+  would pause the program (rarely) to walk all live objects, which
+  could take arbitrarily long if your process is using a whole lot of
+  RAM.  Now the same work is done in steps.  This should make PyPy
+  more responsive, e.g. in games.  There are still other pauses, from
+  the GC and the JIT, but they should be on the order of 5
+  milliseconds each.
+
+* The JIT counters for hot code were never reset, which meant that a
+  process running for long enough would eventually JIT-compile more
+  and more rarely executed code.  Not only is it useless to compile
+  such code, but as more compiled code means more memory used, this
+  gives the impression of a memory leak.  This has been tentatively
+  fixed by decreasing the counters from time to time.
+
+* NumPy has been split: now PyPy only contains the core module, called
+  ``_numpypy``.  The ``numpy`` module itself has been moved to
+  ``https://bitbucket.org/pypy/numpy`` and ``numpypy`` disappeared.
+  You need to install NumPy separately with a virtualenv:
+  ``pip install git+https://bitbucket.org/pypy/numpy.git``;
+  or directly:
+  ``git clone https://bitbucket.org/pypy/numpy.git``;
+  ``cd numpy``; ``pypy setup.py install``.
+
+* non-inlined calls have less overhead
+
+* Things that use ``sys.set_trace`` are now JITted (like coverage)
+
+* JSON decoding is now very fast (JSON encoding was already very fast)
+
+* various buffer copying methods experience speedups (like list-of-ints to
+  ``int[]`` buffer from cffi)
+
+* We finally wrote (hopefully) all the missing ``os.xxx()`` functions,
+  including ``os.startfile()`` on Windows and a handful of rare ones
+  on Posix.
+
+* numpy has a rudimentary C API that cooperates with ``cpyext``
+
+Cheers,
+Armin Rigo and Maciej Fijalkowski

pypy/doc/whatsnew-head.rst

 .. this is a revision shortly after release-2.3.x
 .. startrev: ba569fe1efdb
 
-
-
 .. branch: small-unroll-improvements
 Improve optimiziation of small allocation-heavy loops in the JIT
+
+.. branch: reflex-support
+
+.. branch: refactor-buffer-api
+Properly implement old/new buffer API for objects and start work on replacing bufferstr usage

pypy/interpreter/baseobjspace.py

 from rpython.rlib import jit, types
 from rpython.rlib.debug import make_sure_not_resized
 from rpython.rlib.objectmodel import (we_are_translated, newlist_hint,
-     compute_unique_id)
+     compute_unique_id, specialize)
 from rpython.rlib.signature import signature
 from rpython.rlib.rarithmetic import r_uint, SHRT_MIN, SHRT_MAX, \
     INT_MIN, INT_MAX, UINT_MAX
     def immutable_unique_id(self, space):
         return None
 
-    def buffer_w(self, space):
+    def buffer_w(self, space, flags):
         w_impl = space.lookup(self, '__buffer__')
         if w_impl is not None:
             w_result = space.get_and_call_function(w_impl, self)
             if space.isinstance_w(w_result, space.w_buffer):
-                return w_result.buffer_w(space)
-        self._typed_unwrap_error(space, "buffer")
+                return w_result.buffer_w(space, flags)
+        raise TypeError
+
+    def readbuf_w(self, space):
+        w_impl = space.lookup(self, '__buffer__')
+        if w_impl is not None:
+            w_result = space.get_and_call_function(w_impl, self)
+            if space.isinstance_w(w_result, space.w_buffer):
+                return w_result.readbuf_w(space)
+        raise TypeError
+
+    def writebuf_w(self, space):
+        w_impl = space.lookup(self, '__buffer__')
+        if w_impl is not None:
+            w_result = space.get_and_call_function(w_impl, self)
+            if space.isinstance_w(w_result, space.w_buffer):
+                return w_result.writebuf_w(space)
+        raise TypeError
+
+    def charbuf_w(self, space):
+        w_impl = space.lookup(self, '__buffer__')
+        if w_impl is not None:
+            w_result = space.get_and_call_function(w_impl, self)
+            if space.isinstance_w(w_result, space.w_buffer):
+                return w_result.charbuf_w(space)
+        raise TypeError
 
     def str_w(self, space):
         self._typed_unwrap_error(space, "string")
                                  self.wrap('cannot convert negative integer '
                                            'to unsigned int'))
 
-    def buffer_w(self, w_obj):
-        return w_obj.buffer_w(self)
+    BUF_SIMPLE   = 0x0000
+    BUF_WRITABLE = 0x0001
+    BUF_FORMAT   = 0x0004
+    BUF_ND       = 0x0008
+    BUF_STRIDES  = 0x0010 | BUF_ND
+    BUF_INDIRECT = 0x0100 | BUF_STRIDES
 
-    def rwbuffer_w(self, w_obj):
-        # returns a RWBuffer instance
-        from pypy.interpreter.buffer import RWBuffer
-        buffer = self.buffer_w(w_obj)
-        if not isinstance(buffer, RWBuffer):
-            raise OperationError(self.w_TypeError,
-                                 self.wrap('read-write buffer expected'))
-        return buffer
+    BUF_CONTIG_RO = BUF_ND
+    BUF_CONTIG    = BUF_ND | BUF_WRITABLE
 
-    def bufferstr_new_w(self, w_obj):
-        # Implement the "new buffer interface" (new in Python 2.7)
-        # returning an unwrapped string. It doesn't accept unicode
-        # strings
-        buffer = self.buffer_w(w_obj)
-        return buffer.as_str()
+    BUF_FULL_RO = BUF_INDIRECT | BUF_FORMAT
+    BUF_FULL    = BUF_INDIRECT | BUF_FORMAT | BUF_WRITABLE
 
+    def check_buf_flags(self, flags, readonly):
+        if readonly and flags & self.BUF_WRITABLE == self.BUF_WRITABLE:
+            raise oefmt(self.w_BufferError, "Object is not writable.")
+
+    def buffer_w(self, w_obj, flags):
+        # New buffer interface, returns a buffer based on flags (PyObject_GetBuffer)
+        try:
+            return w_obj.buffer_w(self, flags)
+        except TypeError:
+            raise oefmt(self.w_TypeError,
+                        "'%T' does not have the buffer interface", w_obj)
+
+    def readbuf_w(self, w_obj):
+        # Old buffer interface, returns a readonly buffer (PyObject_AsReadBuffer)
+        try:
+            return w_obj.readbuf_w(self)
+        except TypeError:
+            raise oefmt(self.w_TypeError,
+                        "expected a readable buffer object")
+
+    def writebuf_w(self, w_obj):
+        # Old buffer interface, returns a writeable buffer (PyObject_AsWriteBuffer)
+        try:
+            return w_obj.writebuf_w(self)
+        except TypeError:
+            raise oefmt(self.w_TypeError,
+                        "expected a writeable buffer object")
+
+    def charbuf_w(self, w_obj):
+        # Old buffer interface, returns a character buffer (PyObject_AsCharBuffer)
+        try:
+            return w_obj.charbuf_w(self)
+        except TypeError:
+            raise oefmt(self.w_TypeError,
+                        "expected a character buffer object")
+
+    def _getarg_error(self, expected, w_obj):
+        if self.is_none(w_obj):
+            name = "None"
+        else:
+            name = self.type(w_obj).get_module_type_name()
+        raise oefmt(self.w_TypeError, "must be %s, not %s", expected, name)
+
+    @specialize.arg(1)
+    def getarg_w(self, code, w_obj):
+        if code == 'z*':
+            if self.is_none(w_obj):
+                return None
+            code = 's*'
+        if code == 's*':
+            if self.isinstance_w(w_obj, self.w_str):
+                return w_obj.readbuf_w(self)
+            if self.isinstance_w(w_obj, self.w_unicode):
+                return self.str(w_obj).readbuf_w(self)
+            try:
+                return w_obj.buffer_w(self, 0)
+            except TypeError:
+                pass
+            try:
+                return w_obj.readbuf_w(self)
+            except TypeError:
+                self._getarg_error("string or buffer", w_obj)
+        elif code == 's#':
+            if self.isinstance_w(w_obj, self.w_str):
+                return w_obj.str_w(self)
+            if self.isinstance_w(w_obj, self.w_unicode):
+                return self.str(w_obj).str_w(self)
+            try:
+                return w_obj.readbuf_w(self).as_str()
+            except TypeError:
+                self._getarg_error("string or read-only buffer", w_obj)
+        elif code == 'w*':
+            try:
+                try:
+                    return w_obj.buffer_w(self, self.BUF_WRITABLE)
+                except OperationError:
+                    self._getarg_error("read-write buffer", w_obj)
+            except TypeError:
+                pass
+            try:
+                return w_obj.writebuf_w(self)
+            except TypeError:
+                self._getarg_error("read-write buffer", w_obj)
+        elif code == 't#':
+            try:
+                return w_obj.charbuf_w(self)
+            except TypeError:
+                self._getarg_error("string or read-only character buffer", w_obj)
+        else:
+            assert False
+
+    # XXX rename/replace with code more like CPython getargs for buffers
     def bufferstr_w(self, w_obj):
         # Directly returns an interp-level str.  Note that if w_obj is a
         # unicode string, this is different from str_w(buffer(w_obj)):
         except OperationError, e:
             if not e.match(self, self.w_TypeError):
                 raise
-            buffer = self.buffer_w(w_obj)
-            return buffer.as_str()
+        try:
+            buf = w_obj.buffer_w(self, 0)
+        except TypeError:
+            pass
+        else:
+            return buf.as_str()
+        try:
+            buf = w_obj.readbuf_w(self)
+        except TypeError:
+            self._getarg_error("string or buffer", w_obj)
+        else:
+            return buf.as_str()
 
     def str_or_None_w(self, w_obj):
         if self.is_w(w_obj, self.w_None):
     'AssertionError',
     'AttributeError',
     'BaseException',
+    'BufferError',
     'DeprecationWarning',
     'EOFError',
     'EnvironmentError',

pypy/interpreter/buffer.py

-"""
-Buffer protocol support.
-"""
-from rpython.rlib.objectmodel import import_from_mixin
-
-
-class Buffer(object):
-    """Abstract base class for buffers."""
-    __slots__ = []
-
-    def getlength(self):
-        raise NotImplementedError
-
-    def as_str(self):
-        "Returns an interp-level string with the whole content of the buffer."
-        # May be overridden.
-        return self.getslice(0, self.getlength(), 1, self.getlength())
-
-    def getitem(self, index):
-        "Returns the index'th character in the buffer."
-        raise NotImplementedError   # Must be overriden.  No bounds checks.
-
-    def getslice(self, start, stop, step, size):
-        # May be overridden.  No bounds checks.
-        return ''.join([self.getitem(i) for i in range(start, stop, step)])
-
-    def get_raw_address(self):
-        raise ValueError("no raw buffer")
-
-    def is_writable(self):
-        return False
-
-
-class RWBuffer(Buffer):
-    """Abstract base class for read-write buffers."""
-    __slots__ = []
-
-    def is_writable(self):
-        return True
-
-    def setitem(self, index, char):
-        "Write a character into the buffer."
-        raise NotImplementedError   # Must be overriden.  No bounds checks.
-
-    def setslice(self, start, string):
-        # May be overridden.  No bounds checks.
-        for i in range(len(string)):
-            self.setitem(start + i, string[i])
-
-
-class StringBuffer(Buffer):
-    __slots__ = ['value']
-
-    def __init__(self, value):
-        self.value = value
-
-    def getlength(self):
-        return len(self.value)
-
-    def as_str(self):
-        return self.value
-
-    def getitem(self, index):
-        return self.value[index]
-
-    def getslice(self, start, stop, step, size):
-        if size == 0:
-            return ""
-        if step == 1:
-            assert 0 <= start <= stop
-            return self.value[start:stop]
-        return "".join([self.value[start + i*step] for i in xrange(size)])
-# ____________________________________________________________
-
-
-class SubBufferMixin(object):
-    _attrs_ = ['buffer', 'offset', 'size']
-
-    def __init__(self, buffer, offset, size):
-        self.buffer = buffer
-        self.offset = offset
-        self.size = size
-
-    def getlength(self):
-        at_most = self.buffer.getlength() - self.offset
-        if 0 <= self.size <= at_most:
-            return self.size
-        elif at_most >= 0:
-            return at_most
-        else:
-            return 0
-
-    def getitem(self, index):
-        return self.buffer.getitem(self.offset + index)
-
-    def getslice(self, start, stop, step, size):
-        if start == stop:
-            return ''     # otherwise, adding self.offset might make them
-                          # out of bounds
-        return self.buffer.getslice(self.offset + start, self.offset + stop,
-                                    step, size)
-
-
-class SubBuffer(Buffer):
-    import_from_mixin(SubBufferMixin)
-
-
-class RWSubBuffer(RWBuffer):
-    import_from_mixin(SubBufferMixin)
-
-    def setitem(self, index, char):
-        self.buffer.setitem(self.offset + index, char)
-
-    def setslice(self, start, string):
-        if len(string) == 0:
-            return        # otherwise, adding self.offset might make 'start'
-                          # out of bounds
-        self.buffer.setslice(self.offset + start, string)

pypy/interpreter/pyopcode.py

 
     def LOAD_NAME(self, nameindex, next_instr):
         if self.w_locals is not self.w_globals:
-            w_varname = self.getname_w(nameindex)
-            w_value = self.space.finditem(self.w_locals, w_varname)
+            varname = self.getname_u(nameindex)
+            w_value = self.space.finditem_str(self.w_locals, varname)
             if w_value is not None:
                 self.pushvalue(w_value)
                 return

pypy/interpreter/test/test_buffer.py

-import py
-from rpython.tool.udir import udir
-
-testdir = udir.ensure('test_buffer', dir=1)
-
-
-class TestBuffer:
-    def test_buffer_w(self):
-        space = self.space
-        w_hello = space.wrap('hello world')
-        buf = space.buffer_w(w_hello)
-        assert buf.getlength() == 11
-        assert buf.as_str() == 'hello world'
-        assert buf.getslice(1, 6, 1, 5) == 'ello '
-        assert space.buffer_w(space.newbuffer(buf)) is buf
-        assert space.bufferstr_w(w_hello) == 'hello world'
-        assert space.bufferstr_w(space.newbuffer(space.buffer_w(w_hello))) == 'hello world'
-        space.raises_w(space.w_TypeError, space.buffer_w, space.wrap(5))
-
-    def test_file_write(self):
-        space = self.space
-        w_buffer = space.newbuffer(space.buffer_w(space.wrap('hello world')))
-        filename = str(testdir.join('test_file_write'))
-        space.appexec([w_buffer, space.wrap(filename)], """(buffer, filename):
-            f = open(filename, 'wb')
-            f.write(buffer)
-            f.close()
-        """)
-        f = open(filename, 'rb')
-        data = f.read()
-        f.close()
-        assert data == 'hello world'
-
-    def test_unicode(self):
-        space = self.space
-        s = space.bufferstr_w(space.wrap(u'hello'))
-        assert type(s) is str
-        assert s == 'hello'
-        space.raises_w(space.w_UnicodeEncodeError,
-                       space.bufferstr_w, space.wrap(u'\xe9'))
-
-
-# Note: some app-level tests for buffer are in objspace/std/test/test_memoryview.py.

pypy/module/__pypy__/bytebuffer.py

 # A convenient read-write buffer.  Located here for want of a better place.
 #
 
-from pypy.interpreter.buffer import RWBuffer
+from rpython.rlib.buffer import Buffer
 from pypy.interpreter.gateway import unwrap_spec
 
 
-class ByteBuffer(RWBuffer):
+class ByteBuffer(Buffer):
+    _immutable_ = True
+
     def __init__(self, len):
         self.data = ['\x00'] * len
+        self.readonly = False
 
     def getlength(self):
         return len(self.data)

pypy/module/__pypy__/test/test_bytebuffer.py

         assert b[-1] == '*'
         assert b[-2] == '-'
         assert b[-3] == '+'
+        exc = raises(TypeError, "b[3] = 'abc'")
+        assert str(exc.value) == "right operand must be a single byte"
+        exc = raises(TypeError, "b[3:5] = 'abc'")
+        assert str(exc.value) == "right operand length must match slice length"
+        exc = raises(TypeError, "b[3:7:2] = 'abc'")
+        assert str(exc.value) == "right operand length must match slice length"
+
+        b = bytebuffer(10)
+        b[1:3] = 'xy'
+        assert str(b) == "\x00xy" + "\x00" * 7
+        b[4:8:2] = 'zw'
+        assert str(b) == "\x00xy\x00z\x00w" + "\x00" * 3
+        r = str(buffer(u'#'))
+        b[6:6+len(r)] = u'#'
+        assert str(b[:6+len(r)]) == "\x00xy\x00z\x00" + r

pypy/module/_cffi_backend/cbuffer.py

-from pypy.interpreter.buffer import RWBuffer
-from pypy.interpreter.error import oefmt
+from pypy.interpreter.error import oefmt, OperationError
 from pypy.interpreter.gateway import unwrap_spec, interp2app
 from pypy.interpreter.typedef import TypeDef, make_weakref_descr
 from pypy.module._cffi_backend import cdataobj, ctypeptr, ctypearray
-from pypy.objspace.std.memoryview import W_Buffer
+from pypy.objspace.std.bufferobject import W_Buffer
 
+from rpython.rlib.buffer import Buffer
 from rpython.rtyper.annlowlevel import llstr
 from rpython.rtyper.lltypesystem import rffi
 from rpython.rtyper.lltypesystem.rstr import copy_string_to_raw
 
 
-class LLBuffer(RWBuffer):
+class LLBuffer(Buffer):
     _immutable_ = True
 
     def __init__(self, raw_cdata, size):
         self.raw_cdata = raw_cdata
         self.size = size
+        self.readonly = False
 
     def getlength(self):
         return self.size
     def getslice(self, start, stop, step, size):
         if step == 1:
             return rffi.charpsize2str(rffi.ptradd(self.raw_cdata, start), size)
-        return RWBuffer.getslice(self, start, stop, step, size)
+        return Buffer.getslice(self, start, stop, step, size)
 
     def setslice(self, start, string):
         raw_cdata = rffi.ptradd(self.raw_cdata, start)
         W_Buffer.__init__(self, buffer)
         self.keepalive = keepalive
 
+    def descr_setitem(self, space, w_index, w_obj):
+        try:
+            W_Buffer.descr_setitem(self, space, w_index, w_obj)
+        except OperationError as e:
+            if e.match(space, space.w_TypeError):
+                e.w_type = space.w_ValueError
+            raise
+
 MiniBuffer.typedef = TypeDef(
     "buffer",
     __module__ = "_cffi_backend",

pypy/module/_codecs/__init__.py

          'utf_32_le_decode' : 'interp_codecs.utf_32_le_decode',
          'utf_32_le_encode' : 'interp_codecs.utf_32_le_encode',
          'utf_32_ex_decode' : 'interp_codecs.utf_32_ex_decode',
-         'charbuffer_encode': 'interp_codecs.buffer_encode',
-         'readbuffer_encode': 'interp_codecs.buffer_encode',
+         'charbuffer_encode': 'interp_codecs.charbuffer_encode',
+         'readbuffer_encode': 'interp_codecs.readbuffer_encode',
          'charmap_decode'   : 'interp_codecs.charmap_decode',
          'charmap_encode'   : 'interp_codecs.charmap_encode',
          'escape_encode'    : 'interp_codecs.escape_encode',

pypy/module/_codecs/interp_codecs.py

     w_res = space.call_function(w_encoder, w_obj, space.wrap(errors))
     return space.getitem(w_res, space.wrap(0))
 
-@unwrap_spec(s='bufferstr', errors='str_or_None')
-def buffer_encode(space, s, errors='strict'):
+@unwrap_spec(errors='str_or_None')
+def readbuffer_encode(space, w_data, errors='strict'):
+    s = space.getarg_w('s#', w_data)
+    return space.newtuple([space.wrap(s), space.wrap(len(s))])
+
+@unwrap_spec(errors='str_or_None')
+def charbuffer_encode(space, w_data, errors='strict'):
+    s = space.getarg_w('t#', w_data)
     return space.newtuple([space.wrap(s), space.wrap(len(s))])
 
 @unwrap_spec(errors=str)

pypy/module/_codecs/test/test_codecs.py

         for (i, line) in enumerate(reader):
             assert line == s[i]
 
-    def test_array(self):
+    def test_buffer_encode(self):
         import _codecs, array
-        _codecs.readbuffer_encode(array.array('c', 'spam')) == ('spam', 4)
+        assert _codecs.readbuffer_encode(array.array('c', 'spam')) == ('spam', 4)
+        exc = raises(TypeError, _codecs.charbuffer_encode, array.array('c', 'spam'))
+        assert str(exc.value) == "must be string or read-only character buffer, not array.array"
+        assert _codecs.readbuffer_encode(u"test") == ('test', 4)
+        assert _codecs.charbuffer_encode(u"test") == ('test', 4)
 
     def test_utf8sig(self):
         import codecs

pypy/module/_file/interp_file.py

 
     def direct_write(self, w_data):
         space = self.space
-        if not self.binary and space.isinstance_w(w_data, space.w_unicode):
-            w_data = space.call_method(w_data, "encode", space.wrap(self.encoding), space.wrap(self.errors))
-        data = space.bufferstr_w(w_data)
+        if self.binary:
+            data = space.getarg_w('s*', w_data).as_str()
+        else:
+            if space.isinstance_w(w_data, space.w_unicode):
+                w_data = space.call_method(w_data, "encode",
+                                           space.wrap(self.encoding),
+                                           space.wrap(self.errors))
+            data = space.charbuf_w(w_data)
         self.do_direct_write(data)
 
     def do_direct_write(self, data):
         """readinto() -> Undocumented.  Don't use this; it may go away."""
         # XXX not the most efficient solution as it doesn't avoid the copying
         space = self.space
-        rwbuffer = space.rwbuffer_w(w_rwbuffer)
+        rwbuffer = space.writebuf_w(w_rwbuffer)
         w_data = self.file_read(rwbuffer.getlength())
         data = space.str_w(w_data)
         rwbuffer.setslice(0, data)

pypy/module/_io/interp_bufferedio.py

 from pypy.interpreter.typedef import (
     TypeDef, GetSetProperty, generic_new_descr, interp_attrproperty_w)
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
-from pypy.interpreter.buffer import RWBuffer
+from rpython.rlib.buffer import Buffer
 from rpython.rlib.rstring import StringBuilder
 from rpython.rlib.rarithmetic import r_longlong, intmask
 from rpython.rlib import rposix
         self._unsupportedoperation(space, "detach")
 
     def readinto_w(self, space, w_buffer):
-        rwbuffer = space.rwbuffer_w(w_buffer)
+        rwbuffer = space.getarg_w('w*', w_buffer)
         length = rwbuffer.getlength()
         w_data = space.call_method(self, "read", space.wrap(length))
 
     readinto = interp2app(W_BufferedIOBase.readinto_w),
 )
 
-class RawBuffer(RWBuffer):
+class RawBuffer(Buffer):
+    _immutable_ = True
+
     def __init__(self, buf, start, length):
         self.buf = buf
         self.start = start
         self.length = length
+        self.readonly = False
 
     def getlength(self):
         return self.length
     def write_w(self, space, w_data):
         self._check_init(space)
         self._check_closed(space, "write to closed file")
-        data = space.bufferstr_w(w_data)
+        data = space.getarg_w('s*', w_data).as_str()
         size = len(data)
 
         with self.lock:

pypy/module/_io/interp_bytesio.py

 
     def readinto_w(self, space, w_buffer):
         self._check_closed(space)
-        rwbuffer = space.rwbuffer_w(w_buffer)
+        rwbuffer = space.getarg_w('w*', w_buffer)
         size = rwbuffer.getlength()
 
         output = self.read(size)
 
     def write_w(self, space, w_data):
         self._check_closed(space)
-        if space.isinstance_w(w_data, space.w_unicode):
-            raise OperationError(space.w_TypeError, space.wrap(
-                "bytes string of buffer expected"))
-        buf = space.bufferstr_w(w_data)
+        buf = space.buffer_w(w_data, space.BUF_CONTIG_RO).as_str()
         length = len(buf)
         if length <= 0:
             return space.wrap(0)

pypy/module/_io/interp_fileio.py

     def write_w(self, space, w_data):
         self._check_closed(space)
         self._check_writable(space)
-        data = space.bufferstr_w(w_data)
+        data = space.getarg_w('s*', w_data).as_str()
 
         try:
             n = os.write(self.fd, data)
     def readinto_w(self, space, w_buffer):
         self._check_closed(space)
         self._check_readable(space)
-        rwbuffer = space.rwbuffer_w(w_buffer)
+        rwbuffer = space.getarg_w('w*', w_buffer)
         length = rwbuffer.getlength()
         try:
             buf = os.read(self.fd, length)

pypy/module/_io/test/test_bufferedio.py

         raw = _io.FileIO(self.tmpfile)
         f = _io.BufferedReader(raw)
         assert f.readinto(a) == 5
+        exc = raises(TypeError, f.readinto, u"hello")
+        assert str(exc.value) == "cannot use unicode as modifiable buffer"
+        exc = raises(TypeError, f.readinto, buffer(b"hello"))
+        assert str(exc.value) == "must be read-write buffer, not buffer"
+        exc = raises(TypeError, f.readinto, buffer(bytearray("hello")))
+        assert str(exc.value) == "must be read-write buffer, not buffer"
+        exc = raises(TypeError, f.readinto, memoryview(b"hello"))
+        assert str(exc.value) == "must be read-write buffer, not memoryview"
         f.close()
         assert a == 'a\nb\ncxxxxx'
 
         import _io
         raw = _io.FileIO(self.tmpfile, 'w')
         f = _io.BufferedWriter(raw)
-        f.write("abcd")
+        f.write("ab")
+        f.write(u"cd")
         f.close()
         assert self.readfile() == "abcd"
 

pypy/module/_io/test/test_bytesio.py

         f = _io.BytesIO()
         assert f.write("") == 0
         assert f.write("hello") == 5
+        exc = raises(TypeError, f.write, u"lo")
+        assert str(exc.value) == "'unicode' does not have the buffer interface"
         import gc; gc.collect()
         assert f.getvalue() == "hello"
         f.close()
         a2 = bytearray('testing')
         assert b.readinto(a1) == 1
         assert b.readinto(a2) == 4
+        exc = raises(TypeError, b.readinto, u"hello")
+        assert str(exc.value) == "cannot use unicode as modifiable buffer"
+        exc = raises(TypeError, b.readinto, buffer(b"hello"))
+        assert str(exc.value) == "must be read-write buffer, not buffer"
+        exc = raises(TypeError, b.readinto, buffer(bytearray("hello")))
+        assert str(exc.value) == "must be read-write buffer, not buffer"
+        exc = raises(TypeError, b.readinto, memoryview(b"hello"))
+        assert str(exc.value) == "must be read-write buffer, not memoryview"
         b.close()
         assert a1 == "h"
         assert a2 == "elloing"

pypy/module/_io/test/test_fileio.py

         import _io
         filename = self.tmpfile + '_w'
         f = _io.FileIO(filename, 'wb')
-        f.write("test")
+        f.write("te")
+        f.write(u"st")
         # try without flushing
         f2 = _io.FileIO(filename, 'rb')
         assert f2.read() == "test"
         a = bytearray('x' * 10)
         f = _io.FileIO(self.tmpfile, 'r+')
         assert f.readinto(a) == 10
+        exc = raises(TypeError, f.readinto, u"hello")
+        assert str(exc.value) == "cannot use unicode as modifiable buffer"
+        exc = raises(TypeError, f.readinto, buffer(b"hello"))
+        assert str(exc.value) == "must be read-write buffer, not buffer"
+        exc = raises(TypeError, f.readinto, buffer(bytearray("hello")))
+        assert str(exc.value) == "must be read-write buffer, not buffer"
+        exc = raises(TypeError, f.readinto, memoryview(b"hello"))
+        assert str(exc.value) == "must be read-write buffer, not memoryview"
         f.close()
         assert a == 'a\nb\nc\0\0\0\0\0'
         #

pypy/module/_multiprocessing/interp_connection.py

             raise OperationError(space.w_IOError,
                                  space.wrap("connection is read-only"))
 
-    @unwrap_spec(buf='bufferstr', offset='index', size='index')
-    def send_bytes(self, space, buf, offset=0, size=PY_SSIZE_T_MIN):
+    @unwrap_spec(offset='index', size='index')
+    def send_bytes(self, space, w_buf, offset=0, size=PY_SSIZE_T_MIN):
+        buf = space.getarg_w('s*', w_buf).as_str()
         length = len(buf)
         self._check_writable(space)
         if offset < 0:
 
     @unwrap_spec(offset='index')
     def recv_bytes_into(self, space, w_buffer, offset=0):
-        rwbuffer = space.rwbuffer_w(w_buffer)
+        rwbuffer = space.writebuf_w(w_buffer)
         length = rwbuffer.getlength()
 
         res, newbuf = self.do_recv_string(
         w_pickled = space.call_method(
             w_picklemodule, "dumps", w_obj, w_protocol)
 
-        buf = space.bufferstr_w(w_pickled)
+        buf = space.str_w(w_pickled)
         self.do_send_string(space, buf, 0, len(buf))
 
     def recv(self, space):

pypy/module/_rawffi/buffer.py

-from pypy.interpreter.buffer import RWBuffer
+from rpython.rlib.buffer import Buffer
 
 # XXX not the most efficient implementation
 
 
-class RawFFIBuffer(RWBuffer):
+class RawFFIBuffer(Buffer):
+    _immutable_ = True
 
     def __init__(self, datainstance):
         self.datainstance = datainstance
+        self.readonly = False
 
     def getlength(self):
         return self.datainstance.getrawsize()

pypy/module/_rawffi/interp_rawffi.py

 
 from rpython.tool.sourcetools import func_with_new_name
 from rpython.rlib.rarithmetic import intmask, r_uint
+from pypy.module._rawffi.buffer import RawFFIBuffer
 from pypy.module._rawffi.tracker import tracker
 
 TYPEMAP = {
         lltype.free(self.ll_buffer, flavor='raw')
         self.ll_buffer = lltype.nullptr(rffi.VOIDP.TO)
 
-    def buffer_w(self, space):
-        from pypy.module._rawffi.buffer import RawFFIBuffer
+    def buffer_w(self, space, flags):
+        return RawFFIBuffer(self)
+
+    def readbuf_w(self, space):
+        return RawFFIBuffer(self)
+
+    def writebuf_w(self, space):
         return RawFFIBuffer(self)
 
     def getrawsize(self):

pypy/module/_rawffi/test/test__rawffi.py

         assert a[3] == 'z'
         assert a[4] == 't'
 
+        b = memoryview(a)
+        assert len(b) == 10
+        assert b[3] == 'z'
+        b[3] = 'x'
+        assert b[3] == 'x'
+
     def test_union(self):
         import _rawffi
         longsize = _rawffi.sizeof('l')

pypy/module/_socket/interp_socket.py

 
     @unwrap_spec(nbytes=int, flags=int)
     def recv_into_w(self, space, w_buffer, nbytes=0, flags=0):
-        rwbuffer = space.rwbuffer_w(w_buffer)
+        rwbuffer = space.getarg_w('w*', w_buffer)
         lgt = rwbuffer.getlength()
         if nbytes == 0 or nbytes > lgt:
             nbytes = lgt
 
     @unwrap_spec(nbytes=int, flags=int)
     def recvfrom_into_w(self, space, w_buffer, nbytes=0, flags=0):
-        rwbuffer = space.rwbuffer_w(w_buffer)
+        rwbuffer = space.getarg_w('w*', w_buffer)
         lgt = rwbuffer.getlength()
         if nbytes == 0 or nbytes > lgt:
             nbytes = lgt

pypy/module/_socket/test/test_sock_app.py

             s.connect(("www.python.org", 80))
         except _socket.gaierror, ex:
             skip("GAIError - probably no connection: %s" % str(ex.args))
+        exc = raises(TypeError, s.send, None)
+        assert str(exc.value) == "must be string or buffer, not None"
         assert s.send(buffer('')) == 0
         assert s.sendall(buffer('')) is None
+        assert s.send(memoryview('')) == 0
+        assert s.sendall(memoryview('')) is None
         assert s.send(u'') == 0
         assert s.sendall(u'') is None
         raises(UnicodeEncodeError, s.send, u'\xe9')
         msg = buf.tostring()[:len(MSG)]
         assert msg == MSG
 
+        conn.send(MSG)
+        buf = bytearray(1024)
+        nbytes = cli.recv_into(memoryview(buf))
+        assert nbytes == len(MSG)
+        msg = buf[:len(MSG)]
+        assert msg == MSG
+
     def test_recvfrom_into(self):
         import socket
         import array
         msg = buf.tostring()[:len(MSG)]
         assert msg == MSG
 
+        conn.send(MSG)
+        buf = bytearray(1024)
+        nbytes, addr = cli.recvfrom_into(memoryview(buf))
+        assert nbytes == len(MSG)
+        msg = buf[:len(MSG)]
+        assert msg == MSG
+
     def test_family(self):
         import socket
         cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

pypy/module/_sre/interp_sre.py

 
 def slice_w(space, ctx, start, end, w_default):
     if 0 <= start <= end:
-        if isinstance(ctx, rsre_core.StrMatchContext):
-            return space.wrap(ctx._string[start:end])
+        if isinstance(ctx, rsre_core.BufMatchContext):
+            return space.wrap(ctx._buffer.getslice(start, end, 1, end-start))
         elif isinstance(ctx, rsre_core.UnicodeMatchContext):
             return space.wrap(ctx._unicodestr[start:end])
         else:
                              space.wrap("cannot copy this pattern object"))
 
     def make_ctx(self, w_string, pos=0, endpos=sys.maxint):
-        """Make a StrMatchContext or a UnicodeMatchContext for searching
+        """Make a BufMatchContext or a UnicodeMatchContext for searching
         in the given w_string object."""
         space = self.space
         if pos < 0:
             return rsre_core.UnicodeMatchContext(self.code, unicodestr,
                                                  pos, endpos, self.flags)
         else:
-            str = space.bufferstr_w(w_string)
-            if pos > len(str):
-                pos = len(str)
-            if endpos > len(str):
-                endpos = len(str)
-            return rsre_core.StrMatchContext(self.code, str,
+            buf = space.readbuf_w(w_string)
+            size = buf.getlength()
+            assert size >= 0
+            if pos > size:
+                pos = size
+            if endpos > size:
+                endpos = size
+            return rsre_core.BufMatchContext(self.code, buf,
                                              pos, endpos, self.flags)
 
     def getmatch(self, ctx, found):
 
     def fget_string(self, space):
         ctx = self.ctx
-        if isinstance(ctx, rsre_core.StrMatchContext):
-            return space.wrap(ctx._string)
+        if isinstance(ctx, rsre_core.BufMatchContext):
+            return space.wrap(ctx._buffer.as_str())
         elif isinstance(ctx, rsre_core.UnicodeMatchContext):
             return space.wrap(ctx._unicodestr)
         else:

pypy/module/_winreg/interp_winreg.py

 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
-from pypy.interpreter.error import OperationError, wrap_windowserror
+from pypy.interpreter.error import OperationError, wrap_windowserror, oefmt
 from rpython.rtyper.lltypesystem import rffi, lltype
 from rpython.rlib import rwinreg, rwin32
 from rpython.rlib.rarithmetic import r_uint, intmask
             buf = lltype.malloc(rffi.CCHARP.TO, 1, flavor='raw')
             buf[0] = '\0'
         else:
-            value = space.bufferstr_w(w_value)
+            try:
+                value = w_value.readbuf_w(space)
+            except TypeError:
+                raise oefmt(space.w_TypeError,
+                            "Objects of type '%T' can not be used as binary "
+                            "registry values", w_value)
+            else:
+                value = value.as_str()
             buflen = len(value)
             buf = rffi.str2charp(value)
 

pypy/module/_winreg/test/test_winreg.py

             assert 0, "Did not raise"
 
     def test_SetValueEx(self):
-        from _winreg import CreateKey, SetValueEx
+        from _winreg import CreateKey, SetValueEx, REG_BINARY
         key = CreateKey(self.root_key, self.test_key_name)
         sub_key = CreateKey(key, "sub_key")
         for name, value, type in self.test_data:
             SetValueEx(sub_key, name, 0, type, value)
+        exc = raises(TypeError, SetValueEx, sub_key, 'test_name', None,
+                                            REG_BINARY, memoryview('abc'))
+        assert str(exc.value) == ("Objects of type 'memoryview' can not "
+                                  "be used as binary registry values")
 
     def test_readValues(self):
         from _winreg import OpenKey, EnumValue, QueryValueEx, EnumKey

pypy/module/array/interp_array.py

 from __future__ import with_statement
 
 from rpython.rlib import jit
+from rpython.rlib.buffer import Buffer
 from rpython.rlib.objectmodel import keepalive_until_here
 from rpython.rlib.rarithmetic import ovfcheck, widen
 from rpython.rlib.unroll import unrolling_iterable
 from rpython.rtyper.lltypesystem.rstr import copy_string_to_raw
 
 from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.buffer import RWBuffer
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.gateway import (
     interp2app, interpindirect2app, unwrap_spec)
             if len(__args__.arguments_w) > 0:
                 w_initializer = __args__.arguments_w[0]
                 if space.type(w_initializer) is space.w_str:
-                    a.descr_fromstring(space, space.str_w(w_initializer))
+                    a.descr_fromstring(space, w_initializer)
                 elif space.type(w_initializer) is space.w_list:
                     a.descr_fromlist(space, w_initializer)
                 else:
         self.len = 0
         self.allocated = 0
 
-    def buffer_w(self, space):
-        return ArrayBuffer(self)
+    def readbuf_w(self, space):
+        return ArrayBuffer(self, True)
+
+    def writebuf_w(self, space):
+        return ArrayBuffer(self, False)
 
     def descr_append(self, space, w_x):
         """ append(x)
         self._charbuf_stop()
         return self.space.wrap(s)
 
-    @unwrap_spec(s=str)
-    def descr_fromstring(self, space, s):
+    def descr_fromstring(self, space, w_s):
         """ fromstring(string)
 
         Appends items from the string, interpreting it as an array of machine
         values,as if it had been read from a file using the fromfile() method).
         """
+        s = space.getarg_w('s#', w_s)
         if len(s) % self.itemsize != 0:
             msg = 'string length not a multiple of item size'
             raise OperationError(self.space.w_ValueError, self.space.wrap(msg))
             elems = max(0, len(item) - (len(item) % self.itemsize))
             if n != 0:
                 item = item[0:elems]
-            self.descr_fromstring(space, item)
+            self.descr_fromstring(space, space.wrap(item))
             msg = "not enough items in file"
             raise OperationError(space.w_EOFError, space.wrap(msg))
-        self.descr_fromstring(space, item)
+        self.descr_fromstring(space, w_item)
 
     @unwrap_spec(w_f=W_File)
     def descr_tofile(self, space, w_f):
     v.typecode = k
 unroll_typecodes = unrolling_iterable(types.keys())
 
-class ArrayBuffer(RWBuffer):
-    def __init__(self, array):
+class ArrayBuffer(Buffer):
+    _immutable_ = True
+
+    def __init__(self, array, readonly):
         self.array = array
+        self.readonly = readonly
 
     def getlength(self):
         return self.array.len * self.array.itemsize

pypy/module/array/test/test_array.py

         a.fromstring('Hi!')
         assert a[0] == 'H' and a[1] == 'i' and a[2] == '!' and len(a) == 3
         a = self.array('c')
+        a.fromstring(buffer('xyz'))
+        exc = raises(TypeError, a.fromstring, memoryview('xyz'))
+        assert str(exc.value) == "must be string or read-only buffer, not memoryview"
+        assert a[0] == 'x' and a[1] == 'y' and a[2] == 'z' and len(a) == 3
+        a = self.array('c')
         a.fromstring('')
         assert not len(a)
 
     def test_buffer_write(self):
         a = self.array('c', 'hello')
         buf = buffer(a)
-        print repr(buf)
-        try:
-            buf[3] = 'L'
-        except TypeError:
-            skip("buffer(array) returns a read-only buffer on CPython")
-        assert a.tostring() == 'helLo'
+        exc = raises(TypeError, "buf[3] = 'L'")
+        assert str(exc.value) == "buffer is read-only"
 
     def test_buffer_keepalive(self):
         buf = buffer(self.array('c', 'text'))

pypy/module/cStringIO/interp_stringio.py

             raise OperationError(space.w_IOError, space.wrap("negative size"))
         self.truncate(size)
 
-    @unwrap_spec(buffer='bufferstr')
-    def descr_write(self, buffer):
+    def descr_write(self, space, w_buffer):
+        buffer = space.getarg_w('s*', w_buffer)
         self.check_closed()
-        self.write(buffer)
+        self.write(buffer.as_str())
 
     def descr_writelines(self, w_lines):
         self.check_closed()
     if space.is_none(w_string):
         return space.wrap(W_OutputType(space))
     else:
-        string = space.bufferstr_w(w_string)
+        string = space.getarg_w('s*', w_string).as_str()
         return space.wrap(W_InputType(space, string))

pypy/module/cppyy/capi/loadable_capi.py

             'stdstring2stdstring'      : ([c_object],                 c_object),
         }
 
+        # size/offset are backend-specific but fixed after load
+        self.c_sizeof_farg = 0
+        self.c_offset_farg = 0
+
+
 def load_reflection_library(space):
     state = space.fromcache(State)
     if state.library is None:
         from pypy.module._cffi_backend.libraryobj import W_Library
         state.library = W_Library(space, reflection_library, rdynload.RTLD_LOCAL | rdynload.RTLD_LAZY)
+        if state.library:
+            # fix constants
+            state.c_sizeof_farg = _cdata_to_size_t(space, call_capi(space, 'function_arg_sizeof', []))
+            state.c_offset_farg = _cdata_to_size_t(space, call_capi(space, 'function_arg_typeoffset', []))
     return state.library
 
 def verify_backend(space):
     return _cdata_to_ptr(space, call_capi(space, 'allocate_function_args', [_Arg(l=size)]))
 def c_deallocate_function_args(space, cargs):
     call_capi(space, 'deallocate_function_args', [_Arg(vp=cargs)])
-@jit.elidable
 def c_function_arg_sizeof(space):
-    return _cdata_to_size_t(space, call_capi(space, 'function_arg_sizeof', []))
-@jit.elidable
+    state = space.fromcache(State)
+    return state.c_sizeof_farg
 def c_function_arg_typeoffset(space):
-    return _cdata_to_size_t(space, call_capi(space, 'function_arg_typeoffset', []))
+    state = space.fromcache(State)
+    return state.c_offset_farg
 
 # scope reflection information -----------------------------------------------
 def c_is_namespace(space, scope):
 def c_base_name(space, cppclass, base_index):
     args = [_Arg(l=cppclass.handle), _Arg(l=base_index)]
     return charp2str_free(space, call_capi(space, 'base_name', args))
-@jit.elidable_promote('2')
 def c_is_subtype(space, derived, base):
+    jit.promote(base)
     if derived == base:
         return bool(1)
     return space.bool_w(call_capi(space, 'is_subtype', [_Arg(l=derived.handle), _Arg(l=base.handle)]))
 
-@jit.elidable_promote('1,2,4')
 def _c_base_offset(space, derived_h, base_h, address, direction):
     args = [_Arg(l=derived_h), _Arg(l=base_h), _Arg(l=address), _Arg(l=direction)]
     return _cdata_to_size_t(space, call_capi(space, 'base_offset', args))

pypy/module/cppyy/converter.py

 def get_rawbuffer(space, w_obj):
     # raw buffer
     try:
-        buf = space.buffer_w(w_obj)
+        buf = space.readbuf_w(w_obj)
         return rffi.cast(rffi.VOIDP, buf.get_raw_address())
     except Exception:
         pass
     def to_memory(self, space, w_obj, w_value, offset):
         # copy the full array (uses byte copy for now)
         address = rffi.cast(rffi.CCHARP, self._get_raw_address(space, w_obj, offset))
-        buf = space.buffer_w(w_value)
+        buf = space.readbuf_w(w_value)
         # TODO: report if too many items given?
         for i in range(min(self.size*self.typesize, buf.getlength())):
             address[i] = buf.getitem(i)
         # copy only the pointer value
         rawobject = get_rawobject_nonnull(space, w_obj)
         byteptr = rffi.cast(rffi.CCHARPP, capi.direct_ptradd(rawobject, offset))
-        buf = space.buffer_w(w_value)
+        buf = space.readbuf_w(w_value)
         try:
             byteptr[0] = buf.get_raw_address()
         except ValueError:

pypy/module/cppyy/interp_cppyy.py

     def get_returntype(self):
         return self.space.wrap(self.converter.name)
 
-    @jit.elidable_promote()
     def _get_offset(self, cppinstance):
         if cppinstance:
             assert lltype.typeOf(cppinstance.cppclass.handle) == lltype.typeOf(self.scope.handle)
-            offset = self.offset + capi.c_base_offset(self.space,
-                cppinstance.cppclass, self.scope, cppinstance.get_rawobject(), 1)
+            offset = self.offset + cppinstance.cppclass.get_base_offset(cppinstance, self.scope)
         else:
             offset = self.offset
         return offset
         self.datamembers[name] = new_dm
         return new_dm
 
-    @jit.elidable_promote()
     def dispatch(self, name, signature):
         overload = self.get_overload(name)
         sig = '(%s)' % signature
     def find_datamember(self, name):
         raise self.missing_attribute_error(name)
 
+    def get_base_offset(self, cppinstance, calling_scope):
+        assert self == cppinstance.cppclass
+        return 0
+
     def get_cppthis(self, cppinstance, calling_scope):
         assert self == cppinstance.cppclass
         return cppinstance.get_rawobject()
 
 class W_ComplexCPPClass(W_CPPClass):
 
-    def get_cppthis(self, cppinstance, calling_scope):
+    def get_base_offset(self, cppinstance, calling_scope):
         assert self == cppinstance.cppclass
         offset = capi.c_base_offset(self.space,
                                     self, calling_scope, cppinstance.get_rawobject(), 1)
+        return offset
+
+    def get_cppthis(self, cppinstance, calling_scope):
+        assert self == cppinstance.cppclass
+        offset = self.get_base_offset(cppinstance, calling_scope)
         return capi.direct_ptradd(cppinstance.get_rawobject(), offset)
 
 W_ComplexCPPClass.typedef = TypeDef(

pypy/module/cppyy/src/dummy_backend.cxx

 typedef std::map<cppyy_scope_t, Cppyy_PseudoClassInfo> Scopes_t;
 static Scopes_t s_scopes;
 
+class PseudoExample01 {
+public:
+    PseudoExample01() : m_somedata(-99) {}
+    PseudoExample01(int a) : m_somedata(a) {}
+    PseudoExample01(const PseudoExample01& e) : m_somedata(e.m_somedata) {}
+    PseudoExample01& operator=(const PseudoExample01& e) {
+        if (this != &e) m_somedata = e.m_somedata;
+        return *this;
+    }
+   virtual ~PseudoExample01() {}
+
+public:
+    int m_somedata;
+};
+
+static int example01_last_static_method = 0;
+static int example01_last_constructor = 0;
+
 struct Cppyy_InitPseudoReflectionInfo {
     Cppyy_InitPseudoReflectionInfo() {
         // class example01 --
 
         std::vector<Cppyy_PseudoMethodInfo> methods;
 
-        // static double staticAddToDouble(double a);
+        // ( 0) static double staticAddToDouble(double a)
         std::vector<std::string> argtypes;
         argtypes.push_back("double");
         methods.push_back(Cppyy_PseudoMethodInfo("staticAddToDouble", argtypes, "double"));
 
-        // static int staticAddOneToInt(int a);
-        // static int staticAddOneToInt(int a, int b);
+        // ( 1) static int staticAddOneToInt(int a)
+        // ( 2) static int staticAddOneToInt(int a, int b)
         argtypes.clear();
         argtypes.push_back("int");
         methods.push_back(Cppyy_PseudoMethodInfo("staticAddOneToInt", argtypes, "int"));
         argtypes.push_back("int");
         methods.push_back(Cppyy_PseudoMethodInfo("staticAddOneToInt", argtypes, "int"));
 
-        // static int staticAtoi(const char* str);
+        // ( 3) static int staticAtoi(const char* str)
         argtypes.clear();
         argtypes.push_back("const char*");
         methods.push_back(Cppyy_PseudoMethodInfo("staticAtoi", argtypes, "int"));
 
-        // static char* staticStrcpy(const char* strin);
+        // ( 4) static char* staticStrcpy(const char* strin)
         methods.push_back(Cppyy_PseudoMethodInfo("staticStrcpy", argtypes, "char*"));
 
+        // ( 5) static void staticSetPayload(payload* p, double d)
+        // ( 6) static payload* staticCyclePayload(payload* p, double d)
+        // ( 7) static payload staticCopyCyclePayload(payload* p, double d)
+        argtypes.clear();
+        argtypes.push_back("payload*");
+        argtypes.push_back("double");
+        methods.push_back(Cppyy_PseudoMethodInfo("staticSetPayload", argtypes, "void"));
+        methods.push_back(Cppyy_PseudoMethodInfo("staticCyclePayload", argtypes, "payload*"));
+        methods.push_back(Cppyy_PseudoMethodInfo("staticCopyCyclePayload", argtypes, "payload"));
+
+        // ( 8) static int getCount()
+        // ( 9) static void setCount(int)
+        argtypes.clear();
+        methods.push_back(Cppyy_PseudoMethodInfo("getCount", argtypes, "int"));
+        argtypes.push_back("int");
+        methods.push_back(Cppyy_PseudoMethodInfo("setCount", argtypes, "void"));
+
+        // cut-off is used in cppyy_is_static
+        example01_last_static_method = methods.size();
+
+        // (10) example01()
+        // (11) example01(int a)
+        argtypes.clear();
+        methods.push_back(Cppyy_PseudoMethodInfo("example01", argtypes, "constructor"));
+        argtypes.push_back("int");
+        methods.push_back(Cppyy_PseudoMethodInfo("example01", argtypes, "constructor"));
+
+        // cut-off is used in cppyy_is_constructor
+        example01_last_constructor = methods.size();
+
+        // (12) double addDataToDouble(double a)
+        argtypes.clear();
+        argtypes.push_back("double");
+        methods.push_back(Cppyy_PseudoMethodInfo("addDataToDouble", argtypes, "double"));
+
         Cppyy_PseudoClassInfo info(methods);
         s_scopes[(cppyy_scope_t)s_scope_id] = info;
         // -- class example01
 }
 
 
+/* memory management ------------------------------------------------------ */
+void cppyy_destruct(cppyy_type_t handle, cppyy_object_t self) {
+    if (handle == s_handles["example01"])
+       delete (PseudoExample01*)self;
+}
+
+
 /* method/function dispatching -------------------------------------------- */
-template<typename T>
-static inline T cppyy_call_T(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
-    T result = T();
+int cppyy_call_i(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+    int result = 0;
     switch ((long)method) {
-    case 0:             // double staticAddToDouble(double)
-        assert(!self && nargs == 1);
-        result = ((CPPYY_G__value*)args)[0].obj.d + 0.01;
-        break;
-    case 1:             // int staticAddOneToInt(int)
+    case 1:             // static int staticAddOneToInt(int)
         assert(!self && nargs == 1);
         result = ((CPPYY_G__value*)args)[0].obj.in + 1;
         break;
-    case 2:             // int staticAddOneToInt(int, int)
+    case 2:             // static int staticAddOneToInt(int, int)
         assert(!self && nargs == 2);
         result = ((CPPYY_G__value*)args)[0].obj.in + ((CPPYY_G__value*)args)[1].obj.in + 1;
         break;
-    case 3:             // int staticAtoi(const char* str)
+    case 3:             // static int staticAtoi(const char* str)
         assert(!self && nargs == 1);
         result = ::atoi((const char*)(*(long*)&((CPPYY_G__value*)args)[0]));
         break;
+    case 8:             // static int getCount()
+       assert(!self && nargs == 0);
+       // can't actually call this method (would need to resolve example01::count), but
+       // other than the memory tests, most tests just check for 0 at the end
+       result = 0;
+       break;
     default:
+        assert(!"method unknown in cppyy_call_i");
         break;
     }
     return result;
 }
 
-int cppyy_call_i(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
-    return cppyy_call_T<int>(method, self, nargs, args);
-}
-
 long cppyy_call_l(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
-    // char* staticStrcpy(const char* strin)
-    const char* strin = (const char*)(*(long*)&((CPPYY_G__value*)args)[0]);
-    char* strout = (char*)malloc(::strlen(strin)+1);
-    ::strcpy(strout, strin);
-    return (long)strout;
+    if ((long)method == 4) {  // static char* staticStrcpy(const char* strin)
+       const char* strin = (const char*)(*(long*)&((CPPYY_G__value*)args)[0]);
+       char* strout = (char*)malloc(::strlen(strin)+1);
+       ::strcpy(strout, strin);
+       return (long)strout;
+    }
+    assert(!"method unknown in cppyy_call_l");
+    return 0;
 }
 
 double cppyy_call_d(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
-    return cppyy_call_T<double>(method, self, nargs, args);
+    double result = 0.;
+    switch ((long)method) {
+    case 0:             // static double staticAddToDouble(double)
+        assert(!self && nargs == 1);
+        result = ((CPPYY_G__value*)args)[0].obj.d + 0.01;
+        break;
+    case 12:            // double addDataToDouble(double a)
+        assert(self && nargs == 1);
+        result = ((PseudoExample01*)self)->m_somedata + ((CPPYY_G__value*)args)[0].obj.d;
+        break;
+    default:
+        assert(!"method unknown in cppyy_call_d");
+        break;
+    }
+    return result;
 }
 
 char* cppyy_call_s(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
     return strout;
 }
 
+cppyy_object_t cppyy_constructor(cppyy_method_t method, cppyy_type_t handle, int nargs, void* args) {
+    void* result = 0;
+    if (handle == s_handles["example01"]) {
+        switch ((long)method) {
+        case 10:
+            assert(nargs == 0);
+            result = new PseudoExample01;
+            break;
+        case 11:
+            assert(nargs == 1);
+            result = new PseudoExample01(((CPPYY_G__value*)args)[0].obj.in);
+            break;
+        default:
+            assert(!"method unknown in cppyy_constructor");
+            break;
+        }
+    }
+    return (cppyy_object_t)result;
+}
+
 cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_type_t /* handle */, cppyy_index_t /* method_index */) {
     return (cppyy_methptrgetter_t)0;
 }
 
+
 /* handling of function argument buffer ----------------------------------- */
 void* cppyy_allocate_function_args(size_t nargs) {
     CPPYY_G__value* args = (CPPYY_G__value*)malloc(nargs*sizeof(CPPYY_G__value));
 }   
 
 int cppyy_has_complex_hierarchy(cppyy_type_t /* handle */) {
-    return 1;
+    return 0;
+}
+
+int cppyy_num_bases(cppyy_type_t /*handle*/) {
+   return 0;
 }
 
 
 
 
 /* method properties -----------------------------------------------------  */
-int cppyy_is_constructor(cppyy_type_t /* handle */, cppyy_index_t /* method_index */) {
+int cppyy_is_constructor(cppyy_type_t handle, cppyy_index_t method_index) {
+    if (handle == s_handles["example01"])
+       return example01_last_static_method <= method_index
+           && method_index < example01_last_constructor;
     return 0;
 }
 
-int cppyy_is_staticmethod(cppyy_type_t /* handle */, cppyy_index_t /* method_index */) {
+int cppyy_is_staticmethod(cppyy_type_t handle, cppyy_index_t method_index) {
+    if (handle == s_handles["example01"])
+        return method_index < example01_last_static_method ? 1 : 0;
     return 1;
 }
 

pypy/module/cppyy/test/conftest.py

         if 'dummy' in lcapi.reflection_library:
             # run only tests that are covered by the dummy backend and tests
             # that do not rely on reflex
-            if not item.location[0] in ['test_helper.py', 'test_cppyy.py']:
+            if not ('test_helper.py' in item.location[0] or \
+                    'test_cppyy.py' in item.location[0]):
                 py.test.skip("genreflex is not installed")
             import re
-            if item.location[0] == 'test_cppyy.py' and \
-                not re.search("test0[1-3]", item.location[2]):
+            if 'test_cppyy.py' in item.location[0] and \
+                not re.search("test0[1-36]", item.location[2]):