https://github.com/python/cpython/commit/f33d21e24fdb05da7512c2a203467c3ffd0e7713 commit: f33d21e24fdb05da7512c2a203467c3ffd0e7713 branch: main author: Serhiy Storchaka <storch...@gmail.com> committer: serhiy-storchaka <storch...@gmail.com> date: 2025-03-05T13:10:05+02:00 summary:
gh-127750: Improve repr of functools.singledispatchmethod (GH-130220) files: A Misc/NEWS.d/next/Library/2025-02-17-12-36-39.gh-issue-127750.ZC-hBq.rst M Lib/functools.py M Lib/test/test_functools.py diff --git a/Lib/functools.py b/Lib/functools.py index 5e2579f6d8eb0f..e0e45bc336c1ef 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -1033,6 +1033,15 @@ def __get__(self, obj, cls=None): def __isabstractmethod__(self): return getattr(self.func, '__isabstractmethod__', False) + def __repr__(self): + try: + name = self.func.__qualname__ + except AttributeError: + try: + name = self.func.__name__ + except AttributeError: + name = '?' + return f'<single dispatch method descriptor {name}>' class _singledispatchmethod_get: def __init__(self, unbound, obj, cls): @@ -1052,6 +1061,19 @@ def __init__(self, unbound, obj, cls): except AttributeError: pass + def __repr__(self): + try: + name = self.__qualname__ + except AttributeError: + try: + name = self.__name__ + except AttributeError: + name = '?' + if self._obj is not None: + return f'<bound single dispatch method {name} of {self._obj!r}>' + else: + return f'<single dispatch method {name}>' + def __call__(self, /, *args, **kwargs): if not args: funcname = getattr(self._unbound.func, '__name__', diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index ef85664cb78f64..5e04b15e014ea2 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -2934,6 +2934,67 @@ def static_func(arg: int) -> str: self.assertEqual(A.static_func.__name__, 'static_func') self.assertEqual(A().static_func.__name__, 'static_func') + def test_method_repr(self): + class Callable: + def __call__(self, *args): + pass + + class CallableWithName: + __name__ = 'NOQUALNAME' + def __call__(self, *args): + pass + + class A: + @functools.singledispatchmethod + def func(self, arg): + pass + @functools.singledispatchmethod + @classmethod + def cls_func(cls, arg): + pass + @functools.singledispatchmethod + @staticmethod + def static_func(arg): + pass + # No __qualname__, only __name__ + no_qualname = functools.singledispatchmethod(CallableWithName()) + # No __qualname__, no __name__ + no_name = functools.singledispatchmethod(Callable()) + + self.assertEqual(repr(A.__dict__['func']), + f'<single dispatch method descriptor {A.__qualname__}.func>') + self.assertEqual(repr(A.__dict__['cls_func']), + f'<single dispatch method descriptor {A.__qualname__}.cls_func>') + self.assertEqual(repr(A.__dict__['static_func']), + f'<single dispatch method descriptor {A.__qualname__}.static_func>') + self.assertEqual(repr(A.__dict__['no_qualname']), + f'<single dispatch method descriptor NOQUALNAME>') + self.assertEqual(repr(A.__dict__['no_name']), + f'<single dispatch method descriptor ?>') + + self.assertEqual(repr(A.func), + f'<single dispatch method {A.__qualname__}.func>') + self.assertEqual(repr(A.cls_func), + f'<single dispatch method {A.__qualname__}.cls_func>') + self.assertEqual(repr(A.static_func), + f'<single dispatch method {A.__qualname__}.static_func>') + self.assertEqual(repr(A.no_qualname), + f'<single dispatch method NOQUALNAME>') + self.assertEqual(repr(A.no_name), + f'<single dispatch method ?>') + + a = A() + self.assertEqual(repr(a.func), + f'<bound single dispatch method {A.__qualname__}.func of {a!r}>') + self.assertEqual(repr(a.cls_func), + f'<bound single dispatch method {A.__qualname__}.cls_func of {a!r}>') + self.assertEqual(repr(a.static_func), + f'<bound single dispatch method {A.__qualname__}.static_func of {a!r}>') + self.assertEqual(repr(a.no_qualname), + f'<bound single dispatch method NOQUALNAME of {a!r}>') + self.assertEqual(repr(a.no_name), + f'<bound single dispatch method ? of {a!r}>') + def test_double_wrapped_methods(self): def classmethod_friendly_decorator(func): wrapped = func.__func__ diff --git a/Misc/NEWS.d/next/Library/2025-02-17-12-36-39.gh-issue-127750.ZC-hBq.rst b/Misc/NEWS.d/next/Library/2025-02-17-12-36-39.gh-issue-127750.ZC-hBq.rst new file mode 100644 index 00000000000000..e438dbba52192c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-02-17-12-36-39.gh-issue-127750.ZC-hBq.rst @@ -0,0 +1,2 @@ +Improve repr of :class:`functools.singledispatchmethod` methods and +descriptors. _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com