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&#228;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&#228;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

Reply via email to