[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