Restore special method docstrings.
authorRobert Bradshaw <robertwb@math.washington.edu>
Sun, 15 Aug 2010 07:12:36 +0000 (00:12 -0700)
committerRobert Bradshaw <robertwb@math.washington.edu>
Sun, 15 Aug 2010 07:12:36 +0000 (00:12 -0700)
Cython/Compiler/ModuleNode.py
Cython/Compiler/Naming.py
Cython/Compiler/Nodes.py

index e8099b8feb14b6ff1d2e6e696fc83964c7c82812..cfc04096daf7efba351d866db096a5c45cc8daac 100644 (file)
@@ -2041,6 +2041,29 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                     "if (PyType_Ready(&%s) < 0) %s" % (
                         typeobj_cname,
                         code.error_goto(entry.pos)))
+                # Fix special method docstrings. This is a bit of a hack, but 
+                # unless we let PyType_Ready create the slot wrappers we have
+                # a significant performance hit. (See trac #561.) 
+                for func in entry.type.scope.pyfunc_entries:
+                    if func.is_special and func.doc:
+                        code.putln("{");
+                        code.putln(
+                            'PyObject *wrapper = PyObject_GetAttrString((PyObject *)&%s, "%s"); %s' % (
+                                typeobj_cname,
+                                func.name,
+                                code.error_goto_if_null('wrapper', entry.pos)));
+                        code.putln(
+                            "if (Py_TYPE(wrapper) == &PyWrapperDescr_Type) {");
+                        code.putln(
+                            "%s = *((PyWrapperDescrObject *)wrapper)->d_base;" % (
+                                func.wrapperbase_cname));
+                        code.putln(
+                            "%s.doc = %s;" % (func.wrapperbase_cname, func.doc_cname));
+                        code.putln(
+                            "((PyWrapperDescrObject *)wrapper)->d_base = &%s;" % (
+                                func.wrapperbase_cname));
+                        code.putln("}");
+                        code.putln("}");
                 if type.vtable_cname:
                     code.putln(
                         "if (__Pyx_SetVtable(%s.tp_dict, %s) < 0) %s" % (
index 9413a696ac9cc8c341c7664ee8e81bdb4c430b65..d351efd6a73cbdd24e989a448f6d207927c0dd7d 100644 (file)
@@ -35,6 +35,7 @@ prop_set_prefix   = pyrex_prefix + "setprop_"
 type_prefix       = pyrex_prefix + "t_"
 typeobj_prefix    = pyrex_prefix + "type_"
 var_prefix        = pyrex_prefix + "v_"
+wrapperbase_prefix= pyrex_prefix + "wrapperbase_"
 bufstruct_prefix  = pyrex_prefix + "bstruct_"
 bufstride_prefix  = pyrex_prefix + "bstride_"
 bufshape_prefix   = pyrex_prefix + "bshape_"
index 05ce3c965aba325ca363235870b15a4b483abebf..5c0d273b3cdc5b5b91cc562598cc5e5e8f4d790f 100644 (file)
@@ -2110,6 +2110,8 @@ class DefNode(FuncDefNode):
             entry.doc = embed_position(self.pos, self.doc)
             entry.doc_cname = \
                 Naming.funcdoc_prefix + prefix + name
+            if entry.is_special:
+                entry.wrapperbase_cname = Naming.wrapperbase_prefix + prefix + name
         else:
             entry.doc = None
 
@@ -2224,10 +2226,7 @@ class DefNode(FuncDefNode):
         if proto_only:
             return
         if (Options.docstrings and self.entry.doc and
-            (not self.entry.is_special or
-             self.entry.signature.method_flags()) and
-            not self.entry.scope.is_property_scope
-            ):
+                not self.entry.scope.is_property_scope):
             docstr = self.entry.doc
             if docstr.is_unicode:
                 docstr = docstr.utf8encode()
@@ -2235,6 +2234,9 @@ class DefNode(FuncDefNode):
                 'static char %s[] = "%s";' % (
                     self.entry.doc_cname,
                     split_string_literal(escape_byte_string(docstr))))
+            if self.entry.is_special:
+                code.putln(
+                    "struct wrapperbase %s;" % self.entry.wrapperbase_cname)
         if with_pymethdef:
             code.put(
                 "static PyMethodDef %s = " %