[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?
> 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