[Grok-dev] Re: Global utilities registered too early?

Philipp von Weitershausen philipp at weitershausen.de
Tue Jun 19 13:33:36 EDT 2007

Jan-Wijbrand Kolman wrote:
> I'm trying to create/register a global utility by subclassing
> grok.GlobalUtility. If I understand correctly, exactly one instance of
> this utility class is created at registration time, right? It is this
> instance that is returned when calling getUtility, right?

Right; Right.

> Now, in my case the __init__ of my utility class makes use of other
> global utilities that are registered by a "third party" package
> (called userschema). However, when creating the instance for my
> utility class, the "third party" utilities are not registered (yet)
> and thus cannot be found.
> I'm not sure I fully understand why this is the case (and thus I do
> not see a way around it yet). I also tried to <include
> package="userschema" ?> just before the <grok:grok package="."/>
> directive in my package's configure.zcml, but to no avail; My global
> utility seems always to be registered before the utilities from
> userschema are registered.
> Maybe somebody can nudge me in the right direction with this?

In general I would say you're doing it wrong. As I asserted above, 
utility's __init__ is called during registration time at which time the 
state of the component registry cannot be known. I don't think you 
should make any assumptions at that point. In particular, you shouldn't 
make any assumptions for the rest of the Python process.

One of the key features of the Component Architecture is 
overrideability. We can have it by simply registering a new utility 
"over" an old one, we can do it elegantly with ZCML overrides and we can 
do it locally using local sites. Point is, to ensure this 
overrideability, there are certain sacrifices to make which can be, I 
think, summed up in two simple rules of thumb:

* don't register during import time

* don't look up during registration time

In particular, you only want to do look-ups during request time because 
the way components are acquired may be different in each individual 
requests, thanks to local sites.

"I don't have local components, they're all global utilities" you might 
say. Well, getUtility() isn't aware of that and I think you should never 
code in a way that it implicitly has to make that assumption. So, 
whenever you need those secondary utilities in your utility, get them by 
doing getUtility() each time. Might not be particularly elegant from a 
Python perspective, but it's the price to pay for flexibility.

http://worldcookery.com -- Professional Zope documentation and training

More information about the Grok-dev mailing list