<div class="gmail_quote">On Thu, May 19, 2011 at 11:33 PM, Eric Snow <span dir="ltr"><<a href="mailto:ericsnowcurrently@gmail.com" target="_blank">ericsnowcurrently@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<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><font color="#888888"><div>-eric</div><div><br></div><div><br></div><div><br>
</div><div><br></div>
</font></blockquote></div><div><br></div><div>I have revised this and made a recipe for it:</div><div><br></div><div><a href="http://code.activestate.com/recipes/577711-validating-classes-and-objects-against-an-abstract/">http://code.activestate.com/recipes/577711-validating-classes-and-objects-against-an-abstract/</a></div>
<div><br></div><div>The question remains of what alternatives exist to this solution. Thanks!</div><div><br></div><div>-eric</div><div><br></div>