diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 82a48ad4d1aced..3591d3c1e1d7fa 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1832,6 +1832,24 @@ def test_staticmethods_in_c(self): self.assertEqual(a, a1) self.assertEqual(d, d1) + def test_staticmethod_new(self): + sm = staticmethod.__new__(staticmethod, None) + self.assertEqual(repr(sm), '') + + def test_classmethod_new(self): + cm = classmethod.__new__(classmethod, None) + self.assertEqual(repr(cm), '') + + def test_staticmethod_func_readonly(self): + sm = staticmethod(lambda x: x) + with self.assertRaises(AttributeError): + sm.__func__ = None + + def test_classmethod_func_readonly(self): + cm = classmethod(lambda x: x) + with self.assertRaises(AttributeError): + cm.__func__ = None + def test_classic(self): # Testing classic classes... class C: diff --git a/Objects/funcobject.c b/Objects/funcobject.c index b659ac8023373b..c8acd109189c41 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -1555,11 +1555,24 @@ static PyMethodDef cm_methodlist[] = { {NULL} /* Sentinel */ }; +static PyObject * +cm_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + classmethod *cm = (classmethod *)PyType_GenericAlloc(type, 0); + if (cm == NULL) { + return NULL; + } + cm->cm_callable = Py_None; + cm->cm_dict = NULL; + return (PyObject *)cm; +} + static PyObject* cm_repr(PyObject *self) { classmethod *cm = _PyClassMethod_CAST(self); - return PyUnicode_FromFormat("", cm->cm_callable); + PyObject *callable = cm->cm_callable != NULL ? cm->cm_callable : Py_None; + return PyUnicode_FromFormat("", callable); } PyDoc_STRVAR(classmethod_doc, @@ -1623,7 +1636,7 @@ PyTypeObject PyClassMethod_Type = { offsetof(classmethod, cm_dict), /* tp_dictoffset */ cm_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ + cm_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; @@ -1796,7 +1809,20 @@ static PyObject* sm_repr(PyObject *self) { staticmethod *sm = _PyStaticMethod_CAST(self); - return PyUnicode_FromFormat("", sm->sm_callable); + PyObject *callable = sm->sm_callable != NULL ? sm->sm_callable : Py_None; + return PyUnicode_FromFormat("", callable); +} + +static PyObject * +sm_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + staticmethod *sm = (staticmethod *)PyType_GenericAlloc(type, 0); + if (sm == NULL) { + return NULL; + } + sm->sm_callable = Py_None; + sm->sm_dict = NULL; + return (PyObject *)sm; } PyDoc_STRVAR(staticmethod_doc, @@ -1858,7 +1884,7 @@ PyTypeObject PyStaticMethod_Type = { offsetof(staticmethod, sm_dict), /* tp_dictoffset */ sm_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ + sm_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ };