Author: Matti Picus <[email protected]>
Branch: unicode-utf8-py3
Changeset: r95110:0e9637ca2d97
Date: 2018-09-12 15:02 +0300
http://bitbucket.org/pypy/pypy/changeset/0e9637ca2d97/
Log: merge py3.5 into branch
diff too long, truncating to 2000 out of 23978 lines
diff --git a/pypy/module/cpyext/test/test_arraymodule.py
b/pypy/module/cpyext/test/test_arraymodule.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_arraymodule.py
@@ -0,0 +1,190 @@
+import pytest
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.conftest import option
+
+class AppTestArrayModule(AppTestCpythonExtensionBase):
+ enable_leak_checking = True
+
+ def test_basic(self):
+ module = self.import_module(name='array')
+ arr = module.array('i', [1,2,3])
+ assert arr.typecode == 'i'
+ assert arr.itemsize == 4
+ assert arr[2] == 3
+ assert len(arr.buffer_info()) == 2
+ exc = raises(TypeError, module.array.append)
+ errstr = str(exc.value)
+ assert errstr.startswith("descriptor 'append' of")
+ arr.append(4)
+ assert arr.tolist() == [1, 2, 3, 4]
+ assert len(arr) == 4
+
+ def test_iter(self):
+ module = self.import_module(name='array')
+ arr = module.array('i', [1,2,3])
+ sum = 0
+ for i in arr:
+ sum += i
+ assert sum == 6
+
+ def test_index(self):
+ module = self.import_module(name='array')
+ arr = module.array('i', [1, 2, 3, 4])
+ assert arr[3] == 4
+ raises(IndexError, arr.__getitem__, 10)
+ del arr[2]
+ assert arr.tolist() == [1, 2, 4]
+ arr[2] = 99
+ assert arr.tolist() == [1, 2, 99]
+
+ def test_slice_get(self):
+ module = self.import_module(name='array')
+ arr = module.array('i', [1, 2, 3, 4])
+ assert arr[:].tolist() == [1, 2, 3, 4]
+ assert arr[1:].tolist() == [2, 3, 4]
+ assert arr[:2].tolist() == [1, 2]
+ assert arr[1:3].tolist() == [2, 3]
+
+ def test_slice_object(self):
+ module = self.import_module(name='array')
+ arr = module.array('i', [1, 2, 3, 4])
+ assert arr[slice(1, 3)].tolist() == [2,3]
+ arr[slice(1, 3)] = module.array('i', [21, 22, 23])
+ assert arr.tolist() == [1, 21, 22, 23, 4]
+ del arr[slice(1, 3)]
+ assert arr.tolist() == [1, 23, 4]
+ raises(TypeError, 'arr[slice(1, 3)] = "abc"')
+
+ def test_buffer(self):
+ import sys
+ module = self.import_module(name='array')
+ arr = module.array('i', [1, 2, 3, 4])
+ buf = memoryview(arr)
+ exc = raises(TypeError, "buf[1] = 1")
+ assert str(exc.value) == "cannot modify read-only memory"
+ if sys.byteorder == 'big':
+ expected = b'\0\0\0\x01\0\0\0\x02\0\0\0\x03\0\0\0\x04'
+ else:
+ expected = b'\x01\0\0\0\x02\0\0\0\x03\0\0\0\x04\0\0\0'
+ assert bytes(buf) == expected
+
+ def test_releasebuffer(self):
+ module = self.import_module(name='array')
+ arr = module.array('i', [1,2,3,4])
+ assert module.get_releasebuffer_cnt() == 0
+ module.create_and_release_buffer(arr)
+ assert module.get_releasebuffer_cnt() == 1
+
+ def test_Py_buffer(self):
+ module = self.import_module(name='array')
+ arr = module.array('i', [1,2,3,4])
+ assert module.get_releasebuffer_cnt() == 0
+ m = memoryview(arr)
+ assert module.get_releasebuffer_cnt() == 0
+ del m
+ self.debug_collect()
+ assert module.get_releasebuffer_cnt() == 1
+
+ def test_0d_view(self):
+ module = self.import_module(name='array')
+ arr = module.array('B', b'\0\0\0\x01')
+ buf = memoryview(arr).cast('i', shape=())
+ assert bytes(buf) == b'\0\0\0\x01'
+ assert buf.shape == ()
+ assert buf.strides == ()
+
+ def test_binop_mul_impl(self):
+ # check that rmul is called
+ module = self.import_module(name='array')
+ arr = module.array('i', [2])
+ res = [1, 2, 3] * arr
+ assert res == [1, 2, 3, 1, 2, 3]
+ module.switch_multiply()
+ res = [1, 2, 3] * arr
+ assert res == [2, 4, 6]
+
+ @pytest.mark.xfail
+ def test_subclass_dealloc(self):
+ module = self.import_module(name='array')
+ class Sub(module.array):
+ pass
+
+ arr = Sub('i', [2])
+ module.readbuffer_as_string(arr)
+ class A(object):
+ pass
+ assert not module.same_dealloc(arr, module.array('i', [2]))
+ assert module.same_dealloc(arr, A())
+
+ def test_string_buf(self):
+ module = self.import_module(name='array')
+ arr = module.array('u', '123')
+ view = memoryview(arr)
+ assert view.itemsize == 4
+ assert module.write_buffer_len(arr) == 12
+ assert len(module.readbuffer_as_string(arr)) == 12
+ assert len(module.readbuffer_as_string(view)) == 12
+
+ def test_subclass(self):
+ import struct
+ module = self.import_module(name='array')
+ class Sub(module.array):
+ pass
+
+ arr = Sub('i', [2])
+ res = [1, 2, 3] * arr
+ assert res == [1, 2, 3, 1, 2, 3]
+
+ val = module.readbuffer_as_string(arr)
+ assert val == struct.pack('i', 2)
+
+ def test_unicode_readbuffer(self):
+ # Not really part of array, refactor
+ import struct
+ module = self.import_module(name='array')
+ val = module.readbuffer_as_string(b'abcd')
+ assert val == b'abcd'
+
+ def test_readinto(self):
+ module = self.import_module(name='array')
+ a = module.array('B')
+ a.fromstring(b'0123456789')
+ filename = self.udir + "/_test_file"
+ f = open(filename, 'w+b')
+ f.write(b'foobar')
+ f.seek(0)
+ n = f.readinto(a)
+ f.close()
+ assert n == 6
+ assert len(a) == 10
+ assert a.tostring() == b'foobar6789'
+
+ def test_iowrite(self):
+ module = self.import_module(name='array')
+ from io import BytesIO
+ a = module.array('B')
+ a.fromstring(b'0123456789')
+ fd = BytesIO()
+ # only test that it works
+ fd.write(a)
+
+ def test_getitem_via_PySequence_GetItem(self):
+ module = self.import_module(name='array')
+ a = module.array('i', range(10))
+ # call via tp_as_mapping.mp_subscript
+ assert 5 == a[-5]
+ # PySequence_ITEM used to call space.getitem() which
+ # prefers tp_as_mapping.mp_subscript over tp_as_sequence.sq_item
+ # Now fixed so this test raises (array_item does not add len(a),
+ # array_subscr does)
+ raises(IndexError, module.getitem, a, -5)
+
+ def test_subclass_with_attribute(self):
+ module = self.import_module(name='array')
+ class Sub(module.array):
+ def addattrib(self):
+ print('called addattrib')
+ self.attrib = True
+ import gc
+ module.subclass_with_attribute(Sub, "addattrib", "attrib", gc.collect)
+ assert Sub.__module__ == __name__
diff --git a/pypy/module/cpyext/test/test_boolobject.py
b/pypy/module/cpyext/test/test_boolobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_boolobject.py
@@ -0,0 +1,48 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.boolobject import PyBool_FromLong
+
+class TestBoolObject(BaseApiTest):
+ def test_fromlong(self, space):
+ for i in range(-3, 3):
+ obj = PyBool_FromLong(space, i)
+ if i:
+ assert obj is space.w_True
+ else:
+ assert obj is space.w_False
+
+class AppTestBoolMacros(AppTestCpythonExtensionBase):
+ def test_macros(self):
+ module = self.import_extension('foo', [
+ ("get_true", "METH_NOARGS", "Py_RETURN_TRUE;"),
+ ("get_false", "METH_NOARGS", "Py_RETURN_FALSE;"),
+ ])
+ assert module.get_true() == True
+ assert module.get_false() == False
+
+ def test_toint(self):
+ module = self.import_extension('foo', [
+ ("to_int", "METH_O",
+ '''
+ if (args->ob_type->tp_as_number &&
args->ob_type->tp_as_number->nb_int) {
+ return args->ob_type->tp_as_number->nb_int(args);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,"cannot convert bool to
int");
+ return NULL;
+ }
+ '''), ])
+ assert module.to_int(False) == 0
+ assert module.to_int(True) == 1
+
+ def test_check(self):
+ module = self.import_extension('foo', [
+ ("type_check", "METH_O",
+ '''
+ return PyLong_FromLong(PyBool_Check(args));
+ ''')])
+ assert module.type_check(True)
+ assert module.type_check(False)
+ assert not module.type_check(None)
+ assert not module.type_check(1.0)
+
diff --git a/pypy/module/cpyext/test/test_borrow.py
b/pypy/module/cpyext/test/test_borrow.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_borrow.py
@@ -0,0 +1,69 @@
+import py
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.pyobject import make_ref
+
+
+class AppTestBorrow(AppTestCpythonExtensionBase):
+ def test_tuple_borrowing(self):
+ module = self.import_extension('foo', [
+ ("test_borrowing", "METH_NOARGS",
+ """
+ PyObject *t = PyTuple_New(1);
+ PyObject *f = PyFloat_FromDouble(42.0);
+ PyObject *g = NULL;
+ printf("Refcnt1: %ld\\n", f->ob_refcnt);
+ PyTuple_SetItem(t, 0, f); // steals reference
+ printf("Refcnt2: %ld\\n", f->ob_refcnt);
+ f = PyTuple_GetItem(t, 0); // borrows reference
+ printf("Refcnt3: %ld\\n", f->ob_refcnt);
+ g = PyTuple_GetItem(t, 0); // borrows reference again
+ printf("Refcnt4: %ld\\n", f->ob_refcnt);
+ printf("COMPARE: %i\\n", f == g);
+ fflush(stdout);
+ Py_DECREF(t);
+ Py_RETURN_TRUE;
+ """),
+ ])
+ assert module.test_borrowing() # the test should not leak
+
+ def test_borrow_destroy(self):
+ module = self.import_extension('foo', [
+ ("test_borrow_destroy", "METH_NOARGS",
+ """
+ PyObject *i = PyLong_FromLong(42);
+ PyObject *j;
+ PyObject *t1 = PyTuple_Pack(1, i);
+ PyObject *t2 = PyTuple_Pack(1, i);
+ Py_DECREF(i);
+
+ i = PyTuple_GetItem(t1, 0);
+ PyTuple_GetItem(t2, 0);
+ Py_DECREF(t2);
+
+ j = PyLong_FromLong(PyLong_AsLong(i));
+ Py_DECREF(t1);
+ return j;
+ """),
+ ])
+ assert module.test_borrow_destroy() == 42
+
+ def test_double_borrow(self):
+ module = self.import_extension('foo', [
+ ("run", "METH_NOARGS",
+ """
+ PyObject *t = PyTuple_New(1);
+ PyObject *s = PyRun_String("set()", Py_eval_input,
+ Py_None, Py_None);
+ PyObject *w = PyWeakref_NewRef(s, Py_None);
+ PyTuple_SetItem(t, 0, s);
+ PyTuple_GetItem(t, 0);
+ PyTuple_GetItem(t, 0);
+ Py_DECREF(t);
+ return w;
+ """),
+ ])
+ wr = module.run()
+ # check that the set() object was deallocated
+ self.debug_collect()
+ assert wr() is None
diff --git a/pypy/module/cpyext/test/test_bytearrayobject.py
b/pypy/module/cpyext/test/test_bytearrayobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_bytearrayobject.py
@@ -0,0 +1,188 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+
+
+class AppTestStringObject(AppTestCpythonExtensionBase):
+ def test_basic(self):
+ module = self.import_extension('foo', [
+ ("get_hello1", "METH_NOARGS",
+ """
+ return PyByteArray_FromStringAndSize(
+ "Hello world<should not be included>", 11);
+ """),
+ ("get_hello2", "METH_NOARGS",
+ """
+ return PyByteArray_FromStringAndSize("Hello world", 12);
+ """),
+ ("test_Size", "METH_NOARGS",
+ """
+ PyObject* s = PyByteArray_FromStringAndSize("Hello world",
12);
+ int result = 0;
+
+ if(PyByteArray_Size(s) == 12) {
+ result = 1;
+ }
+ Py_DECREF(s);
+ return PyBool_FromLong(result);
+ """),
+ ("test_is_bytearray", "METH_VARARGS",
+ """
+ return PyBool_FromLong(PyByteArray_Check(PyTuple_GetItem(args,
0)));
+ """)], prologue='#include <stdlib.h>')
+ assert module.get_hello1() == b'Hello world'
+ assert module.get_hello2() == b'Hello world\x00'
+ assert module.test_Size()
+ assert module.test_is_bytearray(bytearray(b""))
+ assert not module.test_is_bytearray(())
+
+ def test_bytearray_buffer_init(self):
+ module = self.import_extension('foo', [
+ ("getbytearray", "METH_NOARGS",
+ """
+ PyObject *s, *t;
+ char* c;
+
+ s = PyByteArray_FromStringAndSize(NULL, 4);
+ if (s == NULL)
+ return NULL;
+ t = PyByteArray_FromStringAndSize(NULL, 3);
+ if (t == NULL)
+ return NULL;
+ Py_DECREF(t);
+ c = PyByteArray_AsString(s);
+ if (c == NULL)
+ {
+ PyErr_SetString(PyExc_ValueError, "non-null bytearray
object expected");
+ return NULL;
+ }
+ c[0] = 'a';
+ c[1] = 'b';
+ c[2] = 0;
+ c[3] = 'c';
+ return s;
+ """),
+ ])
+ s = module.getbytearray()
+ assert len(s) == 4
+ assert s == b'ab\x00c'
+
+ def test_bytearray_mutable(self):
+ module = self.import_extension('foo', [
+ ("mutable", "METH_NOARGS",
+ """
+ PyObject *base;
+ base = PyByteArray_FromStringAndSize("test", 10);
+ if (PyByteArray_GET_SIZE(base) != 10)
+ return PyLong_FromLong(-PyByteArray_GET_SIZE(base));
+ memcpy(PyByteArray_AS_STRING(base), "works", 6);
+ Py_INCREF(base);
+ return base;
+ """),
+ ])
+ s = module.mutable()
+ if s == b'\x00' * 10:
+ assert False, "no RW access to bytearray"
+ assert s[:6] == b'works\x00'
+
+ def test_AsByteArray(self):
+ module = self.import_extension('foo', [
+ ("getbytearray", "METH_NOARGS",
+ """
+ const char *c;
+ PyObject *s2, *s1 = PyByteArray_FromStringAndSize("test", 4);
+ if (s1 == NULL)
+ return NULL;
+ c = PyByteArray_AsString(s1);
+ s2 = PyByteArray_FromStringAndSize(c, 4);
+ Py_DECREF(s1);
+ return s2;
+ """),
+ ])
+ s = module.getbytearray()
+ assert s == b'test'
+
+ def test_manipulations(self):
+ import sys
+ module = self.import_extension('foo', [
+ ("bytearray_from_bytes", "METH_VARARGS",
+ '''
+ return PyByteArray_FromStringAndSize(PyBytes_AsString(
+ PyTuple_GetItem(args, 0)), 4);
+ '''
+ ),
+ ("bytes_from_bytearray", "METH_VARARGS",
+ '''
+ char * buf;
+ int n;
+ PyObject * obj;
+ obj = PyTuple_GetItem(args, 0);
+ buf = PyByteArray_AsString(obj);
+ if (buf == NULL)
+ {
+ PyErr_SetString(PyExc_ValueError, "non-null bytearray
object expected");
+ return NULL;
+ }
+ n = PyByteArray_Size(obj);
+ return PyBytes_FromStringAndSize(buf, n);
+ '''
+ ),
+ ("concat", "METH_VARARGS",
+ """
+ PyObject * ret, *right, *left;
+ PyObject *ba1, *ba2;
+ if (!PyArg_ParseTuple(args, "OO", &left, &right)) {
+ return PyUnicode_FromString("parse failed");
+ }
+ ba1 = PyByteArray_FromObject(left);
+ ba2 = PyByteArray_FromObject(right);
+ if (ba1 == NULL || ba2 == NULL)
+ {
+ /* exception should be set */
+ return NULL;
+ }
+ ret = PyByteArray_Concat(ba1, ba2);
+ return ret;
+ """)])
+ assert module.bytearray_from_bytes(b"huheduwe") == b"huhe"
+ assert module.bytes_from_bytearray(bytearray(b'abc')) == b'abc'
+ if '__pypy__' in sys.builtin_module_names:
+ # CPython only makes an assert.
+ raises(ValueError, module.bytes_from_bytearray, 4.0)
+ ret = module.concat(b'abc', b'def')
+ assert ret == b'abcdef'
+ assert not isinstance(ret, str)
+ assert isinstance(ret, bytearray)
+ raises(TypeError, module.concat, b'abc', u'def')
+
+ def test_bytearray_resize(self):
+ module = self.import_extension('foo', [
+ ("bytearray_resize", "METH_VARARGS",
+ '''
+ PyObject *obj, *ba;
+ int newsize, oldsize, ret;
+ if (!PyArg_ParseTuple(args, "Oi", &obj, &newsize)) {
+ return PyUnicode_FromString("parse failed");
+ }
+
+ ba = PyByteArray_FromObject(obj);
+ if (ba == NULL)
+ return NULL;
+ oldsize = PyByteArray_Size(ba);
+ if (oldsize == 0)
+ {
+ return PyUnicode_FromString("oldsize is 0");
+ }
+ ret = PyByteArray_Resize(ba, newsize);
+ if (ret != 0)
+ {
+ printf("ret, oldsize, newsize= %d, %d, %d\\n", ret, oldsize,
newsize);
+ return NULL;
+ }
+ return ba;
+ '''
+ )])
+ ret = module.bytearray_resize(b'abc', 6)
+ assert len(ret) == 6,"%s, len=%d" % (ret, len(ret))
+ assert ret[:4] == b'abc\x00'
+ ret = module.bytearray_resize(b'abcdefghi', 4)
+ assert len(ret) == 4,"%s, len=%d" % (ret, len(ret))
+ assert ret == b'abcd'
diff --git a/pypy/module/cpyext/test/test_bytesobject.py
b/pypy/module/cpyext/test/test_bytesobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_bytesobject.py
@@ -0,0 +1,611 @@
+# encoding: utf-8
+from rpython.rtyper.lltypesystem import rffi, lltype
+from pypy.module.cpyext.test.test_api import BaseApiTest, raises_w
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.bytesobject import (
+ new_empty_str, PyBytesObject, _PyBytes_Resize, PyBytes_Concat,
+ PyBytes_ConcatAndDel,
+ _PyBytes_Eq,
+ _PyBytes_Join)
+from pypy.module.cpyext.api import PyObjectP, PyObject, Py_ssize_tP
+from pypy.module.cpyext.pyobject import decref, from_ref, make_ref
+from pypy.module.cpyext.buffer import PyObject_AsCharBuffer
+
+
+class AppTestBytesObject(AppTestCpythonExtensionBase):
+ def test_bytesobject(self):
+ module = self.import_extension('foo', [
+ ("get_hello1", "METH_NOARGS",
+ """
+ return PyBytes_FromStringAndSize(
+ "Hello world<should not be included>", 11);
+ """),
+ ("get_hello2", "METH_NOARGS",
+ """
+ return PyBytes_FromString("Hello world");
+ """),
+ ("test_Size", "METH_NOARGS",
+ """
+ PyObject* s = PyBytes_FromString("Hello world");
+ int result = PyBytes_Size(s);
+
+ Py_DECREF(s);
+ return PyLong_FromLong(result);
+ """),
+ ("test_Size_exception", "METH_NOARGS",
+ """
+ PyObject* f = PyFloat_FromDouble(1.0);
+ PyBytes_Size(f);
+
+ Py_DECREF(f);
+ return NULL;
+ """),
+ ("test_is_bytes", "METH_VARARGS",
+ """
+ return PyBool_FromLong(PyBytes_Check(PyTuple_GetItem(args,
0)));
+ """)], prologue='#include <stdlib.h>')
+ assert module.get_hello1() == b'Hello world'
+ assert module.get_hello2() == b'Hello world'
+ assert module.test_Size()
+ raises(TypeError, module.test_Size_exception)
+
+ assert module.test_is_bytes(b"")
+ assert not module.test_is_bytes(())
+
+ def test_bytes_buffer_init(self):
+ module = self.import_extension('foo', [
+ ("getbytes", "METH_NOARGS",
+ """
+ PyObject *s, *t;
+ char* c;
+
+ s = PyBytes_FromStringAndSize(NULL, 4);
+ if (s == NULL)
+ return NULL;
+ t = PyBytes_FromStringAndSize(NULL, 3);
+ if (t == NULL)
+ return NULL;
+ Py_DECREF(t);
+ c = PyBytes_AS_STRING(s);
+ c[0] = 'a';
+ c[1] = 'b';
+ c[2] = 0;
+ c[3] = 'c';
+ return s;
+ """),
+ ])
+ s = module.getbytes()
+ assert len(s) == 4
+ assert s == b'ab\x00c'
+
+ def test_bytes_tp_alloc(self):
+ module = self.import_extension('foo', [
+ ("tpalloc", "METH_NOARGS",
+ """
+ PyObject *base;
+ PyTypeObject * type;
+ PyObject *obj;
+ base = PyBytes_FromString("test");
+ if (PyBytes_GET_SIZE(base) != 4)
+ return PyLong_FromLong(-PyBytes_GET_SIZE(base));
+ type = base->ob_type;
+ if (type->tp_itemsize != 1)
+ return PyLong_FromLong(type->tp_itemsize);
+ obj = type->tp_alloc(type, 10);
+ if (PyBytes_GET_SIZE(obj) != 10)
+ return PyLong_FromLong(PyBytes_GET_SIZE(obj));
+ /* cannot work, there is only RO access
+ memcpy(PyBytes_AS_STRING(obj), "works", 6); */
+ Py_INCREF(obj);
+ return obj;
+ """),
+ ('alloc_rw', "METH_NOARGS",
+ '''
+ PyObject *obj = (PyObject*)_PyObject_NewVar(&PyBytes_Type, 10);
+ memcpy(PyBytes_AS_STRING(obj), "works", 6);
+ return (PyObject*)obj;
+ '''),
+ ])
+ s = module.alloc_rw()
+ assert s[:6] == b'works\0' # s[6:10] contains random garbage
+ s = module.tpalloc()
+ assert s == b'\x00' * 10
+
+ def test_AsString(self):
+ module = self.import_extension('foo', [
+ ("getbytes", "METH_NOARGS",
+ """
+ char *c;
+ PyObject* s2, *s1 = PyBytes_FromStringAndSize("test", 4);
+ c = PyBytes_AsString(s1);
+ s2 = PyBytes_FromStringAndSize(c, 4);
+ Py_DECREF(s1);
+ return s2;
+ """),
+ ])
+ s = module.getbytes()
+ assert s == b'test'
+
+ def test_manipulations(self):
+ module = self.import_extension('foo', [
+ ("bytes_as_string", "METH_VARARGS",
+ '''
+ return PyBytes_FromStringAndSize(PyBytes_AsString(
+ PyTuple_GetItem(args, 0)), 4);
+ '''
+ ),
+ ("concat", "METH_VARARGS",
+ """
+ PyObject ** v;
+ PyObject * left = PyTuple_GetItem(args, 0);
+ Py_INCREF(left); /* the reference will be stolen! */
+ v = &left;
+ PyBytes_Concat(v, PyTuple_GetItem(args, 1));
+ return *v;
+ """)])
+ assert module.bytes_as_string(b"huheduwe") == b"huhe"
+ ret = module.concat(b'abc', b'def')
+ assert ret == b'abcdef'
+
+ def test_py_bytes_as_string_None(self):
+ module = self.import_extension('foo', [
+ ("string_None", "METH_VARARGS",
+ '''
+ if (PyBytes_AsString(Py_None)) {
+ Py_RETURN_NONE;
+ }
+ return NULL;
+ '''
+ )])
+ raises(TypeError, module.string_None)
+
+ def test_AsStringAndSize(self):
+ module = self.import_extension('foo', [
+ ("getbytes", "METH_NOARGS",
+ """
+ PyObject* s1 = PyBytes_FromStringAndSize("te\\0st", 5);
+ char *buf;
+ Py_ssize_t len;
+ if (PyBytes_AsStringAndSize(s1, &buf, &len) < 0)
+ return NULL;
+ if (len != 5) {
+ PyErr_SetString(PyExc_AssertionError, "Bad Length");
+ return NULL;
+ }
+ if (PyBytes_AsStringAndSize(s1, &buf, NULL) >= 0) {
+ PyErr_SetString(PyExc_AssertionError, "Should Have
failed");
+ return NULL;
+ }
+ PyErr_Clear();
+ Py_DECREF(s1);
+ Py_INCREF(Py_None);
+ return Py_None;
+ """),
+ ("c_only", "METH_NOARGS",
+ """
+ int ret;
+ char * buf2;
+ PyObject * obj = PyBytes_FromStringAndSize(NULL, 1024);
+ if (!obj)
+ return NULL;
+ buf2 = PyBytes_AsString(obj);
+ if (!buf2)
+ return NULL;
+ /* buf should not have been forced, issue #2395 */
+ ret = _PyBytes_Resize(&obj, 512);
+ if (ret < 0)
+ return NULL;
+ Py_DECREF(obj);
+ Py_INCREF(Py_None);
+ return Py_None;
+ """),
+ ])
+ module.getbytes()
+ module.c_only()
+
+ def test_FromFormat(self):
+ module = self.import_extension('foo', [
+ ("fmt", "METH_VARARGS",
+ """
+ PyObject* fmt = PyTuple_GetItem(args, 0);
+ int n = PyLong_AsLong(PyTuple_GetItem(args, 1));
+ PyObject* result = PyBytes_FromFormat(PyBytes_AsString(fmt),
n);
+ return result;
+ """),
+ ])
+ print(module.fmt(b'd:%d', 10))
+ assert module.fmt(b'd:%d', 10) == b'd:10'
+
+ def test_suboffsets(self):
+ module = self.import_extension('foo', [
+ ("check_suboffsets", "METH_O",
+ """
+ Py_buffer view;
+ PyObject_GetBuffer(args, &view, 0);
+ return PyLong_FromLong(view.suboffsets == NULL);
+ """)])
+ assert module.check_suboffsets(b'1234') == 1
+
+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)
+ _PyBytes_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)
+ _PyBytes_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_Concat(self, space):
+ ref = make_ref(space, space.newbytes('abc'))
+ ptr = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+ ptr[0] = ref
+ prev_refcnt = ref.c_ob_refcnt
+ PyBytes_Concat(space, ptr, space.newbytes('def'))
+ assert ref.c_ob_refcnt == prev_refcnt - 1
+ assert space.bytes_w(from_ref(space, ptr[0])) == 'abcdef'
+ with raises_w(space, TypeError):
+ PyBytes_Concat(space, ptr, space.w_None)
+ assert not ptr[0]
+ ptr[0] = lltype.nullptr(PyObject.TO)
+ PyBytes_Concat(space, ptr, space.newbytes('def')) # should not crash
+ lltype.free(ptr, flavor='raw')
+
+ def test_ConcatAndDel(self, space):
+ ref1 = make_ref(space, space.newbytes('abc'))
+ ref2 = make_ref(space, space.newbytes('def'))
+ ptr = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+ ptr[0] = ref1
+ prev_refcnf = ref2.c_ob_refcnt
+ PyBytes_ConcatAndDel(space, ptr, ref2)
+ assert space.bytes_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.newbytes('foo'))
+ prev_refcnf = ref2.c_ob_refcnt
+ PyBytes_ConcatAndDel(space, ptr, ref2) # should not crash
+ assert ref2.c_ob_refcnt == prev_refcnf - 1
+ lltype.free(ptr, flavor='raw')
+
+ 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.newbytes("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_eq(self, space):
+ assert 1 == _PyBytes_Eq(space, space.newbytes("hello"),
space.newbytes("hello"))
+ assert 0 == _PyBytes_Eq(space, space.newbytes("hello"),
space.newbytes("world"))
+
+ def test_join(self, space):
+ w_sep = space.newbytes('<sep>')
+ w_seq = space.newtuple([space.newbytes('a'), space.newbytes('b')])
+ w_joined = _PyBytes_Join(space, w_sep, w_seq)
+ assert space.bytes_w(w_joined) == 'a<sep>b'
+
+ def test_FromObject(self, space, api):
+ w_obj = space.newbytes("test")
+ assert space.eq_w(w_obj, api.PyBytes_FromObject(w_obj))
+ w_obj = space.call_function(space.w_bytearray, w_obj)
+ assert space.eq_w(w_obj, api.PyBytes_FromObject(w_obj))
+ 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/test/test_capsule.py
b/pypy/module/cpyext/test/test_capsule.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_capsule.py
@@ -0,0 +1,29 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+
+class AppTestCapsule(AppTestCpythonExtensionBase):
+ def test_capsule_import(self):
+ module = self.import_extension('foo', [
+ ("set_ptr", "METH_O",
+ """
+ PyObject *capsule, *module;
+ void *ptr = PyLong_AsVoidPtr(args);
+ if (PyErr_Occurred()) return NULL;
+ capsule = PyCapsule_New(ptr, "foo._ptr", NULL);
+ if (PyErr_Occurred()) return NULL;
+ module = PyImport_ImportModule("foo");
+ PyModule_AddObject(module, "_ptr", capsule);
+ Py_DECREF(module);
+ if (PyErr_Occurred()) return NULL;
+ Py_RETURN_NONE;
+ """),
+ ("get_ptr", "METH_NOARGS",
+ """
+ void *ptr = PyCapsule_Import("foo._ptr", 0);
+ if (PyErr_Occurred()) return NULL;
+ return PyLong_FromVoidPtr(ptr);
+ """)])
+ module.set_ptr(1234)
+ assert 'capsule object "foo._ptr" at ' in str(module._ptr)
+ import gc; gc.collect()
+ assert module.get_ptr() == 1234
+ del module._ptr
diff --git a/pypy/module/cpyext/test/test_cell.py
b/pypy/module/cpyext/test/test_cell.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_cell.py
@@ -0,0 +1,20 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+
+
+class AppTestCell(AppTestCpythonExtensionBase):
+ def test_cell_type(self):
+ module = self.import_extension('foo', [
+ ("cell_type", "METH_O",
+ """
+ PyDict_SetItemString(args, "cell", (PyObject*)&PyCell_Type);
+ Py_RETURN_NONE;
+ """)])
+ d = {}
+ module.cell_type(d)
+ def f(o):
+ def g():
+ return o
+ return g
+
+ cell_type = type(f(0).__closure__[0])
+ assert d["cell"] is cell_type
diff --git a/pypy/module/cpyext/test/test_classobject.py
b/pypy/module/cpyext/test/test_classobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_classobject.py
@@ -0,0 +1,56 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+
+
+class AppTestInstanceMethod(AppTestCpythonExtensionBase):
+ def test_instancemethod(self):
+ module = self.import_extension('foo', [
+ ("instancemethod", "METH_O",
+ """
+ return PyInstanceMethod_New(args);
+ """)])
+
+ def testfunction(self):
+ """some doc"""
+ return self
+
+ class InstanceMethod:
+ id = module.instancemethod(id)
+ testmethod = module.instancemethod(testfunction)
+
+ inst = InstanceMethod()
+ assert id(inst) == inst.id()
+ assert inst.testmethod() is inst
+ assert InstanceMethod.testmethod(inst) is inst
+ assert InstanceMethod.__dict__['testmethod'](inst) is inst
+ assert inst.testmethod.__doc__ == testfunction.__doc__
+ assert InstanceMethod.testmethod.__doc__ == testfunction.__doc__
+
+ InstanceMethod.testmethod.attribute = "test"
+ assert testfunction.attribute == "test"
+ raises(AttributeError, setattr, inst.testmethod, "attribute", "test")
+
+ def test_instancemethod_cpyext_attributes(self):
+ module = self.import_extension('foo', [
+ ("instancemethod_get_doc", "METH_O",
+ """
+ PyObject* instancemethod = PyInstanceMethod_New(args);
+ return PyObject_GetAttrString(instancemethod, "__doc__");
+ """),
+ ("instancemethod_get_name", "METH_O",
+ """
+ PyObject* instancemethod = PyInstanceMethod_New(args);
+ return PyObject_GetAttrString(instancemethod, "__name__");
+ """),
+ ("instancemethod_get_module", "METH_O",
+ """
+ PyObject* instancemethod = PyInstanceMethod_New(args);
+ return PyObject_GetAttrString(instancemethod, "__module__");
+ """)
+ ])
+
+ def testfunction(self):
+ """some doc"""
+ return self
+ assert(module.instancemethod_get_doc(testfunction) ==
testfunction.__doc__)
+ assert(module.instancemethod_get_module(testfunction) ==
testfunction.__module__)
+ assert(module.instancemethod_get_name(testfunction) ==
testfunction.__name__)
\ No newline at end of file
diff --git a/pypy/module/cpyext/test/test_codecs.py
b/pypy/module/cpyext/test/test_codecs.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_codecs.py
@@ -0,0 +1,15 @@
+# encoding: iso-8859-15
+from pypy.module.cpyext.test.test_api import BaseApiTest
+from rpython.rtyper.lltypesystem import rffi
+from pypy.module.cpyext.codecs import (
+ PyCodec_IncrementalEncoder, PyCodec_IncrementalDecoder)
+
+class TestCodecs(BaseApiTest):
+ def test_incremental(self, space):
+ utf8 = rffi.str2charp('utf-8')
+ w_encoder = PyCodec_IncrementalEncoder(space, utf8, None)
+ w_encoded = space.call_method(w_encoder, 'encode',
space.wrap(u'späm'))
+ w_decoder = PyCodec_IncrementalDecoder(space, utf8, None)
+ w_decoded = space.call_method(w_decoder, 'decode', w_encoded)
+ assert space.utf8_w(w_decoded) == u'späm'.encode("utf-8")
+ rffi.free_charp(utf8)
diff --git a/pypy/module/cpyext/test/test_complexobject.py
b/pypy/module/cpyext/test/test_complexobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_complexobject.py
@@ -0,0 +1,64 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.test.test_api import BaseApiTest, raises_w
+from pypy.module.cpyext.complexobject import (
+ PyComplex_FromDoubles, PyComplex_RealAsDouble, PyComplex_ImagAsDouble)
+
+class TestComplexObject(BaseApiTest):
+ def test_complexobject(self, space):
+ w_value = PyComplex_FromDoubles(space, 1.2, 3.4)
+ assert space.unwrap(w_value) == 1.2+3.4j
+ assert PyComplex_RealAsDouble(space, w_value) == 1.2
+ assert PyComplex_ImagAsDouble(space, w_value) == 3.4
+
+ assert PyComplex_RealAsDouble(space, space.wrap(42)) == 42
+ assert PyComplex_RealAsDouble(space, space.wrap(1.5)) == 1.5
+ assert PyComplex_ImagAsDouble(space, space.wrap(1.5)) == 0.0
+
+ # cpython accepts anything for PyComplex_ImagAsDouble
+ assert PyComplex_ImagAsDouble(space, space.w_None) == 0.0
+ with raises_w(space, TypeError):
+ PyComplex_RealAsDouble(space, space.w_None)
+
+class AppTestCComplex(AppTestCpythonExtensionBase):
+ def test_AsCComplex(self):
+ module = self.import_extension('foo', [
+ ("as_tuple", "METH_O",
+ """
+ Py_complex c = PyComplex_AsCComplex(args);
+ if (PyErr_Occurred()) return NULL;
+ return Py_BuildValue("dd", c.real, c.imag);
+ """)])
+ assert module.as_tuple(12-34j) == (12, -34)
+ assert module.as_tuple(-3.14) == (-3.14, 0.0)
+ raises(TypeError, module.as_tuple, "12")
+
+ def test_FromCComplex(self):
+ module = self.import_extension('foo', [
+ ("test", "METH_NOARGS",
+ """
+ Py_complex c = {1.2, 3.4};
+ return PyComplex_FromCComplex(c);
+ """)])
+ assert module.test() == 1.2 + 3.4j
+
+ def test_PyComplex_to_WComplex(self):
+ module = self.import_extension('foo', [
+ ("test", "METH_NOARGS",
+ """
+ Py_complex c = {1.2, 3.4};
+ PyObject *obj = PyObject_Malloc(sizeof(PyComplexObject));
+ obj = PyObject_Init(obj, &PyComplex_Type);
+ assert(obj != NULL);
+ ((PyComplexObject *)obj)->cval = c;
+ return obj;
+ """)])
+ assert module.test() == 1.2 + 3.4j
+
+ def test_WComplex_to_PyComplex(self):
+ module = self.import_extension('foo', [
+ ("test", "METH_O",
+ """
+ Py_complex c = ((PyComplexObject *)args)->cval;
+ return Py_BuildValue("dd", c.real, c.imag);
+ """)])
+ assert module.test(1.2 + 3.4j) == (1.2, 3.4)
diff --git a/pypy/module/cpyext/test/test_cparser.py
b/pypy/module/cpyext/test/test_cparser.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_cparser.py
@@ -0,0 +1,260 @@
+from rpython.flowspace.model import const
+from rpython.flowspace.objspace import build_flow
+from rpython.translator.simplify import simplify_graph
+from rpython.rtyper.lltypesystem import rffi, lltype
+from pypy.module.cpyext.cparser import parse_source, CTypeSpace
+
+def test_configure():
+ decl = """
+ typedef ssize_t Py_ssize_t;
+
+ typedef struct {
+ Py_ssize_t ob_refcnt;
+ Py_ssize_t ob_pypy_link;
+ double ob_fval;
+ } TestFloatObject;
+ """
+ cts = parse_source(decl)
+ TestFloatObject = cts.definitions['TestFloatObject']
+ assert isinstance(TestFloatObject, lltype.Struct)
+ assert TestFloatObject.c_ob_refcnt == rffi.SSIZE_T
+ assert TestFloatObject.c_ob_pypy_link == rffi.SSIZE_T
+ assert TestFloatObject.c_ob_fval == rffi.DOUBLE
+
+def test_simple():
+ decl = "typedef ssize_t Py_ssize_t;"
+ cts = parse_source(decl)
+ assert cts.definitions == {'Py_ssize_t': rffi.SSIZE_T}
+
+def test_macro():
+ decl = """
+ typedef ssize_t Py_ssize_t;
+
+ #define PyObject_HEAD \
+ Py_ssize_t ob_refcnt; \
+ Py_ssize_t ob_pypy_link; \
+
+ typedef struct {
+ PyObject_HEAD
+ double ob_fval;
+ } PyFloatObject;
+ """
+ cts = parse_source(decl)
+ assert 'PyFloatObject' in cts.definitions
+ assert 'PyObject_HEAD' in cts.macros
+
+def test_include():
+ cdef1 = """
+ typedef ssize_t Py_ssize_t;
+
+ #define PyObject_HEAD \
+ Py_ssize_t ob_refcnt; \
+ Py_ssize_t ob_pypy_link; \
+
+ typedef struct {
+ char *name;
+ } Type;
+ """
+ cdef2 = """
+ typedef struct {
+ PyObject_HEAD
+ Py_ssize_t ob_foo;
+ Type *type;
+ } Object;
+ """
+ cts1 = parse_source(cdef1)
+ Type = cts1.definitions['Type']
+ assert isinstance(Type, lltype.Struct)
+ cts2 = parse_source(cdef2, includes=[cts1])
+ assert 'Type' not in cts2.definitions
+ Object = cts2.definitions['Object']
+ assert Object.c_type.TO is Type
+
+def test_multiple_sources():
+ cdef1 = """
+ typedef ssize_t Py_ssize_t;
+
+ #define PyObject_HEAD \
+ Py_ssize_t ob_refcnt; \
+ Py_ssize_t ob_pypy_link; \
+
+ typedef struct {
+ char *name;
+ } Type;
+ """
+ cdef2 = """
+ typedef struct {
+ PyObject_HEAD
+ Py_ssize_t ob_foo;
+ Type *type;
+ } Object;
+ """
+ cts = CTypeSpace()
+ cts.parse_source(cdef1)
+ Type = cts.definitions['Type']
+ assert isinstance(Type, lltype.Struct)
+ assert 'Object' not in cts.definitions
+ cts.parse_source(cdef2)
+ Object = cts.definitions['Object']
+ assert Object.c_type.TO is Type
+
+def test_incomplete():
+ cdef = """
+ typedef ssize_t Py_ssize_t;
+
+ typedef struct {
+ Py_ssize_t ob_refcnt;
+ Py_ssize_t ob_pypy_link;
+ struct _typeobject *ob_type;
+ } Object;
+
+ typedef struct {
+ void *buf;
+ Object *obj;
+ } Buffer;
+
+ """
+ cts = parse_source(cdef)
+ Object = cts.gettype('Object')
+ assert isinstance(Object, lltype.Struct)
+
+def test_recursive():
+ cdef = """
+ typedef ssize_t Py_ssize_t;
+
+ typedef struct {
+ Py_ssize_t ob_refcnt;
+ Py_ssize_t ob_pypy_link;
+ struct _typeobject *ob_type;
+ } Object;
+
+ typedef struct {
+ void *buf;
+ Object *obj;
+ } Buffer;
+
+ typedef struct _typeobject {
+ Object *obj;
+ } Type;
+ """
+ cts = parse_source(cdef)
+ Object = cts.definitions['Object']
+ assert isinstance(Object, lltype.Struct)
+ hash(Object)
+
+def test_nested_struct():
+ cdef = """
+ typedef struct {
+ int x;
+ } foo;
+ typedef struct {
+ foo y;
+ } bar;
+ """
+ cts = parse_source(cdef)
+ bar = cts.gettype('bar')
+ assert isinstance(bar, lltype.Struct)
+ hash(bar) # bar is hashable
+
+def test_const():
+ cdef = """
+ typedef struct {
+ const char * const foo;
+ } bar;
+ """
+ cts = parse_source(cdef)
+ assert cts.definitions['bar'].c_foo == rffi.CONST_CCHARP != rffi.CCHARP
+
+def test_gettype():
+ decl = """
+ typedef ssize_t Py_ssize_t;
+
+ #define PyObject_HEAD \
+ Py_ssize_t ob_refcnt; \
+ Py_ssize_t ob_pypy_link; \
+
+ typedef struct {
+ PyObject_HEAD
+ double ob_fval;
+ } TestFloatObject;
+ """
+ cts = parse_source(decl)
+ assert cts.gettype('Py_ssize_t') == rffi.SSIZE_T
+ assert cts.gettype('TestFloatObject *').TO.c_ob_refcnt == rffi.SSIZE_T
+ assert cts.cast('Py_ssize_t', 42) == rffi.cast(rffi.SSIZE_T, 42)
+
+def test_parse_funcdecl():
+ decl = """
+ typedef ssize_t Py_ssize_t;
+
+ #define PyObject_HEAD \
+ Py_ssize_t ob_refcnt; \
+ Py_ssize_t ob_pypy_link; \
+
+ typedef struct {
+ PyObject_HEAD
+ double ob_fval;
+ } TestFloatObject;
+
+ typedef TestFloatObject* (*func_t)(int, int);
+ """
+ cts = parse_source(decl)
+ func_decl = cts.parse_func("func_t * some_func(TestFloatObject*)")
+ assert func_decl.name == 'some_func'
+ assert func_decl.get_llresult(cts) == cts.gettype('func_t*')
+ assert func_decl.get_llargs(cts) == [cts.gettype('TestFloatObject *')]
+
+def test_write_func():
+ from ..api import ApiFunction
+ from rpython.translator.c.database import LowLevelDatabase
+ db = LowLevelDatabase()
+ cdef = """
+ typedef ssize_t Py_ssize_t;
+ """
+ cts = parse_source(cdef)
+ cdecl = "Py_ssize_t * some_func(Py_ssize_t*)"
+ decl = cts.parse_func(cdecl)
+ api_function = ApiFunction(
+ decl.get_llargs(cts), decl.get_llresult(cts), lambda space, x: None,
+ cdecl=decl)
+ assert (api_function.get_api_decl('some_func', db) ==
+ "PyAPI_FUNC(Py_ssize_t *) some_func(Py_ssize_t * arg0);")
+
+
+def test_wchar_t():
+ cdef = """
+ typedef struct { wchar_t* x; } test;
+ """
+ cts = parse_source(cdef, headers=['stddef.h'])
+ obj = lltype.malloc(cts.gettype('test'), flavor='raw')
+ obj.c_x = cts.cast('wchar_t*', 0)
+ obj.c_x = lltype.nullptr(rffi.CWCHARP.TO)
+ lltype.free(obj, flavor='raw')
+
+
+def test_translate_cast():
+ cdef = "typedef ssize_t Py_ssize_t;"
+ cts = parse_source(cdef)
+
+ def f():
+ return cts.cast('Py_ssize_t*', 0)
+ graph = build_flow(f)
+ simplify_graph(graph)
+ assert len(graph.startblock.operations) == 1
+ op = graph.startblock.operations[0]
+ assert op.args[0] == const(rffi.cast)
+ assert op.args[1].value is cts.gettype('Py_ssize_t*')
+
+def test_translate_gettype():
+ cdef = "typedef ssize_t Py_ssize_t;"
+ cts = parse_source(cdef)
+
+ def f():
+ return cts.gettype('Py_ssize_t*')
+ graph = build_flow(f)
+ simplify_graph(graph)
+ # Check that the result is constant-folded
+ assert graph.startblock.operations == []
+ [link] = graph.startblock.exits
+ assert link.target is graph.returnblock
+ assert link.args[0] == const(rffi.CArrayPtr(rffi.SSIZE_T))
diff --git a/pypy/module/cpyext/test/test_datetime.py
b/pypy/module/cpyext/test/test_datetime.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_datetime.py
@@ -0,0 +1,354 @@
+import pytest
+
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.cdatetime import *
+from pypy.module.cpyext.cdatetime import (
+ _PyDateTime_Import, _PyDateTime_FromDateAndTime, _PyDate_FromDate,
+ _PyTime_FromTime, _PyDelta_FromDelta)
+import datetime
+
+class TestDatetime(BaseApiTest):
+ def test_date(self, space):
+ date_api = _PyDateTime_Import(space)
+ w_date = _PyDate_FromDate(space, 2010, 06, 03, date_api.c_DateType)
+ assert space.unwrap(space.str(w_date)) == '2010-06-03'
+
+ assert PyDate_Check(space, w_date)
+ assert PyDate_CheckExact(space, w_date)
+
+ assert PyDateTime_GET_YEAR(space, w_date) == 2010
+ assert PyDateTime_GET_MONTH(space, w_date) == 6
+ assert PyDateTime_GET_DAY(space, w_date) == 3
+
+ def test_time(self, space):
+ date_api = _PyDateTime_Import(space)
+ w_time = _PyTime_FromTime(
+ space, 23, 15, 40, 123456, space.w_None, date_api.c_TimeType)
+ assert space.unwrap(space.str(w_time)) == '23:15:40.123456'
+
+ assert PyTime_Check(space, w_time)
+ assert PyTime_CheckExact(space, w_time)
+
+ assert PyDateTime_TIME_GET_HOUR(space, w_time) == 23
+ assert PyDateTime_TIME_GET_MINUTE(space, w_time) == 15
+ assert PyDateTime_TIME_GET_SECOND(space, w_time) == 40
+ assert PyDateTime_TIME_GET_MICROSECOND(space, w_time) == 123456
+
+ def test_datetime(self, space):
+ date_api = _PyDateTime_Import(space)
+ w_date = _PyDateTime_FromDateAndTime(
+ space, 2010, 06, 03, 23, 15, 40, 123456, space.w_None,
+ date_api.c_DateTimeType)
+ assert space.unwrap(space.str(w_date)) == '2010-06-03 23:15:40.123456'
+
+ assert PyDateTime_Check(space, w_date)
+ assert PyDateTime_CheckExact(space, w_date)
+ assert PyDate_Check(space, w_date)
+ assert not PyDate_CheckExact(space, w_date)
+
+ assert PyDateTime_GET_YEAR(space, w_date) == 2010
+ assert PyDateTime_GET_MONTH(space, w_date) == 6
+ assert PyDateTime_GET_DAY(space, w_date) == 3
+ assert PyDateTime_DATE_GET_HOUR(space, w_date) == 23
+ assert PyDateTime_DATE_GET_MINUTE(space, w_date) == 15
+ assert PyDateTime_DATE_GET_SECOND(space, w_date) == 40
+ assert PyDateTime_DATE_GET_MICROSECOND(space, w_date) == 123456
+
+ def test_delta(self, space):
+ date_api = _PyDateTime_Import(space)
+ w_delta = space.appexec(
+ [space.wrap(3), space.wrap(15)], """(days, seconds):
+ from datetime import timedelta
+ return timedelta(days, seconds)
+ """)
+ assert PyDelta_Check(space, w_delta)
+ assert PyDelta_CheckExact(space, w_delta)
+
+ w_delta = _PyDelta_FromDelta(space, 10, 20, 30, True,
date_api.c_DeltaType)
+ assert PyDelta_Check(space, w_delta)
+ assert PyDelta_CheckExact(space, w_delta)
+
+ assert PyDateTime_DELTA_GET_DAYS(space, w_delta) == 10
+ assert PyDateTime_DELTA_GET_SECONDS(space, w_delta) == 20
+ assert PyDateTime_DELTA_GET_MICROSECONDS(space, w_delta) == 30
+
+ def test_fromtimestamp(self, space):
+ w_args = space.wrap((0,))
+ w_date = PyDate_FromTimestamp(space, w_args)
+ date = datetime.date.fromtimestamp(0)
+ assert space.unwrap(space.str(w_date)) == str(date)
+
+ w_args = space.wrap((0,))
+ w_date = PyDateTime_FromTimestamp(space, w_args)
+ date = datetime.datetime.fromtimestamp(0)
+ assert space.unwrap(space.str(w_date)) == str(date)
+
+ @pytest.mark.parametrize('name', ['Time', 'DateTime', 'Date', 'Delta'])
+ def test_basicsize(self, space, name):
+ datetime = _PyDateTime_Import(space)
+ py_size = getattr(datetime, "c_%sType" % name).c_tp_basicsize
+ c_size = rffi.sizeof(cts.gettype("PyDateTime_%s" % name))
+ assert py_size == c_size
+
+
+class AppTestDatetime(AppTestCpythonExtensionBase):
+ def test_CAPI(self):
+ module = self.import_extension('foo', [
+ ("get_types", "METH_NOARGS",
+ """
+ PyDateTime_IMPORT;
+ if (!PyDateTimeAPI) {
+ PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
+ return NULL;
+ }
+ return PyTuple_Pack(5,
+ PyDateTimeAPI->DateType,
+ PyDateTimeAPI->DateTimeType,
+ PyDateTimeAPI->TimeType,
+ PyDateTimeAPI->DeltaType,
+ PyDateTimeAPI->TZInfoType);
+ """),
+ ("clear_types", "METH_NOARGS",
+ """
+ Py_DECREF(PyDateTimeAPI->DateType);
+ Py_DECREF(PyDateTimeAPI->DateTimeType);
+ Py_DECREF(PyDateTimeAPI->TimeType);
+ Py_DECREF(PyDateTimeAPI->DeltaType);
+ Py_DECREF(PyDateTimeAPI->TZInfoType);
+ Py_RETURN_NONE;
+ """
+ )
+ ], prologue='#include "datetime.h"\n')
+ import datetime
+ assert module.get_types() == (datetime.date,
+ datetime.datetime,
+ datetime.time,
+ datetime.timedelta,
+ datetime.tzinfo)
+ module.clear_types()
+
+ def test_constructors(self):
+ module = self.import_extension('foo', [
+ ("new_date", "METH_NOARGS",
+ """ PyDateTime_IMPORT;
+ return PyDateTimeAPI->Date_FromDate(
+ 2000, 6, 6, PyDateTimeAPI->DateType);
+ """),
+ ("new_time", "METH_NOARGS",
+ """ PyDateTime_IMPORT;
+ return PyDateTimeAPI->Time_FromTime(
+ 6, 6, 6, 6, Py_None, PyDateTimeAPI->TimeType);
+ """),
+ ("new_datetime", "METH_NOARGS",
+ """ PyDateTime_IMPORT;
+ return PyDateTimeAPI->DateTime_FromDateAndTime(
+ 2000, 6, 6, 6, 6, 6, 6, Py_None,
+ PyDateTimeAPI->DateTimeType);
+ """),
+ ], prologue='#include "datetime.h"\n')
+ import datetime
+ assert module.new_date() == datetime.date(2000, 6, 6)
+ assert module.new_time() == datetime.time(6, 6, 6, 6)
+ assert module.new_datetime() == datetime.datetime(
+ 2000, 6, 6, 6, 6, 6, 6)
+
+ def test_macros(self):
+ module = self.import_extension('foo', [
+ ("test_date_macros", "METH_NOARGS",
+ """
+ PyObject* obj;
+ PyDateTime_Date* d;
+ PyDateTime_IMPORT;
+ if (!PyDateTimeAPI) {
+ PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
+ return NULL;
+ }
+ obj = PyDate_FromDate(2000, 6, 6);
+ d = (PyDateTime_Date*)obj;
+
+ PyDateTime_GET_YEAR(obj);
+ PyDateTime_GET_YEAR(d);
+
+ PyDateTime_GET_MONTH(obj);
+ PyDateTime_GET_MONTH(d);
+
+ PyDateTime_GET_DAY(obj);
+ PyDateTime_GET_DAY(d);
+
+ return obj;
+ """),
+ ("test_datetime_macros", "METH_NOARGS",
+ """
+ PyObject* obj;
+ PyDateTime_DateTime *dt;
+ PyDateTime_IMPORT;
+ if (!PyDateTimeAPI) {
+ PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
+ return NULL;
+ }
+ obj = PyDateTime_FromDateAndTime(2000, 6, 6, 6, 6, 6, 6);
+ dt = (PyDateTime_DateTime*)obj;
+
+ PyDateTime_GET_YEAR(obj);
+ PyDateTime_GET_YEAR(dt);
+
+ PyDateTime_GET_MONTH(obj);
+ PyDateTime_GET_MONTH(dt);
+
+ PyDateTime_GET_DAY(obj);
+ PyDateTime_GET_DAY(dt);
+
+ PyDateTime_DATE_GET_HOUR(obj);
+ PyDateTime_DATE_GET_HOUR(dt);
+
+ PyDateTime_DATE_GET_MINUTE(obj);
+ PyDateTime_DATE_GET_MINUTE(dt);
+
+ PyDateTime_DATE_GET_SECOND(obj);
+ PyDateTime_DATE_GET_SECOND(dt);
+
+ PyDateTime_DATE_GET_MICROSECOND(obj);
+ PyDateTime_DATE_GET_MICROSECOND(dt);
+
+ return obj;
+ """),
+ ("test_time_macros", "METH_NOARGS",
+ """
+ PyObject* obj;
+ PyDateTime_Time* t;
+ PyDateTime_IMPORT;
+ if (!PyDateTimeAPI) {
+ PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
+ return NULL;
+ }
+ obj = PyTime_FromTime(6, 6, 6, 6);
+ t = (PyDateTime_Time*)obj;
+
+ PyDateTime_TIME_GET_HOUR(obj);
+ PyDateTime_TIME_GET_HOUR(t);
+
+ PyDateTime_TIME_GET_MINUTE(obj);
+ PyDateTime_TIME_GET_MINUTE(t);
+
+ PyDateTime_TIME_GET_SECOND(obj);
+ PyDateTime_TIME_GET_SECOND(t);
+
+ PyDateTime_TIME_GET_MICROSECOND(obj);
+ PyDateTime_TIME_GET_MICROSECOND(t);
+
+ return obj;
+ """),
+ ("test_delta_macros", "METH_NOARGS",
+ """
+ PyObject* obj;
+ PyDateTime_Delta* delta;
+ PyDateTime_IMPORT;
+ if (!PyDateTimeAPI) {
+ PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
+ return NULL;
+ }
+ obj = PyDelta_FromDSU(6, 6, 6);
+ delta = (PyDateTime_Delta*)obj;
+
+#if defined(PYPY_VERSION) || PY_VERSION_HEX >= 0x03030000
+ // These macros are only defined in CPython 3.x and PyPy.
+ // See: http://bugs.python.org/issue13727
+ PyDateTime_DELTA_GET_DAYS(obj);
+ PyDateTime_DELTA_GET_DAYS(delta);
+
+ PyDateTime_DELTA_GET_SECONDS(obj);
+ PyDateTime_DELTA_GET_SECONDS(delta);
+
+ PyDateTime_DELTA_GET_MICROSECONDS(obj);
+ PyDateTime_DELTA_GET_MICROSECONDS(delta);
+#endif
+ return obj;
+ """),
+ ], prologue='#include "datetime.h"\n')
+ import datetime
+ assert module.test_date_macros() == datetime.date(2000, 6, 6)
+ assert module.test_datetime_macros() == datetime.datetime(
+ 2000, 6, 6, 6, 6, 6, 6)
+ assert module.test_time_macros() == datetime.time(6, 6, 6, 6)
+ assert module.test_delta_macros() == datetime.timedelta(6, 6, 6)
+
+ def test_tzinfo(self):
+ module = self.import_extension('foo', [
+ ("time_with_tzinfo", "METH_O",
+ """ PyDateTime_IMPORT;
+ return PyDateTimeAPI->Time_FromTime(
+ 6, 6, 6, 6, args, PyDateTimeAPI->TimeType);
+ """),
+ ("datetime_with_tzinfo", "METH_O",
+ """
+ PyObject * obj;
+ int tzrefcnt = args->ob_refcnt;
+ PyDateTime_IMPORT;
+ obj = PyDateTimeAPI->DateTime_FromDateAndTime(
+ 2000, 6, 6, 6, 6, 6, 6, args,
+ PyDateTimeAPI->DateTimeType);
+ if (!((PyDateTime_DateTime*)obj)->hastzinfo)
+ {
+ Py_DECREF(obj);
+ PyErr_SetString(PyExc_ValueError, "missing tzinfo");
+ return NULL;
+ }
+ if (((PyDateTime_DateTime*)obj)->tzinfo->ob_refcnt <= tzrefcnt)
+ {
+ Py_DECREF(obj);
+ PyErr_SetString(PyExc_ValueError, "tzinfo refcnt not
incremented");
+ return NULL;
+ }
+ return obj;
+
+ """),
+ ], prologue='#include "datetime.h"\n')
+ from datetime import tzinfo, datetime, timedelta, time
+ # copied from datetime documentation
+ class GMT1(tzinfo):
+ def __del__(self):
+ print('deleting GMT1')
+ def utcoffset(self, dt):
+ return timedelta(hours=1) + self.dst(dt)
+ def dst(self, dt):
+ return timedelta(0)
+ def tzname(self,dt):
+ return "GMT +1"
+ gmt1 = GMT1()
+ dt1 = module.time_with_tzinfo(gmt1)
+ assert dt1 == time(6, 6, 6, 6, gmt1)
+ assert '+01' in str(dt1)
+ dt_tz = module.datetime_with_tzinfo(gmt1)
+ assert dt_tz == datetime(2000, 6, 6, 6, 6, 6, 6, gmt1)
+
+ def test_checks(self):
+ module = self.import_extension('foo', [
+ ("checks", "METH_O",
+ """ PyDateTime_IMPORT;
+ return PyTuple_Pack(10,
+ PyBool_FromLong(PyDateTime_Check(args)),
+ PyBool_FromLong(PyDateTime_CheckExact(args)),
+ PyBool_FromLong(PyDate_Check(args)),
+ PyBool_FromLong(PyDate_CheckExact(args)),
+ PyBool_FromLong(PyTime_Check(args)),
+ PyBool_FromLong(PyTime_CheckExact(args)),
+ PyBool_FromLong(PyDelta_Check(args)),
+ PyBool_FromLong(PyDelta_CheckExact(args)),
+ PyBool_FromLong(PyTZInfo_Check(args)),
+ PyBool_FromLong(PyTZInfo_CheckExact(args))
+ );
+ """),
+ ], prologue='#include "datetime.h"\n')
+ from datetime import tzinfo, datetime, timedelta, time, date
+ o = date(1, 1, 1)
+ assert module.checks(o) == (False,) * 2 + (True,) * 2 + (False,) * 6
+ o = time(1, 1, 1)
+ assert module.checks(o) == (False,) * 4 + (True,) * 2 + (False,) * 4
+ o = timedelta(1, 1, 1)
+ assert module.checks(o) == (False,) * 6 + (True,) * 2 + (False,) * 2
+ o = datetime(1, 1, 1)
+ assert module.checks(o) == (True,) * 3 + (False,) * 7 #
isinstance(datetime, date)
+ o = tzinfo()
+ assert module.checks(o) == (False,) * 8 + (True,) * 2
+
diff --git a/pypy/module/cpyext/test/test_dictobject.py
b/pypy/module/cpyext/test/test_dictobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_dictobject.py
@@ -0,0 +1,334 @@
+import py
+from pytest import raises
+from rpython.rtyper.lltypesystem import rffi, lltype
+from pypy.module.cpyext.test.test_api import BaseApiTest, raises_w
+from pypy.module.cpyext.api import Py_ssize_tP, PyObjectP, PyTypeObjectPtr
+from pypy.module.cpyext.pyobject import make_ref, from_ref
+from pypy.interpreter.error import OperationError
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.dictproxyobject import *
+from pypy.module.cpyext.dictobject import *
+from pypy.module.cpyext.pyobject import decref
+
+class TestDictObject(BaseApiTest):
+ def test_dict(self, space):
+ d = PyDict_New(space)
+ assert space.eq_w(d, space.newdict())
+
+ assert space.eq_w(PyDict_GetItem(space, space.wrap({"a": 72}),
+ space.wrap("a")),
+ space.wrap(72))
+
+ PyDict_SetItem(space, d, space.wrap("c"), space.wrap(42))
+ assert space.eq_w(space.getitem(d, space.wrap("c")),
+ space.wrap(42))
+
+ space.setitem(d, space.wrap("name"), space.wrap(3))
+ assert space.eq_w(PyDict_GetItem(space, d, space.wrap("name")),
+ space.wrap(3))
+
+ space.delitem(d, space.wrap("name"))
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit