From: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> Date: Fri, 6 Feb 2026 09:48:55 +0000 (+0100) Subject: [3.13] gh-144330: Initialize classmethod and staticmethod in new (GH-144498) (#144537) X-Git-Tag: v3.13.13~213 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b6c6cd632115a38b0a58aa03a90deff7fb2a1295;p=thirdparty%2FPython%2Fcpython.git [3.13] gh-144330: Initialize classmethod and staticmethod in new (GH-144498) (#144537) [3.14] gh-144330: Initialize classmethod and staticmethod in new (GH-144498) gh-144330: Initialize classmethod and staticmethod in new Initialize cm_callable and sm_callable to None in classmethod and staticmethod constructor. (cherry picked from commit 160810de89477836f2fde7139f7ab0670399efff) Co-authored-by: Victor Stinner Co-authored-by: Aniket Singh Yadav Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> --- diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index be49ce8c0660..e98dccc39c17 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -5065,6 +5065,26 @@ class ClassPropertiesAndMethods(unittest.TestCase, ExtraAssertions): with self.assertRaisesRegex(NotImplementedError, "BAR"): B().foo + def test_staticmethod_new(self): + class MyStaticMethod(staticmethod): + def __init__(self, func): + pass + def func(): pass + sm = MyStaticMethod(func) + self.assertEqual(repr(sm), '') + self.assertIsNone(sm.__func__) + self.assertIsNone(sm.__wrapped__) + + def test_classmethod_new(self): + class MyClassMethod(classmethod): + def __init__(self, func): + pass + def func(): pass + cm = MyClassMethod(func) + self.assertEqual(repr(cm), '') + self.assertIsNone(cm.__func__) + self.assertIsNone(cm.__wrapped__) + class DictProxyTests(unittest.TestCase): def setUp(self): diff --git a/Objects/funcobject.c b/Objects/funcobject.c index caa58ad0f18e..61140fd4f185 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -1226,6 +1226,18 @@ cm_descr_get(PyObject *self, PyObject *obj, PyObject *type) return PyMethod_New(cm->cm_callable, type); } +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 int cm_init(PyObject *self, PyObject *args, PyObject *kwds) { @@ -1337,7 +1349,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 */ }; @@ -1415,6 +1427,18 @@ sm_descr_get(PyObject *self, PyObject *obj, PyObject *type) return Py_NewRef(sm->sm_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; +} + static int sm_init(PyObject *self, PyObject *args, PyObject *kwds) { @@ -1531,7 +1555,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 */ };