How can I ensure some structure for classes for a plug-in system written in Python? I have written a toolkit (hwrt) which has a plugin system. One type of plugin is a feature (see this) for many of them.

There are some restrictions of feature classes. I expect some structure amongst them:

# Every feature class must have a __str__, __repr__ function so that error
# messages can help you to find and fix bugs in features.
# Every feature class must have a __call__ function which is used to get the
# features value(s) for a given recording.
# Every feature class must have a get_dimension function so that the total
# number of features can be calculated and checked for consistency.
#
# * __call__ must take exactly one argument of type HandwrittenData
# * __call__ must return a list of length get_dimension()
# * get_dimension must return a positive number
# * have a 'normalize' attribute that is either True or False


I have a lot of lines starting with

def __call__(self, handwritten_data):
    assert isinstance(handwritten_data, HandwrittenData.HandwrittenData), \
        "handwritten data is not of type HandwrittenData, but of %r" % \
        type(handwritten_data)


which I would like to write in a shorter notation.

Currently, my classes all inherit from object. I thought about changing that to letting them inherit from a Feature class, but I'm not too sure how I should write it. This was one try:

import abc


class Feature:
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def __call__(self):
        pass

    @abc.abstractmethod
    def get_dimension(self):
        pass


I expected that if I let a class which did not implement get_dimension inherit from Feature that I would get an assertion error as soon as the class is used, but nothing happened.

How can I rewrite the code to have less repetitions and to check for more mistakes programmatically instead of just giving this long comment and hoping that the user implements everything?
You did not mention which Python version you are targeting. If the ABCMeta metaclass does not seem to be working you are probably on Python 3 where you must apply a metaclass in this manner:

class Feature(metaclass=abc.ABCMeta):




To answer your main question, one possible approach is this: let the base class check the arguments, and call a different, abstract method to do the work. Subclasses will then override the abstract method only.

class Feature(object):
    __metaclass__ = abc.ABCMeta

    def __call__(self, handwritten_data):
        assert isinstance(handwritten_data, HandwrittenData.HandwrittenData), \
            "handwritten data is not of type HandwrittenData, but of %r" % \
            type(handwritten_data)
        return self._call(handwritten_data)

    @abc.abstractmethod
    def _call(self, handwritten_data):
        pass