When I write some utility, register it and then query with getUtility
it works ok:
class IOperation(Interface):
def __call__(a, b):
''' performs operation on two operands '''
class Plus(object):
implements(IOperation)
def __call__(self, a, b):
return a + b
plus = Plus()
class Minus(object):
implements(IOperation)
def __call__(self, a, b):
return a - b
minus = Minus()
gsm = getGlobalSiteManager()
gsm.registerUtility(plus, IOperation, '+')
gsm.registerUtility(minus, IOperation, '-')
def calc(expr):
a, op, b = expr.split()
res = getUtility(IOperation, op)(eval(a), eval(b))
return res
assert calc('2 + 2') == 4
Now, as I understand I could move registration of utilities to the configure.zcml
, like this:
<configure xmlns="http://namespaces.zope.org/zope">
<utility
component=".calc.plus"
provides=".calc.IOperation"
name="+"
/>
<utility
component=".calc.minus"
provides=".calc.IOperation"
name="-"
/>
</configure>
But I don't know how to make globbal site manager read this zcml.
Actually, all that was needed to make this work - move parsing of zcml to another file. So, the solution now consists of three files:
calc.py
:
from zope.interface import Interface, implements
from zope.component import getUtility
class IOperation(Interface):
def __call__(a, b):
''' performs operation on two operands '''
class Plus(object):
implements(IOperation)
def __call__(self, a, b):
return a + b
class Minus(object):
implements(IOperation)
def __call__(self, a, b):
return a - b
def eval(expr):
a, op, b = expr.split()
return getUtility(IOperation, op)(float(a), float(b))
configure.zcml
:
<configure xmlns="http://namespaces.zope.org/zope">
<include package="zope.component" file="meta.zcml" />
<utility
factory="calc.Plus"
provides="calc.IOperation"
name="+"
/>
<utility
factory="calc.Minus"
provides="calc.IOperation"
name="-"
/>
</configure>
And main.py
:
from zope.configuration import xmlconfig
from calc import eval
xmlconfig.file('configure.zcml')
assert eval('2 + 2') == 4