[Grok-dev] Simple adapter question

Carsten Senger senger at rehfisch.de
Thu Mar 5 16:25:26 EST 2009


Jan Ulrich Hasecke schrieb:

> Am 05.03.2009 um 20:26 schrieb Martin Aspeli:
>>>> import grok
>>>> from zope import interface
>>>>
>>>> class Fireplace(grok.Model):
>>>>    pass
>>>>
>>>> class Cave(grok.Model):
>>>>    pass
>>>>
>>>> class IHome(interface.Interface):
>>>>    pass
>>>>
>>>> class Home(grok.MultiAdapter):
>>>>    grok.adapts(Cave, Fireplace)
>>>>    grok.implements(IHome)
>>>>
>>>>    def __init__(self, cave, fireplace):
>>>>        self.cave = cave
>>>>        self.fireplace = fireplace
>>>>
>>>> home = IHome(cave, fireplace)
>> This looks fishy to me. Unless Grok is doing something very evil, this
>> won't work: it'll try to adapt `cave` to IHome, and if that fails,  
>> it'll
>> fall back to the second argument 'fireplace'.

Yes, Martin is right.

There was a discussion on zope-dev some time ago that the semantics of 
[get|query]Adapter and IMyInterface(...) are slightly different and can 
be overlooked easily:
http://thread.gmane.org/gmane.comp.web.zope.devel/16881

- Home is an adapter for Cave AND Fireplace.
- IHome(cave, fireplace) tries to find an adapter for cave to IHome,
   but that fails in this case cause the adapter is for Case AND
   Fireplace.
- IHome(cave, fireplace) will return the fireplace object itself as the
   fallback.


>> I think what you want is:
>>
>>  home = getMultiAdapter((cave, fireplace), IHome)
>>
>>>> Why is there an IHome in the last line? I would think that
>>>>
>>>> home = Home(cave, fireplace)
>>>>
>>>> would create a home-instance.
>> It does, and in this case, the two are probably equivalent. "Calling"
>> the interface (for a single-adapter!) or using
>> getAdapter/getMultiAdapter, means "Get the adapter from what I give  
>> you,
>> to the interface I ask for". If there was a more specific adapter to
>> IHome, then you'd get that one instead.
>>
> 
> So why the class Home is defined at all?

The class is the adapter itself, and it's registered for the IHome 
interface.

As said, you could use your 'Home' directly for this simple case. Using 
the component registry (IHome(...) or getAdapter(...), getMultiAdapter 
etc.) gives the flexibility, e.g. to have different adapters in 
different situations.

Additionally to the examples I gave, a common example is the one where 
you can turn different things into a home by providing different 
adapters that provide the home functionality:

Cave, Fireplace
House, Oven
Caravan, CampingStove

You write and register adapters for these combinations (all in one class 
in grok) and you can do

getMultiAdapter([a_housing_object, a_corresponding_stove_object], IHome)

and get the right adapter that gives you the home functionality you need.

 >> If you can, find Brandon Craig Rhodes "using grok to walk like a duck"
 >> talk on video and watch it. :)
 >
 > I presume that I miss something obvious to everyone else, so I'll
 > watch the film again. It is really great.

I found the parts about [multi]adapters in chapter 9 in Martin's book a 
nice summary.

..Carsten



More information about the Grok-dev mailing list