[TransWarp] PyProtocols: adapting classes to instance

Phillip J. Eby pje at telecommunity.com
Tue Sep 30 00:00:41 EDT 2003


At 10:17 PM 9/29/03 -0500, Ian Bicking wrote:

>It's using objects like:
>
>class Declarative(object):
>     def __init__(self, **kw):
>         for name, value in kw.items():
>             setattr(self, name, value)
>     def __call__(self, **kw):
>         if not kw: return self
>         newdict = self.__dict__.copy()
>         newdict.update(kw)
>         return self.__class__(**newdict)
>
>If you can adapt classes, then these two expressions would be equivalent 
>(assuming Regex subclasses Declarative):
>
>validator = Regex(strip=True, regex=r'^[a-zA-Z]*$', ifInvalid='[Invalid]')
>
>class validator(Regex):
>     strip = True
>     regex = r'^[a-zA-Z]*$'
>     ifInvalid = '[Invalid]'

Hm.  I guess I'd just define the behavior in the metaclass, and add a 
metaclass-level __call__ operation that just created a new subclass, if it 
was called with keyword arguments rather than positional parameters.  That 
is, I'd make it so that calling Regex with keyword arguments created a 
subclass of Regex.  The way you're trying to do it seems like a hack to me; 
the approach I suggest could produce meaningful and consistent behavior 
even without PyProtocols.  But of course I don't know all the requirements 
you have.

>I haven't really been able to understand what the Open* classes/interfaces 
>really are, or what they mean in the overall system.  The names are very 
>vague to me... but then, many of the names in PyProtocols feel vague to 
>me.  Maybe a little glossary would help.

Well, each one has a fairly detailed explanation in the reference portion 
of the manual.  But basically, everything boils down to the three 
fundamental adapter declaration APIs, and what they do.  You can declare 
adapters:

* from a protocol to a protocol (using IOpenProtocol)
* from a class' instances to a protocol (optionally using IOpenImplementor)
* from a specific instance to a protocol (optionally using IOpenProvider)

The three API calls generally adapt their target protocol to IOpenProtocol, 
and call a method on it to perform the declaration.  If a class or instance 
is being declared, the protocol will adapt the class (to IOpenImplementor) 
or instance (to IOpenProvider), and delegate some of the registration to 
that object.  So, if you have a class whose metaclass provides 
IOpenImplementor, then the metaclass will have its 
'declareClassImplements()' called once for each protocol listed in the 
'advise(instancesProvide=[])' call.

Similarly, when individual objects are declared to support something, they 
are adapted to IOpenProvider.  The default adapter for this "pokes" a 
__conform__ method into the object, if it can do so safely.  Since your 
classes had this method already, you got an error, and had to use the 
alternate mechanism for supporting IOpenProvider: i.e., mixing in 
ProviderMixin.




More information about the PEAK mailing list