[pypy-commit] pypy cpyext-injection: (arigato, plan_rich) extend tests to a slightly bigger example (inject into numpy)

plan_rich pypy.commits at gmail.com
Thu Oct 20 08:20:12 EDT 2016


Author: Richard Plangger <planrichi at gmail.com>
Branch: cpyext-injection
Changeset: r87890:0a625570287d
Date: 2016-10-20 14:19 +0200
http://bitbucket.org/pypy/pypy/changeset/0a625570287d/

Log:	(arigato, plan_rich) extend tests to a slightly bigger example
	(inject into numpy)

diff --git a/pypy/module/cpyext/injection/injection.py b/pypy/module/cpyext/injection/injection.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/injection/injection.py
@@ -0,0 +1,18 @@
+from rpython.rlib.objectmodel import we_are_translated
+
+def inject_operators(space, name, dict_w, pto):
+    if not we_are_translated() and name == 'test_module.test_mytype':
+        from pypy.module.cpyext.injection._test_module import inject
+        inject(space, name, dict_w, pto)
+
+def inject_global(space, w_func, modulename, funcname):
+    if (not we_are_translated() and modulename == 'injection'
+          and funcname == 'make'):
+        from pypy.module.cpyext.injection._test_module import inject_global
+        w_func = inject_global(space, w_func, funcname)
+    return w_func
+
+def inject_module(space, w_mod, name):
+    if not we_are_translated() and name == 'injection':
+        from pypy.module.cpyext.injection._test_module import inject_module
+        inject_module(space, w_mod, name)
diff --git a/pypy/module/cpyext/injection/numpy.py b/pypy/module/cpyext/injection/numpy.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/injection/numpy.py
@@ -0,0 +1,41 @@
+from rpython.rtyper.lltypesystem import lltype, rffi
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.typedef import unwrap_spec, TypeDef
+from pypy.module.cpyext.pyobject import as_pyobj, make_typedescr, track_reference
+from pypy.module.cpyext.api import PyObjectFields
+from pypy.interpreter import typedef
+from pypy.objspace.std.intobject import W_IntObject
+from pypy.module.cpyext.api import bootstrap_function
+
+PyArrayObject = lltype.Ptr(lltype.Struct(
+    'PyArrayObject',
+    *(PyObjectFields + 
+        (("data", rffi.CHARP),
+         ("nd", rffi.INT),
+         ("dimensions", rffi.SIGNEDP),
+         ("strides", rffi.SIGNEDP),
+         ("base", rffi.VOIDP),
+         ("descr", rffi.VOIDP),
+        )))
+    )
+
+class Original:
+    def __init__(self, space):
+        pass
+
+class W_ArrayObject(object):
+    pass
+
+W_ArrayObject.typedef = TypeDef("ndarray")
+
+def mything_realize(space, obj):
+    intval = rffi.cast(lltype.Signed, rffi.cast(PyArrayObject, obj).foo)
+    w_obj = W_ArrayObject(intval)
+    track_reference(space, obj, w_obj)
+    return w_obj
+
+ at bootstrap_function
+def init_mything(space):
+    make_typedescr(W_ArrayObject.typedef,
+                   basestruct=mytype_object.TO,
+                   realize=mything_realize)
diff --git a/pypy/module/cpyext/injection/test/injection.c b/pypy/module/cpyext/injection/test/injection.c
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/injection/test/injection.c
@@ -0,0 +1,146 @@
+#include "Python.h"
+
+typedef struct {
+    PyObject_HEAD
+    long foo;
+} mytype_object;
+
+
+static PyObject *
+mytype_item(mytype_object *o, Py_ssize_t i)
+{
+    return PyInt_FromLong(i + o->foo);
+}
+
+static PyObject *
+mytype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    mytype_object *o = (mytype_object *)type->tp_alloc(type, 0);
+    o->foo = 42;
+    return (PyObject *)o;
+}
+
+static PySequenceMethods mytype_as_sequence = {
+    (lenfunc)0,                      /*sq_length*/
+    (binaryfunc)0,                   /*sq_concat*/
+    (ssizeargfunc)0,                 /*sq_repeat*/
+    (ssizeargfunc)mytype_item,       /*sq_item*/
+};
+
+static PyTypeObject mytype_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "test_module.test_mytype",   /*tp_name*/
+    sizeof(mytype_object),       /*tp_size*/
+    0,                       /*tp_itemsize*/
+    /* methods */
+    0,                       /*tp_dealloc*/
+    0,                       /*tp_print*/
+    0,                       /*tp_getattr*/
+    0,                       /*tp_setattr*/
+    0,                       /*tp_compare*/
+    0,                       /*tp_repr*/
+    0,                       /*tp_as_number*/
+    &mytype_as_sequence,     /*tp_as_sequence*/
+    0,                       /*tp_as_mapping*/
+    0,                       /*tp_hash*/
+    0,                       /*tp_call*/
+    0,                       /*tp_str*/
+    0,                       /*tp_getattro*/
+    0,                       /*tp_setattro*/
+    0,                       /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+    0,                       /*tp_doc*/
+    0,                       /*tp_traverse*/
+    0,                       /*tp_clear*/
+    0,                       /*tp_richcompare*/
+    0,                       /*tp_weaklistoffset*/
+    0,                       /*tp_iter*/
+    0,                       /*tp_iternext*/
+    0,                       /*tp_methods*/
+    0,                       /*tp_members*/
+    0,                       /*tp_getset*/
+    &PyInt_Type,                                /* tp_base */
+    0,                                          /* tp_dict */
+    0,                                          /* tp_descr_get */
+    0,                                          /* tp_descr_set */
+    0,                                          /* tp_dictoffset */
+    0,                                          /* tp_init */
+    PyType_GenericAlloc,                        /* tp_alloc */
+    mytype_new,                                 /* tp_new */
+    PyObject_Del,                               /* tp_free */
+};
+
+
+static PyObject *glob_make(PyObject *self, PyObject *args)
+{
+    int i;
+    if (!PyArg_ParseTuple(args, "i", &i))
+        return NULL;
+
+    PyTypeObject *type = &mytype_type;
+    mytype_object *o = (mytype_object *)type->tp_alloc(type, 0);
+    o->foo = i;
+    return (PyObject *)o;
+}
+
+/* List of functions exported by this module */
+
+static PyMethodDef foo_functions[] = {
+    {"make",      (PyCFunction)glob_make, METH_VARARGS, NULL},
+    {NULL,        NULL}    /* Sentinel */
+};
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+    PyModuleDef_HEAD_INIT,
+    "injection",
+    "Module Doc",
+    -1,
+    foo_functions,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+};
+#define INITERROR return NULL
+
+/* Initialize this module. */
+#ifdef __GNUC__
+extern __attribute__((visibility("default")))
+#else
+extern __declspec(dllexport)
+#endif
+
+PyMODINIT_FUNC
+PyInit_foo(void)
+
+#else
+
+#define INITERROR return
+
+/* Initialize this module. */
+#ifdef __GNUC__
+extern __attribute__((visibility("default")))
+#else
+extern __declspec(dllexport)
+#endif
+
+PyMODINIT_FUNC
+initinjection(void)
+#endif
+{
+#if PY_MAJOR_VERSION >= 3
+    PyObject *module = PyModule_Create(&moduledef);
+#else
+    PyObject *module = Py_InitModule("injection", foo_functions);
+#endif
+    if (module == NULL)
+        INITERROR;
+
+    if (PyType_Ready(&mytype_type) < 0)
+        INITERROR;
+    PyModule_AddObject(module, "test_mytype", (PyObject *)&mytype_type);
+#if PY_MAJOR_VERSION >=3
+    return module;
+#endif
+}
diff --git a/pypy/module/cpyext/injection/test/multiarray.c b/pypy/module/cpyext/injection/test/multiarray.c
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/injection/test/multiarray.c
@@ -0,0 +1,195 @@
+#include "Python.h"
+
+typedef Py_intptr_t npy_intp;
+
+typedef struct _PyArray_Descr  PyArray_Descr;
+
+typedef struct tagPyArrayObject_fields {
+    PyObject_HEAD
+    /* Pointer to the raw data buffer */
+    char *data;
+    /* The number of dimensions, also called 'ndim' */
+    int nd;
+    /* The size in each dimension, also called 'shape' */
+    npy_intp *dimensions;
+    /*
+     * Number of bytes to jump to get to the
+     * next element in each dimension
+     */
+    npy_intp *strides;
+    /*
+     * This object is decref'd upon
+     * deletion of array. Except in the
+     * case of UPDATEIFCOPY which has
+     * special handling.
+     *
+     * For views it points to the original
+     * array, collapsed so no chains of
+     * views occur.
+     *
+     * For creation from buffer object it
+     * points to an object that should be
+     * decref'd on deletion
+     *
+     * For UPDATEIFCOPY flag this is an
+     * array to-be-updated upon deletion
+     * of this one
+     */
+    PyObject *base;
+    /* Pointer to type structure */
+    PyArray_Descr *descr;
+    /* Flags describing array -- see below */
+    int flags;
+    /* For weak references */
+    PyObject *weakreflist;
+} PyArrayObject;
+
+static
+void array_dealloc(PyArrayObject * self){
+    Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static
+PyTypeObject PyArray_Type = {
+#if defined(NPY_PY3K)
+    PyVarObject_HEAD_INIT(NULL, 0)
+#else
+    PyObject_HEAD_INIT(NULL)
+    0,                                          /* ob_size */
+#endif
+    "numpy.ndarray",                            /* tp_name */
+    sizeof(PyArrayObject),                      /* tp_basicsize */
+    0,                                          /* tp_itemsize */
+    /* methods */
+    (destructor)array_dealloc,                  /* tp_dealloc */
+    (printfunc)NULL,                            /* tp_print */
+    0,                                          /* tp_getattr */
+    0,                                          /* tp_setattr */
+#if defined(NPY_PY3K)
+    0,                                          /* tp_reserved */
+#else
+    0,                                          /* tp_compare */
+#endif
+    (reprfunc)NULL,                       /* tp_repr */
+    0,
+    //&array_as_number,                           /* tp_as_number */
+    0,
+    //&array_as_sequence,                         /* tp_as_sequence */
+    0,
+    //&array_as_mapping,                          /* tp_as_mapping */
+    /*
+     * The tp_hash slot will be set PyObject_HashNotImplemented when the
+     * module is loaded.
+     */
+    (hashfunc)0,                                /* tp_hash */
+    (ternaryfunc)0,                             /* tp_call */
+    0,
+    //(reprfunc)array_str,                        /* tp_str */
+    (getattrofunc)0,                            /* tp_getattro */
+    (setattrofunc)0,                            /* tp_setattro */
+    0,
+    //&array_as_buffer,                           /* tp_as_buffer */
+    (Py_TPFLAGS_DEFAULT
+#if !defined(NPY_PY3K)
+     | Py_TPFLAGS_CHECKTYPES
+     | Py_TPFLAGS_HAVE_NEWBUFFER
+#endif
+     | Py_TPFLAGS_BASETYPE),                    /* tp_flags */
+    0,                                          /* tp_doc */
+
+    (traverseproc)0,                            /* tp_traverse */
+    (inquiry)0,                                 /* tp_clear */
+    0,
+    //(richcmpfunc)array_richcompare,             /* tp_richcompare */
+    offsetof(PyArrayObject, weakreflist), /* tp_weaklistoffset */
+    0,
+    //(getiterfunc)array_iter,                    /* tp_iter */
+    (iternextfunc)0,                            /* tp_iternext */
+    0,
+    //array_methods,                              /* tp_methods */
+    0,                                          /* tp_members */
+    0,
+    //array_getsetlist,                           /* tp_getset */
+    0,                                          /* tp_base */
+    0,                                          /* tp_dict */
+    0,                                          /* tp_descr_get */
+    0,                                          /* tp_descr_set */
+    0,                                          /* tp_dictoffset */
+    (initproc)0,                                /* tp_init */
+    0,
+    //(allocfunc)array_alloc,                     /* tp_alloc */
+    0,
+    //(newfunc)array_new,                         /* tp_new */
+    0,
+    //(freefunc)array_free,                       /* tp_free */
+    0,                                          /* tp_is_gc */
+    0,                                          /* tp_bases */
+    0,                                          /* tp_mro */
+    0,                                          /* tp_cache */
+    0,                                          /* tp_subclasses */
+    0,                                          /* tp_weaklist */
+    0,                                          /* tp_del */
+    0,                                          /* tp_version_tag */
+};
+
+/* List of functions exported by this module */
+
+static PyMethodDef multiarray_functions[] = {
+    //{"make",      (PyCFunction)glob_make, METH_VARARGS, NULL},
+    {NULL,        NULL}    /* Sentinel */
+};
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+    PyModuleDef_HEAD_INIT,
+    "numpy.core.multiarray",
+    "Module Doc",
+    -1,
+    multiarray_functions,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+};
+#define INITERROR return NULL
+
+/* Initialize this module. */
+#ifdef __GNUC__
+extern __attribute__((visibility("default")))
+#else
+extern __declspec(dllexport)
+#endif
+
+PyMODINIT_FUNC
+PyInit_multiarray(void)
+
+#else
+
+#define INITERROR return
+
+/* Initialize this module. */
+#ifdef __GNUC__
+extern __attribute__((visibility("default")))
+#else
+extern __declspec(dllexport)
+#endif
+
+PyMODINIT_FUNC
+initmultiarray(void)
+#endif
+{
+#if PY_MAJOR_VERSION >= 3
+    PyObject *module = PyModule_Create(&moduledef);
+#else
+    PyObject *module = Py_InitModule("numpy.core.multiarray", multiarray_functions);
+#endif
+    if (module == NULL)
+        INITERROR;
+
+    if (PyType_Ready(&PyArray_Type) < 0)
+        INITERROR;
+    PyModule_AddObject(module, "ndarray", (PyObject *)&PyArray_Type);
+#if PY_MAJOR_VERSION >=3
+    return module;
+#endif
+}
diff --git a/pypy/module/cpyext/injection/test/test_injection.py b/pypy/module/cpyext/injection/test/test_injection.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/injection/test/test_injection.py
@@ -0,0 +1,37 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.pyobject import _has_a_pyobj
+from pypy.interpreter.gateway import interp2app
+
+class AppTestTypeObject(AppTestCpythonExtensionBase):
+
+    def setup_class(cls):
+        def is_there_an_pyobj_version(space, w_obj):
+            if _has_a_pyobj(space, w_obj):
+                return space.w_True
+            return space.w_False
+        cls.w_is_there_an_pyobj_version = cls.space.wrap(
+                         interp2app(is_there_an_pyobj_version))
+        AppTestCpythonExtensionBase.setup_class.im_func(cls)
+
+    def test_getitem_basic(self):
+        module = self.import_module(name='injection', filename='../injection/test/injection')
+        mything = module.test_mytype()
+        assert mything[100] == 4200
+        assert mything[-100] == -100+42
+
+    def test_glob_make(self):
+        module = self.import_module(name='injection', filename='../injection/test/injection')
+        mything = module.make(5)
+        assert mything is Ellipsis
+        mything = module.make(15)
+        assert mything[-100] == -100+15
+
+    def test_pypy_only_version_of_object(self):
+        module = self.import_module(name='injection', filename='../injection/test/injection')
+        mything = module.make(25)
+        assert not self.is_there_an_pyobj_version(mything)
+        assert mything[100] == 25*100
+        assert not self.is_there_an_pyobj_version(mything)
+        assert mything[-100] == -100+25
+        assert self.is_there_an_pyobj_version(mything)
+
diff --git a/pypy/module/cpyext/injection/test/test_numpy.py b/pypy/module/cpyext/injection/test/test_numpy.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/injection/test/test_numpy.py
@@ -0,0 +1,11 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.pyobject import _has_a_pyobj
+from pypy.interpreter.gateway import interp2app
+
+class AppTestTypeObject(AppTestCpythonExtensionBase):
+
+    def setup_class(cls):
+        AppTestCpythonExtensionBase.setup_class.im_func(cls)
+
+    def test_getitem_basic(self):
+        module = self.import_module(name='multiarray', filename='../injection/test/multiarray')
diff --git a/pypy/module/cpyext/test/injection.c b/pypy/module/cpyext/test/injection.c
deleted file mode 100644
--- a/pypy/module/cpyext/test/injection.c
+++ /dev/null
@@ -1,146 +0,0 @@
-#include "Python.h"
-
-typedef struct {
-    PyObject_HEAD
-    long foo;
-} mytype_object;
-
-
-static PyObject *
-mytype_item(mytype_object *o, Py_ssize_t i)
-{
-    return PyInt_FromLong(i + o->foo);
-}
-
-static PyObject *
-mytype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    mytype_object *o = (mytype_object *)type->tp_alloc(type, 0);
-    o->foo = 42;
-    return (PyObject *)o;
-}
-
-static PySequenceMethods mytype_as_sequence = {
-    (lenfunc)0,                      /*sq_length*/
-    (binaryfunc)0,                   /*sq_concat*/
-    (ssizeargfunc)0,                 /*sq_repeat*/
-    (ssizeargfunc)mytype_item,       /*sq_item*/
-};
-
-static PyTypeObject mytype_type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "test_module.test_mytype",   /*tp_name*/
-    sizeof(mytype_object),       /*tp_size*/
-    0,                       /*tp_itemsize*/
-    /* methods */
-    0,                       /*tp_dealloc*/
-    0,                       /*tp_print*/
-    0,                       /*tp_getattr*/
-    0,                       /*tp_setattr*/
-    0,                       /*tp_compare*/
-    0,                       /*tp_repr*/
-    0,                       /*tp_as_number*/
-    &mytype_as_sequence,     /*tp_as_sequence*/
-    0,                       /*tp_as_mapping*/
-    0,                       /*tp_hash*/
-    0,                       /*tp_call*/
-    0,                       /*tp_str*/
-    0,                       /*tp_getattro*/
-    0,                       /*tp_setattro*/
-    0,                       /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
-    0,                       /*tp_doc*/
-    0,                       /*tp_traverse*/
-    0,                       /*tp_clear*/
-    0,                       /*tp_richcompare*/
-    0,                       /*tp_weaklistoffset*/
-    0,                       /*tp_iter*/
-    0,                       /*tp_iternext*/
-    0,                       /*tp_methods*/
-    0,                       /*tp_members*/
-    0,                       /*tp_getset*/
-    &PyInt_Type,                                /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    PyType_GenericAlloc,                        /* tp_alloc */
-    mytype_new,                                 /* tp_new */
-    PyObject_Del,                               /* tp_free */
-};
-
-
-static PyObject *glob_make(PyObject *self, PyObject *args)
-{
-    int i;
-    if (!PyArg_ParseTuple(args, "i", &i))
-        return NULL;
-
-    PyTypeObject *type = &mytype_type;
-    mytype_object *o = (mytype_object *)type->tp_alloc(type, 0);
-    o->foo = i;
-    return (PyObject *)o;
-}
-
-/* List of functions exported by this module */
-
-static PyMethodDef foo_functions[] = {
-    {"make",      (PyCFunction)glob_make, METH_VARARGS, NULL},
-    {NULL,        NULL}    /* Sentinel */
-};
-
-#if PY_MAJOR_VERSION >= 3
-static struct PyModuleDef moduledef = {
-    PyModuleDef_HEAD_INIT,
-    "injection",
-    "Module Doc",
-    -1,
-    foo_functions,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-};
-#define INITERROR return NULL
-
-/* Initialize this module. */
-#ifdef __GNUC__
-extern __attribute__((visibility("default")))
-#else
-extern __declspec(dllexport)
-#endif
-
-PyMODINIT_FUNC
-PyInit_foo(void)
-
-#else
-
-#define INITERROR return
-
-/* Initialize this module. */
-#ifdef __GNUC__
-extern __attribute__((visibility("default")))
-#else
-extern __declspec(dllexport)
-#endif
-
-PyMODINIT_FUNC
-initinjection(void)
-#endif
-{
-#if PY_MAJOR_VERSION >= 3
-    PyObject *module = PyModule_Create(&moduledef);
-#else
-    PyObject *module = Py_InitModule("injection", foo_functions);
-#endif
-    if (module == NULL)
-        INITERROR;
-
-    if (PyType_Ready(&mytype_type) < 0)
-        INITERROR;
-    PyModule_AddObject(module, "test_mytype", (PyObject *)&mytype_type);
-#if PY_MAJOR_VERSION >=3
-    return module;
-#endif
-}
diff --git a/pypy/module/cpyext/test/test_injection.py b/pypy/module/cpyext/test/test_injection.py
deleted file mode 100644
--- a/pypy/module/cpyext/test/test_injection.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
-from pypy.module.cpyext.pyobject import _has_a_pyobj
-from pypy.interpreter.gateway import interp2app
-
-class AppTestTypeObject(AppTestCpythonExtensionBase):
-
-    def setup_class(cls):
-        def is_there_an_pyobj_version(space, w_obj):
-            if _has_a_pyobj(space, w_obj):
-                return space.w_True
-            return space.w_False
-        cls.w_is_there_an_pyobj_version = cls.space.wrap(
-                         interp2app(is_there_an_pyobj_version))
-        AppTestCpythonExtensionBase.setup_class.im_func(cls)
-
-    def test_getitem_basic(self):
-        module = self.import_module(name='injection')
-        mything = module.test_mytype()
-        assert mything[100] == 4200
-        assert mything[-100] == -100+42
-
-    def test_glob_make(self):
-        module = self.import_module(name='injection')
-        mything = module.make(5)
-        assert mything is Ellipsis
-        mything = module.make(15)
-        assert mything[-100] == -100+15
-
-    def test_pypy_only_version_of_object(self):
-        module = self.import_module(name='injection')
-        mything = module.make(25)
-        assert not self.is_there_an_pyobj_version(mything)
-        assert mything[100] == 25*100
-        assert not self.is_there_an_pyobj_version(mything)
-        assert mything[-100] == -100+25
-        assert self.is_there_an_pyobj_version(mything)
-


More information about the pypy-commit mailing list