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
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 ''
_______________________________________________ Zope-CMF maillist - Zope-CMF@lists.zope.org http://mail.zope.org/mailman/listinfo/zope-cmf See http://collector.zope.org/CMF for bug reports and feature requests