[3.13] gh-127750: Backport some tests for singledispatchmethod (GH-130309) (GH-130340)

(cherry picked from commit 395335d0ff)
(cherry picked from commit 10b32054ad)
This commit is contained in:
Serhiy Storchaka 2025-02-20 11:49:23 +02:00 committed by GitHub
parent 270ec26c51
commit 68c57d6f33
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 132 additions and 0 deletions

View file

@ -2758,6 +2758,7 @@ class TestSingleDispatch(unittest.TestCase):
"""My function docstring"""
return str(arg)
prefix = A.__qualname__ + '.'
for meth in (
A.func,
A().func,
@ -2767,6 +2768,7 @@ class TestSingleDispatch(unittest.TestCase):
A().static_func
):
with self.subTest(meth=meth):
self.assertEqual(meth.__qualname__, prefix + meth.__name__)
self.assertEqual(meth.__doc__,
('My function docstring'
if support.HAVE_DOCSTRINGS
@ -3077,6 +3079,115 @@ class TestSingleDispatch(unittest.TestCase):
self.assertEqual(f(""), "default")
self.assertEqual(f(b""), "default")
def test_method_equal_instances(self):
# gh-127750: Reference to self was cached
class A:
def __eq__(self, other):
return True
def __hash__(self):
return 1
@functools.singledispatchmethod
def t(self, arg):
return self
a = A()
b = A()
self.assertIs(a.t(1), a)
self.assertIs(b.t(2), b)
def test_method_bad_hash(self):
class A:
def __eq__(self, other):
raise AssertionError
def __hash__(self):
raise AssertionError
@functools.singledispatchmethod
def t(self, arg):
pass
# Should not raise
A().t(1)
hash(A().t)
A().t == A().t
def test_method_no_reference_loops(self):
# gh-127750: Created a strong reference to self
class A:
@functools.singledispatchmethod
def t(self, arg):
return weakref.ref(self)
a = A()
r = a.t(1)
self.assertIsNotNone(r())
del a # delete a after a.t
if not support.check_impl_detail(cpython=True):
support.gc_collect()
self.assertIsNone(r())
a = A()
t = a.t
del a # delete a before a.t
support.gc_collect()
r = t(1)
self.assertIsNotNone(r())
del t
if not support.check_impl_detail(cpython=True):
support.gc_collect()
self.assertIsNone(r())
def test_signatures(self):
@functools.singledispatch
def func(item, arg: int) -> str:
return str(item)
@func.register
def _(item: int, arg: bytes) -> str:
return str(item)
self.assertEqual(str(Signature.from_callable(func)),
'(item, arg: int) -> str')
def test_method_signatures(self):
class A:
def m(self, item, arg: int) -> str:
return str(item)
@classmethod
def cm(cls, item, arg: int) -> str:
return str(item)
@functools.singledispatchmethod
def func(self, item, arg: int) -> str:
return str(item)
@func.register
def _(self, item, arg: bytes) -> str:
return str(item)
@functools.singledispatchmethod
@classmethod
def cls_func(cls, item, arg: int) -> str:
return str(arg)
@func.register
@classmethod
def _(cls, item, arg: bytes) -> str:
return str(item)
@functools.singledispatchmethod
@staticmethod
def static_func(item, arg: int) -> str:
return str(arg)
@func.register
@staticmethod
def _(item, arg: bytes) -> str:
return str(item)
self.assertEqual(str(Signature.from_callable(A.func)),
'(self, item, arg: int) -> str')
self.assertEqual(str(Signature.from_callable(A().func)),
'(self, item, arg: int) -> str')
self.assertEqual(str(Signature.from_callable(A.cls_func)),
'(cls, item, arg: int) -> str')
self.assertEqual(str(Signature.from_callable(A.static_func)),
'(item, arg: int) -> str')
class CachedCostItem:
_cost = 1

View file

@ -408,6 +408,27 @@ class TestPredicates(IsTestBase):
# partial
self.assertFalse(inspect.isroutine(functools.partial(mod.spam)))
def test_isroutine_singledispatch(self):
self.assertTrue(inspect.isroutine(functools.singledispatch(mod.spam)))
class A:
@functools.singledispatchmethod
def method(self, arg):
pass
@functools.singledispatchmethod
@classmethod
def class_method(cls, arg):
pass
@functools.singledispatchmethod
@staticmethod
def static_method(arg):
pass
self.assertTrue(inspect.isroutine(A.method))
self.assertTrue(inspect.isroutine(A().method))
self.assertTrue(inspect.isroutine(A.static_method))
self.assertTrue(inspect.isroutine(A.class_method))
def test_isclass(self):
self.istest(inspect.isclass, 'mod.StupidGit')
self.assertTrue(inspect.isclass(list))