Utility design pattern in Zope 3 allows overridable singleton class instances for your code.
Utility classes provide site-wide utility functions.
They are registered by marker interfaces.
Site customization logic or add-on products can override utilities for enhanced or modified functionality
Utilities can be looked up by name or interface
Compared to “plain Python functions”, utilities provide the advantage of being plug-in points without need of monkey-patching.
Read more in
Local and global utilities¶
Utilities can be
global - registered during Zope start-up
local - registered during add-on installer for a certain site/content item
Local utilities are registered to persistent objects. The context of local utilities is stored in a thread-local variable which is set during traversal. Thus, when you ask for local utilities, they usually come from a persistent registry set up in the Plone site root object.
Global utilities are registered in ZCML and affect all Zope application server and Plone site instances.
<Moo^_^> what's difference between gsm.queryUtility() (global site manager) and zope.component.queryUtility() <agroszer> Moo^_^, I think gsm... takes the global registrations, z.c.queryUtility respects the current context
Registering a global utility¶
A utility is constructed when Plone is started and ZCML is read. Utilities take no constructor parameters. If you need to use parameters like context or request, consider using views or adapters instead. Utilities may or may not have a name.
A utility can be provided by a function: the function is called and it returns the utility object.
A utility can be provided by a class: the class
__call__()method itself acts as an factory and returns a new class instance.
<!-- Register header animation picking logic - override this for your custom logic --> <utility provides="gomobile.convergence.interfaces.IConvergenceMediaFilter" factory=".filter.ConvergedMediaFilter" />
Python example (named utility):
def registerOnsitePaymentProcessor(processor_class): """ """ # Make OnsitePaymentProcessor class available as utiltiy processor = processor_class() gsm = component.getGlobalSiteManager() gsm.registerUtility(processor, interfaces.IOnsitePaymentProcessor, processor.name)
The utility class “factory” is in its simplest form a class which implements the interface:
class ConvergedMediaFilter(object): """ Helper class to deal with media state of content objects. """ zope.interface.implements(IConvergenceMediaFilter) def foobar(x): """ An example method """ return x+2
Class is constructed / factory is run during the ZCML initialization.
To use this class:
from gomobile.convergence.interfaces import IConvergenceMediaFilter def something(): filter = getUtility(IConvergenceMediaFilter) x = filter.foobar(3)
Registering a local utility¶
Local utilities may be destroyed when the add-on product that provides them is reinstalled. Do not use them to store any data.
If you want to override any existing utility you can re-register the utility
overrides.zcml file in your product.
Getting a utility¶
There are two functions:
will raise an exception if the utility is not found.
Noneif the utility is not found.
Utility query parameters are passed to the utility class constructor.
from zope.component import getUtility, queryUtility # context and request are passed to the utility class constructor # they are optional and depend on the utility itself picker = getUtility(IHeaderAnimationPicker, context, request)
You cannot use
getUtility() on Python module level code
during import, as the Zope Component Architecture is not yet initialized
at that time.
getUtility() from an HTTP request end point or after
Zope has been started.
Query local + global utilities:
zope.component.queryUtility() for local utilities, with global fallback.
Query only global utilities:
from zope.app import zapi gsm = zapi.getGlobalSiteManager() return gsm.getUtility(IConvergenceMediaFilter)
Due to Zope component architecture initialization order, you cannot call
getUtility() in module-level Python code.
Module-level Python code is run when the module is being
imported, and Zope components are not yet set up at this point.
Getting all named utilities of one interface¶
def OnsitePaymentProcessors(context): """ List all registered on-site payment processors. Mostly useful for validating form input. Vocabulary contains all payment processors, not just active ones. @return: zope.vocabulary.SimpleVocabulary """ utilities = component.getUtilitiesFor(interfaces.IOnsitePaymentProcessor) for name, instance in utilities: pass