0

I have a product for a plone site with a module containing a utility class, and in the module that will/should use this utility, I am trying to have it setup at the module level.

In the module containing the utility (my.product.testutility), I have this:

from five import grok
from zope.interface import Interface

class ITestUtil(Interface):
    """Interface of utility
    """

    def returnTest(self):
        """return a string for now
        """ 

class TestUtil(object):
    """Utility class test
    """
    grok.implements(ITestUtil)

    def returnTest(self):
        return "testing"

grok.global_utility(TestUtil, name="TestUtility")

In the module that will use this utility (my.product.stringtesting):

from five import grok
from my.package.testutility import ITestUtil
from zope import component, schema
from Products.CMFCore.interfaces import ISiteRoot

utilForTesting = component.getUtility(ITestUtil, name="TestUtility")

class IStringTest(Interface):
     ......


class View(grok.View):
     def returnStringForTest(self):
         return utilForTesting.returnTest()

I also had the template file that would call the returnStringForTest to display the string on the rendered page.

I end up getting this error unfortunately: ComponentLookupError: (< InterfaceClass my.product.testutility.ITestUtil >, "TestUtility")

I did try several different things like using grok.GlobalUtility as a base as opposed to making it an object registering it through grok.global_utility. I did remove the name parameter in the class using this while testing this.

The documentation I was trying to follow was the References on the grok site, looking at the directives page where it has the global utility information.

Also, I am using grok 0.9. Edit: The version of Plone I am using is Plone 4 and the version of python I am using is 2.7.

Is it possible to have the utility set up at the module level like I was trying?

Mathias
  • 6,777
  • 2
  • 20
  • 32
Patrick Downey
  • 965
  • 8
  • 13
  • 1
    If I was 100% sure, I'd make this an answer, rather than a comment :) When using grok, you can't rely on everything happening in procedural order. There are all kinds of deferred processing tricks built into grok. Use the zope.component utility registration api instead. zope.component.getGlobalSiteManager().registerUtility(ob, I1). – SteveM Nov 06 '14 at 00:53
  • 1
    What about using zcml? – Mathias Nov 06 '14 at 06:57
  • I was reading through the Plone 4.3 Utilities documentation on Plone.org and found that its not possible to use getUtility at module level because of the "Zope component architecture initialization order." That would explain why I kept on getting that error. It seems I'll have to rely on ZCML? Thank you for your responses, I appreciate it. – Patrick Downey Nov 07 '14 at 17:42

1 Answers1

3

You can do what you want without relying on Zope at all.

You can change the line in my.product.stringtesting: from

utilForTesting = component.getUtility(ITestUtil, name="TestUtility")

to

utilForTesting = TestUtil()
alepisa
  • 1,324
  • 8
  • 14
  • I've been actually using the utility (for a lack of a better term?) this way. The reason for utility is I was attempting to create several utilities for handling database connections (through sqlalchemy). The idea was I had multiple utilities, each one with their own engine defined at module level. I would've obtained the connection and declarative base from the utility. This might not be efficient and perhaps nonsensical, but I'm sort of struggling with trying to setup independent engines.That's a whole other question though and I might be on the wrong trail. Anyhow, thanks for your answer. – Patrick Downey Nov 14 '14 at 00:42
  • I think I get your point. You can register a utility that has utilForTesting accessible as a class attribute. In any case you getUtility will fail until the ZCA is ready to serve the utility. Anyway https://pypi.python.org/pypi/z3c.saconfig is doing something similar – alepisa Nov 14 '14 at 08:37