Author: Matti Picus <[email protected]> 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 _______________________________________________ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
