https://github.com/python/cpython/commit/160810de89477836f2fde7139f7ab0670399efff commit: 160810de89477836f2fde7139f7ab0670399efff branch: 3.14 author: Victor Stinner <[email protected]> committer: vstinner <[email protected]> date: 2026-02-06T10:21:02+01:00 summary:
[3.14] gh-144330: Initialize classmethod and staticmethod in new (#144498) gh-144330: Initialize classmethod and staticmethod in new Initialize cm_callable and sm_callable to None in classmethod and staticmethod constructor. Co-authored-by: Aniket Singh Yadav <[email protected]> Co-authored-by: Stan Ulbrych <[email protected]> files: M Lib/test/test_descr.py M Objects/funcobject.c diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index d420f097e74721..99f3f1ba999130 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -5138,6 +5138,26 @@ def foo(self): 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), '<staticmethod(None)>') + 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), '<classmethod(None)>') + 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 9532c21fc7082e..b870106479a607 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -1470,6 +1470,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) { @@ -1616,7 +1628,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 */ }; @@ -1701,6 +1713,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) { @@ -1851,7 +1875,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 */ }; _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
