FWIW, I went back and read PEP 246. That PEP goes to great lengths to permit arbitrary objects to be used as protocols, with the process of checking for compliance being a bit of a tap dance back and forth between the object and the protocol. Great effort was also put into registering adaptability without mutating any attributes of the protocol object.
The current discussion has persuaded me that it's better to require that protocols be special types, themselves providing a particular interface for adaptation purposes, and having ultimate authority over what it means to be compliant to themselves (thus allowing, e.g. an IIndex protocol to consider anything with a zero-argument __index__ method to be compliant - the act of defining a special interpreter method is a fair indication that the class considers itself compliant with that protocol). The fact that PyProtocols, Twisted and Zope all use special objects to define their interfaces is also a factor in forming that opinion. The PyProtocols docs mention the possibility of using arbitrary objects, and then points out that doing so means you miss out on most of the benefits of PyProtocols. Yet the usability of the entire API suffers for the sake of that genericity. So I'd be inclined to make the interface for a protocol reasonably fat by including things like adapter and implementation registration as methods. With such an approach (and class decorators), it would be straightforward to write: class Duck(object): """The duck class""" @class implements(IDuckWalk, IDuckQuack, IDuckLook) # ... where implements works something like: def implements(*interfaces): def register_class(cls): for interface in interfaces: interface.register_type(cls) return register_class The protocol itself can preregister known good classes in its class definition. Third parties that know a particular class implements a particular protocol can simply register that class directly. Tim Hochberg wrote: > In this thread, Alex has been advocating adaption where types are > adapted to protocols: T->P adaption for short. By contrast, my two > sample implementations have involved Protocol->Protocol adaption where > objects that implement a certain protocol are adapted to another > protocol: P->P adaption for short. I suppose this also could be > considered T->P->P adaptation since you look up the protocol from the > type, but let's stick with the terminology P->P adaption. > > Alex has been advocating for adaption for quite a while (I imagine it > seems like forever to him), so I give his views here great weight. > Still, something about T->P adaption has been bothering me, but until > now I haven't been able to put my finger on it beyond a vague sense that > pressing concrete types into service in this way is asking for trouble. > > Here's the problem I have with T->P adaption: it increases coupling > between the various clients of the adaption process. Lets talk about > these clients, I believe Alex said there were four: > > 1. The author of the type: T > 2. The writer of the adapter: A > 3. The person defining the destination protocol: P > 3. The user of the whole shebang: U > > Now under a T->P regime, T needs to search out all relevant adapters and > register them for their type. Similarly when adding a new adapter, A > needs to search out all relevant classes and register the new adapter > for them. Thus A and T become highly coupled. This misses the whole point of dynamic adaptation. T and P might define a few convenience adaptations (e.g. to or from standard library interfaces), but A and U will usually be the same person. Suppose framework X produces a Wibble, and framework Y expects an IWobble in various places. The integrator (U) needs to plug them together. If Wibble provides the right interface, U can simply write: IWobble.register_type(Wibble) Or, more commonly, U may need to write an adapter: class WibbleAsIWobble(object): def __init__(self, the_wibble): self.the_wibble = the_wibble # delegate the IWobble API to the Wibble instance IWobble.register_type_adapter(Wibble, WibbleAsIWobble) Either way, after either conformance or the adapter have been registered, a Wibble can be used seamlessly anywhere an IWobble was expected. On a completely different note, now that I've researched things a bit further, I think PyProtocols really has done a good job thrashing out the issues associated with adaptation. The *only* thing I really disagree with in PyProtocols is that I think the API usability has suffered due to the fact that state is spread out amongst not only protocol objects, but is also sometimes stored on the types being adapted. This leads to all sorts of "well sometimes you can do this, but sometimes you can't, depending on what you're adapting, so maybe you shouldn't rely on it" caveats. If the protocol API itself was richer (mandating that protocol objects support dynamic registration), then the API could be simplified significantly (as most operations would simply become method invocations on the target protocol, and the source objects could be whatever you wanted, since the state would all be on the protocol objects). Regards, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org _______________________________________________ Python-3000 mailing list Python-3000@python.org http://mail.python.org/mailman/listinfo/python-3000 Unsubscribe: http://mail.python.org/mailman/options/python-3000/archive%40mail-archive.com