Discussion:
Expose __abstractmethods__/__isabstractmethod__ in abc
Andrew Barnert
2014-07-25 20:46:29 UTC
Permalink
An ABC built with abc.ABCMeta has a member __abstractmethods__, which is an iterable of all of the abstract methods defined in that ABC that need to be overridden. A method decorated with @abstractmethod gets a member __isabstractmethod__=True, which is how the ABC (or, rather, the interpreter) checks whether each of its abstract methods have been overridden.


However, they're part of a private protocol used by the CPython implementation of the abc module, which means any third-party code that uses them isn't portable or future-proof. Which is a shame, because there are all kinds of things you can build easily on top of abc with them, but would have to duplicate most of the module (and the special interpreter support for it) without them.

The simplest change is just to document these two members as part of the module interface.


Alternatively, there could be functions abc.isabstractmethod(method) and abc.abstractmethods(cls), which would allow for implementations that didn't use the same protocol internally but supported the same interface.

Examples where this could be useful:


* Write a runtime check-and-register function.

* Explicitly test that a set of classes have implemented their ABC(s) without having to know how to correctly instantiate them.

* Write a generic @autoabc decorator or similar for creating ABCs that are automatically virtual base classes of any type with the right methods, instead of doing it manually in each class (as collections.abc does today), like Go interfaces, C++ auto concepts, traditional ObjC checked informal protocols, etc.).

* Build a signature-checking (rather than just name-checking) ABC (like https://github.com/apieum/ducktype).

* Build a simplified version of PyProtocols-like adapters on top of abc instead of PyProtocols.

Some of these might belong in the stdlib (in fact, it looks like http://bugs.python.org/issue9731 basically covers the first two), in which case they don't need to be implementable from outside… but that's certainly not true for all of them. (Without a precise algorithm for "compatible signature" or a standardized notion of adaptation, stdlib inclusion isn't even sensible for the last two, much less a good idea.) So, outside libraries should be able to implement them.
Nick Coghlan
2014-07-25 23:34:28 UTC
Permalink
The additional module level functions sound like a good idea to me. I see
it as similar to the functools.singledispatch driven addition to expose a
way to obtain a cache validity token for the virtual object graph.

I thought "__isabstractmethod__" was already documented though, since we
rely on it to control the pass through behaviour of property and other
decorators like classmethod and staticmethod. If it isn't, that's really a
bug rather than an RFE.

Cheers,
Nick.
Andrew Barnert
2014-07-26 02:22:26 UTC
Permalink
The additional module level functions sound like a good idea to me. I see it as similar to the functools.singledispatch driven addition to expose a way to obtain a cache validity token for the virtual object graph.
Another reason the function seems better than the attribute.

The only advantage to the attribute is that we could document that it already existed in 3.4 and earlier, instead of just documenting a new function. And if that was desirable we could always add that as a note to the documentation of the function.
I thought "__isabstractmethod__" was already documented though, since we rely on it to control the pass through behaviour of property and other decorators like classmethod and staticmethod. If it isn't, that's really a bug rather than an RFE.
You're right; I was looking for it in the wrong place. It doesn't document that abstract methods created by @abstractmethod have that attribute, but it does document that if you want to create an abstract method manually you have to set it, and shows how @property both uses and exposes the attribute, which is more than enough. So, never mind that part.
Loading...