]> granicus.if.org Git - python/commitdiff
Issue 5982: Classmethod and staticmethod expose wrapped function with __func__.
authorRaymond Hettinger <python@rcn.com>
Fri, 29 May 2009 04:52:27 +0000 (04:52 +0000)
committerRaymond Hettinger <python@rcn.com>
Fri, 29 May 2009 04:52:27 +0000 (04:52 +0000)
Lib/test/test_funcattrs.py
Misc/NEWS
Objects/funcobject.c

index 5e47d6bf864abb8920a8dff99ce1027d0b3bab31..b42f6cc4bebbd91b6cd563c83b438882b8005159 100644 (file)
@@ -254,11 +254,23 @@ class CellTest(unittest.TestCase):
         self.assert_(cell(-36) == cell(-36.0))
         self.assert_(cell(True) > empty_cell())
 
+class StaticMethodAttrsTest(unittest.TestCase):
+    def test_func_attribute(self):
+        def f():
+            pass
+
+        c = classmethod(f)
+        self.assert_(c.__func__ is f)
+
+        s = staticmethod(f)
+        self.assert_(s.__func__ is f)
+
 
 def test_main():
     support.run_unittest(FunctionPropertiesTest, ImplicitReferencesTest,
                               ArbitraryFunctionAttrTest, FunctionDictsTest,
-                              FunctionDocstringTest, CellTest)
+                              FunctionDocstringTest, CellTest,
+                              StaticMethodAttrsTest)
 
 if __name__ == "__main__":
     test_main()
index 7d3a2370328633733c723cf3dc29d3ead2e97e8c..772ca8546a95dc582b89d9d90745bc851e343c94 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -15,6 +15,9 @@ Core and Builtins
 - Issue #6089: Fixed str.format with certain invalid field specifiers
   that would raise SystemError.
 
+- Issue #5982: staticmethod and classmethod now expose the wrapped
+  function with __func__.
+
 - Added support for multiple context managers in the same with-statement.
   Deprecated contextlib.nested() which is no longer needed.
 
index 1bb2092d66fd54fdf70f52c64dcf4dbc2794f047..acd662cb32785d4cad9609550db4e23726a61e7a 100644 (file)
@@ -775,6 +775,11 @@ cm_init(PyObject *self, PyObject *args, PyObject *kwds)
        return 0;
 }
 
+static PyMemberDef cm_memberlist[] = {
+       {"__func__", T_OBJECT, offsetof(classmethod, cm_callable), READONLY},
+       {NULL}  /* Sentinel */
+};
+
 PyDoc_STRVAR(classmethod_doc,
 "classmethod(function) -> method\n\
 \n\
@@ -825,7 +830,7 @@ PyTypeObject PyClassMethod_Type = {
        0,                                      /* tp_iter */
        0,                                      /* tp_iternext */
        0,                                      /* tp_methods */
-       0,                                      /* tp_members */
+       cm_memberlist,          /* tp_members */
        0,                                      /* tp_getset */
        0,                                      /* tp_base */
        0,                                      /* tp_dict */
@@ -925,6 +930,11 @@ sm_init(PyObject *self, PyObject *args, PyObject *kwds)
        return 0;
 }
 
+static PyMemberDef sm_memberlist[] = {
+       {"__func__", T_OBJECT, offsetof(staticmethod, sm_callable), READONLY},
+       {NULL}  /* Sentinel */
+};
+
 PyDoc_STRVAR(staticmethod_doc,
 "staticmethod(function) -> method\n\
 \n\
@@ -972,7 +982,7 @@ PyTypeObject PyStaticMethod_Type = {
        0,                                      /* tp_iter */
        0,                                      /* tp_iternext */
        0,                                      /* tp_methods */
-       0,                                      /* tp_members */
+       sm_memberlist,          /* tp_members */
        0,                                      /* tp_getset */
        0,                                      /* tp_base */
        0,                                      /* tp_dict */