__implements__ on arguments to ABCMeta.register
ABCMeta.register is great. It adds the cls argument to the _abc_registry of the ABC. However, the class that was passed in does not get touched. If you then want to find out to which classes a class has been registered, you can't find out from that class. Whereas your can find out from an abstract base class which classes have been registered to it. I propose having ABCMeta.register add/update a special method __implements__ to the class that is getting registered. This would not be done to builtin/extension types. It adds the ABC to the __implements__ of the subclass that is getting registered. Something along these lines, right before the final return in the method: if not hasattr(subclass, "__implements__"): try: subclass.__implements__ = {cls} except TypeError: pass else: subclass.__implements__.add(cls) This is a small addition, but I realize it [potentially] adds another special method to classes, so it's not trivial. The use case is that I want to be able to validate that a class implements all of the abstract methods of all the classes to which it has been registered. I don't have a programmatic way of discovering that set without asking every class out there. This is an easy way to accomplish this (for non-extension/non-builtin types). An alternative is to subclass ABCMeta and tack this on, but that only works for my ABCs. Another is to use a class decorator to do this any place I do a register (or even to do the register too), but again, only for the places that I do the registration. Anyway, if it's useful to me then it may be useful to others, so I wanted to put this out there. I expect this has come up before, particularly during discussions about PEP 3119. However, I wasn't able to track down anything specifically about doing this sort of "reverse registration". And, of course, I may be overestimating the value of this functionality. If this does not seem that valuable to anyone else, then no big deal. :) -eric
On Sat, May 21, 2011 at 10:03 AM, Eric Snow <ericsnowcurrently@gmail.com> wrote:
This is a small addition, but I realize it [potentially] adds another special method to classes, so it's not trivial. The use case is that I want to be able to validate that a class implements all of the abstract methods of all the classes to which it has been registered. I don't have a programmatic way of discovering that set without asking every class out there. This is an easy way to accomplish this (for non-extension/non-builtin types). An alternative is to subclass ABCMeta and tack this on, but that only works for my ABCs. Another is to use a class decorator to do this any place I do a register (or even to do the register too), but again, only for the places that I do the registration. Anyway, if it's useful to me then it may be useful to others, so I wanted to put this out there. I expect this has come up before, particularly during discussions about PEP 3119. However, I wasn't able to track down anything specifically about doing this sort of "reverse registration". And, of course, I may be overestimating the value of this functionality. If this does not seem that valuable to anyone else, then no big deal. :)
An alternative approach to the same idea was to be able to register callbacks with ABCs to track registration and deregistration operations on that ABC and any subclasses. This has the advantage of working with arbitrary objects, including those without mutable __dict__ attributes. Such an approach would start by building a type map (via ABC.__subclasses__) and then using the callback hooks to keep the mapping up to date. I believe there is an open tracker item for that concept, but I can't currently find a reference to it. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
On Sun, May 22, 2011 at 11:46 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
On Sat, May 21, 2011 at 10:03 AM, Eric Snow <ericsnowcurrently@gmail.com> wrote:
This is a small addition, but I realize it [potentially] adds another special method to classes, so it's not trivial. The use case is that I want to be able to validate that a class implements all of the abstract methods of all the classes to which it has been registered. I don't have a programmatic way of discovering that set without asking every class out there. This is an easy way to accomplish this (for non-extension/non-builtin types). An alternative is to subclass ABCMeta and tack this on, but that only works for my ABCs. Another is to use a class decorator to do this any place I do a register (or even to do the register too), but again, only for the places that I do the registration. Anyway, if it's useful to me then it may be useful to others, so I wanted to put this out there. I expect this has come up before, particularly during discussions about PEP 3119. However, I wasn't able to track down anything specifically about doing this sort of "reverse registration". And, of course, I may be overestimating the value of this functionality. If this does not seem that valuable to anyone else, then no big deal. :)
An alternative approach to the same idea was to be able to register callbacks with ABCs to track registration and deregistration operations on that ABC and any subclasses. This has the advantage of working with arbitrary objects, including those without mutable __dict__ attributes. Such an approach would start by building a type map (via ABC.__subclasses__) and then using the callback hooks to keep the mapping up to date.
That would be pretty cool. A simple __implements__ like I described it would definitely be less flexible.
I believe there is an open tracker item for that concept, but I can't currently find a reference to it.
I believe you are talking about http://bugs.python.org/issue5405. -eric
Cheers, Nick.
-- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
On Tue, May 24, 2011 at 11:30 AM, Eric Snow <ericsnowcurrently@gmail.com> wrote:
On Sun, May 22, 2011 at 11:46 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
I believe there is an open tracker item for that concept, but I can't currently find a reference to it.
I believe you are talking about http://bugs.python.org/issue5405.
That's the one (my tracker-fu failed me when I was trying to find it). I added a link from that issue back to the archive of this thread on python.org. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
On Fri, May 20, 2011 at 5:03 PM, Eric Snow <ericsnowcurrently@gmail.com>wrote:
The use case is that I want to be able to validate that a class implements all of the abstract methods of all the classes to which it has been registered.
If you're going down that road, would you be willing to write a patch for http://bugs.python.org/issue9731 along the way?
I don't have a programmatic way of discovering that set without asking every class out there.
I agree it would be nice to have a way to ask a class "which ABCs do you implement?" It would be handy for introspection and debugging purposes. -- Daniel Stutzbach
On Fri, May 20, 2011 at 5:03 PM, Eric Snow <ericsnowcurrently@gmail.com>wrote:
The use case is that I want to be able to validate that a class implements all of the abstract methods of all the classes to which it has been registered.
If you're going down that road, would you be willing to write a patch for http://bugs.python.org/issue9731 along the way?
Interesting. I was motivated in a similar situation to write a validater in
On Mon, May 23, 2011 at 6:54 PM, Daniel Stutzbach <stutzbach@google.com>wrote: the same vein [1]. In fact, working on that is where I got thinking about something like __implements__. The class I wrote would work with registered classes in addition to subclasses, if there were such a mechanism. -eric [1] http://code.activestate.com/recipes/577711-validating-classes-and-objects-ag...
I don't have a programmatic way of discovering that set without asking
every class out there.
I agree it would be nice to have a way to ask a class "which ABCs do you implement?" It would be handy for introspection and debugging purposes.
-- Daniel Stutzbach
participants (3)
-
Daniel Stutzbach
-
Eric Snow
-
Nick Coghlan