How to make zope load my ZCML?

359 views Asked by At

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.

2

There are 2 answers

0
Bunyk On BEST ANSWER

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
0
Marius Gedminas On

You include it from some other ZCML file with

<include package="your.package" />

If you're writing an application from scratch, you'll have to have a top-level ZCML file that first registers all the ZCML directives (e.g. <utility>) by including the right meta.zcml before you can use them in your own included ZCML files:

<include package="zope.component" file="meta.zcml" />

On the Python side, you use one of the APIs in the zope.configuration.xmlconfig module to load the ZCML file:

  • zope.configuration.xmlconfig.file
  • zope.configuration.xmlconfig.string
  • zope.configuration.xmlconfig.xmlconfig
  • zope.configuration.xmlconfig.XMLConfig

Which one? How are they different? I don't know! It's all supposedly documented, but I can't make heads or tails of it! I used xmlconfig.string in ZODBBrowser, and it seems to work, but was that a good idea? I don't know!

Don't use Zope if you value your sanity.