[PEAK] Type and class adaptation

Radek Kanovsky rk at dat.cz
Sun Nov 21 06:40:56 EST 2004


On Fri, Nov 19, 2004 at 02:15:30PM -0500, Phillip J. Eby wrote:

> On my second reading, I caught a couple of things that I missed before...
> 
> 
> At 06:21 PM 11/19/04 +0100, Radek Kanovsky wrote:
> >Additionally if I declare
> >adapter for MyClass, this adapter is not applicable to SubClass.
> 
> This doesn't sound right; do you have a short code sample I could use to 
> test this?

I meant that the only way one can simply define some adapter for user
defined class or type is as follows (fails for int, float, unicode) :

    protocols.declareAdapter(
        factory    = MyClassAsTypeDescriptor,
        provides   = ITypeDescriptor,
        forObjects = [MyClass]
    )

I would bet, that it didn't work for subclasses when I have tried it
last time. But it always worked, of course.

> >def dispatch_by_subclass (klass, table):
> >    while True:
> >        if klass in table:
> >            return table[klass]
> >        try:
> >            klass, = klass.__bases__
> 
> This code will raise an AttributeError if it is used on a non-class.

Insufficient testing :-( It worked for few examples with types/classes
arguments. I haven't understood all internals of dispatch package yet.

> >        except ValueError:
> >            if klass.__bases__:
> >                return table.reseed(klass)
> >            else:
> >                break
> >    if klass in table:
> >        return table[object]
> 
> This last bit is also broken; it's *always* going to return None.
> 
> Essentially, the problem with your implementation as far as I can tell, is 
> that it doesn't at all consider the possibility that the object is not a 
> class.  I would recommend that you use 'None' as the key for that 
> situation.  So, the code would look something like this:
> 
> def dispatch_by_subclass (klass, table):
>     if isinstance(klass,ClassTypes):
>         while True:
>             if klass in table:
>                 return table[klass]
>             try:
>                 klass, = klass.__bases__
>             except ValueError:
>                 if klass.__bases__:
>                     return table.reseed(klass)
>                 else:
>                     break
>     if None in table:
>         return table[None]
> 
> And, the 'ISSubclass.seeds()' method should also include 'None' in its 
> seeds.
> 
> Essentially, a dispatch function must never return 'None' unless there are 
> no cases registered for that situation, and an ITest must create seeds for 
> all the possibilities  regarding that test.  One of the possibilities of a 
> subclass test is that the object being tested is not a class, so there 
> needs to be a key for that condition.  Also, there is the possibility that 
> a class is not a subclass of any known test (i.e., it's a new classic 
> class).  In both of these cases, the 'None' key represents the default 
> dispatch path, which is basically a path where none of the subclass-testing 
> alternatives are applicable.
> 
> This is different from dispatch_by_mro, because in Python everything is an 
> *instance* of 'object' eventually, so 'InstanceType' and 'object' are the 
> default keys.  But, in this case, not everything is a *subclass* of 
> 'object', so a different default is needed.

I will try to repair it. Thanks.

Radekk



More information about the PEAK mailing list