Hello, This to thread has gotten no responses at all, so: Ping!
On Sun, Aug 22, 2021, 3:16 PM Finn Mason <finnjavie...@gmail.com> wrote: > Sorry, the formatting was terrible. I copy and pasted it from the original > issue without really thinking about it. > Here's the same thing, but actually readable: > > In _collections_abc.py is a private function titled _check_methods(). It > takes a class and a number of method names (as strings), checks if the > class has all of the methods, and returns NotImplemented if any are > missing. The code is below: > > def _check_methods(C, *methods): > mro = C.__mro__ > for method in methods: > for B in mro: > if method in B.__dict__: > if B.__dict__[method] is None: > return NotImplemented > break > else: > return NotImplemented > return True > > This is an incredibly convenient function (referred to as check_methods > here on out) for creating abstract base classes, and is much simpler than > using hasattr for each method you want to check. For example: > > from abc import ABCMeta > # Without check_methods > class A(metaclass=ABCMeta): > @classmethod > def __subclasshook__(cls, subclass): > return (hasattr(subclass, 'foo') and > callable(subclass.foo) and > hasattr(subclass, 'bar') and > callable(subclass.bar) or > NotImplemented) > > # With check_methods > class B(metaclass=ABCMeta): > @classmethod > def __subclasshook(cls, subclass): > return check_methods(subclass, 'foo', 'bar') > > This would be a great function to add to the standard lib, perhaps in the > abc module. One problem with check_methods() as defined in > _collections_abc.py is that it doesn't check if the name is callable. Also, > type hints and more readable variables may be desirable. The final code, if > implemented, may look something like this: > > # In imports section: from typing import Literal > def check_methods(Class: type, *methods: str) -> Literal[True, > NotImplemented]: > """Check if class `Class` has methods `methods`.""" > mro = Class.__mro__ > for method in methods: > for Base in mro: > if (attr := getattr(Base, method, None)) is not None: > if not callable(attr): > return NotImplemented > break > else: > return NotImplemented > return True > > Again, this would be a great function to add to the `abc` module or a > similar one. I've proposed this in issue 44941. > Another possible implementation may be similar to a dataclass that > implements __subclasshook__ for you with the desired method checks. > > -- > Finn >
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/GCOXW4CJUDRWFRYGTAU2LJO5RUANYQMR/ Code of Conduct: http://python.org/psf/codeofconduct/