Can I prevent class definition unless a method is implemented?

66 views Asked by At

I'm trying to figure out how to provide a base class to plugin writers so that they provide definitions for several static methods.

A plugin class is a collection of static methods which will never be instantiated.

I know how to use ABC to prevent instantiation of a class missing method implementations, which will not provide the safety I would like. Is there a pattern to prevent definition?

1

There are 1 answers

0
BrenBarn On

You can do it by writing your own metaclass similar to ABCMeta, which checks for abstract methods at class-definition time and raises an error if it finds any. Here's an example:

class ClassABC(type):
    def __init__(cls, name, bases, attrs):
        abstracts = set()
        for base in bases:
            abstracts.update(getattr(base, '__abstractclassmethods__', set()))
        for abstract in abstracts:
            if getattr(getattr(cls, abstract), '__isabstractmethod__', False):
                raise TypeError("Your class doesn't define {0}".format(abstract))
        for attr in attrs:
            if getattr(attrs[attr], '__isabstractmethod__', False):
                abstracts.add(attr)
        cls.__abstractclassmethods__ = abstracts

class BaseClass(object):
    __metaclass__ = ClassABC

    @abc.abstractmethod
    def foo(self):
        print("I am base foo")

Then:

>>> class Derived(BaseClass):
...     pass
Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    class Derived(BaseClass):
  File "<pyshell#8>", line 8, in __init__
    raise TypeError("Your class doesn't define {0}".format(abstract))
TypeError: Your class doesn't define foo

My example is fairly quick and dirty and only scantily tested, and you might want to refine it to check various sorts of edge cases. What I did is I raised the error if there is an abstract method that wasn't defined in the currently-being-defined class. (Otherwise an error would be raised because the abstract base class doesn't define concrete implementations of its own abstract methods.)