Problem with a local utility used as a dependency in a product
Here's the problem. I have mynamespace.mypackage
that has as a dependency mynamespace.mydependencypackage
, that is a local utility. It's registered using component registry.
In config.py
from mynamespace.mypackage
, I have
DEPENDENCIES = ['mynamespace.mydependencypackage']
And in my mynamespace.mypackage
's setuphandlers.py
this dependency is installed if not already installed.
Problem is: if I reinstall mynamespace.mypackage
through ZMI
, everything seems to perfectly install (since no errors are shown) but I keep getting a ComponentLookupError
when using methods in mynamespace.mypackage
that gets the utility:
Module zope.component._api, line 207, in getUtility
ComponentLookupError: (<InterfaceClass MY_UTILITY_INTERFACE, '')
I can 'fix' this problem, by reinstalling the mynamespace.mydependencypackage
in my setuphandlers.py
or through the ZMI as well when reinstalling mynamespace.mypackage
, but this doesn't seem the best solution for me.
What am I missing about Generic Setup here? I didn't make this utility persist any value on ZODB whatsoever. I can just forget about all these problems and create a BrowserView
with utilities methods, but I want to understand first why am I having these problems.
EDIT: Now, I have a bigger problem. The TypeError: ('object.__new__(MyClass) is not safe, use Persistence.Persistent.__new__()', <function _reconstructor at 0xb7783e9c>, (<class 'mynamespace.mydependencypackage.package.MyClass'>, <type 'object'>, None))
is being shown. Full traceback:
Traceback (innermost last):
Module ZPublisher.Publish, line 110, in publish
Module开发者_StackOverflow ZPublisher.BaseRequest, line 429, in traverse
Module ZPublisher.BeforeTraverse, line 99, in __call__
Module Products.CMFCore.PortalObject, line 94, in __before_publishing_traverse__
Module zope.event, line 23, in notify
Module zope.component.event, line 26, in dispatch
Module zope.component._api, line 130, in subscribers
Module zope.component.registry, line 290, in subscribers
Module zope.interface.adapter, line 535, in subscribers
Module zope.component.event, line 33, in objectEventNotify
Module zope.component._api, line 130, in subscribers
Module zope.component.registry, line 290, in subscribers
Module zope.interface.adapter, line 535, in subscribers
Module zope.app.component.site, line 375, in threadSiteSubscriber
Module zope.app.component.hooks, line 61, in setSite
Module Products.CMFCore.PortalObject, line 75, in getSiteManager
Module ZODB.Connection, line 761, in setstate
Module ZODB.Connection, line 819, in _setstate
Module ZODB.serialize, line 604, in setGhostState
Module ZODB.serialize, line 597, in getState
Module copy_reg, line 48, in _reconstructor
TypeError: ('object.__new__(MyClass) is not safe, use Persistence.Persistent.__new__()', <function _reconstructor at 0xb7783e9c>, (<class 'mynamespace.mydependencypackage.package.MyClass'>, <type 'object'>, None))
It sounds like you have custom Python code in your setuphandlers.py file to install the dependency. Is there a reason you don't note the dependency in the metadata.xml file? Or can you show us that code?
When activating an add-on in Plone, it does a before/after comparison of various entities to support deactivation. Among these are local persistent utilities, as defined by the componentregistry.xml file. Note: anything defined in GenericSetup xml files results in persistent changes - if you want non-persistent utilities, use ZCML files to register them.
So when you have custom code to add a local utility in your setuphandlers.py code, Plone thinks this utility belongs to your main add-on. If you reinstall that add-on the utility gets removed alongside anything else and then everything is installed again.
I'm guessing your "is it already installed" check fails after the reinstall and the utility isn't added again.
You can avoid all of this, by simple giving both the dependency and main add-on their own GenericSetup profiles and than noting a dependency in the main's metadata.xml, like:
<?xml version="1.0"?>
<metadata>
<version>1</version>
<dependencies>
<dependency>profile-my.dependency:default</dependency>
</dependencies>
</metadata>
Once you do that the dependencies profile will be activated independently and Plone keeps track of it on its own. If you then decide to reinstall the main add-on, the dependency won't be touched at all and remains intact.
精彩评论