summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <rhettinger@users.noreply.github.com>2023-12-21 22:08:35 (GMT)
committerGitHub <noreply@github.com>2023-12-21 22:08:35 (GMT)
commitd058eaeed44766a8291013b275ad22f153935d3b (patch)
treead04f887c91636089b4f19c85ace7997ce7c4341
parent6a5b4736e548fc5827c3bcf1a14193f77e1a989d (diff)
downloadcpython-d058eaeed44766a8291013b275ad22f153935d3b.zip
cpython-d058eaeed44766a8291013b275ad22f153935d3b.tar.gz
cpython-d058eaeed44766a8291013b275ad22f153935d3b.tar.bz2
gh-113157 gh-89519: Fix method descriptors (gh-113233)
Restore behaviors before classmethod descriptor chaining was introduced.
-rw-r--r--Lib/test/test_descr.py15
-rw-r--r--Objects/classobject.c8
2 files changed, 23 insertions, 0 deletions
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index 4a3db80..fd0af9b 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -5004,6 +5004,21 @@ class ClassPropertiesAndMethods(unittest.TestCase):
gc.collect()
self.assertEqual(Parent.__subclasses__(), [])
+ def test_instance_method_get_behavior(self):
+ # test case for gh-113157
+
+ class A:
+ def meth(self):
+ return self
+
+ class B:
+ pass
+
+ a = A()
+ b = B()
+ b.meth = a.meth.__get__(b, B)
+ self.assertEqual(b.meth(), a)
+
def test_attr_raise_through_property(self):
# test case for gh-103272
class A:
diff --git a/Objects/classobject.c b/Objects/classobject.c
index 618d888..d7e520f 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -319,6 +319,13 @@ method_traverse(PyMethodObject *im, visitproc visit, void *arg)
return 0;
}
+static PyObject *
+method_descr_get(PyObject *meth, PyObject *obj, PyObject *cls)
+{
+ Py_INCREF(meth);
+ return meth;
+}
+
PyTypeObject PyMethod_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
.tp_name = "method",
@@ -339,6 +346,7 @@ PyTypeObject PyMethod_Type = {
.tp_methods = method_methods,
.tp_members = method_memberlist,
.tp_getset = method_getset,
+ .tp_descr_get = method_descr_get,
.tp_new = method_new,
};