[Grok-dev] Re: Layer and skin registrations; possible simplification

Philipp von Weitershausen philipp at weitershausen.de
Thu Jul 24 16:16:58 EDT 2008

Jan-Wijbrand Kolman wrote:
> For the applications we're building, we're using layers to quite an 
> extent. Every time I try to explain to my co-workers how the layers and 
> skins we use are being registered, I get confused looks and frankly I 
> get confused explaining it too.
> I think the way we register layers and skins can be a bit simpler.
> In Grok, it looks like a `grok.Skin` is some kind of component even if 
> it really only just triggers the registration of the provision of 
> IBrowserSkinType of some layer.

Yes. That bothers me too. I like how in Grok we write a 
class-per-component, but in most other cases, we actually end up with a 
meaningful component as an instance of the class we wrote. This isn't 
the case with grok.Skin.

> My suggestion:
> Let's deprecate the `grok.Skin` "component" and introduce a 
> `grok.skin()` directive to be declared on layer components. The 
> registration of layers and skins would then look like this::
>   class SomeApplicationLayer(grok.IGrokLayer)
>     grok.skin('myapp') # activated by ++skin++myapp in the URL
> If you need richer layer structure you can of course still create 
> hierarchies of layers::
>   class AdminLayer(grok.IGrokLayer):
>     pass

Why is there IGrokLayer? Let's deprecate that as well. As far as I can 
tell, it bears no use whatsoever. If people are worried about having to 
import a base interface, then let's expose IBrowserRequest from grok. 
Because that's what you should use to base layers and skins on anyways.

>   class CustomAdminLayer(AdminLayer, SomeApplicationLayer):
>     grok.skin('custom') # activated by ++skin++custom in the URL

That looks good to me. Note that grok.skin() is a directive that has to 
work on interfaces (since layers and skins are interfaces). This isn't 
trivial because directives generally want to store attributes on the 
scope they're used at. Interfaces won't allow that (you'll get an 
ominous "Concrete attribute" error).

However, interfaces allow tagged values (sort of like annotations). 
We'll have to make the grok.skin's storage part use tagged values. 
plone.supermodel already implements such a storage that we might be able 
to nick ;). See FieldsetStorage in 

> Alternativeley we could use the `grok.name()` directive to set the name 
> of the skin::
>   class CustomAdminLayer(AdminLayer, SomeApplicationLayer):
>     grok.name('custom') # fallback is whatever the name directive does
>     grok.skin() # activated by ++skin++custom in the URL


grok.name won't work on interfaces (see above for reason) and trying to 
make it would complicate its implementation tremendously.

> As far as I can see now this could be implemented in a "backwards" 
> compatible fashion by properly deprecating the use of `grok.Skin` and by 
> introducing the `grok.skin` directive.
> Hmm, I do think of one issue right now and that is how to register a 
> third-party layer as a skin. You could still subclass that third-party 
> layer and set a `grok.skin()` directive on the subclass.


More information about the Grok-dev mailing list