[Interface-dev] Class -> interface adapters, and design question

Jim Fulton jim at zope.com
Fri Apr 23 06:56:43 EDT 2004


Itamar Shtull-Trauring wrote:
> On Mon, 2004-04-19 at 06:32, Jim Fulton wrote:
> 
> 
>>   adapter.aRegistry.register([implmentedBy(Klass)], [IFoo], '', AdapterClass)
>>
>>The first argument is a seqience of specifications.  You get the specification
>>for a class using implementedBy.
> 
> 
> Thanks. I actually implemented a "create a marker interface on the fly"
> thing, I'm pretty what you're suggesting doesn't do what I want. I want
> to say "here's how to adapt all instances of class Foo to IBar".

register([implementedBy(Foo)], IBar, '', factory)

Does exactly that.

> 
> In my AdapterRegistry subclass:
> 
>     def registerAdapter(self, adapterFactory, origInterface, destInterface):
>         if not issubclass(origInterface, Interface):
>             class IMarker(Interface):
>                 pass
>             declarations.classImplements(origInterface, IMarker)
>             self.classInterfaces[origInterface] = IMarker
>             origInterface = IMarker
>         self.register([destInterface], origInterface, '', adapterFactory)

This is overkill and you got the last line wrong. You wanted:

          self.register([IMarker], destInterface, '', adapterFactory)

> 
> 
>>>I decided that Twisted would have its own (global) registry, and append
>>>it to z.i.interface.adapter_hooks. Make sense?
>>
>>Is that because you don't want to depend on zope.component?
> 
> 
> Well... partially. z.c seems to have lots of complex stuff I'm not sure
> we actually need or want. Perhaps I am mistaken?

I think so.  It's pretty simple at this point. So, what does it have?
It has the concept of services and provides several services that are
simple component registries, including:

- Service services

- Adapter service

- Utility service -- I find utilities *very* useful

- Presentation service  -- This is effectively a skinned
   adapter service with emphasis on UI. In particular, there is
   an assumption that there is an object that represents the user
   in some way, called a request.  I suppose that this might be
   controversial, but I think it could be quite useful. It's
   been profoundly useful to us.

   This is, effectively, a take on MVC.

I also think that events fit into this.  I think I'll end up adding
a dirt simple event registry, as describd in:

   http://dev.zope.org/Zope3/SimplifyEventSystem

A significant project ahead is to write a decent README for this
package that describes the Zen of component-based development.

> The reason I mistakenly thought I'd *have* to have one was
> Componentized, a simplified version of which would look like so:
> 
> class Componentized:
> 
>     def __init__(self):
>         self.components = {}
> 
>     def setComponent(self, iface, obj):
>         self.components[iface] = obj
>   
>     def __conform___(self, iface):
>         if self.components.has_key(iface):
>             return self.components[iface]
>         self.components[iface] = r = adapt(obj, iface)
>         return r
> 
> The problem here is adapt() being recursive. In Twisted right now it
> just goes to the adapter registry and looks it up, instead of doing full
> adaptation algorithm. 
> 
> But, it occurs to me now I can just iterate over adapt_hooks and use
> those, and then __conform__ won't be called again and there's no
> infinite recursion. Not a reason to have our own registry then.

In which case there should be an api for doing this so that you don't
have to rely on adapter hooks directly.

I have been considering treating tuples specially in the adapter service.
We have a concept of multi-adapters, which is quite powerful.  I've
been thinking of making a single-adapter operation on a tuple imply
multi-adaptation. If we did this, then:

   IBar((x, y))

would look up a multi-adapter to IBar. Further,

   IBar((x, ))

would also look up a multi-adapter, which would be the same as looking up
a single adapter in this case except that the __conform__ check would fail
(and, as an optimization, we could mnage to bypass it altogether), as would
the check for whether the objects (a tuple) already provides IBar.

This is very appealing to me, but it would fail if we started declaring interfaces
for or adapting tuple. This has kept me from doing it so far, but it might be worth
saying yagni (for adapting tuple).

>>Note that zope.interface.adapter.AdapterRegistry doesn't actually
>>provide adapter factory sementics.  That's what
>>zope.component.adapter.GlobalAdapterService does.  I'm open to providing
>>those sementics in zope.interface.adapter.
> 
> 
> I'm doing the actual creation of adapters myself, manually, yes. I'll
> take a look at the factory stuff and see if I see any stuff I'd want
> moved.

OK

Jim

-- 
Jim Fulton           mailto:jim at zope.com       Python Powered!
CTO                  (540) 361-1714            http://www.python.org
Zope Corporation     http://www.zope.com       http://www.zope.org




More information about the Interface-dev mailing list