Skip to content
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
e97e3ec
Initialize staticmethod/classmethod callables in tp_new
Aniketsy Jan 31, 2026
a81471a
Merge branch 'main' into fix-144330
Aniketsy Jan 31, 2026
623d522
Update Objects/funcobject.c
Aniketsy Feb 3, 2026
fc67291
Update Objects/funcobject.c
Aniketsy Feb 3, 2026
56f8640
Update Lib/test/test_descr.py
Aniketsy Feb 3, 2026
ab784f0
Update Lib/test/test_descr.py
Aniketsy Feb 3, 2026
270d183
Update Lib/test/test_descr.py
Aniketsy Feb 3, 2026
c2dd91b
Update Lib/test/test_descr.py
Aniketsy Feb 3, 2026
0eb94d2
Fix unused variable 'COLORS' warning in optimizer.c (#144373)
aisk Feb 1, 2026
250efa2
gh-144348: annotationlib: fix test that relies on set ordering (#144359)
JelleZijlstra Feb 1, 2026
11281c0
gh-143904: Raise OverflowError instead of IndexError for too large of…
serhiy-storchaka Feb 1, 2026
0a02e4f
gh-144277: Fix usage of free-threaded terminology in the documentatio…
ZeroIntensity Feb 2, 2026
d8d92b7
gh-144380: Fix incorrect type check in `buffered_iternext()` (#144381)
ruiyangke Feb 2, 2026
02ad4c9
docs: update dangling reference to `LOAD_METHOD` in dis.rst (#144358)
guilhermeleobas Feb 2, 2026
a09aa1e
gh-115231: Fill __module__ for built-in staticmethods (#115232)
skirpichev Feb 2, 2026
2e5794e
gh-144001: Simplify Base64 decoding with altchars and ignorechars spe…
serhiy-storchaka Feb 2, 2026
1f9b093
gh-144145: Revert PR#144122 for performance and potential bugs. (GH-1…
cocolato Feb 2, 2026
b9a7530
gh-134160: "First extension module" tutorial improvements (GH-144183)
encukou Feb 2, 2026
4ffc8fe
gh-142555: Fix null pointer dereference in array.__setitem__ via re-e…
aisk Feb 2, 2026
c5fa3a9
gh-144242: Note that issues aren't needed for typos in docs template …
StanFromIreland Feb 2, 2026
65cee10
gh-144376: Only run 'address' fuzzer for python3-libraries (#144398)
sethmlarson Feb 2, 2026
c6f9612
GH-144179: Add value recording to JIT tracing front-end (GH-144303)
markshannon Feb 2, 2026
9c07998
gh-139109: Replace `_CHECK_STACK_SPACE` with `_CHECK_STACK_SPACE_OPER…
cocolato Feb 2, 2026
20535dc
gh-75572: Speed up test_xpickle (GH-144393)
serhiy-storchaka Feb 2, 2026
a01abdb
gh-144415: Android testbed fixes (#142912)
mhsmith Feb 3, 2026
79abde1
gh-139103: use `METH_FASTCALL` for tp_new_wrapper (#144406)
colesbury Feb 3, 2026
487ebdf
gh-132888: Fix Windows API error checking in pyrepl.windows_console (…
aisk Feb 3, 2026
baa7fd2
gh-144377: Clean up sqlite3 Connection's list of weakrefs to Cursor o…
takluyver Feb 3, 2026
cc363d5
gh-142956: Update `tomllib` to parse TOML 1.1.0 (#144243)
hukkin Feb 3, 2026
de7cedc
gh-106318: Add examples for str.rindex() method (#143887)
adorilson Feb 3, 2026
c3b31ea
gh-74453: Add stronger security warning to os.path.commonprefix (GH-1…
sethmlarson Feb 3, 2026
6f4730c
Initialize staticmethod/classmethod callables in tp_new
Aniketsy Feb 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Lib/test/test_descr.py
Original file line number Diff line number Diff line change
Expand Up @@ -1831,6 +1831,24 @@ def test_refleaks_in_staticmethod___init__(self):
sm.__init__(None)
self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10)

def test_staticmethod_new(self):
sm = staticmethod.__new__(staticmethod, None)
self.assertEqual(repr(sm), '<staticmethod(None)>')

def test_classmethod_new_none_repr(self):
Comment thread
Aniketsy marked this conversation as resolved.
Outdated
cm = classmethod.__new__(classmethod, None)
self.assertEqual(repr(cm), '<classmethod(None)>')

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

@support.impl_detail("the module 'xxsubtype' is internal")
@unittest.skipIf(xxsubtype is None, "requires xxsubtype module")
def test_staticmethods_in_c(self):
Expand Down
36 changes: 32 additions & 4 deletions Objects/funcobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1555,11 +1555,15 @@ static PyMethodDef cm_methodlist[] = {
{NULL} /* Sentinel */
};

static PyObject *cm_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
static PyObject *sm_new(PyTypeObject *type, PyObject *args, PyObject *kwds);

static PyObject*
cm_repr(PyObject *self)
{
classmethod *cm = _PyClassMethod_CAST(self);
return PyUnicode_FromFormat("<classmethod(%R)>", cm->cm_callable);
PyObject *callable = cm->cm_callable != NULL ? cm->cm_callable : Py_None;
return PyUnicode_FromFormat("<classmethod(%R)>", callable);
}

PyDoc_STRVAR(classmethod_doc,
Expand Down Expand Up @@ -1623,7 +1627,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 */
};

Expand All @@ -1638,6 +1642,18 @@ PyClassMethod_New(PyObject *callable)
return (PyObject *)cm;
}

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;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move cm_new() before PyClassMethod_Type, so you don't need to declare it in advance (remove forward declaration line 1558).



/* Static method object */

Expand Down Expand Up @@ -1796,7 +1812,8 @@ static PyObject*
sm_repr(PyObject *self)
{
staticmethod *sm = _PyStaticMethod_CAST(self);
return PyUnicode_FromFormat("<staticmethod(%R)>", sm->sm_callable);
PyObject *callable = sm->sm_callable != NULL ? sm->sm_callable : Py_None;
return PyUnicode_FromFormat("<staticmethod(%R)>", callable);
}

PyDoc_STRVAR(staticmethod_doc,
Expand Down Expand Up @@ -1858,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 */
};

Expand All @@ -1872,3 +1889,14 @@ PyStaticMethod_New(PyObject *callable)
}
return (PyObject *)sm;
}

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_NewRef(Py_None);
sm->sm_dict = NULL;
return (PyObject *)sm;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move sm_new() before PyStaticMethod_Type.

Loading