Skip to content

Commit 160810d

Browse files
vstinnerAniketsyStanFromIreland
authored
[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 <singhyadavaniket43@gmail.com> Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com>
1 parent f4239df commit 160810d

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

Lib/test/test_descr.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5138,6 +5138,26 @@ def foo(self):
51385138
with self.assertRaisesRegex(NotImplementedError, "BAR"):
51395139
B().foo
51405140

5141+
def test_staticmethod_new(self):
5142+
class MyStaticMethod(staticmethod):
5143+
def __init__(self, func):
5144+
pass
5145+
def func(): pass
5146+
sm = MyStaticMethod(func)
5147+
self.assertEqual(repr(sm), '<staticmethod(None)>')
5148+
self.assertIsNone(sm.__func__)
5149+
self.assertIsNone(sm.__wrapped__)
5150+
5151+
def test_classmethod_new(self):
5152+
class MyClassMethod(classmethod):
5153+
def __init__(self, func):
5154+
pass
5155+
def func(): pass
5156+
cm = MyClassMethod(func)
5157+
self.assertEqual(repr(cm), '<classmethod(None)>')
5158+
self.assertIsNone(cm.__func__)
5159+
self.assertIsNone(cm.__wrapped__)
5160+
51415161

51425162
class DictProxyTests(unittest.TestCase):
51435163
def setUp(self):

Objects/funcobject.c

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,18 @@ cm_descr_get(PyObject *self, PyObject *obj, PyObject *type)
14701470
return PyMethod_New(cm->cm_callable, type);
14711471
}
14721472

1473+
static PyObject *
1474+
cm_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1475+
{
1476+
classmethod *cm = (classmethod *)PyType_GenericAlloc(type, 0);
1477+
if (cm == NULL) {
1478+
return NULL;
1479+
}
1480+
cm->cm_callable = Py_None;
1481+
cm->cm_dict = NULL;
1482+
return (PyObject *)cm;
1483+
}
1484+
14731485
static int
14741486
cm_init(PyObject *self, PyObject *args, PyObject *kwds)
14751487
{
@@ -1616,7 +1628,7 @@ PyTypeObject PyClassMethod_Type = {
16161628
offsetof(classmethod, cm_dict), /* tp_dictoffset */
16171629
cm_init, /* tp_init */
16181630
PyType_GenericAlloc, /* tp_alloc */
1619-
PyType_GenericNew, /* tp_new */
1631+
cm_new, /* tp_new */
16201632
PyObject_GC_Del, /* tp_free */
16211633
};
16221634

@@ -1701,6 +1713,18 @@ sm_descr_get(PyObject *self, PyObject *obj, PyObject *type)
17011713
return Py_NewRef(sm->sm_callable);
17021714
}
17031715

1716+
static PyObject *
1717+
sm_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1718+
{
1719+
staticmethod *sm = (staticmethod *)PyType_GenericAlloc(type, 0);
1720+
if (sm == NULL) {
1721+
return NULL;
1722+
}
1723+
sm->sm_callable = Py_None;
1724+
sm->sm_dict = NULL;
1725+
return (PyObject *)sm;
1726+
}
1727+
17041728
static int
17051729
sm_init(PyObject *self, PyObject *args, PyObject *kwds)
17061730
{
@@ -1851,7 +1875,7 @@ PyTypeObject PyStaticMethod_Type = {
18511875
offsetof(staticmethod, sm_dict), /* tp_dictoffset */
18521876
sm_init, /* tp_init */
18531877
PyType_GenericAlloc, /* tp_alloc */
1854-
PyType_GenericNew, /* tp_new */
1878+
sm_new, /* tp_new */
18551879
PyObject_GC_Del, /* tp_free */
18561880
};
18571881

0 commit comments

Comments
 (0)