[Zope-CMF] Re: Tools as local utilities
Hanno Schlichting
plone at hannosch.info
Mon Dec 11 18:14:51 EST 2006
Hi Jens, all!
I haven't seen any progress on the tools as local utilities story for
some time now. Is there anything specific I can help with?
Jens Vagelpohl wrote:
> On 22 Nov 2006, at 12:15, Hanno Schlichting wrote:
>> At the time I wrote this it was kind of experimental and I didn't know
>> if I could make it work. So I put it in an add-on with the clear
>> intention to merge it back into GenericSetup once it was reasonably
>> stable and working. Thx for taking over that part :)
>
> Thanks for the code ;)
I have taken another look at the code and fixed some obvious bugs. As I
still have no commit rights for the svn repo (yes, entirely my fault)
could somebody commit the attached patch (against GS trunk) for me?
With this patch applied I think at least the utility handlers are fully
functional. As I haven't written tests for the adapter handlers so far,
I'm not sure for those yet ;)
Thx in advance,
Hanno
-------------- next part --------------
Index: tests/test_components.py
===================================================================
--- tests/test_components.py (revision 71534)
+++ tests/test_components.py (working copy)
@@ -24,10 +24,14 @@
from Products.Five.component import enableSite
from Products.Five.component.interfaces import IObjectManagerSite
+from Products.GenericSetup.interfaces import IBody
from Products.GenericSetup.testing import BodyAdapterTestCase
from Products.GenericSetup.testing import ExportImportZCMLLayer
+from Products.GenericSetup.tests.common import DummyExportContext
+from Products.GenericSetup.tests.common import DummyImportContext
from zope.app.component.hooks import setSite, clearSite, setHooks
+from zope.component import getMultiAdapter
from zope.component import getSiteManager
from zope.component import queryUtility
from zope.component.globalregistry import base
@@ -50,12 +54,6 @@
def verify():
"""Returns True."""
-class IDummyInterface2(Interface):
- """A second dummy interface."""
-
- def verify():
- """Returns True."""
-
class DummyUtility(object):
"""A dummy utility."""
@@ -64,28 +62,31 @@
def verify(self):
return True
-class DummyUtility2(object):
- """A second dummy utility."""
+class DummyTool(SimpleItem):
+ """A dummy tool."""
+ implements(IDummyInterface)
- implements(IDummyInterface2)
+ id = 'dummy_tool'
+ meta_type = 'dummy tool'
+ security = ClassSecurityInfo()
+ security.declarePublic('verify')
def verify(self):
return True
-dummy2 = DummyUtility2()
-
-class DummyTool(SimpleItem):
- """A dummy tool."""
+class DummyTool2(SimpleItem):
+ """A second dummy tool."""
implements(IDummyInterface)
- id = 'dummy_tool'
- meta_type = 'dummy tool'
+ id = 'dummy_tool2'
+ meta_type = 'dummy tool2'
security = ClassSecurityInfo()
security.declarePublic('verify')
def verify(self):
return True
+
InitializeClass(DummyTool)
_COMPONENTS_BODY = """\
@@ -100,12 +101,10 @@
object="/dummy_tool"/>
<utility name="dummy tool name2"
interface="Products.GenericSetup.tests.test_components.IDummyInterface"
- object="/test_folder_1_/dummy_tool"/>
+ object="/test_folder_1_/dummy_tool2"/>
<utility name="foo"
factory="Products.GenericSetup.tests.test_components.DummyUtility"
interface="Products.GenericSetup.tests.test_components.IDummyInterface"/>
- <utility component="Products.GenericSetup.tests.test_components.dummy2"
- interface="Products.GenericSetup.tests.test_components.IDummyInterface2"/>
</utilities>
</componentregistry>
"""
@@ -115,6 +114,32 @@
layer = ExportImportZCMLLayer
+ def test_body_get(self):
+ self._populate(self._obj)
+ context = DummyExportContext(self.app)
+ adapted = getMultiAdapter((self._obj, context), IBody)
+ self.assertEqual(adapted.body, self._BODY)
+
+ def test_body_set(self):
+ context = DummyImportContext(self.app)
+ adapted = getMultiAdapter((self._obj, context), IBody)
+ adapted.body = self._BODY
+ self._verifyImport(self._obj)
+ self.assertEqual(adapted.body, self._BODY)
+
+ # now in update mode
+ context._should_purge = False
+ adapted = getMultiAdapter((self._obj, context), IBody)
+ adapted.body = self._BODY
+ self._verifyImport(self._obj)
+ self.assertEqual(adapted.body, self._BODY)
+
+ # and again in update mode
+ adapted = getMultiAdapter((self._obj, context), IBody)
+ adapted.body = self._BODY
+ self._verifyImport(self._obj)
+ self.assertEqual(adapted.body, self._BODY)
+
def _getTargetClass(self):
from Products.GenericSetup.components import \
ComponentRegistryXMLAdapter
@@ -139,19 +164,15 @@
self.assertEqual(tool.meta_type, 'dummy tool')
self.assertEquals(repr(util), repr(tool))
- util = queryUtility(IDummyInterface2)
- self.failUnless(IDummyInterface2.providedBy(util))
- self.failUnless(util.verify())
-
util = queryUtility(IDummyInterface, name='dummy tool name2')
self.failUnless(IDummyInterface.providedBy(util))
self.failUnless(util.verify())
- self.assertEqual(util.meta_type, 'dummy tool')
+ self.assertEqual(util.meta_type, 'dummy tool2')
# make sure we can get the tool by normal means
- tool = getattr(self.app.test_folder_1_, 'dummy_tool2')
- self.assertEqual(tool.meta_type, 'dummy tool')
- self.assertEquals(repr(util), repr(tool))
+ tool = getattr(self.folder, 'dummy_tool2')
+ self.assertEqual(tool.meta_type, 'dummy tool2')
+ self.assertEquals(repr(util.aq_base), repr(tool.aq_base))
def afterSetUp(self):
BodyAdapterTestCase.setUp(self)
@@ -164,17 +185,15 @@
sm.registerUtility(DummyUtility(), IDummyInterface)
sm.registerUtility(DummyUtility(), IDummyInterface, name=u'foo')
- sm.registerUtility(dummy2, IDummyInterface2)
tool = DummyTool()
self.app._setObject(tool.id, tool)
obj = self.app[tool.id]
sm.registerUtility(obj, IDummyInterface, name=u'dummy tool name')
- folder = self.app.test_folder_1_
- tool2 = DummyTool()
- folder._setObject('dummy_tool2', tool2)
- obj = folder['dummy_tool2']
+ tool2 = DummyTool2()
+ self.folder._setObject(tool2.id, tool2)
+ obj = self.folder[tool2.id]
sm.registerUtility(obj, IDummyInterface, name=u'dummy tool name2')
self._obj = sm
Index: components.py
===================================================================
--- components.py (revision 71534)
+++ components.py (working copy)
@@ -15,7 +15,6 @@
$Id$
"""
-from zope.app.component.hooks import getSite
from zope.component import adapts
from zope.component import getSiteManager
from zope.component.interfaces import IComponentRegistry
@@ -71,7 +70,7 @@
self._logger.info('Utilities registered.')
def _purgeAdapters(self):
- registrations = self.context.registeredAdapters()
+ registrations = tuple(self.context.registeredAdapters())
for registration in registrations:
factory = registration.factory
@@ -85,7 +84,7 @@
name=name)
def _purgeUtilities(self):
- registrations = self.context.registeredAdapters()
+ registrations = tuple(self.context.registeredUtilities())
for registration in registrations:
provided = registration.provided
@@ -128,22 +127,20 @@
obj_path = child.getAttribute('object')
if obj_path:
- site = getSite()
+ site = self.environ.getSite()
# we support registering aq_wrapped objects only for now
if hasattr(site, 'aq_base'):
# filter out empty path segments
path = [f for f in obj_path.split('/') if f]
- # XXX add support for nested folder
- if len(path) > 1:
- return
- obj = getattr(site, path[0], None)
+ # support for nested folder
+ obj = self._recurseFolder(site, path)
if obj is not None:
self.context.registerUtility(obj, provided, name)
else:
# Log an error, not aq_wrapped
self._logger.warning("The object %s was not acquisition "
"wrapped. Registering these is not "
- "supported right now." % obj)
+ "supported right now." % obj_path)
elif component:
self.context.registerUtility(component, provided, name)
else:
@@ -156,9 +153,9 @@
# which is needed for the tests we convert to a sorted list
registrations = [reg for reg in self.context.registeredAdapters()]
registrations.sort()
-
+
for registration in registrations:
- child=self._doc.createElement('adapter')
+ child = self._doc.createElement('adapter')
factory = _getDottedName(registration.factory)
provided = _getDottedName(registration.provided)
@@ -187,7 +184,7 @@
registrations.sort()
for registration in registrations:
- child=self._doc.createElement('utility')
+ child = self._doc.createElement('utility')
provided = _getDottedName(registration.provided)
child.setAttribute('interface', provided)
@@ -198,45 +195,34 @@
comp = registration.component
# check if the component is acquisition wrapped. If it is export
- # an object reference instead of a component / factory reference
+ # an object reference instead of a factory reference
if hasattr(comp, 'aq_base'):
# if the site is acquistion wrapped as well, get the relative
# path to the site
path = '/'.join(comp.getPhysicalPath())
- site = getSite()
+ site = self.environ.getSite()
if hasattr(site, 'aq_base'):
site_path = '/'.join(site.getPhysicalPath())
rel_path = path[len(site_path):]
child.setAttribute('object', rel_path)
else:
factory = _getDottedName(type(comp))
- reference = self.resolveName(comp)
- if reference:
- module = _getDottedName(comp.__module__)
- component = "%s.%s" % (module, reference)
- child.setAttribute('component', component)
- else:
- child.setAttribute('factory', factory)
+ child.setAttribute('factory', factory)
fragment.appendChild(child)
return fragment
- def resolveName(self, component):
- # extremly ugly hack to get to the reference name, this only
- # works if the utility reference is defined in the namespace of the
- # same module as the class itself
- module = _resolveDottedName(component.__module__)
- namespace = module.__dict__
- name = ''
- for ref in namespace:
- if namespace[ref] is component:
- name = ref
- del module
- del namespace
- return name
+ def _recurseFolder(self, site, path):
+ root = site
+ for pathsegment in path:
+ if root is None:
+ break
+ root = getattr(root, pathsegment, None)
+ return root
+
def dummyGetId():
return ''
More information about the Zope-CMF
mailing list