Utility design pattern in Zope 3 allows easily 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
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
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)
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 in the
file in your product.
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
on Python module level code during import, as the Zope
Component Architecture is not yet initialized at that
time. Always call
from an HTTP request end point or after Zope has been
Query local + global utilities:
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
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.
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