[Checkins] SVN: Products.GenericSetup/trunk/Products/GenericSetup/ Added support for import / export of subscribers from component registry.
Laurence Rowe
l at lrowe.co.uk
Fri Sep 18 15:43:24 EDT 2009
Log message for revision 104358:
Added support for import / export of subscribers from component registry.
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-09-18 19:22:18 UTC (rev 104357)
+++ Products.GenericSetup/trunk/Products/GenericSetup/CHANGES.txt 2009-09-18 19:43:23 UTC (rev 104358)
@@ -4,6 +4,8 @@
GenericSetup 1.5.0 (unreleased)
-------------------------------
+- Added support for import / export of subscribers from component registry.
+
- Adapter removal.
- Fix utility removal so utility is not added when it is missing from the
Modified: Products.GenericSetup/trunk/Products/GenericSetup/components.py
===================================================================
--- Products.GenericSetup/trunk/Products/GenericSetup/components.py 2009-09-18 19:22:18 UTC (rev 104357)
+++ Products.GenericSetup/trunk/Products/GenericSetup/components.py 2009-09-18 19:43:23 UTC (rev 104358)
@@ -64,6 +64,12 @@
self._logger.info('Adapters exported.')
fragment.appendChild(child)
+ child = self._doc.createElement('subscribers')
+ child.appendChild(self._extractSubscriptionAdapters())
+ child.appendChild(self._extractHandlers())
+ self._logger.info('Subscribers exported.')
+ fragment.appendChild(child)
+
child = self._doc.createElement('utilities')
child.appendChild(self._extractUtilities())
self._logger.info('Utilities exported.')
@@ -77,6 +83,9 @@
if self.environ.shouldPurge():
self._purgeAdapters()
self._logger.info('Adapters purged.')
+ self._purgeSubscriptionAdapters()
+ self._purgeHandlers()
+ self._logger.info('Subscribers purged.')
self._purgeUtilities()
self._logger.info('Utilities purged.')
@@ -84,6 +93,10 @@
if child.nodeName == 'adapters':
self._initAdapters(child)
self._logger.info('Adapters registered.')
+ if child.nodeName == 'subscribers':
+ self._initSubscriptionAdapters(child)
+ self._initHandlers(child)
+ self._logger.info('Subscribers registered.')
if child.nodeName == 'utilities':
self._initUtilities(child)
self._logger.info('Utilities registered.')
@@ -105,6 +118,30 @@
provided=provided,
name=name)
+ def _purgeSubscriptionAdapters(self):
+ registrations = tuple(self.context.registeredSubscriptionAdapters())
+ blacklist = self._constructBlacklist()
+
+ for registration in registrations:
+ factory = registration.factory
+ required = registration.required
+ provided = registration.provided
+ if _getDottedName(provided) in blacklist:
+ continue
+
+ self.context.unregisterSubscriptionAdapter(factory=factory,
+ required=required,
+ provided=provided)
+
+ def _purgeHandlers(self):
+ registrations = tuple(self.context.registeredHandlers())
+
+ for registration in registrations:
+ factory = registration.factory
+ required = registration.required
+
+ self.context.unregisterHandler(factory=factory, required=required)
+
def _purgeUtilities(self):
registrations = tuple(self.context.registeredUtilities())
blacklist = self._constructBlacklist()
@@ -147,6 +184,83 @@
provided=provided,
name=name)
+ def _initSubscriptionAdapters(self, node):
+ blacklist = self._constructBlacklist()
+
+ for child in node.childNodes:
+ if child.nodeName != 'subscriber':
+ continue
+
+ factory = child.getAttribute('factory')
+ if not factory:
+ continue
+
+ handler = child.getAttribute('handler')
+ if handler:
+ raise ValueError, "Can not specify both a factory and a " \
+ "handler in a subscriber registration."
+
+ factory = _resolveDottedName(factory)
+
+ provided = child.getAttribute('provides')
+ if provided in blacklist:
+ continue
+
+ provided = _resolveDottedName(provided)
+
+ for_ = child.getAttribute('for') or child.getAttribute('for_') #BBB
+ required = []
+ for interface in for_.split():
+ required.append(_resolveDottedName(interface))
+
+ # Uninstall to prevent duplicate registrations. While this is
+ # allowed in ZCML, GS profiles can be run multiple times.
+ self.context.unregisterSubscriptionAdapter(factory,
+ required=required,
+ provided=provided)
+
+ if child.hasAttribute('remove'):
+ continue
+
+ self.context.registerSubscriptionAdapter(factory,
+ required=required,
+ provided=provided)
+
+ def _initHandlers(self, node):
+ for child in node.childNodes:
+ if child.nodeName != 'subscriber':
+ continue
+
+ handler = child.getAttribute('handler')
+ if not handler:
+ continue
+
+ factory = child.getAttribute('factory')
+ if factory:
+ raise ValueError, "Can not specify both a factory and a " \
+ "handler in a subscriber registration."
+
+ if child.hasAttribute('provides'):
+ raise ValueError, "Cannot use handler with provides " \
+ "in a subscriber registration."
+
+ handler = _resolveDottedName(handler)
+
+ for_ = child.getAttribute('for') or child.getAttribute('for_') #BBB
+ required = []
+
+ for interface in for_.split():
+ required.append(_resolveDottedName(interface))
+
+ # Uninstall to prevent duplicate registrations. While this is
+ # allowed in ZCML, GS profiles can be run multiple times.
+ self.context.unregisterHandler(handler, required=required)
+
+ if child.hasAttribute('remove'):
+ continue
+
+ self.context.registerHandler(handler, required=required)
+
def _getSite(self):
# Get the site by either __parent__ or Acquisition
site = getattr(self.context, '__parent__', None)
@@ -281,6 +395,58 @@
return fragment
+ def _extractSubscriptionAdapters(self):
+ fragment = self._doc.createDocumentFragment()
+
+ registrations = [ {'factory': _getDottedName(reg.factory),
+ 'provided': _getDottedName(reg.provided),
+ 'required': reg.required}
+ for reg in self.context.registeredSubscriptionAdapters() ]
+ registrations.sort(key=itemgetter('factory'))
+ registrations.sort(key=itemgetter('provided'))
+ blacklist = self._constructBlacklist()
+
+ for reg_info in registrations:
+ if reg_info['provided'] in blacklist:
+ continue
+
+ child = self._doc.createElement('subscriber')
+
+ for_ = u''
+ for interface in reg_info['required']:
+ for_ = for_ + _getDottedName(interface) + u'\n '
+
+ child.setAttribute('factory', reg_info['factory'])
+ child.setAttribute('provides', reg_info['provided'])
+ child.setAttribute('for', for_.strip())
+
+ fragment.appendChild(child)
+
+ return fragment
+
+ def _extractHandlers(self):
+ fragment = self._doc.createDocumentFragment()
+
+ registrations = [ {'factory': _getDottedName(reg.factory),
+ 'required': reg.required}
+ for reg in self.context.registeredHandlers() ]
+ registrations.sort(key=itemgetter('factory'))
+ registrations.sort(key=itemgetter('required'))
+
+ for reg_info in registrations:
+ child = self._doc.createElement('subscriber')
+
+ for_ = u''
+ for interface in reg_info['required']:
+ for_ = for_ + _getDottedName(interface) + u'\n '
+
+ child.setAttribute('handler', reg_info['factory'])
+ child.setAttribute('for', for_.strip())
+
+ fragment.appendChild(child)
+
+ return fragment
+
def _extractUtilities(self):
fragment = self._doc.createDocumentFragment()
Modified: Products.GenericSetup/trunk/Products/GenericSetup/tests/test_components.py
===================================================================
--- Products.GenericSetup/trunk/Products/GenericSetup/tests/test_components.py 2009-09-18 19:22:18 UTC (rev 104357)
+++ Products.GenericSetup/trunk/Products/GenericSetup/tests/test_components.py 2009-09-18 19:43:23 UTC (rev 104358)
@@ -41,8 +41,10 @@
from zope.component import getMultiAdapter
from zope.component import getGlobalSiteManager
from zope.component import getSiteManager
+from zope.component import handle
from zope.component import queryAdapter
from zope.component import queryUtility
+from zope.component import subscribers
from zope.component.globalregistry import base
from zope.interface import implements
from zope.interface import Interface
@@ -88,10 +90,32 @@
def verify(self):
return True
+class IAnotherDummyInterface(Interface):
+ """A third dummy interface."""
+
+ def inc():
+ """Increments handle count"""
+
+class IAnotherDummyInterface2(Interface):
+ """A second dummy interface."""
+
+ def verify():
+ """Returns True."""
+
+class DummyObject(object):
+ """A dummy object to pass to the handler."""
+
+ implements(IAnotherDummyInterface)
+
+ handled = 0
+
+ def inc(self):
+ self.handled += 1
+
class DummyAdapter(object):
"""A dummy adapter."""
- implements(IDummyInterface)
+ implements(IAnotherDummyInterface2)
def __init__(self, context):
pass
@@ -99,6 +123,11 @@
def verify(self):
return True
+def dummy_handler(context):
+ """A dummy event handler."""
+
+ context.inc()
+
class DummyTool(SimpleItem):
"""A dummy tool."""
implements(IDummyInterface)
@@ -144,12 +173,21 @@
<adapters>
<adapter factory="Products.GenericSetup.tests.test_components.DummyAdapter"
for="zope.interface.Interface"
- provides="Products.GenericSetup.tests.test_components.IDummyInterface"/>
+ provides="Products.GenericSetup.tests.test_components.IAnotherDummyInterface2"/>
<adapter name="foo"
factory="Products.GenericSetup.tests.test_components.DummyAdapter"
for="zope.interface.Interface"
- provides="Products.GenericSetup.tests.test_components.IDummyInterface"/>
+ provides="Products.GenericSetup.tests.test_components.IAnotherDummyInterface2"/>
</adapters>
+ <subscribers>
+ <subscriber
+ factory="Products.GenericSetup.tests.test_components.DummyAdapter"
+ for="Products.GenericSetup.tests.test_components.IAnotherDummyInterface"
+ provides="Products.GenericSetup.tests.test_components.IAnotherDummyInterface2"/>
+ <subscriber
+ for="Products.GenericSetup.tests.test_components.IAnotherDummyInterface"
+ handler="Products.GenericSetup.tests.test_components.dummy_handler"/>
+ </subscribers>
<utilities>
<utility factory="Products.GenericSetup.tests.test_components.DummyUtility"
id="dummy_utility"
@@ -172,9 +210,20 @@
<componentregistry>
<adapters>
<adapter factory="Products.GenericSetup.tests.test_components.DummyAdapter"
- provides="Products.GenericSetup.tests.test_components.IDummyInterface"
+ provides="Products.GenericSetup.tests.test_components.IAnotherDummyInterface2"
for="*" remove="True"/>
</adapters>
+ <subscribers>
+ <subscriber
+ factory="Products.GenericSetup.tests.test_components.DummyAdapter"
+ for="Products.GenericSetup.tests.test_components.IAnotherDummyInterface"
+ provides="Products.GenericSetup.tests.test_components.IAnotherDummyInterface2"
+ remove="True"/>
+ <subscriber
+ for="Products.GenericSetup.tests.test_components.IAnotherDummyInterface"
+ handler="Products.GenericSetup.tests.test_components.dummy_handler"
+ remove="True"/>
+ </subscribers>
<utilities>
<utility id="dummy_utility"
factory="Products.GenericSetup.tests.test_components.DummyUtility"
@@ -204,7 +253,10 @@
def _populate(self, obj):
obj.registerAdapter(DummyAdapter, required=(None,))
obj.registerAdapter(DummyAdapter, required=(None,), name=u'foo')
-
+
+ obj.registerSubscriptionAdapter(DummyAdapter, required=(IAnotherDummyInterface,))
+ obj.registerHandler(dummy_handler, required=(IAnotherDummyInterface,))
+
util = DummyUtility()
name = 'dummy_utility'
util.__name__ = name
@@ -228,14 +280,22 @@
obj.registerUtility(tool2, IDummyInterface2, name=u'dummy tool name2')
def _verifyImport(self, obj):
- adapted = queryAdapter(object(), IDummyInterface)
- self.failUnless(IDummyInterface.providedBy(adapted))
+ adapted = queryAdapter(object(), IAnotherDummyInterface2)
+ self.failUnless(IAnotherDummyInterface2.providedBy(adapted))
self.failUnless(adapted.verify())
- adapted = queryAdapter(object(), IDummyInterface, name=u'foo')
- self.failUnless(IDummyInterface.providedBy(adapted))
+ adapted = queryAdapter(object(), IAnotherDummyInterface2, name=u'foo')
+ self.failUnless(IAnotherDummyInterface2.providedBy(adapted))
self.failUnless(adapted.verify())
+ dummy = DummyObject()
+ results = [adap.verify() for adap in subscribers([dummy], IAnotherDummyInterface2)]
+ self.assertEquals(results, [True])
+
+ dummy = DummyObject()
+ handle(dummy)
+ self.assertEquals(dummy.handled, 1)
+
util = queryUtility(IDummyInterface2, name=u'foo')
self.failUnless(IDummyInterface.providedBy(util))
self.failUnless(util.verify())
@@ -339,13 +399,21 @@
context._files['componentregistry.xml'] = _REMOVE_IMPORT
importComponentRegistry(context)
- adapted = queryAdapter(object(), IDummyInterface)
+ adapted = queryAdapter(object(), IAnotherDummyInterface2)
self.failUnless(adapted is None)
# This one should still exist
- adapted = queryAdapter(object(), IDummyInterface, name=u'foo')
+ adapted = queryAdapter(object(), IAnotherDummyInterface2, name=u'foo')
self.failIf(adapted is None)
+ dummy = DummyObject()
+ results = [adap.verify() for adap in subscribers([dummy], IAnotherDummyInterface2)]
+ self.assertEquals(results, [])
+
+ dummy = DummyObject()
+ handle(dummy)
+ self.assertEquals(dummy.handled, 0)
+
util = queryUtility(IDummyInterface2, name=u'foo')
name = 'Products.GenericSetup.tests.test_components.IDummyInterface2-foo'
self.failUnless(util is None)
More information about the checkins
mailing list