[pypy-commit] pypy release-pypy3.5-5.x: Issue #2523

arigo pypy.commits at gmail.com
Sun Apr 2 13:58:29 EDT 2017


Author: Armin Rigo <arigo at tunes.org>
Branch: release-pypy3.5-5.x
Changeset: r90925:3ade3b0bc2cf
Date: 2017-04-02 20:46 +0300
http://bitbucket.org/pypy/pypy/changeset/3ade3b0bc2cf/

Log:	Issue #2523

	This should fix it. The slotdefs entry was removed in 1b0451031b2e
	but we didn't have any test for that. (grafted from
	f77701c9f5706a297821c43779219df4a0aa70b0)

diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -1063,6 +1063,7 @@
            wrap_indexargfunc,
            "__imul__($self, value, /)\n--\n\nImplement self*=value."),
 
+        TPSLOT("__getattr__", tp_getattr, NULL, NULL, ""),
     {NULL}
 };
 """
diff --git a/pypy/module/cpyext/test/foo.c b/pypy/module/cpyext/test/foo.c
--- a/pypy/module/cpyext/test/foo.c
+++ b/pypy/module/cpyext/test/foo.c
@@ -670,6 +670,34 @@
     return PyInt_FromLong(tf);
 }
 
+static PyTypeObject GetType1 = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "foo.GetType1",          /*tp_name*/
+    sizeof(PyObject),        /*tp_size*/
+};
+static PyTypeObject GetType2 = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "foo.GetType2",          /*tp_name*/
+    sizeof(PyObject),        /*tp_size*/
+};
+static PyObject *gettype1, *gettype2;
+
+static PyObject *gettype1_getattr(PyObject *self, char *name)
+{
+    char buf[200];
+    strcpy(buf, "getattr:");
+    strcat(buf, name);
+    return PyString_FromString(buf);
+}
+static PyObject *gettype2_getattro(PyObject *self, PyObject *name)
+{
+    char buf[200];
+    strcpy(buf, "getattro:");
+    strcat(buf, PyString_AS_STRING(name));
+    return PyString_FromString(buf);
+}
+
+
 /* List of functions exported by this module */
 
 static PyMethodDef foo_functions[] = {
@@ -767,6 +795,18 @@
     if (PyType_Ready(&TupleLike) < 0)
         INITERROR;
 
+    GetType1.tp_flags = Py_TPFLAGS_DEFAULT;
+    GetType1.tp_getattr = &gettype1_getattr;
+    if (PyType_Ready(&GetType1) < 0)
+        INITERROR;
+    gettype1 = PyObject_New(PyObject, &GetType1);
+
+    GetType2.tp_flags = Py_TPFLAGS_DEFAULT;
+    GetType2.tp_getattro = &gettype2_getattro;
+    if (PyType_Ready(&GetType2) < 0)
+        INITERROR;
+    gettype2 = PyObject_New(PyObject, &GetType2);
+
 
     d = PyModule_GetDict(module);
     if (d == NULL)
@@ -789,6 +829,10 @@
         INITERROR;
     if (PyDict_SetItemString(d, "TupleLike", (PyObject *) &TupleLike) < 0)
         INITERROR;
+    if (PyDict_SetItemString(d, "gettype1", gettype1) < 0)
+        INITERROR;
+    if (PyDict_SetItemString(d, "gettype2", gettype2) < 0)
+        INITERROR;
 #if PY_MAJOR_VERSION >=3
     return module;
 #endif
diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -1221,3 +1221,14 @@
                 pass
             bases = module.foo(C)
             assert bases == (A, B)
+
+    def test_getattr_getattro(self):
+        module = self.import_module(name='foo')
+        assert module.gettype2.dcba == 'getattro:dcba'
+        assert (type(module.gettype2).__getattribute__(module.gettype2, 'dcBA')
+            == 'getattro:dcBA')
+        assert module.gettype1.abcd == 'getattr:abcd'
+        # GetType1 objects have a __getattribute__ method, but this
+        # doesn't call tp_getattr at all, also on CPython
+        raises(AttributeError, type(module.gettype1).__getattribute__,
+                               module.gettype1, 'dcBA')


More information about the pypy-commit mailing list