[Checkins] SVN: Products.GenericSetup/trunk/Products/GenericSetup/ Added new feature to the component handler. For factory based utilities you can now specify an addit
Hanno Schlichting
hannosch at hannosch.eu
Sun May 17 14:05:34 EDT 2009
Log message for revision 100050:
Added new feature to the component handler. For factory based utilities you can now specify an addit
ional id. All factory based utilities will now by default be added to the site manager (being an Obj
ectManager itself) as an object and this persistent object is registered as the utility. On removal
both the registration and the object are removed. The new id argument is used to specify the id of t
he object as set via `__name__`. This change makes these utilities introspectable in the ZMI and cle
arly separates the persistent object and utility registration aspect.
Changed:
U Products.GenericSetup/trunk/Products/GenericSetup/CHANGES.txt
U Products.GenericSetup/trunk/Products/GenericSetup/components.py
U Products.GenericSetup/trunk/Products/GenericSetup/tests/test_components.py
-=-
Modified: Products.GenericSetup/trunk/Products/GenericSetup/CHANGES.txt
===================================================================
--- Products.GenericSetup/trunk/Products/GenericSetup/CHANGES.txt 2009-05-17 17:53:56 UTC (rev 100049)
+++ Products.GenericSetup/trunk/Products/GenericSetup/CHANGES.txt 2009-05-17 18:05:33 UTC (rev 100050)
@@ -4,6 +4,15 @@
GenericSetup 1.5.0 (unreleased)
-------------------------------
+- Added new feature to the component handler. For factory based utilities you
+ can now specify an additional id. All factory based utilities will now by
+ default be added to the site manager (being an ObjectManager itself) as an
+ object and this persistent object is registered as the utility. On removal
+ both the registration and the object are removed. The new id argument is
+ used to specify the id of the object as set via `__name__`. This change
+ makes these utilities introspectable in the ZMI and clearly separates the
+ persistent object and utility registration aspect.
+
- Adjusted TarballImportContext to work with Python 2.6's tarfile module.
- Cleaned up / normalized imports:
Modified: Products.GenericSetup/trunk/Products/GenericSetup/components.py
===================================================================
--- Products.GenericSetup/trunk/Products/GenericSetup/components.py 2009-05-17 17:53:56 UTC (rev 100049)
+++ Products.GenericSetup/trunk/Products/GenericSetup/components.py 2009-05-17 18:05:33 UTC (rev 100050)
@@ -175,6 +175,9 @@
if ( child.hasAttribute('remove') and
self.context.queryUtility(provided, name) is not None ):
+ ofs_id = self._ofs_id(child)
+ if ofs_id in self.context.objectIds():
+ self.context._delObject(ofs_id, suppress_events=True)
self.context.unregisterUtility(provided=provided, name=name)
continue
@@ -207,22 +210,37 @@
self.context.registerUtility(component, provided, name)
elif factory:
current = [ utility for utility in current_utilities
- if utility.provided==provided and
+ if utility.provided==provided and
utility.name==name ]
- assert len(current) <=1
if current and getattr(current[0], "factory", None)==factory:
continue
- try:
- self.context.registerUtility(None, provided, name, factory=factory)
- except TypeError:
- # zope.component < 3.5.0
- self.context.registerUtility(factory(), provided, name)
+ obj = factory()
+ ofs_id = self._ofs_id(child)
+ if ofs_id not in self.context.objectIds():
+ self.context._setObject(ofs_id, aq_base(obj),
+ set_owner=False, suppress_events=True)
+ obj = self.context.get(ofs_id)
+ obj.__name__ = ofs_id
+ obj.__parent__ = aq_base(self.context)
+ self.context.registerUtility(aq_base(obj), provided, name)
else:
self._logger.warning("Invalid utility registration for "
"interface %s" % provided)
+ def _ofs_id(self, child):
+ # We build a valid OFS id by using the interface's full
+ # dotted path or using the specified id
+ name = str(child.getAttribute('name'))
+ ofs_id = str(child.getAttribute('id'))
+ if not ofs_id:
+ ofs_id = str(child.getAttribute('interface'))
+ # In case of named utilities we append the name
+ if name:
+ ofs_id += '-' + str(name)
+ return ofs_id
+
def _extractAdapters(self):
fragment = self._doc.createDocumentFragment()
@@ -279,8 +297,10 @@
child.setAttribute('name', reg_info['name'])
if reg_info['factory'] is not None:
- child.setAttribute('factory', _getDottedName(reg_info['factory']))
+ factory = _getDottedName(reg_info['factory'])
+ child.setAttribute('factory', factory)
else:
+ factory = None
comp = reg_info['component']
# check if the component is acquisition wrapped. If it is, export
# an object reference instead of a factory reference
@@ -296,6 +316,11 @@
else:
factory = _getDottedName(type(comp))
child.setAttribute('factory', factory)
+ if factory is not None:
+ ofs_id = self._ofs_id(child)
+ name = getattr(comp, '__name__', '')
+ if ofs_id != name:
+ child.setAttribute('id', name)
fragment.appendChild(child)
Modified: Products.GenericSetup/trunk/Products/GenericSetup/tests/test_components.py
===================================================================
--- Products.GenericSetup/trunk/Products/GenericSetup/tests/test_components.py 2009-05-17 17:53:56 UTC (rev 100049)
+++ Products.GenericSetup/trunk/Products/GenericSetup/tests/test_components.py 2009-05-17 18:05:33 UTC (rev 100050)
@@ -54,7 +54,7 @@
def createComponentRegistry(context):
enableSite(context, iface=IObjectManagerSite)
- components = PersistentComponents()
+ components = PersistentComponents('++etc++site')
components.__bases__ = (base,)
components.__parent__ = aq_base(context)
context.setSiteManager(components)
@@ -125,6 +125,7 @@
<adapters/>
<utilities>
<utility factory="Products.GenericSetup.tests.test_components.DummyUtility"
+ id="dummy_utility"
interface="Products.GenericSetup.tests.test_components.IDummyInterface"/>
<utility name="dummy tool name"
interface="Products.GenericSetup.tests.test_components.IDummyInterface"
@@ -143,7 +144,8 @@
<?xml version="1.0"?>
<componentregistry>
<utilities>
- <utility factory="Products.GenericSetup.tests.test_components.DummyUtility"
+ <utility id="dummy_utility"
+ factory="Products.GenericSetup.tests.test_components.DummyUtility"
interface="Products.GenericSetup.tests.test_components.IDummyInterface"
remove="True"/>
<utility name="dummy tool name"
@@ -168,9 +170,22 @@
return ComponentRegistryXMLAdapter
def _populate(self, obj):
- obj.registerUtility(DummyUtility(), IDummyInterface)
- obj.registerUtility(DummyUtility(), IDummyInterface2, name=u'foo')
+ util = DummyUtility()
+ name = 'dummy_utility'
+ util.__name__ = name
+ util.__parent__ = aq_base(obj)
+ obj._setObject(name, aq_base(util),
+ set_owner=False, suppress_events=True)
+ obj.registerUtility(aq_base(obj[name]), IDummyInterface)
+ util = DummyUtility()
+ name = 'Products.GenericSetup.tests.test_components.IDummyInterface2-foo'
+ util.__name__ = name
+ util.__parent__ = aq_base(obj)
+ obj._setObject(name, aq_base(util),
+ set_owner=False, suppress_events=True)
+ obj.registerUtility(aq_base(obj[name]), IDummyInterface2, name=u'foo')
+
tool = aq_base(obj.aq_parent['dummy_tool'])
obj.registerUtility(tool, IDummyInterface, name=u'dummy tool name')
@@ -181,10 +196,18 @@
util = queryUtility(IDummyInterface2, name=u'foo')
self.failUnless(IDummyInterface.providedBy(util))
self.failUnless(util.verify())
+ self.failUnless(util.__parent__ == obj)
+ name = 'Products.GenericSetup.tests.test_components.IDummyInterface2-foo'
+ self.assertEquals(util.__name__, name)
+ self.failUnless(name in obj.objectIds())
util = queryUtility(IDummyInterface)
self.failUnless(IDummyInterface.providedBy(util))
self.failUnless(util.verify())
+ self.failUnless(util.__parent__ == obj)
+ name = 'dummy_utility'
+ self.assertEquals(util.__name__, name)
+ self.failUnless(name in obj.objectIds())
util = queryUtility(IDummyInterface, name='dummy tool name')
self.failUnless(IDummyInterface.providedBy(util))
@@ -274,10 +297,13 @@
importComponentRegistry(context)
util = queryUtility(IDummyInterface2, name=u'foo')
+ name = 'Products.GenericSetup.tests.test_components.IDummyInterface2-foo'
self.failUnless(util is None)
+ self.failIf(name in obj.objectIds())
util = queryUtility(IDummyInterface)
self.failUnless(util is None)
+ self.failIf('dummy_utility' in obj.objectIds())
util = queryUtility(IDummyInterface, name='dummy tool name')
self.failUnless(util is None)
More information about the Checkins
mailing list