Viktor Roytman <viktor.royt...@gmail.com> added the comment:
I tried to apply this change but it didn't work, failing with this error $ ~/.pyenv/versions/3.8.1/bin/python -m bad_classmethod_as_documented Traceback (most recent call last): File "/home/viktor/.pyenv/versions/3.8.1/lib/python3.8/runpy.py", line 193, in _run_module_as_main return _run_code(code, main_globals, None, File "/home/viktor/.pyenv/versions/3.8.1/lib/python3.8/runpy.py", line 86, in _run_code exec(code, run_globals) File "/home/viktor/scratch/bad_classmethod_as_documented.py", line 4, in <module> class Negator: File "/home/viktor/scratch/bad_classmethod_as_documented.py", line 12, in Negator def _(cls, arg: int): File "/home/viktor/.pyenv/versions/3.8.1/lib/python3.8/functools.py", line 1006, in register return self.dispatcher.register(cls, func=method) File "/home/viktor/.pyenv/versions/3.8.1/lib/python3.8/functools.py", line 959, in register argname, cls = next(iter(get_type_hints(func).items())) File "/home/viktor/.pyenv/versions/3.8.1/lib/python3.8/typing.py", line 1252, in get_type_hints raise TypeError('{!r} is not a module, class, method, ' TypeError: <classmethod object at 0x7f84e1e69c40> is not a module, class, method, or function. After digging around a bit, this diff seems to work (not sure if there's a better way to do it) (also this one doesn't seem to care whether @staticmethod is applied to the implementation methods): $ diff -u functools-orig.py functools.py --- functools-orig.py 2020-02-21 16:14:56.141934001 -0500 +++ functools.py 2020-02-21 16:17:19.959905849 -0500 @@ -843,14 +843,18 @@ if func is None: if isinstance(cls, type): return lambda f: register(cls, f) - ann = getattr(cls, '__annotations__', {}) + if isinstance(cls, (classmethod, staticmethod)): + ann = getattr(cls.__func__, '__annotations__', {}) + func = cls.__func__ + else: + ann = getattr(cls, '__annotations__', {}) + func = cls if not ann: raise TypeError( f"Invalid first argument to `register()`: {cls!r}. " f"Use either `@register(some_class)` or plain `@register` " f"on an annotated function." ) - func = cls # only import typing if annotation parsing is necessary from typing import get_type_hints @@ -908,6 +912,8 @@ def __get__(self, obj, cls=None): def _method(*args, **kwargs): method = self.dispatcher.dispatch(args[0].__class__) + if isinstance(self.func, classmethod): + return method.__get__(obj, cls)(cls, *args, **kwargs) return method.__get__(obj, cls)(*args, **kwargs) _method.__isabstractmethod__ = self.__isabstractmethod__ ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue39679> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com