Author: Armin Rigo <ar...@tunes.org> Branch: release-pypy2.7-5.x Changeset: r90851:32cd8a5d7221 Date: 2017-03-28 22:17 +0300 http://bitbucket.org/pypy/pypy/changeset/32cd8a5d7221/
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 @@ -1032,6 +1032,7 @@ TPSLOT("__getattribute__", tp_getattro, slot_tp_getattr_hook, wrap_binaryfunc, "x.__getattribute__('name') <==> x.name"), TPSLOT("__getattr__", tp_getattro, slot_tp_getattr, NULL, ""), + TPSLOT("__getattr__", tp_getattr, NULL, NULL, ""), TPSLOT("__setattr__", tp_setattro, slot_tp_setattro, wrap_setattr, "x.__setattr__('name', value) <==> x.name = value"), TPSLOT("__setattr__", tp_setattr, 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[] = { @@ -769,6 +797,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) @@ -791,6 +831,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 @@ -1245,3 +1245,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') _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit