<div>Thinking about class APIs and validating a class against an API. The abc module provides the tools to do some of this. One thing I realized, that I hadn't noticed before, is that the abstractness of a class is measured when instances of the class are created. This happens in object.__new__ (pyobject.c). Validating thus when a class is defined would not be as helpful, since there is no guarantee that the class is not meant to be abstract as well.</div>
<div><br></div><div>However, I have found that it is sometimes nice to validate a class at definition time. This is particularly true for a class that does not inherit from the abstract base class (but registers instead).</div>
<div><br></div><div>Taking cues from abc.py and pyobject.c, here is a stab at a class decorator that validates a class against another.</div><div><br></div><div>def validate(abc):</div><div> if not isinstance(abc, type):</div>
<div> raise TypeError("Can only validate against classes")</div><div> def decorator(cls):</div><div> if not __debug__:</div><div> return cls</div><div> if not isinstance(cls, type):</div>
<div> raise TypeError("Can only validate classes")</div><div> abstracts = set()</div><div> for name in getattr(abc, "__abstractmethods__", set()):</div><div> value = getattr(cls, name, None)</div>
<div> if not value:</div><div> abstracts.add(name)</div><div> elif getattr(value, "__isabstractmethod__", False):</div><div> abstracts.add(name)</div><div> if abstracts:</div>
<div> sorted_methods = sorted(abstracts)</div><div> joined = ", ".join(sorted_methods)</div><div><div> msg = "Class {} does not implement abstract methods {} of class {}"</div>
</div><div><div> raise TypeError(msg.format(cls.__name__, joined, abc.__name__))</div></div><div> return cls</div><div> return decorator</div><div><br></div><div>Stack this with the ABCMeta.register method and you can ensure that your class is compliant with the ABC at the time you register it on that ABC.</div>
<div><br></div><div>Does anyone find this irrelevant or superfluous? I know that it would be a good idea to stay on top of your class's implementation of an ABC's abstract methods. However, this seems like a good way of doing that programmatically.</div>
<div><br></div><div>Does anyone know a better way to do ABC validation at definition time?</div><div><br></div><div>Thanks.</div><div><br></div><div>-eric</div><div><br></div><div><br></div><div><br></div><div><br></div>