Author: Matti Picus <matti.pi...@gmail.com> Branch: py3.5 Changeset: r95037:c76008be29e5 Date: 2018-08-29 08:17 +0200 http://bitbucket.org/pypy/pypy/changeset/c76008be29e5/
Log: merge default into py3.5 diff --git a/pypy/module/cpyext/cdatetime.py b/pypy/module/cpyext/cdatetime.py --- a/pypy/module/cpyext/cdatetime.py +++ b/pypy/module/cpyext/cdatetime.py @@ -137,8 +137,9 @@ If it is a datetime.time or datetime.datetime, it may have tzinfo ''' state = space.fromcache(State) - # cannot raise here, so just crash - assert len(state.datetimeAPI) > 0 + if len(state.datetimeAPI) ==0: + # can happen in subclassing + _PyDateTime_Import(space) if state.datetimeAPI[0].c_TimeType == py_obj.c_ob_type: py_datetime = rffi.cast(PyDateTime_Time, py_obj) w_tzinfo = space.getattr(w_obj, space.newtext('tzinfo')) diff --git a/pypy/module/cpyext/include/pymath.h b/pypy/module/cpyext/include/pymath.h --- a/pypy/module/cpyext/include/pymath.h +++ b/pypy/module/cpyext/include/pymath.h @@ -6,6 +6,74 @@ functions and constants **************************************************************************/ +/* High precision definition of pi and e (Euler) + * The values are taken from libc6's math.h. + */ +#ifndef Py_MATH_PIl +#define Py_MATH_PIl 3.1415926535897932384626433832795029L +#endif +#ifndef Py_MATH_PI +#define Py_MATH_PI 3.14159265358979323846 +#endif + +#ifndef Py_MATH_El +#define Py_MATH_El 2.7182818284590452353602874713526625L +#endif + +#ifndef Py_MATH_E +#define Py_MATH_E 2.7182818284590452354 +#endif + +/* Tau (2pi) to 40 digits, taken from tauday.com/tau-digits. */ +#ifndef Py_MATH_TAU +#define Py_MATH_TAU 6.2831853071795864769252867665590057683943L +#endif + +/* Py_IS_NAN(X) + * Return 1 if float or double arg is a NaN, else 0. + * Caution: + * X is evaluated more than once. + * This may not work on all platforms. Each platform has *some* + * way to spell this, though -- override in pyconfig.h if you have + * a platform where it doesn't work. + */ +#ifndef Py_IS_NAN +#if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L +#define Py_IS_NAN(X) isnan(X) +#else +#define Py_IS_NAN(X) ((X) != (X)) +#endif +#endif + +/* Py_IS_INFINITY(X) + * Return 1 if float or double arg is an infinity, else 0. + * Caution: + * X is evaluated more than once. + * This implementation may set the underflow flag if |X| is very small; + * it really can't be implemented correctly (& easily) before C99. + * Override in pyconfig.h if you have a better spelling on your platform. + */ +#ifndef Py_IS_INFINITY +# if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L +# define Py_IS_INFINITY(X) isinf(X) +# else +# define Py_IS_INFINITY(X) ((X) && ((X)*0.5 == (X))) +# endif +#endif + +/* Py_IS_FINITE(X) + * Return 1 if float or double arg is neither infinite nor NAN, else 0. + * Some compilers (e.g. VisualStudio) have intrisics for this, so a special + * macro for this particular test is useful + */ +#ifndef Py_IS_FINITE +#if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L +#define Py_IS_FINITE(X) isfinite(X) +#else +#define Py_IS_FINITE(X) (!Py_IS_INFINITY(X) && !Py_IS_NAN(X)) +#endif +#endif + /* HUGE_VAL is supposed to expand to a positive double infinity. Python * uses Py_HUGE_VAL instead because some platforms are broken in this * respect. We used to embed code in pyport.h to try to worm around that, diff --git a/pypy/module/cpyext/test/test_floatobject.py b/pypy/module/cpyext/test/test_floatobject.py deleted file mode 100644 --- a/pypy/module/cpyext/test/test_floatobject.py +++ /dev/null @@ -1,112 +0,0 @@ -import pytest -from pypy.interpreter.error import OperationError -from pypy.module.cpyext.test.test_api import BaseApiTest -from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase -from rpython.rtyper.lltypesystem import rffi -from pypy.module.cpyext.floatobject import ( - PyFloat_FromDouble, PyFloat_AsDouble, PyFloat_AS_DOUBLE, PyNumber_Float, - _PyFloat_Unpack4, _PyFloat_Unpack8) - -class TestFloatObject(BaseApiTest): - def test_floatobject(self, space): - assert space.unwrap(PyFloat_FromDouble(space, 3.14)) == 3.14 - assert PyFloat_AsDouble(space, space.wrap(23.45)) == 23.45 - assert PyFloat_AS_DOUBLE(space, space.wrap(23.45)) == 23.45 - with pytest.raises(OperationError): - PyFloat_AsDouble(space, space.w_None) - - def test_coerce(self, space): - assert space.type(PyNumber_Float(space, space.wrap(3))) is space.w_float - assert space.type(PyNumber_Float(space, space.wrap("3"))) is space.w_float - - w_obj = space.appexec([], """(): - class Coerce(object): - def __float__(self): - return 42.5 - return Coerce()""") - assert space.eq_w(PyNumber_Float(space, w_obj), space.wrap(42.5)) - - def test_unpack(self, space): - with rffi.scoped_str2charp("\x9a\x99\x99?") as ptr: - assert abs(_PyFloat_Unpack4(space, ptr, 1) - 1.2) < 1e-7 - with rffi.scoped_str2charp("?\x99\x99\x9a") as ptr: - assert abs(_PyFloat_Unpack4(space, ptr, 0) - 1.2) < 1e-7 - with rffi.scoped_str2charp("\x1f\x85\xebQ\xb8\x1e\t@") as ptr: - assert abs(_PyFloat_Unpack8(space, ptr, 1) - 3.14) < 1e-15 - with rffi.scoped_str2charp("@\t\x1e\xb8Q\xeb\x85\x1f") as ptr: - assert abs(_PyFloat_Unpack8(space, ptr, 0) - 3.14) < 1e-15 - -class AppTestFloatObject(AppTestCpythonExtensionBase): - def test_fromstring(self): - module = self.import_extension('foo', [ - ("from_string", "METH_NOARGS", - """ - PyObject* str = PyUnicode_FromString("1234.56"); - PyObject* res = PyFloat_FromString(str); - Py_DECREF(str); - return res; - """), - ]) - assert module.from_string() == 1234.56 - assert type(module.from_string()) is float - -class AppTestFloatMacros(AppTestCpythonExtensionBase): - def test_return_nan(self): - import math - - module = self.import_extension('foo', [ - ("return_nan", "METH_NOARGS", - "Py_RETURN_NAN;"), - ]) - assert math.isnan(module.return_nan()) - - def test_return_inf(self): - import math - - module = self.import_extension('foo', [ - ("return_inf", "METH_NOARGS", - "Py_RETURN_INF(10);"), - ]) - inf = module.return_inf() - assert inf > 0 - assert math.isinf(inf) - - def test_return_inf_negative(self): - import math - - module = self.import_extension('foo', [ - ("return_neginf", "METH_NOARGS", - "Py_RETURN_INF(-10);"), - ]) - neginf = module.return_neginf() - assert neginf < 0 - assert math.isinf(neginf) - - def test_macro_accepts_wrong_pointer_type(self): - module = self.import_extension('foo', [ - ("test_macros", "METH_NOARGS", - """ - PyObject* o = PyFloat_FromDouble(1.0); - // no PyFloatObject - char* dumb_pointer = (char*)o; - - PyFloat_AS_DOUBLE(o); - PyFloat_AS_DOUBLE(dumb_pointer); - - Py_RETURN_NONE;"""), - ]) - - def test_PyFloat_Check(self): - module = self.import_extension('foo', [ - ("test", "METH_NOARGS", - """ - PyObject* pyobj = PyFloat_FromDouble(1.0); - PyFloatObject* pfo = (PyFloatObject*)pyobj; - int res = (PyFloat_Check(pyobj) + - PyFloat_CheckExact(pyobj) * 10 + - PyFloat_Check(pfo) * 100 + - PyFloat_CheckExact(pfo) * 1000); - Py_DecRef(pyobj); - return PyLong_FromLong(res);"""), - ]) - assert module.test() == 1111 diff --git a/pypy/module/cpyext/test0/__init__.py b/pypy/module/cpyext/test0/__init__.py new file mode 100644 diff --git a/pypy/module/cpyext/test/conftest.py b/pypy/module/cpyext/test0/conftest.py copy from pypy/module/cpyext/test/conftest.py copy to pypy/module/cpyext/test0/conftest.py 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/test/test_arraymodule.py b/pypy/module/cpyext/test0/test_arraymodule.py rename from pypy/module/cpyext/test/test_arraymodule.py rename to pypy/module/cpyext/test0/test_arraymodule.py diff --git a/pypy/module/cpyext/test/test_boolobject.py b/pypy/module/cpyext/test0/test_boolobject.py rename from pypy/module/cpyext/test/test_boolobject.py rename to pypy/module/cpyext/test0/test_boolobject.py diff --git a/pypy/module/cpyext/test/test_borrow.py b/pypy/module/cpyext/test0/test_borrow.py rename from pypy/module/cpyext/test/test_borrow.py rename to pypy/module/cpyext/test0/test_borrow.py 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/test/test_bytearrayobject.py b/pypy/module/cpyext/test0/test_bytearrayobject.py rename from pypy/module/cpyext/test/test_bytearrayobject.py rename to pypy/module/cpyext/test0/test_bytearrayobject.py diff --git a/pypy/module/cpyext/test/test_bytesobject.py b/pypy/module/cpyext/test0/test_bytesobject.py rename from pypy/module/cpyext/test/test_bytesobject.py rename to pypy/module/cpyext/test0/test_bytesobject.py diff --git a/pypy/module/cpyext/test/test_capsule.py b/pypy/module/cpyext/test0/test_capsule.py rename from pypy/module/cpyext/test/test_capsule.py rename to pypy/module/cpyext/test0/test_capsule.py diff --git a/pypy/module/cpyext/test/test_cell.py b/pypy/module/cpyext/test0/test_cell.py rename from pypy/module/cpyext/test/test_cell.py rename to pypy/module/cpyext/test0/test_cell.py diff --git a/pypy/module/cpyext/test/test_classobject.py b/pypy/module/cpyext/test0/test_classobject.py rename from pypy/module/cpyext/test/test_classobject.py rename to pypy/module/cpyext/test0/test_classobject.py diff --git a/pypy/module/cpyext/test/test_codecs.py b/pypy/module/cpyext/test0/test_codecs.py rename from pypy/module/cpyext/test/test_codecs.py rename to pypy/module/cpyext/test0/test_codecs.py diff --git a/pypy/module/cpyext/test/test_complexobject.py b/pypy/module/cpyext/test0/test_complexobject.py rename from pypy/module/cpyext/test/test_complexobject.py rename to pypy/module/cpyext/test0/test_complexobject.py diff --git a/pypy/module/cpyext/test/test_cparser.py b/pypy/module/cpyext/test0/test_cparser.py rename from pypy/module/cpyext/test/test_cparser.py rename to pypy/module/cpyext/test0/test_cparser.py diff --git a/pypy/module/cpyext/test/test_datetime.py b/pypy/module/cpyext/test0/test_datetime.py rename from pypy/module/cpyext/test/test_datetime.py rename to pypy/module/cpyext/test0/test_datetime.py diff --git a/pypy/module/cpyext/test/test_dictobject.py b/pypy/module/cpyext/test0/test_dictobject.py rename from pypy/module/cpyext/test/test_dictobject.py rename to pypy/module/cpyext/test0/test_dictobject.py diff --git a/pypy/module/cpyext/test/test_eval.py b/pypy/module/cpyext/test0/test_eval.py rename from pypy/module/cpyext/test/test_eval.py rename to pypy/module/cpyext/test0/test_eval.py diff --git a/pypy/module/cpyext/test/test_fileobject.py b/pypy/module/cpyext/test0/test_fileobject.py rename from pypy/module/cpyext/test/test_fileobject.py rename to pypy/module/cpyext/test0/test_fileobject.py diff --git a/pypy/module/cpyext/test0/test_floatobject.py b/pypy/module/cpyext/test0/test_floatobject.py new file mode 100644 --- /dev/null +++ b/pypy/module/cpyext/test0/test_floatobject.py @@ -0,0 +1,196 @@ +import pytest +from pypy.interpreter.error import OperationError +from pypy.module.cpyext.test.test_api import BaseApiTest +from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase +from rpython.rtyper.lltypesystem import rffi +from pypy.module.cpyext.floatobject import ( + PyFloat_FromDouble, PyFloat_AsDouble, PyFloat_AS_DOUBLE, PyNumber_Float, + _PyFloat_Unpack4, _PyFloat_Unpack8) + +class TestFloatObject(BaseApiTest): + def test_floatobject(self, space): + assert space.unwrap(PyFloat_FromDouble(space, 3.14)) == 3.14 + assert PyFloat_AsDouble(space, space.wrap(23.45)) == 23.45 + assert PyFloat_AS_DOUBLE(space, space.wrap(23.45)) == 23.45 + with pytest.raises(OperationError): + PyFloat_AsDouble(space, space.w_None) + + def test_coerce(self, space): + assert space.type(PyNumber_Float(space, space.wrap(3))) is space.w_float + assert space.type(PyNumber_Float(space, space.wrap("3"))) is space.w_float + + w_obj = space.appexec([], """(): + class Coerce(object): + def __float__(self): + return 42.5 + return Coerce()""") + assert space.eq_w(PyNumber_Float(space, w_obj), space.wrap(42.5)) + + def test_unpack(self, space): + with rffi.scoped_str2charp("\x9a\x99\x99?") as ptr: + assert abs(_PyFloat_Unpack4(space, ptr, 1) - 1.2) < 1e-7 + with rffi.scoped_str2charp("?\x99\x99\x9a") as ptr: + assert abs(_PyFloat_Unpack4(space, ptr, 0) - 1.2) < 1e-7 + with rffi.scoped_str2charp("\x1f\x85\xebQ\xb8\x1e\t@") as ptr: + assert abs(_PyFloat_Unpack8(space, ptr, 1) - 3.14) < 1e-15 + with rffi.scoped_str2charp("@\t\x1e\xb8Q\xeb\x85\x1f") as ptr: + assert abs(_PyFloat_Unpack8(space, ptr, 0) - 3.14) < 1e-15 + +class AppTestFloatObject(AppTestCpythonExtensionBase): + def test_fromstring(self): + module = self.import_extension('foo', [ + ("from_string", "METH_NOARGS", + """ + PyObject* str = PyUnicode_FromString("1234.56"); + PyObject* res = PyFloat_FromString(str); + Py_DECREF(str); + return res; + """), + ]) + assert module.from_string() == 1234.56 + assert type(module.from_string()) is float + +class AppTestFloatMacros(AppTestCpythonExtensionBase): + def test_return_nan(self): + import math + + module = self.import_extension('foo', [ + ("return_nan", "METH_NOARGS", + "Py_RETURN_NAN;"), + ]) + assert math.isnan(module.return_nan()) + + def test_return_inf(self): + import math + + module = self.import_extension('foo', [ + ("return_inf", "METH_NOARGS", + "Py_RETURN_INF(10);"), + ]) + inf = module.return_inf() + assert inf > 0 + assert math.isinf(inf) + + def test_return_inf_negative(self): + import math + + module = self.import_extension('foo', [ + ("return_neginf", "METH_NOARGS", + "Py_RETURN_INF(-10);"), + ]) + neginf = module.return_neginf() + assert neginf < 0 + assert math.isinf(neginf) + + def test_macro_accepts_wrong_pointer_type(self): + module = self.import_extension('foo', [ + ("test_macros", "METH_NOARGS", + """ + PyObject* o = PyFloat_FromDouble(1.0); + // no PyFloatObject + char* dumb_pointer = (char*)o; + + PyFloat_AS_DOUBLE(o); + PyFloat_AS_DOUBLE(dumb_pointer); + + Py_RETURN_NONE;"""), + ]) + + def test_PyFloat_Check(self): + module = self.import_extension('foo', [ + ("test", "METH_NOARGS", + """ + PyObject* pyobj = PyFloat_FromDouble(1.0); + PyFloatObject* pfo = (PyFloatObject*)pyobj; + int res = (PyFloat_Check(pyobj) + + PyFloat_CheckExact(pyobj) * 10 + + PyFloat_Check(pfo) * 100 + + PyFloat_CheckExact(pfo) * 1000); + Py_DecRef(pyobj); + return PyLong_FromLong(res);"""), + ]) + assert module.test() == 1111 + + def test_pymath_consts(self): + # test preprocessor constants in their string form to avoid + # floating-point conversion issues (and to avoid having to + # conditionalize on compiler support for long double) + for const_name, const_strval in [ + ('Py_MATH_PIl', "3.1415926535897932384626433832795029L"), + ('Py_MATH_PI', "3.14159265358979323846"), + ('Py_MATH_El', "2.7182818284590452353602874713526625L"), + ('Py_MATH_E', "2.7182818284590452354"), + ('Py_MATH_TAU', "6.2831853071795864769252867665590057683943L"), + ]: + module = self.import_extension('foo_%s' % const_name, [ + ("test", "METH_NOARGS", + """ + #define xstr(s) str(s) + #define str(s) #s + return PyString_FromString(xstr(%s));""" % const_name) + ]) + assert module.test() == const_strval + + def test_Py_IS_NAN(self): + module = self.import_extension('foo', [ + ("test", "METH_O", + """ + double d = PyFloat_AsDouble(args); + return PyBool_FromLong(Py_IS_NAN(d)); + """), + ]) + assert not module.test(0) + assert not module.test(1) + assert not module.test(-1) + assert not module.test(float('inf')) + assert module.test(float('nan')) + + def test_Py_IS_INFINITY(self): + module = self.import_extension('foo', [ + ("test", "METH_O", + """ + double d = PyFloat_AsDouble(args); + return PyBool_FromLong(Py_IS_INFINITY(d)); + """), + ]) + assert not module.test(0) + assert not module.test(1) + assert not module.test(-1) + assert not module.test(float('nan')) + assert module.test(float('inf')) + assert module.test(float('-inf')) + + def test_Py_IS_FINITE(self): + module = self.import_extension('foo', [ + ("test", "METH_O", + """ + double d = PyFloat_AsDouble(args); + return PyBool_FromLong(Py_IS_FINITE(d)); + """), + ]) + assert module.test(0) + assert module.test(1) + assert module.test(-1) + assert not module.test(float('nan')) + assert not module.test(float('inf')) + assert not module.test(float('-inf')) + + def test_Py_HUGE_VAL(self): + module = self.import_extension('foo', [ + ("test", "METH_NOARGS", + """ + return PyFloat_FromDouble(Py_HUGE_VAL); + """), + ]) + assert module.test() == float('inf') + + def test_Py_NAN(self): + module = self.import_extension('foo', [ + ("test", "METH_NOARGS", + """ + return PyFloat_FromDouble(Py_NAN); + """), + ]) + import struct + float_bits = struct.Struct('d').pack + assert float_bits(module.test()) == float_bits(float('nan')) diff --git a/pypy/module/cpyext/test/test_frameobject.py b/pypy/module/cpyext/test0/test_frameobject.py rename from pypy/module/cpyext/test/test_frameobject.py rename to pypy/module/cpyext/test0/test_frameobject.py diff --git a/pypy/module/cpyext/test/test_funcobject.py b/pypy/module/cpyext/test0/test_funcobject.py rename from pypy/module/cpyext/test/test_funcobject.py rename to pypy/module/cpyext/test0/test_funcobject.py diff --git a/pypy/module/cpyext/test/test_genobject.py b/pypy/module/cpyext/test0/test_genobject.py rename from pypy/module/cpyext/test/test_genobject.py rename to pypy/module/cpyext/test0/test_genobject.py diff --git a/pypy/module/cpyext/test/test_getargs.py b/pypy/module/cpyext/test0/test_getargs.py rename from pypy/module/cpyext/test/test_getargs.py rename to pypy/module/cpyext/test0/test_getargs.py diff --git a/pypy/module/cpyext/test/test_import.py b/pypy/module/cpyext/test0/test_import.py rename from pypy/module/cpyext/test/test_import.py rename to pypy/module/cpyext/test0/test_import.py 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/cpyext/test/test_iterator.py b/pypy/module/cpyext/test0/test_iterator.py rename from pypy/module/cpyext/test/test_iterator.py rename to pypy/module/cpyext/test0/test_iterator.py diff --git a/pypy/module/cpyext/test/test_listobject.py b/pypy/module/cpyext/test0/test_listobject.py rename from pypy/module/cpyext/test/test_listobject.py rename to pypy/module/cpyext/test0/test_listobject.py diff --git a/pypy/module/cpyext/test/test_longobject.py b/pypy/module/cpyext/test0/test_longobject.py rename from pypy/module/cpyext/test/test_longobject.py rename to pypy/module/cpyext/test0/test_longobject.py diff --git a/pypy/module/cpyext/test/test_mapping.py b/pypy/module/cpyext/test0/test_mapping.py rename from pypy/module/cpyext/test/test_mapping.py rename to pypy/module/cpyext/test0/test_mapping.py diff --git a/pypy/module/cpyext/test/test_marshal.py b/pypy/module/cpyext/test0/test_marshal.py rename from pypy/module/cpyext/test/test_marshal.py rename to pypy/module/cpyext/test0/test_marshal.py diff --git a/pypy/module/cpyext/test/test_memoryobject.py b/pypy/module/cpyext/test0/test_memoryobject.py rename from pypy/module/cpyext/test/test_memoryobject.py rename to pypy/module/cpyext/test0/test_memoryobject.py diff --git a/pypy/module/cpyext/test/test_methodobject.py b/pypy/module/cpyext/test0/test_methodobject.py rename from pypy/module/cpyext/test/test_methodobject.py rename to pypy/module/cpyext/test0/test_methodobject.py diff --git a/pypy/module/cpyext/test/test_module.py b/pypy/module/cpyext/test0/test_module.py rename from pypy/module/cpyext/test/test_module.py rename to pypy/module/cpyext/test0/test_module.py diff --git a/pypy/module/cpyext/test/test_ndarrayobject.py b/pypy/module/cpyext/test0/test_ndarrayobject.py rename from pypy/module/cpyext/test/test_ndarrayobject.py rename to pypy/module/cpyext/test0/test_ndarrayobject.py diff --git a/pypy/module/cpyext/test/test_number.py b/pypy/module/cpyext/test0/test_number.py rename from pypy/module/cpyext/test/test_number.py rename to pypy/module/cpyext/test0/test_number.py diff --git a/pypy/module/cpyext/test1/__init__.py b/pypy/module/cpyext/test1/__init__.py new file mode 100644 diff --git a/pypy/module/cpyext/test/conftest.py b/pypy/module/cpyext/test1/conftest.py copy from pypy/module/cpyext/test/conftest.py copy to pypy/module/cpyext/test1/conftest.py diff --git a/pypy/module/cpyext/test/test_object.py b/pypy/module/cpyext/test1/test_object.py rename from pypy/module/cpyext/test/test_object.py rename to pypy/module/cpyext/test1/test_object.py diff --git a/pypy/module/cpyext/test1/test_pycobject.py b/pypy/module/cpyext/test1/test_pycobject.py new file mode 100644 --- /dev/null +++ b/pypy/module/cpyext/test1/test_pycobject.py @@ -0,0 +1,30 @@ +import py +from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase + +class AppTestStringObject(AppTestCpythonExtensionBase): + def test_pycobject_import(self): + module = self.import_extension('foo', [ + ("set_ptr", "METH_O", + """ + PyObject *pointer, *module; + void *ptr = PyLong_AsVoidPtr(args); + if (PyErr_Occurred()) return NULL; + pointer = PyCObject_FromVoidPtr(ptr, NULL); + if (PyErr_Occurred()) return NULL; + module = PyImport_ImportModule("foo"); + PyModule_AddObject(module, "_ptr", pointer); + Py_DECREF(module); + if (PyErr_Occurred()) return NULL; + Py_RETURN_NONE; + """), + ("get_ptr", "METH_NOARGS", + """ + void *ptr = PyCObject_Import("foo", "_ptr"); + if (PyErr_Occurred()) return NULL; + return PyLong_FromVoidPtr(ptr); + """)]) + module.set_ptr(1234) + assert "PyCObject object" in str(module._ptr) + import gc; gc.collect() + assert module.get_ptr() == 1234 + del module._ptr diff --git a/pypy/module/cpyext/test/test_pyerrors.py b/pypy/module/cpyext/test1/test_pyerrors.py rename from pypy/module/cpyext/test/test_pyerrors.py rename to pypy/module/cpyext/test1/test_pyerrors.py diff --git a/pypy/module/cpyext/test/test_pyfile.py b/pypy/module/cpyext/test1/test_pyfile.py rename from pypy/module/cpyext/test/test_pyfile.py rename to pypy/module/cpyext/test1/test_pyfile.py diff --git a/pypy/module/cpyext/test/test_pysignals.py b/pypy/module/cpyext/test1/test_pysignals.py rename from pypy/module/cpyext/test/test_pysignals.py rename to pypy/module/cpyext/test1/test_pysignals.py diff --git a/pypy/module/cpyext/test/test_pystate.py b/pypy/module/cpyext/test1/test_pystate.py rename from pypy/module/cpyext/test/test_pystate.py rename to pypy/module/cpyext/test1/test_pystate.py diff --git a/pypy/module/cpyext/test/test_pystrtod.py b/pypy/module/cpyext/test1/test_pystrtod.py rename from pypy/module/cpyext/test/test_pystrtod.py rename to pypy/module/cpyext/test1/test_pystrtod.py diff --git a/pypy/module/cpyext/test/test_sequence.py b/pypy/module/cpyext/test1/test_sequence.py rename from pypy/module/cpyext/test/test_sequence.py rename to pypy/module/cpyext/test1/test_sequence.py diff --git a/pypy/module/cpyext/test/test_setobject.py b/pypy/module/cpyext/test1/test_setobject.py rename from pypy/module/cpyext/test/test_setobject.py rename to pypy/module/cpyext/test1/test_setobject.py diff --git a/pypy/module/cpyext/test/test_sliceobject.py b/pypy/module/cpyext/test1/test_sliceobject.py rename from pypy/module/cpyext/test/test_sliceobject.py rename to pypy/module/cpyext/test1/test_sliceobject.py diff --git a/pypy/module/cpyext/test/test_structseq.py b/pypy/module/cpyext/test1/test_structseq.py rename from pypy/module/cpyext/test/test_structseq.py rename to pypy/module/cpyext/test1/test_structseq.py diff --git a/pypy/module/cpyext/test/test_sysmodule.py b/pypy/module/cpyext/test1/test_sysmodule.py rename from pypy/module/cpyext/test/test_sysmodule.py rename to pypy/module/cpyext/test1/test_sysmodule.py diff --git a/pypy/module/cpyext/test/test_thread.py b/pypy/module/cpyext/test1/test_thread.py rename from pypy/module/cpyext/test/test_thread.py rename to pypy/module/cpyext/test1/test_thread.py diff --git a/pypy/module/cpyext/test/test_traceback.py b/pypy/module/cpyext/test1/test_traceback.py rename from pypy/module/cpyext/test/test_traceback.py rename to pypy/module/cpyext/test1/test_traceback.py diff --git a/pypy/module/cpyext/test/test_translate.py b/pypy/module/cpyext/test1/test_translate.py rename from pypy/module/cpyext/test/test_translate.py rename to pypy/module/cpyext/test1/test_translate.py diff --git a/pypy/module/cpyext/test/test_tupleobject.py b/pypy/module/cpyext/test1/test_tupleobject.py rename from pypy/module/cpyext/test/test_tupleobject.py rename to pypy/module/cpyext/test1/test_tupleobject.py diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test1/test_typeobject.py rename from pypy/module/cpyext/test/test_typeobject.py rename to pypy/module/cpyext/test1/test_typeobject.py diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test1/test_unicodeobject.py rename from pypy/module/cpyext/test/test_unicodeobject.py rename to pypy/module/cpyext/test1/test_unicodeobject.py diff --git a/pypy/module/cpyext/test/test_userslots.py b/pypy/module/cpyext/test1/test_userslots.py rename from pypy/module/cpyext/test/test_userslots.py rename to pypy/module/cpyext/test1/test_userslots.py diff --git a/pypy/module/cpyext/test/test_version.py b/pypy/module/cpyext/test1/test_version.py rename from pypy/module/cpyext/test/test_version.py rename to pypy/module/cpyext/test1/test_version.py diff --git a/pypy/module/cpyext/test/test_weakref.py b/pypy/module/cpyext/test1/test_weakref.py rename from pypy/module/cpyext/test/test_weakref.py rename to pypy/module/cpyext/test1/test_weakref.py diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py --- a/pypy/module/imp/importing.py +++ b/pypy/module/imp/importing.py @@ -85,6 +85,8 @@ w_mod = check_sys_modules_w(space, modulename) if w_mod: + if parts[-1] == '': + del parts[-1] return w_mod lock = getimportlock(space) try: diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py --- a/pypy/module/imp/test/test_import.py +++ b/pypy/module/imp/test/test_import.py @@ -302,6 +302,13 @@ assert ambig == sys.modules.get('ambig') assert hasattr(ambig,'imapackage') + def test_trailing_dot(self): + # bug-for-bug compatibility with CPython + import sys + __import__('pkg.pkg1.') + assert 'pkg.pkg1' in sys.modules + assert 'pkg.pkg1.' not in sys.modules + def test_from_a(self): import sys from a import imamodule @@ -709,7 +716,6 @@ exec("from pkg.withoutall import *", d) assert "" in d - def test_import_star_with_bogus___all__(self): for case in ["not-imported-yet", "already-imported"]: try: diff --git a/pypy/module/micronumpy/concrete.py b/pypy/module/micronumpy/concrete.py --- a/pypy/module/micronumpy/concrete.py +++ b/pypy/module/micronumpy/concrete.py @@ -388,7 +388,7 @@ not self.flags & NPY.ARRAY_F_CONTIGUOUS): raise oefmt(errtype, "ndarray is not Fortran contiguous") if ((flags & space.BUF_ANY_CONTIGUOUS) == space.BUF_ANY_CONTIGUOUS and - not (self.flags & NPY.ARRAY_F_CONTIGUOUS and + not (self.flags & NPY.ARRAY_F_CONTIGUOUS or self.flags & NPY.ARRAY_C_CONTIGUOUS)): raise oefmt(errtype, "ndarray is not contiguous") if ((flags & space.BUF_STRIDES) != space.BUF_STRIDES and diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -874,11 +874,11 @@ if traits.str is unicode: if path and path[-1] not in (u'/', u'\\', u':'): - path += u'/' + path += u'\\' mask = path + u'*.*' else: if path and path[-1] not in ('/', '\\', ':'): - path += '/' + path += '\\' mask = path + '*.*' filedata = lltype.malloc(win32traits.WIN32_FIND_DATA, flavor='raw') _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit