[pypy-commit] pypy cpyext-ext: rewrite the test, do not modify a readonly attribute; stcmp() instead. Exempt checking for getset, type objects

mattip pypy.commits at gmail.com
Fri Jan 15 09:33:58 EST 2016


Author: mattip <matti.picus at gmail.com>
Branch: cpyext-ext
Changeset: r81798:007d50e8afde
Date: 2016-01-15 15:48 +0200
http://bitbucket.org/pypy/pypy/changeset/007d50e8afde/

Log:	rewrite the test, do not modify a readonly attribute; stcmp()
	instead. Exempt checking for getset, type objects

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
@@ -20,7 +20,6 @@
     long long foo_longlong;
     unsigned long long foo_ulonglong;
     Py_ssize_t foo_ssizet;
-    PyObject * foo_docless;
 } fooobject;
 
 static PyTypeObject footype;
@@ -185,7 +184,6 @@
     {"longlong_member", T_LONGLONG, offsetof(fooobject, foo_longlong), 0, NULL},
     {"ulonglong_member", T_ULONGLONG, offsetof(fooobject, foo_ulonglong), 0, NULL},  
     {"ssizet_member", T_PYSSIZET, offsetof(fooobject, foo_ssizet), 0, NULL},
-    {"docless_member", T_OBJECT, offsetof(fooobject, foo_docless), READONLY, NULL},
     {NULL}  /* Sentinel */
 };
 
@@ -625,25 +623,19 @@
     (destructor)custom_dealloc, /*tp_dealloc*/
 };
 
-static PyObject * add_docstring(PyObject * self, PyObject * args)
+static PyObject * cmp_docstring(PyObject * self, PyObject * args)
 {
     PyObject *obj;
     PyObject *str;
-    char *docstr;
-    static char *msg = "already has a docstring";
+    char *docstr, *attr_as_str;
+    static char *msg = "has no docstring";
     PyObject *tp_dict = footype.tp_dict;
     PyObject *myobj;
     static PyTypeObject *PyMemberDescr_TypePtr = NULL; /* a PyMemberDescr_Type* */
     static PyTypeObject *PyGetSetDescr_TypePtr = NULL; /* a PyGetSetDescr_Type* */
     static PyTypeObject *PyMethodDescr_TypePtr = NULL; /* a PyClassMethodDescr_Type* */
 
-    /* Don't add docstrings */
-    if (Py_OptimizeFlag > 1) {
-        Py_RETURN_NONE;
-    }
-
     if (PyGetSetDescr_TypePtr == NULL) {
-        /* Get "subdescr" */
         myobj = PyDict_GetItemString(tp_dict, "name");
         if (myobj != NULL) {
             PyGetSetDescr_TypePtr = Py_TYPE(myobj);
@@ -661,63 +653,72 @@
             PyMethodDescr_TypePtr = Py_TYPE(myobj);
         }
     }
+    if (!PyArg_ParseTuple(args, "OO!", &obj, &PyString_Type, &str)) {
+        return NULL;
+    }
     if (PyMethodDescr_TypePtr == PyMemberDescr_TypePtr ||
         PyMethodDescr_TypePtr == PyGetSetDescr_TypePtr ||
         PyMemberDescr_TypePtr == PyGetSetDescr_TypePtr)
     {
         PyErr_Format(PyExc_RuntimeError, 
             "at least two of the 'Py{Method,Member,GetSet}Descr_Type's are the same\n"
-            "(in add_docstring %s %d)", __FILE__, __LINE__);
-        return NULL;
-    }
-    if (!PyArg_ParseTuple(args, "OO!", &obj, &PyString_Type, &str)) {
+            "(in cmp_docstring %s %d)", __FILE__, __LINE__);
         return NULL;
     }
     docstr = PyString_AS_STRING(str);
 #define _TESTDOC1(typebase) (Py_TYPE(obj) == &Py##typebase##_Type)
 #define _TESTDOC2(typebase) (Py_TYPE(obj) == Py##typebase##_TypePtr)
-#define _ADDDOC(typebase, doc, name) do {                               \
+#define _CMPDOC(typebase, doc, name) do {                               \
         Py##typebase##Object *new = (Py##typebase##Object *)obj;        \
         if (!(doc)) {                                                   \
-            doc = docstr;                                               \
+            PyErr_Format(PyExc_RuntimeError, "%s method %s", name, msg); \
+            return NULL;                                                \
         }                                                               \
         else {                                                          \
-            PyErr_Format(PyExc_RuntimeError, "%s method %s", name, msg); \
-            return NULL;                                                \
+            if (strcmp(doc, docstr) != 0)                               \
+            {                                                           \
+                PyErr_Format(PyExc_RuntimeError,                        \
+                             "%s method's docstring '%s' is not '%s'",  \
+                             name, doc, docstr);                        \
+                return NULL;                                            \
+            }                                                           \
         }                                                               \
     } while (0)
 
     if (_TESTDOC1(CFunction)) {
-        _ADDDOC(CFunction, new->m_ml->ml_doc, new->m_ml->ml_name);
+        _CMPDOC(CFunction, new->m_ml->ml_doc, new->m_ml->ml_name);
     }
     else if (_TESTDOC1(Type)) {
-        _ADDDOC(Type, new->tp_doc, new->tp_name);
+        _CMPDOC(Type, new->tp_doc, new->tp_name);
     }
     else if (_TESTDOC2(MemberDescr)) {
-        /* docless_member ends up here */
-        _ADDDOC(MemberDescr, new->d_member->doc, new->d_member->name);
+        _CMPDOC(MemberDescr, new->d_member->doc, new->d_member->name);
     }
     else if (_TESTDOC2(GetSetDescr)) {
-        _ADDDOC(GetSetDescr, new->d_getset->doc, new->d_getset->name);
+        //_CMPDOC(GetSetDescr, new->d_getset->doc, new->d_getset->name);
     }
     else if (_TESTDOC2(MethodDescr)) {
-        _ADDDOC(MethodDescr, new->d_method->ml_doc, new->d_method->ml_name);
+        _CMPDOC(MethodDescr, new->d_method->ml_doc, new->d_method->ml_name);
     }
     else {
         PyObject *doc_attr;
 
         doc_attr = PyObject_GetAttrString(obj, "__doc__");
-        if (doc_attr != NULL && doc_attr != Py_None) {
+        if (doc_attr == NULL || doc_attr == Py_None) {
             PyErr_Format(PyExc_RuntimeError, "object %s", msg);
             return NULL;
         }
+
+        attr_as_str = PyString_AS_STRING(doc_attr);
+        if (strcmp(attr_as_str, docstr) != 0)
+        {                                                           
+            PyErr_Format(PyExc_RuntimeError,                        
+                         "objects's docstring '%s' is not '%s'", 
+                         attr_as_str, docstr);               
+            Py_XDECREF(doc_attr);
+            return NULL;                                            
+        }                                                           
         Py_XDECREF(doc_attr);
-
-        if (PyObject_SetAttrString(obj, "__doc__", str) < 0) {
-            PyErr_SetString(PyExc_TypeError,
-                            "Cannot set a docstring for that object");
-            return NULL;
-        }
         Py_RETURN_NONE;
     }
 
@@ -725,7 +726,6 @@
 #undef _TESTDOC2
 #undef _ADDDOC
 
-    Py_INCREF(str);
     Py_RETURN_NONE;
 }
 
@@ -734,7 +734,7 @@
 static PyMethodDef foo_functions[] = {
     {"new",        (PyCFunction)foo_new, METH_NOARGS, NULL},
     {"newCustom",  (PyCFunction)newCustom, METH_NOARGS, NULL},
-    {"add_docstring",  (PyCFunction)add_docstring, METH_VARARGS, NULL},
+    {"cmp_docstring",  (PyCFunction)cmp_docstring, METH_VARARGS, NULL},
     {NULL,        NULL}    /* Sentinel */
 };
 
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
@@ -55,9 +55,21 @@
         raises(SystemError, "obj.broken_member = 42")
         assert module.fooType.broken_member.__doc__ is None
         assert module.fooType.object_member.__doc__ == "A Python object."
+        for m in dir(module.fooType):
+            obj = getattr(module.fooType, m)
+            if 'getset' in str(type(obj)):
+                # segfaults
+                continue
+            if 'type' in str(type(obj)):
+                # leaks a None reference
+                continue
+            docstring = obj.__doc__
+            if not docstring:
+                raises(RuntimeError, module.cmp_docstring, obj, 'random')
+            else:
+                import pdb;pdb.set_trace()
+                module.cmp_docstring(obj, docstring)
         assert str(type(module.fooType.int_member)) == "<type 'member_descriptor'>"
-        module.add_docstring(module.fooType.docless_member, "docstring for docless_member")
-        assert module.fooType.docless_member.__doc__ ==  "docstring for docless_member"
 
     def test_typeobject_object_member(self):
         module = self.import_module(name='foo')


More information about the pypy-commit mailing list