[pypy-commit] pypy unicode-utf8-py3: merge unicode-utf8 into branch

mattip pypy.commits at gmail.com
Tue Sep 11 16:33:09 EDT 2018


Author: Matti Picus <matti.picus at gmail.com>
Branch: unicode-utf8-py3
Changeset: r95097:d9069a2d3f11
Date: 2018-09-11 22:38 +0300
http://bitbucket.org/pypy/pypy/changeset/d9069a2d3f11/

Log:	merge unicode-utf8 into branch

diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -330,7 +330,8 @@
 -------------
 
 * Hash randomization (``-R``) `is ignored in PyPy`_.  In CPython
-  before 3.4 it has `little point`_.
+  before 3.4 it has `little point`_.  Both CPython >= 3.4 and PyPy3
+  implement the randomized SipHash algorithm and ignore ``-R``.
 
 * You can't store non-string keys in type objects.  For example::
 
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
@@ -32,11 +32,14 @@
 The reverse-debugger branch has been merged.  For more information, see
 https://bitbucket.org/pypy/revdb
 
+.. branch: pyparser-improvements-3
+
+Small refactorings in the Python parser.
+
 .. branch: unicode-utf8-re
 .. branch: utf8-io
 
 Utf8 handling for unicode
 
 .. branch: pyparser-improvements-3
-
-Small refactorings in the Python parser.
+Small refactorings in the Python parser.
\ No newline at end of file
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -1250,7 +1250,6 @@
 
     def test_revdb_metavar(self):
         from pypy.interpreter.reverse_debugging import dbstate, setup_revdb
-        self.space.config.translation.reverse_debugger = True
         self.space.reverse_debugging = True
         try:
             setup_revdb(self.space)
diff --git a/pypy/module/cpyext/test0/test_abstract.py b/pypy/module/cpyext/test0/test_abstract.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test0/test_abstract.py
@@ -0,0 +1,130 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+import pytest
+
+class AppTestBufferProtocol(AppTestCpythonExtensionBase):
+    """Tests for the old buffer protocol."""
+
+    def w_get_buffer_support(self):
+        return self.import_extension('buffer_support', [
+            ("charbuffer_as_string", "METH_O",
+             """
+                 char *ptr;
+                 Py_ssize_t size;
+                 if (PyObject_AsCharBuffer(args, (const char **)&ptr, &size) < 0)
+                     return NULL;
+                 return PyString_FromStringAndSize(ptr, size);
+             """),
+            ("check_readbuffer", "METH_O",
+             """
+                 return PyBool_FromLong(PyObject_CheckReadBuffer(args));
+             """),
+            ("readbuffer_as_string", "METH_O",
+             """
+                 const void *ptr;
+                 Py_ssize_t size;
+                 if (PyObject_AsReadBuffer(args, &ptr, &size) < 0)
+                     return NULL;
+                 return PyString_FromStringAndSize((char*)ptr, size);
+             """),
+            ("writebuffer_as_string", "METH_O",
+             """
+                 void *ptr;
+                 Py_ssize_t size;
+                 if (PyObject_AsWriteBuffer(args, &ptr, &size) < 0)
+                     return NULL;
+                 return PyString_FromStringAndSize((char*)ptr, size);
+             """),
+            ("zero_out_writebuffer", "METH_O",
+             """
+                 void *ptr;
+                 Py_ssize_t size;
+                 Py_ssize_t i;
+                 if (PyObject_AsWriteBuffer(args, &ptr, &size) < 0)
+                     return NULL;
+                 for (i = 0; i < size; i++) {
+                     ((char*)ptr)[i] = 0;
+                 }
+                 Py_RETURN_NONE;
+             """),
+            ])
+
+    def test_string(self):
+        buffer_support = self.get_buffer_support()
+
+        s = 'a\0x'
+
+        assert buffer_support.check_readbuffer(s)
+        assert s == buffer_support.readbuffer_as_string(s)
+        assert raises(TypeError, buffer_support.writebuffer_as_string, s)
+        assert s == buffer_support.charbuffer_as_string(s)
+
+    def test_buffer(self):
+        buffer_support = self.get_buffer_support()
+
+        s = 'a\0x'
+        buf = buffer(s)
+
+        assert buffer_support.check_readbuffer(buf)
+        assert s == buffer_support.readbuffer_as_string(buf)
+        assert raises(TypeError, buffer_support.writebuffer_as_string, buf)
+        assert s == buffer_support.charbuffer_as_string(buf)
+
+    def test_mmap(self):
+        import mmap
+        buffer_support = self.get_buffer_support()
+
+        s = 'a\0x'
+        mm = mmap.mmap(-1, 3)
+        mm[:] = s
+
+        assert buffer_support.check_readbuffer(mm)
+        assert s == buffer_support.readbuffer_as_string(mm)
+        assert s == buffer_support.writebuffer_as_string(mm)
+        assert s == buffer_support.charbuffer_as_string(mm)
+
+        s = '\0' * 3
+        buffer_support.zero_out_writebuffer(mm)
+        assert s == ''.join(mm)
+        assert s == buffer_support.readbuffer_as_string(mm)
+        assert s == buffer_support.writebuffer_as_string(mm)
+        assert s == buffer_support.charbuffer_as_string(mm)
+
+        s = '\0' * 3
+        ro_mm = mmap.mmap(-1, 3, access=mmap.ACCESS_READ)
+        assert buffer_support.check_readbuffer(ro_mm)
+        assert s == buffer_support.readbuffer_as_string(ro_mm)
+        assert raises(TypeError, buffer_support.writebuffer_as_string, ro_mm)
+        assert s == buffer_support.charbuffer_as_string(ro_mm)
+
+    def test_array(self):
+        import array
+        buffer_support = self.get_buffer_support()
+
+        s = 'a\0x'
+        a = array.array('B', [5, 0, 10])
+
+        buffer_support.zero_out_writebuffer(a)
+        assert list(a) == [0, 0, 0]
+
+    def test_nonbuffer(self):
+        # e.g. int
+        buffer_support = self.get_buffer_support()
+
+        assert not buffer_support.check_readbuffer(42)
+        assert raises(TypeError, buffer_support.readbuffer_as_string, 42)
+        assert raises(TypeError, buffer_support.writebuffer_as_string, 42)
+        assert raises(TypeError, buffer_support.charbuffer_as_string, 42)
+
+    def test_user_class(self):
+        class MyBuf(str):
+            pass
+        s = 'a\0x'
+        buf = MyBuf(s)
+        buffer_support = self.get_buffer_support()
+
+        assert buffer_support.check_readbuffer(buf)
+        assert s == buffer_support.readbuffer_as_string(buf)
+        assert raises(TypeError, buffer_support.writebuffer_as_string, buf)
+        assert s == buffer_support.charbuffer_as_string(buf)
+
+
diff --git a/pypy/module/cpyext/test0/test_bufferobject.py b/pypy/module/cpyext/test0/test_bufferobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test0/test_bufferobject.py
@@ -0,0 +1,123 @@
+from rpython.rtyper.lltypesystem import lltype
+from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.api import PyObject
+
+class AppTestBufferObject(AppTestCpythonExtensionBase):
+
+    def test_FromMemory(self):
+        module = self.import_extension('foo', [
+            ("get_FromMemory", "METH_NOARGS",
+             """
+                 cbuf = malloc(4);
+                 cbuf[0] = 'a';
+                 cbuf[1] = 'b';
+                 cbuf[2] = 'c';
+                 cbuf[3] = '\\0';
+                 return PyBuffer_FromMemory(cbuf, 4);
+             """),
+            ("free_buffer", "METH_NOARGS",
+             """
+                 free(cbuf);
+                 Py_RETURN_NONE;
+             """),
+            ("check_ascharbuffer", "METH_O",
+             """
+                 char *ptr;
+                 Py_ssize_t size;
+                 if (PyObject_AsCharBuffer(args, (const char **)&ptr, &size) < 0)
+                     return NULL;
+                 return PyString_FromStringAndSize(ptr, size);
+             """)
+            ], prologue = """
+            static char* cbuf = NULL;
+            """)
+        buf = module.get_FromMemory()
+        assert str(buf) == 'abc\0'
+
+        assert module.check_ascharbuffer(buf) == 'abc\0'
+
+        module.free_buffer()
+
+    def test_Buffer_New(self):
+        module = self.import_extension('foo', [
+            ("buffer_new", "METH_NOARGS",
+             """
+                 return PyBuffer_New(150);
+             """),
+            ])
+        b = module.buffer_new()
+        raises(AttributeError, getattr, b, 'x')
+
+    def test_array_buffer(self):
+        if self.runappdirect:
+            skip('PyBufferObject not available outside buffer object.c')
+        module = self.import_extension('foo', [
+            ("roundtrip", "METH_O",
+             """
+                 PyBufferObject *buf = (PyBufferObject *)args;
+                 return PyString_FromStringAndSize(buf->b_ptr, buf->b_size);
+             """),
+            ])
+        import array
+        a = array.array('c', 'text')
+        b = buffer(a)
+        assert module.roundtrip(b) == 'text'
+
+
+    def test_issue2752(self):
+        iterations = 10
+        if self.runappdirect:
+            iterations = 2000
+        module = self.import_extension('foo', [
+            ("test_mod", 'METH_VARARGS',
+            """
+                PyObject *obj;
+                Py_buffer bp;
+                if (!PyArg_ParseTuple(args, "O", &obj))
+                    return NULL;
+
+                if (PyObject_GetBuffer(obj, &bp, PyBUF_SIMPLE) == -1)
+                    return NULL;
+                
+                if (((unsigned char*)bp.buf)[0] != '0') {
+                    void * buf = (void*)bp.buf;
+                    unsigned char val[4];
+                    char * s = PyString_AsString(obj);
+                    memcpy(val, bp.buf, 4);
+                    PyBuffer_Release(&bp);
+                    if (PyObject_GetBuffer(obj, &bp, PyBUF_SIMPLE) == -1)
+                        return NULL;
+                    PyErr_Format(PyExc_ValueError,
+                            "mismatch: %p [%x %x %x %x...] now %p [%x %x %x %x...] as str '%s'",
+                            buf, val[0], val[1], val[2], val[3],
+                            (void *)bp.buf,
+                            ((unsigned char*)bp.buf)[0],
+                            ((unsigned char*)bp.buf)[1],
+                            ((unsigned char*)bp.buf)[2],
+                            ((unsigned char*)bp.buf)[3],
+                            s);
+                    PyBuffer_Release(&bp);
+                    return NULL;
+                }
+
+                PyBuffer_Release(&bp);
+                Py_RETURN_NONE;
+            """),
+            ])
+        bufsize = 4096
+        def getdata(bufsize):
+            data = b'01234567'
+            for x in range(18):
+                data += data
+                if len(data) >= bufsize:
+                    break
+            return data
+        for j in range(iterations):
+            block = getdata(bufsize)
+            assert block[:8] == '01234567'
+            try:
+                module.test_mod(block)
+            except ValueError as e:
+                print("%s at it=%d" % (e, j))
+                assert False
diff --git a/pypy/module/cpyext/test0/test_bytesobject.py b/pypy/module/cpyext/test0/test_bytesobject.py
--- a/pypy/module/cpyext/test0/test_bytesobject.py
+++ b/pypy/module/cpyext/test0/test_bytesobject.py
@@ -314,3 +314,298 @@
         w_obj = space.wrap(u"test")
         with raises_w(space, TypeError):
             api.PyBytes_FromObject(w_obj)
+                PyString_AS_STRING(o);
+                PyString_AS_STRING(u);
+
+                return o;
+             """)])
+        assert module.test_macro_invocations() == ''
+
+    def test_hash_and_state(self):
+        module = self.import_extension('foo', [
+            ("test_hash", "METH_VARARGS",
+             '''
+                PyObject* obj = (PyTuple_GetItem(args, 0));
+                long hash = ((PyBytesObject*)obj)->ob_shash;
+                return PyLong_FromLong(hash);
+             '''
+             ),
+            ("test_sstate", "METH_NOARGS",
+             '''
+                PyObject *s = PyString_FromString("xyz");
+                /*int sstate = ((PyBytesObject*)s)->ob_sstate;
+                printf("sstate now %d\\n", sstate);*/
+                PyString_InternInPlace(&s);
+                /*sstate = ((PyBytesObject*)s)->ob_sstate;
+                printf("sstate now %d\\n", sstate);*/
+                Py_DECREF(s);
+                return PyBool_FromLong(1);
+             '''),
+            ], prologue='#include <stdlib.h>')
+        res = module.test_hash("xyz")
+        assert res == hash('xyz')
+        # doesn't really test, but if printf is enabled will prove sstate
+        assert module.test_sstate()
+
+    def test_subclass(self):
+        # taken from PyStringArrType_Type in numpy's scalartypes.c.src
+        module = self.import_extension('bar', [
+            ("newsubstr", "METH_O",
+             """
+                PyObject * obj;
+                char * data;
+                int len;
+
+                data = PyString_AS_STRING(args);
+                len = PyString_GET_SIZE(args);
+                if (data == NULL)
+                    Py_RETURN_NONE;
+                obj = PyArray_Scalar(data, len);
+                return obj;
+             """),
+            ("get_len", "METH_O",
+             """
+                return PyLong_FromLong(PyObject_Size(args));
+             """),
+            ('has_nb_add', "METH_O",
+             '''
+                if (args->ob_type->tp_as_number == NULL) {
+                    Py_RETURN_FALSE;
+                }
+                if (args->ob_type->tp_as_number->nb_add == NULL) {
+                    Py_RETURN_FALSE;
+                }
+                Py_RETURN_TRUE;
+             '''),
+            ], prologue="""
+                #include <Python.h>
+                PyTypeObject PyStringArrType_Type = {
+                    PyObject_HEAD_INIT(NULL)
+                    0,                            /* ob_size */
+                    "bar.string_",                /* tp_name*/
+                    sizeof(PyBytesObject), /* tp_basicsize*/
+                    0                             /* tp_itemsize */
+                    };
+
+                    static PyObject *
+                    stringtype_repr(PyObject *self)
+                    {
+                        const char *dptr, *ip;
+                        int len;
+                        PyObject *new;
+
+                        ip = dptr = PyString_AS_STRING(self);
+                        len = PyString_GET_SIZE(self);
+                        dptr += len-1;
+                        while(len > 0 && *dptr-- == 0) {
+                            len--;
+                        }
+                        new = PyString_FromStringAndSize(ip, len);
+                        if (new == NULL) {
+                            return PyString_FromString("");
+                        }
+                        return new;
+                    }
+
+                    static PyObject *
+                    stringtype_str(PyObject *self)
+                    {
+                        const char *dptr, *ip;
+                        int len;
+                        PyObject *new;
+
+                        ip = dptr = PyString_AS_STRING(self);
+                        len = PyString_GET_SIZE(self);
+                        dptr += len-1;
+                        while(len > 0 && *dptr-- == 0) {
+                            len--;
+                        }
+                        new = PyString_FromStringAndSize(ip, len);
+                        if (new == NULL) {
+                            return PyString_FromString("");
+                        }
+                        return new;
+                    }
+
+                    PyObject *
+                    PyArray_Scalar(char *data, int n)
+                    {
+                        PyTypeObject *type = &PyStringArrType_Type;
+                        PyObject *obj;
+                        void *destptr;
+                        int itemsize = n;
+                        obj = type->tp_alloc(type, itemsize);
+                        if (obj == NULL) {
+                            return NULL;
+                        }
+                        destptr = PyString_AS_STRING(obj);
+                        ((PyBytesObject *)obj)->ob_shash = -1;
+                        memcpy(destptr, data, itemsize);
+                        return obj;
+                    }
+            """, more_init = '''
+                PyStringArrType_Type.tp_alloc = NULL;
+                PyStringArrType_Type.tp_free = NULL;
+
+                PyStringArrType_Type.tp_repr = stringtype_repr;
+                PyStringArrType_Type.tp_str = stringtype_str;
+                PyStringArrType_Type.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
+                PyStringArrType_Type.tp_itemsize = sizeof(char);
+                PyStringArrType_Type.tp_base = &PyString_Type;
+                PyStringArrType_Type.tp_hash = PyString_Type.tp_hash;
+                if (PyType_Ready(&PyStringArrType_Type) < 0) INITERROR;
+            ''')
+
+        a = module.newsubstr('abc')
+        assert module.has_nb_add('a') is False
+        assert module.has_nb_add(a) is False
+        assert type(a).__name__ == 'string_'
+        assert a == 'abc'
+        assert 3 == module.get_len(a)
+        b = module.newsubstr('')
+        assert 0 == module.get_len(b)
+
+class TestBytes(BaseApiTest):
+    def test_bytes_resize(self, space):
+        py_str = new_empty_str(space, 10)
+        ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+        py_str.c_ob_sval[0] = 'a'
+        py_str.c_ob_sval[1] = 'b'
+        py_str.c_ob_sval[2] = 'c'
+        ar[0] = rffi.cast(PyObject, py_str)
+        _PyString_Resize(space, ar, 3)
+        py_str = rffi.cast(PyBytesObject, ar[0])
+        assert py_str.c_ob_size == 3
+        assert py_str.c_ob_sval[1] == 'b'
+        assert py_str.c_ob_sval[3] == '\x00'
+        # the same for growing
+        ar[0] = rffi.cast(PyObject, py_str)
+        _PyString_Resize(space, ar, 10)
+        py_str = rffi.cast(PyBytesObject, ar[0])
+        assert py_str.c_ob_size == 10
+        assert py_str.c_ob_sval[1] == 'b'
+        assert py_str.c_ob_sval[10] == '\x00'
+        decref(space, ar[0])
+        lltype.free(ar, flavor='raw')
+
+    def test_string_buffer(self, space):
+        py_str = new_empty_str(space, 10)
+        c_buf = py_str.c_ob_type.c_tp_as_buffer
+        assert c_buf
+        py_obj = rffi.cast(PyObject, py_str)
+        assert generic_cpy_call(space, c_buf.c_bf_getsegcount,
+                                py_obj, lltype.nullptr(Py_ssize_tP.TO)) == 1
+        ref = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw')
+        assert generic_cpy_call(space, c_buf.c_bf_getsegcount,
+                                py_obj, ref) == 1
+        assert ref[0] == 10
+        lltype.free(ref, flavor='raw')
+        ref = lltype.malloc(rffi.VOIDPP.TO, 1, flavor='raw')
+        assert generic_cpy_call(space, c_buf.c_bf_getreadbuffer,
+                                py_obj, 0, ref) == 10
+        lltype.free(ref, flavor='raw')
+        decref(space, py_obj)
+
+    def test_Concat(self, space):
+        ref = make_ref(space, space.wrap('abc'))
+        ptr = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+        ptr[0] = ref
+        prev_refcnt = ref.c_ob_refcnt
+        PyString_Concat(space, ptr, space.wrap('def'))
+        assert ref.c_ob_refcnt == prev_refcnt - 1
+        assert space.str_w(from_ref(space, ptr[0])) == 'abcdef'
+        with pytest.raises(OperationError):
+            PyString_Concat(space, ptr, space.w_None)
+        assert not ptr[0]
+        ptr[0] = lltype.nullptr(PyObject.TO)
+        PyString_Concat(space, ptr, space.wrap('def')) # should not crash
+        lltype.free(ptr, flavor='raw')
+
+    def test_ConcatAndDel(self, space):
+        ref1 = make_ref(space, space.wrap('abc'))
+        ref2 = make_ref(space, space.wrap('def'))
+        ptr = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+        ptr[0] = ref1
+        prev_refcnf = ref2.c_ob_refcnt
+        PyString_ConcatAndDel(space, ptr, ref2)
+        assert space.str_w(from_ref(space, ptr[0])) == 'abcdef'
+        assert ref2.c_ob_refcnt == prev_refcnf - 1
+        decref(space, ptr[0])
+        ptr[0] = lltype.nullptr(PyObject.TO)
+        ref2 = make_ref(space, space.wrap('foo'))
+        prev_refcnf = ref2.c_ob_refcnt
+        PyString_ConcatAndDel(space, ptr, ref2) # should not crash
+        assert ref2.c_ob_refcnt == prev_refcnf - 1
+        lltype.free(ptr, flavor='raw')
+
+    def test_format(self, space):
+        assert "1 2" == space.unwrap(
+            PyString_Format(space, space.wrap('%s %d'), space.wrap((1, 2))))
+
+    def test_asbuffer(self, space):
+        bufp = lltype.malloc(rffi.CCHARPP.TO, 1, flavor='raw')
+        lenp = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw')
+
+        w_text = space.wrap("text")
+        ref = make_ref(space, w_text)
+        prev_refcnt = ref.c_ob_refcnt
+        assert PyObject_AsCharBuffer(space, ref, bufp, lenp) == 0
+        assert ref.c_ob_refcnt == prev_refcnt
+        assert lenp[0] == 4
+        assert rffi.charp2str(bufp[0]) == 'text'
+        lltype.free(bufp, flavor='raw')
+        lltype.free(lenp, flavor='raw')
+        decref(space, ref)
+
+    def test_intern(self, space):
+        buf = rffi.str2charp("test")
+        w_s1 = PyString_InternFromString(space, buf)
+        w_s2 = PyString_InternFromString(space, buf)
+        rffi.free_charp(buf)
+        assert w_s1 is w_s2
+
+    def test_AsEncodedObject(self, space):
+        ptr = space.wrap('abc')
+
+        errors = rffi.str2charp("strict")
+
+        encoding = rffi.str2charp("hex")
+        res = PyString_AsEncodedObject(space, ptr, encoding, errors)
+        assert space.unwrap(res) == "616263"
+
+        res = PyString_AsEncodedObject(space,
+            ptr, encoding, lltype.nullptr(rffi.CCHARP.TO))
+        assert space.unwrap(res) == "616263"
+        rffi.free_charp(encoding)
+
+        encoding = rffi.str2charp("unknown_encoding")
+        with raises_w(space, LookupError):
+            PyString_AsEncodedObject(space, ptr, encoding, errors)
+        rffi.free_charp(encoding)
+
+        rffi.free_charp(errors)
+
+        NULL = lltype.nullptr(rffi.CCHARP.TO)
+        res = PyString_AsEncodedObject(space, ptr, NULL, NULL)
+        assert space.unwrap(res) == "abc"
+        with raises_w(space, TypeError):
+            PyString_AsEncodedObject(space, space.wrap(2), NULL, NULL)
+
+    def test_AsDecodedObject(self, space):
+        w_str = space.wrap('caf\xe9')
+        encoding = rffi.str2charp("latin-1")
+        w_res = PyString_AsDecodedObject(space, w_str, encoding, None)
+        rffi.free_charp(encoding)
+        assert w_res._utf8 == u"caf\xe9".encode('utf8')
+
+    def test_eq(self, space):
+        assert 1 == _PyString_Eq(
+            space, space.wrap("hello"), space.wrap("hello"))
+        assert 0 == _PyString_Eq(
+            space, space.wrap("hello"), space.wrap("world"))
+
+    def test_join(self, space):
+        w_sep = space.wrap('<sep>')
+        w_seq = space.wrap(['a', 'b'])
+        w_joined = _PyString_Join(space, w_sep, w_seq)
+        assert space.unwrap(w_joined) == 'a<sep>b'
diff --git a/pypy/module/cpyext/test0/test_intobject.py b/pypy/module/cpyext/test0/test_intobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test0/test_intobject.py
@@ -0,0 +1,247 @@
+from pypy.module.cpyext.test.test_api import BaseApiTest, raises_w
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.intobject import (
+    PyInt_Check, PyInt_AsLong, PyInt_AS_LONG,
+    PyInt_AsUnsignedLong, PyInt_AsUnsignedLongMask,
+    PyInt_AsUnsignedLongLongMask)
+from pypy.module.cpyext.pyobject import (decref, make_ref,
+                                         get_w_obj_and_decref)
+from pypy.module.cpyext.state import State
+import sys
+
+class TestIntObject(BaseApiTest):
+    def test_intobject(self, space):
+        state = space.fromcache(State)
+        assert PyInt_Check(space, space.wrap(3))
+        assert PyInt_Check(space, space.w_True)
+        assert not PyInt_Check(space, space.wrap((1, 2, 3)))
+        for i in [3, -5, -1, -sys.maxint, sys.maxint - 1]:
+            x = PyInt_AsLong(space, space.wrap(i))
+            y = PyInt_AS_LONG(space, space.wrap(i))
+            assert x == i
+            assert y == i
+            py_x = state.C.PyInt_FromLong(x + 1)
+            w_x = get_w_obj_and_decref(space, py_x)
+            assert space.type(w_x) is space.w_int
+            assert space.eq_w(w_x, space.wrap(i + 1))
+
+        with raises_w(space, TypeError):
+            PyInt_AsLong(space, space.w_None)
+
+        with raises_w(space, TypeError):
+            PyInt_AsLong(space, None)
+
+        assert PyInt_AsUnsignedLong(space, space.wrap(sys.maxint)) == sys.maxint
+        with raises_w(space, ValueError):
+            PyInt_AsUnsignedLong(space, space.wrap(-5))
+
+        assert (PyInt_AsUnsignedLongMask(space, space.wrap(sys.maxint))
+                == sys.maxint)
+        assert (PyInt_AsUnsignedLongMask(space, space.wrap(10 ** 30))
+                == 10 ** 30 % ((sys.maxint + 1) * 2))
+
+        assert (PyInt_AsUnsignedLongLongMask(space, space.wrap(sys.maxint))
+                == sys.maxint)
+        assert (PyInt_AsUnsignedLongLongMask(space, space.wrap(10 ** 30))
+                == 10 ** 30 % (2 ** 64))
+
+    def test_freelist_direct(self, space):
+        state = space.fromcache(State)
+        p_x = state.C.PyInt_FromLong(12345678)
+        decref(space, p_x)
+        p_y = state.C.PyInt_FromLong(87654321)
+        # check that the address is the same, i.e. that the freelist did its
+        # job
+        assert p_x == p_y
+        decref(space, p_y)
+
+    def test_freelist_make_ref(self, space):
+        w_x = space.newint(12345678)
+        w_y = space.newint(87654321)
+        p_x = make_ref(space, w_x)
+        decref(space, p_x)
+        p_y = make_ref(space, w_y)
+        # check that the address is the same: note that w_x does NOT keep p_x
+        # alive, because in make_ref we have a special case for ints
+        assert p_x == p_y
+        decref(space, p_y)
+
+    def test_freelist_int_subclass(self, space):
+        w_MyInt = space.appexec([], """():
+            class MyInt(int):
+                pass
+            return MyInt""")
+        w_x = space.call_function(w_MyInt, space.newint(12345678))
+        w_y = space.call_function(w_MyInt, space.newint(87654321))
+        p_x = make_ref(space, w_x)
+        decref(space, p_x)
+        p_y = make_ref(space, w_y)
+        # now the address is different because the freelist does not work for
+        # int subclasses
+        assert p_x != p_y
+        decref(space, p_y)
+
+    def test_coerce(self, space):
+        w_obj = space.appexec([], """():
+            class Coerce(object):
+                def __int__(self):
+                    return 42
+            return Coerce()""")
+        assert PyInt_AsLong(space, w_obj) == 42
+
+class AppTestIntObject(AppTestCpythonExtensionBase):
+    def test_fromstring(self):
+        module = self.import_extension('foo', [
+            ("from_string", "METH_NOARGS",
+             """
+                 return PyInt_FromString("1234", NULL, 16);
+             """),
+            ])
+        assert module.from_string() == 0x1234
+        assert type(module.from_string()) is int
+
+    def test_size_t(self):
+        module = self.import_extension('foo', [
+            ("values", "METH_NOARGS",
+             """
+                 return Py_BuildValue("NNNN",
+                     PyInt_FromSize_t(123),
+                     PyInt_FromSize_t((size_t)-1),
+                     PyInt_FromSsize_t(123),
+                     PyInt_FromSsize_t((size_t)-1));
+             """),
+            ])
+        values = module.values()
+        types = [type(x) for x in values]
+        assert types == [int, long, int, int]
+
+    def test_int_subtype(self):
+        module = self.import_extension(
+            'foo', [
+            ("newEnum", "METH_VARARGS",
+             """
+                EnumObject *enumObj;
+                int intval;
+                PyObject *name;
+
+                if (!PyArg_ParseTuple(args, "Oi", &name, &intval))
+                    return NULL;
+
+                enumObj = PyObject_New(EnumObject, &Enum_Type);
+                if (!enumObj) {
+                    return NULL;
+                }
+
+                enumObj->ob_ival = intval;
+                Py_INCREF(name);
+                enumObj->ob_name = name;
+
+                return (PyObject *)enumObj;
+             """),
+            ],
+            prologue="""
+            #include "structmember.h"
+            typedef struct
+            {
+                PyObject_HEAD
+                long ob_ival;
+                PyObject* ob_name;
+            } EnumObject;
+
+            static void
+            enum_dealloc(PyObject *op)
+            {
+                    Py_DECREF(((EnumObject *)op)->ob_name);
+                    Py_TYPE(op)->tp_free(op);
+            }
+
+            static PyMemberDef enum_members[] = {
+                {"name", T_OBJECT, offsetof(EnumObject, ob_name), 0, NULL},
+                {NULL}  /* Sentinel */
+            };
+
+            PyTypeObject Enum_Type = {
+                PyVarObject_HEAD_INIT(NULL, 0)
+                /*tp_name*/             "Enum",
+                /*tp_basicsize*/        sizeof(EnumObject),
+                /*tp_itemsize*/         0,
+                /*tp_dealloc*/          enum_dealloc,
+                /*tp_print*/            0,
+                /*tp_getattr*/          0,
+                /*tp_setattr*/          0,
+                /*tp_compare*/          0,
+                /*tp_repr*/             0,
+                /*tp_as_number*/        0,
+                /*tp_as_sequence*/      0,
+                /*tp_as_mapping*/       0,
+                /*tp_hash*/             0,
+                /*tp_call*/             0,
+                /*tp_str*/              0,
+                /*tp_getattro*/         0,
+                /*tp_setattro*/         0,
+                /*tp_as_buffer*/        0,
+                /*tp_flags*/            Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+                /*tp_doc*/              0,
+                /*tp_traverse*/         0,
+                /*tp_clear*/            0,
+                /*tp_richcompare*/      0,
+                /*tp_weaklistoffset*/   0,
+                /*tp_iter*/             0,
+                /*tp_iternext*/         0,
+                /*tp_methods*/          0,
+                /*tp_members*/          enum_members,
+                /*tp_getset*/           0,
+                /*tp_base*/             0, /* set to &PyInt_Type in init function for MSVC */
+                /*tp_dict*/             0,
+                /*tp_descr_get*/        0,
+                /*tp_descr_set*/        0,
+                /*tp_dictoffset*/       0,
+                /*tp_init*/             0,
+                /*tp_alloc*/            0,
+                /*tp_new*/              0
+            };
+            """, more_init = '''
+                Enum_Type.tp_base = &PyInt_Type;
+                if (PyType_Ready(&Enum_Type) < 0) INITERROR;
+            ''')
+
+        a = module.newEnum("ULTIMATE_ANSWER", 42)
+        assert type(a).__name__ == "Enum"
+        assert isinstance(a, int)
+        assert a == int(a) == 42
+        assert a.name == "ULTIMATE_ANSWER"
+
+    def test_int_cast(self):
+        mod = self.import_extension('foo', [
+                #prove it works for ints
+                ("test_int", "METH_NOARGS",
+                """
+                PyObject * obj = PyInt_FromLong(42);
+                PyObject * val;
+                if (!PyInt_Check(obj)) {
+                    Py_DECREF(obj);
+                    PyErr_SetNone(PyExc_ValueError);
+                    return NULL;
+                }
+                val = PyInt_FromLong(((PyIntObject *)obj)->ob_ival);
+                Py_DECREF(obj);
+                return val;
+                """
+                ),
+                ])
+        i = mod.test_int()
+        assert isinstance(i, int)
+        assert i == 42
+
+    def test_int_macros(self):
+        mod = self.import_extension('foo', [
+                ("test_macros", "METH_NOARGS",
+                """
+                PyObject * obj = PyInt_FromLong(42);
+                PyIntObject * i = (PyIntObject*)obj;
+                PyInt_AS_LONG(obj);
+                PyInt_AS_LONG(i);
+                Py_RETURN_NONE;
+                """
+                ),
+                ])
diff --git a/pypy/module/select/__init__.py b/pypy/module/select/__init__.py
--- a/pypy/module/select/__init__.py
+++ b/pypy/module/select/__init__.py
@@ -3,6 +3,7 @@
 
 import sys
 import os
+from rpython.rlib import _rsocket_rffi as _c
 
 
 class Module(MixedModule):
@@ -31,6 +32,10 @@
         for symbol in symbol_map:
             interpleveldefs[symbol] = "space.wrap(interp_kqueue.%s)" % symbol
 
+    if _c.PIPE_BUF is not None:
+        interpleveldefs['PIPE_BUF'] = 'space.wrap(%r)' % _c.PIPE_BUF
+
+
     def buildloaders(cls):
         from rpython.rlib import rpoll
         for name in rpoll.eventnames:
diff --git a/pypy/module/select/test/test_select.py b/pypy/module/select/test/test_select.py
--- a/pypy/module/select/test/test_select.py
+++ b/pypy/module/select/test/test_select.py
@@ -319,6 +319,11 @@
         # ^^^ CPython gives 100, PyPy gives 1.  I think both are OK as
         # long as there is no crash.
 
+    def test_PIPE_BUF(self):
+        # no PIPE_BUF on Windows; this test class is skipped on Windows.
+        import select
+        assert isinstance(select.PIPE_BUF, int)
+
 
 class AppTestSelectWithSockets(_AppTestSelect):
     """Same tests with connected sockets.
diff --git a/pypy/module/test_lib_pypy/test_code_extra.py b/pypy/module/test_lib_pypy/test_code_extra.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/test_lib_pypy/test_code_extra.py
@@ -0,0 +1,19 @@
+import py
+import sys
+import cStringIO
+import code
+
+
+def test_flush_stdout_on_error():
+    runner = code.InteractiveInterpreter()
+    old_stdout = sys.stdout
+    try:
+        mystdout = cStringIO.StringIO()
+        sys.stdout = mystdout
+        runner.runcode(compile("print 5,;0/0", "<interactive>", "exec"))
+    finally:
+        sys.stdout = old_stdout
+
+    if '__pypy__' not in sys.builtin_module_names:
+        py.test.skip('pypy only test')
+    assert mystdout.getvalue() == "5\n"
diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py
--- a/pypy/objspace/std/test/test_unicodeobject.py
+++ b/pypy/objspace/std/test/test_unicodeobject.py
@@ -1164,3 +1164,31 @@
         assert u'A\u03a3\u0345'.lower() == u'a\u03c2\u0345'
         assert u'\u03a3\u0345 '.lower() == u'\u03c3\u0345 '
 
+    def test_unicode_constructor_misc(self):
+        x = u'foo'
+        x += u'bar'
+        assert unicode(x) is x
+        #
+        class U(unicode):
+            def __unicode__(self):
+                return u'BOK'
+        u = U(x)
+        assert unicode(u) == u'BOK'
+        #
+        class U2(unicode):
+            pass
+        z = U2(u'foobaz')
+        assert type(unicode(z)) is unicode
+        assert unicode(z) == u'foobaz'
+        #
+        # two completely corner cases where we differ from CPython:
+        #assert unicode(encoding='supposedly_the_encoding') == u''
+        #assert unicode(errors='supposedly_the_error') == u''
+        e = raises(TypeError, unicode, u'', 'supposedly_the_encoding')
+        assert str(e.value) == 'decoding Unicode is not supported'
+        e = raises(TypeError, unicode, u'', errors='supposedly_the_error')
+        assert str(e.value) == 'decoding Unicode is not supported'
+        e = raises(TypeError, unicode, u, 'supposedly_the_encoding')
+        assert str(e.value) == 'decoding Unicode is not supported'
+        e = raises(TypeError, unicode, z, 'supposedly_the_encoding')
+        assert str(e.value) == 'decoding Unicode is not supported'
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -122,7 +122,7 @@
 
     @staticmethod
     def convert_arg_to_w_unicode(space, w_other, strict=None):
-        if isinstance(w_other, W_UnicodeObject):
+        if space.is_w(space.type(w_other), space.w_unicode):
             return w_other
         if space.isinstance_w(w_other, space.w_bytes):
             raise oefmt(space.w_TypeError,
@@ -130,7 +130,7 @@
         if strict:
             raise oefmt(space.w_TypeError,
                 "%s arg must be None, unicode or str", strict)
-        return unicode_from_encoded_object(space, w_other, None, "strict")
+        return unicode_from_encoded_object(space, w_other, 'utf8', "strict")
 
     def convert_to_w_unicode(self, space):
         return self
diff --git a/rpython/doc/examples.rst b/rpython/doc/examples.rst
--- a/rpython/doc/examples.rst
+++ b/rpython/doc/examples.rst
@@ -19,7 +19,7 @@
   * Typhon, 'A virtual machine for Monte', in active development,
     https://github.com/monte-language/typhon
   * Tulip, an untyped functional language, in language design mode, maintained,
-     https://github.com/tulip-lang/tulip/
+    https://github.com/tulip-lang/tulip/
   * Pycket, a Racket implementation, proof of concept, small language core
     working, a lot of primitives are missing. Slow development 
     https://github.com/samth/pycket
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
@@ -33,6 +33,7 @@
                 'arpa/inet.h',
                 'stdint.h',
                 'errno.h',
+                'limits.h',
                 )
     if _HAS_AF_PACKET:
         includes += ('netpacket/packet.h',
@@ -113,6 +114,7 @@
     F_GETFL = platform.DefinedConstantInteger('F_GETFL')
     F_SETFL = platform.DefinedConstantInteger('F_SETFL')
     FIONBIO = platform.DefinedConstantInteger('FIONBIO')
+    PIPE_BUF = platform.DefinedConstantInteger('PIPE_BUF')
 
     INVALID_SOCKET = platform.DefinedConstantInteger('INVALID_SOCKET')
     INET_ADDRSTRLEN = platform.DefinedConstantInteger('INET_ADDRSTRLEN')
@@ -1085,6 +1087,7 @@
 WSAEWOULDBLOCK = cConfig.WSAEWOULDBLOCK or cConfig.EWOULDBLOCK
 WSAEAFNOSUPPORT = cConfig.WSAEAFNOSUPPORT or cConfig.EAFNOSUPPORT
 EISCONN = cConfig.EISCONN or cConfig.WSAEISCONN
+PIPE_BUF = cConfig.PIPE_BUF    # may be None
 
 linux = cConfig.linux
 WIN32 = cConfig.WIN32


More information about the pypy-commit mailing list