[Grok-dev] concerns about grokcore.component.provides

Leonardo Rochael Almeida leorochael at gmail.com
Wed Sep 9 10:38:09 EDT 2009


Oh, and by the way:

> @grok.adapts(from_=ISourceInterface, to=IDestinationInterface)
> def MyFunctionAdapter(source_obj):
>    ....

I know the "from_" in there is a bit jarring (damn useful reserved
keyword), but if it's the first argument, the parameter name can be
omitted:

@grok.adapts(ISourceInterface, to=IDestinationInterface)

And perhaps both parameters can be optional in certain cases, where
"from_" defaults to "Interface" and "to" defaults to the "implements"
of the class if it's non-ambiguous.

On Wed, Sep 9, 2009 at 16:33, Leonardo Rochael
Almeida<leorochael at gmail.com> wrote:
> Hi,
>
> IMO, Adapters are one compliated beast, semantically speaking.
>
> To throw some more wood into the fire, though not necessarily helping,
> for me it helps to differentiate between the adapter and the
> adaptation.
>
> In the Zope Component Architecture, IIUC, an adapter is a callable to
> which you feed an object of one kind (interface), and get an object of
> another kind in return.
>
> In this sense, classes registered as adapters are, at the same time, factories.
>
> Meanwhile, the instances of an adapter class are the things which we
> expect to provide the interface we're currently declaring with the
> "provides" directive. So in this sense, the instances are not the
> adapters, but merely the result of the adaptation.
>
> If the adapter where to be a function instead of a class, the result
> would be the same, the function is the adapter that takes the adapted
> object as argument and returns an adaptation, which we then expect to
> provide a certain interface, no matter what kind of interfaces the
> adapter-function provides (usually none).
>
> Thinking about this. IMHO, one syntax that would be clean enough for
> my tastes would be:
>
> class MyFunkyAdaptor(NotNecessarilyGrokAdapterOrSubclass):
>    implements(IDestinationInterface, IAnotherInterface)
>    grok.adapts(from_=ISourceInterface, to=IDestinationInterface)
>
> Notice this same syntax could be used with functions that act as adapters.
>
> @grok.adapts(from_=ISourceInterface, to=IDestinationInterface)
> def MyFunctionAdapter(source_obj):
>    ....
>
> Cheers, Leo
>
> On Wed, Sep 9, 2009 at 16:02, Martijn Faassen<faassen at startifact.com> wrote:
>> Hey,
>>
>> Gary Poster wrote:
>> [snip]
>>> However, I'm also more convinced that the name of
>>> "grokcore.component.provides" is a problem.
>>
>> I agree it's a problem, as this isn't the first time it came up.
>>
>>> My current preference is
>>> for "provides_adapter".  Reading this, I understand what the grok
>>> directive is doing.
>>
>> One issue with this naming is that grok.provides is also used for global
>> utility registration right now. You'd also need a grok.provides_utility
>> that does the same. The principle is to reuse directives if they do
>> something similar enough, which one argue (also from the underlying
>> code) is the case here.
>>
>> I also think there's a bit of a DRY violation in saying
>> provides_adapter. The base class indicate it's an adapter. The
>> directives specify how it's an adapter. In your example you have your
>> own base class (CookbookTopLevelObject) that obscures this somewhat. One
>> needs to trace base classes. But this is a fairly common thing an object
>> oriented developer needs to do anyway, and it won't be long before they
>> realize it's an adapter.
>>
>> (this is an argument for a different-style martian that allows one to
>> indicate what is being registered not by base-class but by directive:
>> grok.adapter(), grok.view(), etc. That's another discussion and a much
>> bigger topic, though)
>>
>> We still have the confusion of the word provides, which in ZCML means it
>> provides an *interface*. I guess here it would mean "provides an adapter
>> of kind IFoo".
>>
>> Let's think about naming some more. We're writing a class. It implements
>> some interfaces. We now want to look up an instance of this class. We do
>> this by asking for an instance that provides one of these interfaces. In
>> cases of adapters, this instance is created on the fly, in case of
>> utilities, it's been registered already.
>>
>> So what do we call: "this class makes instances that will provide
>> interface X when looked up as an adapter/utility" notion?
>>
>> Let's check the thesaurus.
>>
>> The class is a factory for IFoo adapters (or the IFoo utility).
>> Therefore, we could consider grok.factory(IFoo). There's a slight
>> overloading with the factory notion in Zope 3 (there's such a directive,
>> I think?), but it doesn't appear to be a commonly used notion (and
>> certainly not in Grok). Also I have the feeling there's a subtle
>> difference between the way grok.context and grok.layer are used and
>> grok.factory, but perhaps that's just me.
>>
>> The class creates IFoo adapters (or the IFoo utility). Therefore, you'd
>> write grok.creates(IFoo).
>>
>> Other possibilities might be grok.delivers or grok.produces.
>>
>> Right now, I think I like 'creates' the best.
>>
>> [snip]
>>> If you do a "from foo import bar" style (still advocated in some
>>> quarters, and used at Canonical)
>>
>> [I tend to do quite a lot of this too. I don't buy the arguments for
>> repeating.a.dotted.name.everywhere; in my experience it produces more
>> cycles (and needs for deferredimport) than a few 'from foo import bar'
>> in a package. Especially when you create a clean interface in a
>> package's __init__.py which I really like]
>>
>>> then the distinction is even more
>>> stark, in my opinion.  Current:
>>>
>>> class FeaturedCookbookLink(CookbookTopLevelObject):
>>>      """A link to the currently featured cookbook."""
>>>     implements(ICookbookObject, ITopLevelEntryLink)
>>>      provides(ITopLevelEntryLink)
>>
>> For grokcore.component, I'd recommend doing this:
>>
>> import grokcore.component as grok
>>
>> (or: from grokcore import component as grok)
>>
>> [Inside a package, I often use the pattern where I import a module
>> instead of an individual name. still a from import]
>>
>>> My read: huh?
>>>
>>> Proposed:
>>>
>>> class FeaturedCookbookLink(CookbookTopLevelObject):
>>>      """A link to the currently featured cookbook."""
>>>     implements(ICookbookObject, ITopLevelEntryLink)
>>>     provides_adapter(ITopLevelEntryLink)
>>>
>>> My read: ah so!
>>
>> What do you think about:
>>
>> class FeaturedCookbookLink(CookbookTopLevelObject):
>>     grok.implements(ICookbookObject, ITopLevelEntryLink)
>>     grok.creates(ITopLevelEntryLink)
>>
>> Regards,
>>
>> Martijn
>>
>> _______________________________________________
>> Grok-dev mailing list
>> Grok-dev at zope.org
>> https://mail.zope.org/mailman/listinfo/grok-dev
>>
>


More information about the Grok-dev mailing list