summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_super.py46
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2023-07-21-14-37-48.gh-issue-106917.1jWp_m.rst4
-rw-r--r--Python/bytecodes.c2
-rw-r--r--Python/executor_cases.c.h2
-rw-r--r--Python/generated_cases.c.h2
5 files changed, 51 insertions, 5 deletions
diff --git a/Lib/test/test_super.py b/Lib/test/test_super.py
index 664cf70..43162c5 100644
--- a/Lib/test/test_super.py
+++ b/Lib/test/test_super.py
@@ -5,6 +5,9 @@ from unittest.mock import patch
from test import shadowed_super
+ADAPTIVE_WARMUP_DELAY = 2
+
+
class A:
def f(self):
return 'A'
@@ -419,8 +422,47 @@ class TestSuper(unittest.TestCase):
super(MyType, type(mytype)).__setattr__(mytype, "bar", 1)
self.assertEqual(mytype.bar, 1)
- test("foo1")
- test("foo2")
+ for _ in range(ADAPTIVE_WARMUP_DELAY):
+ test("foo1")
+
+ def test_reassigned_new(self):
+ class A:
+ def __new__(cls):
+ pass
+
+ def __init_subclass__(cls):
+ if "__new__" not in cls.__dict__:
+ cls.__new__ = cls.__new__
+
+ class B(A):
+ pass
+
+ class C(B):
+ def __new__(cls):
+ return super().__new__(cls)
+
+ for _ in range(ADAPTIVE_WARMUP_DELAY):
+ C()
+
+ def test_mixed_staticmethod_hierarchy(self):
+ # This test is just a desugared version of `test_reassigned_new`
+ class A:
+ @staticmethod
+ def some(cls, *args, **kwargs):
+ self.assertFalse(args)
+ self.assertFalse(kwargs)
+
+ class B(A):
+ def some(cls, *args, **kwargs):
+ return super().some(cls, *args, **kwargs)
+
+ class C(B):
+ @staticmethod
+ def some(cls):
+ return super().some(cls)
+
+ for _ in range(ADAPTIVE_WARMUP_DELAY):
+ C.some(C)
if __name__ == "__main__":
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-21-14-37-48.gh-issue-106917.1jWp_m.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-21-14-37-48.gh-issue-106917.1jWp_m.rst
new file mode 100644
index 0000000..82c74d5
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-07-21-14-37-48.gh-issue-106917.1jWp_m.rst
@@ -0,0 +1,4 @@
+Fix classmethod-style :func:`super` method calls (i.e., where the second
+argument to :func:`super`, or the implied second argument drawn from
+``self/cls`` in the case of zero-arg super, is a type) when the target of
+the call is not a classmethod.
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 7ce8978..0705f5b 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -1721,7 +1721,7 @@ dummy_func(
PyTypeObject *cls = (PyTypeObject *)class;
int method_found = 0;
res2 = _PySuper_Lookup(cls, self, name,
- cls->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL);
+ Py_TYPE(self)->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL);
Py_DECREF(global_super);
Py_DECREF(class);
if (res2 == NULL) {
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 064965a..0f04b42 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -1406,7 +1406,7 @@
PyTypeObject *cls = (PyTypeObject *)class;
int method_found = 0;
res2 = _PySuper_Lookup(cls, self, name,
- cls->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL);
+ Py_TYPE(self)->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL);
Py_DECREF(global_super);
Py_DECREF(class);
if (res2 == NULL) {
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 9d25fc6..02ad69a 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -2154,7 +2154,7 @@
PyTypeObject *cls = (PyTypeObject *)class;
int method_found = 0;
res2 = _PySuper_Lookup(cls, self, name,
- cls->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL);
+ Py_TYPE(self)->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL);
Py_DECREF(global_super);
Py_DECREF(class);
if (res2 == NULL) {