mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
gh-127750: Restore inspect and pydoc support of singledispatchmethod (GH-130309)
The code is still flawed, because it does not recognize class and static methods, and the first argument is not removed from the signature of bound methods, but at least it does not worse than in 3.13 and older.
This commit is contained in:
parent
ed831b95a2
commit
10b32054ad
4 changed files with 79 additions and 1 deletions
|
@ -1075,6 +1075,10 @@ class _singledispatchmethod_get:
|
|||
raise AttributeError
|
||||
return getattr(self._unbound.func, name)
|
||||
|
||||
@property
|
||||
def __wrapped__(self):
|
||||
return self._unbound.func
|
||||
|
||||
@property
|
||||
def register(self):
|
||||
return self._unbound.register
|
||||
|
|
|
@ -447,7 +447,8 @@ def isroutine(object):
|
|||
or isfunction(object)
|
||||
or ismethod(object)
|
||||
or ismethoddescriptor(object)
|
||||
or ismethodwrapper(object))
|
||||
or ismethodwrapper(object)
|
||||
or isinstance(object, functools._singledispatchmethod_get))
|
||||
|
||||
def isabstract(object):
|
||||
"""Return true if the object is an abstract base class (ABC)."""
|
||||
|
|
|
@ -3309,6 +3309,58 @@ class TestSingleDispatch(unittest.TestCase):
|
|||
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
|
||||
|
|
|
@ -415,6 +415,27 @@ class TestPredicates(IsTestBase):
|
|||
# partial
|
||||
self.assertTrue(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