mirror of
https://github.com/python/cpython.git
synced 2025-07-24 03:35:53 +00:00
[3.13] gh-127750: Backport some tests for singledispatchmethod (GH-130309) (GH-130340)
(cherry picked from commit395335d0ff
) (cherry picked from commit10b32054ad
)
This commit is contained in:
parent
270ec26c51
commit
68c57d6f33
2 changed files with 132 additions and 0 deletions
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue