[pypy-commit] pypy cpyext-injection: (plan_rich, arigo)

arigo pypy.commits at gmail.com
Thu Oct 20 10:23:02 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: cpyext-injection
Changeset: r87895:fa865a6e760a
Date: 2016-10-20 16:22 +0200
http://bitbucket.org/pypy/pypy/changeset/fa865a6e760a/

Log:	(plan_rich, arigo)

	Next level of tests pass

diff --git a/pypy/module/cpyext/injection/injection.py b/pypy/module/cpyext/injection/injection.py
--- a/pypy/module/cpyext/injection/injection.py
+++ b/pypy/module/cpyext/injection/injection.py
@@ -4,7 +4,6 @@
     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)
-    
     if name == 'numpy.ndarray':
         from pypy.module.cpyext.injection.numpy import inject_operator
         inject_operator(space, name, dict_w, pto)
@@ -20,3 +19,6 @@
     if not we_are_translated() and name == 'injection':
         from pypy.module.cpyext.injection._test_module import inject_module
         inject_module(space, w_mod, name)
+    if name == 'numpy.core.multiarray':
+        from pypy.module.cpyext.injection.numpy 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
--- a/pypy/module/cpyext/injection/numpy.py
+++ b/pypy/module/cpyext/injection/numpy.py
@@ -1,12 +1,13 @@
 from rpython.rtyper.lltypesystem import lltype, rffi
+from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.gateway import interp2app
 from pypy.interpreter.typedef import unwrap_spec, TypeDef
+from pypy.interpreter.error import oefmt
 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
-from pypy.interpreter.error import oefmt
+from pypy.objspace.std.floatobject import W_FloatObject
+
 
 PyArrayObject = lltype.Ptr(lltype.Struct(
     'PyArrayObject',
@@ -24,10 +25,15 @@
     def __init__(self, space):
         pass
 
-class W_ArrayObject(object):
+class W_ArrayObject(W_Root):
     pass
+W_ArrayObject.typedef = TypeDef("ndarray")
 
-W_ArrayObject.typedef = TypeDef("ndarray")
+class W_Float64Object(W_FloatObject):
+    def getclass(self, space):
+        org = space.fromcache(Original)
+        w_type = org.w_float64_type
+        return w_type
 
 def mything_realize(space, obj):
     intval = rffi.cast(lltype.Signed, rffi.cast(PyArrayObject, obj).foo)
@@ -47,7 +53,7 @@
     if index < 0 or index >= py_obj.dimensions[0]:
         raise oefmt(space.w_IndexError, "index out of bounds")
     data = rffi.cast(rffi.DOUBLEP, py_obj.data)
-    return space.newfloat(data[index])
+    return W_Float64Object(data[index])
 
 injected_methods = {
     '__getitem__': interp2app(injected_getitem),
@@ -59,3 +65,11 @@
     org.w_original_getitem = dict_w['__getitem__']
     for key, value in injected_methods.items():
         dict_w[key] = space.wrap(value)
+
+def inject_module(space, w_mod, name):
+    assert name == 'numpy.core.multiarray'
+    org = space.fromcache(Original)
+    w_type = space.appexec([w_mod], """(mod):
+        return mod.typeinfo['DOUBLE'][-1]
+    """)
+    org.w_float64_type = w_type
diff --git a/pypy/module/cpyext/injection/test/multiarray.c b/pypy/module/cpyext/injection/test/multiarray.c
--- a/pypy/module/cpyext/injection/test/multiarray.c
+++ b/pypy/module/cpyext/injection/test/multiarray.c
@@ -44,6 +44,70 @@
     PyObject *weakreflist;
 } PyArrayObject;
 
+typedef struct {
+    PyObject_HEAD
+    double value;
+} PyDoubleScalarObject;
+
+static PyTypeObject PyDoubleArrType_Type = {
+#if defined(NPY_PY3K)
+    PyVarObject_HEAD_INIT(NULL, 0)
+#else
+    PyObject_HEAD_INIT(NULL)
+    0,                                          /* ob_size */
+#endif
+    "numpy.float64",                            /* tp_name*/
+    sizeof(PyDoubleScalarObject),               /* tp_basicsize*/
+    0,                                          /* tp_itemsize */
+    0,                                          /* tp_dealloc */
+    0,                                          /* tp_print */
+    0,                                          /* tp_getattr */
+    0,                                          /* tp_setattr */
+#if defined(NPY_PY3K)
+    0,                                          /* tp_reserved */
+#else
+    0,                                          /* tp_compare */
+#endif
+    0,                                          /* tp_repr */
+    0,                                          /* tp_as_number */
+    0,                                          /* tp_as_sequence */
+    0,                                          /* tp_as_mapping */
+    0,                                          /* tp_hash */
+    0,                                          /* tp_call */
+    0,                                          /* tp_str */
+    0,                                          /* tp_getattro */
+    0,                                          /* tp_setattro */
+    0,                                          /* tp_as_buffer */
+    0,                                          /* tp_flags */
+    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 */
+    &PyFloat_Type,                              /* tp_base */
+    0,                                          /* tp_dict */
+    0,                                          /* tp_descr_get */
+    0,                                          /* tp_descr_set */
+    0,                                          /* tp_dictoffset */
+    0,                                          /* tp_init */
+    0,                                          /* tp_alloc */
+    0,                                          /* tp_new */
+    0,                                          /* 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 */
+};
+
 static
 void array_dealloc(PyArrayObject * self){
     free(self->data);
@@ -84,7 +148,10 @@
        value += 42;
    }
 
-   return PyFloat_FromDouble(value);
+   PyDoubleScalarObject *o = PyObject_New(PyDoubleScalarObject,
+                                          &PyDoubleArrType_Type);
+   o->value = value;
+   return (PyObject *)o;
 }
 
 static
@@ -254,6 +321,7 @@
 initmultiarray(void)
 #endif
 {
+    PyObject *infodict, *s;
 #if PY_MAJOR_VERSION >= 3
     PyObject *module = PyModule_Create(&moduledef);
 #else
@@ -265,7 +333,33 @@
     if (PyType_Ready(&PyArray_Type) < 0)
         INITERROR;
     PyModule_AddObject(module, "ndarray", (PyObject *)&PyArray_Type);
+
+    if (PyType_Ready(&PyDoubleArrType_Type) < 0)
+        INITERROR;
+    infodict = PyDict_New();
+
+    PyDict_SetItemString(infodict, "DOUBLE",
+#if defined(NPY_PY3K)
+            s = Py_BuildValue("CiiiO", whatever,
+#else
+            s = Py_BuildValue("ciiiO", 'd',
+#endif
+                12,
+                64,
+                8,
+                (PyObject *) &PyDoubleArrType_Type));
+    Py_DECREF(s);
+
+    PyModule_AddObject(module, "typeinfo", infodict);
+
 #if PY_MAJOR_VERSION >=3
     return module;
 #endif
 }
+
+PyMODINIT_FUNC
+initmultiarray_PLAIN(void)
+{
+    PyArray_Type.tp_name = "ndarray_dont_patch_me_please";
+    initmultiarray();
+}
diff --git a/pypy/module/cpyext/injection/test/test_numpy.py b/pypy/module/cpyext/injection/test/test_numpy.py
--- a/pypy/module/cpyext/injection/test/test_numpy.py
+++ b/pypy/module/cpyext/injection/test/test_numpy.py
@@ -7,9 +7,25 @@
     def setup_class(cls):
         AppTestCpythonExtensionBase.setup_class.im_func(cls)
 
-    def test_getitem_basic(self):
-        np = self.import_module(name='multiarray', filename='../injection/test/multiarray')
+    def test_float64(self):
+        np = self.import_module(name='numpy.core.multiarray',
+                                filename='../injection/test/multiarray')
+        assert type(np.typeinfo['DOUBLE'][-1]) is type
+
+    def test_plain_getitem(self):
+        np = self.import_module(name='numpy.core.multiarray_PLAIN',
+                                filename='../injection/test/multiarray')
+        array = np.ndarray(100)
+        array[10] = 1.0
+        assert array[10] == 1.0 + 42    # hacked
+        float64 = np.typeinfo['DOUBLE'][-1]
+        assert type(array[10]) is float64
+
+    def test_injected_getitem(self):
+        np = self.import_module(name='numpy.core.multiarray',
+                                filename='../injection/test/multiarray')
         array = np.ndarray(100)
         array[10] = 1.0
         assert array[10] == 1.0
-        assert type(array[10]) is np.float64
+        float64 = np.typeinfo['DOUBLE'][-1]
+        assert type(array[10]) is float64


More information about the pypy-commit mailing list