[Checkins] SVN: z3c.unconfigure/trunk/s Allow the unregistration of
even thandlers
Philipp von Weitershausen
philikon at philikon.de
Wed Aug 6 11:30:32 EDT 2008
Log message for revision 89442:
Allow the unregistration of even thandlers
Changed:
U z3c.unconfigure/trunk/setup.py
U z3c.unconfigure/trunk/src/z3c/unconfigure/config.py
A z3c.unconfigure/trunk/src/z3c/unconfigure/testfixtures/handlers.py
U z3c.unconfigure/trunk/src/z3c/unconfigure/tests.txt
-=-
Modified: z3c.unconfigure/trunk/setup.py
===================================================================
--- z3c.unconfigure/trunk/setup.py 2008-08-06 13:39:44 UTC (rev 89441)
+++ z3c.unconfigure/trunk/setup.py 2008-08-06 15:30:29 UTC (rev 89442)
@@ -35,6 +35,9 @@
zip_safe=False,
install_requires=['setuptools',
'zope.configuration',
+ 'zope.component', # technically [zcml]
+ 'zope.security',
+ 'zope.event',
'zope.testing',
],
)
Modified: z3c.unconfigure/trunk/src/z3c/unconfigure/config.py
===================================================================
--- z3c.unconfigure/trunk/src/z3c/unconfigure/config.py 2008-08-06 13:39:44 UTC (rev 89441)
+++ z3c.unconfigure/trunk/src/z3c/unconfigure/config.py 2008-08-06 15:30:29 UTC (rev 89442)
@@ -14,7 +14,33 @@
"""The 'unconfigure' grouping directive
"""
from zope.configuration.zopeconfigure import ZopeConfigure
+from zope.security import adapter
+import zope.component.zcml
+def is_subscriber(discriminator, callable=None, args=(), kw={},
+ includepath=(), info='', order=0):
+ """Determines whether an action has been emitted from the
+ <subscriber /> directive.
+ """
+ return (discriminator is None and
+ callable is zope.component.zcml.handler and
+ args[0] == 'registerHandler')
+
+def real_subscriber_factory(discriminator, callable=None, args=(), kw={},
+ includepath=(), info='', order=0):
+ """Returns the real subscriber factory (<subscriber /> sometimes
+ wraps them in some security-related adapter factory).
+
+ This function assumes that the action in question is a subscriber
+ action. In other words, is_subscriber(*args) is True.
+ """
+ factory = args[1]
+ if isinstance(factory, (adapter.LocatingTrustedAdapterFactory,
+ adapter.LocatingUntrustedAdapterFactory,
+ adapter.TrustedAdapterFactory)):
+ factory = factory.factory
+ return factory
+
class Unconfigure(ZopeConfigure):
def __init__(self, context, **kw):
@@ -29,15 +55,33 @@
def after(self):
# Get a discriminator -> action representation of all the
# actions that have been churned out so far.
- unique = dict((action[0], action) for action in self.context.actions)
+ unique = dict((action[0], action) for action in self.context.actions
+ if action[0] is not None)
+ # Find all subscriber actions and store them as factory -> action.
+ # They're a special case because their discriminators are None,
+ # so we can't pull the same trick as with other directives.
+ subscribers = dict((real_subscriber_factory(*action), action)
+ for action in self.context.actions
+ if is_subscriber(*action))
+ # XXX should make mapping (factory, required) -> action
+
# Now let's go through the actions within 'unconfigure'
# (hereafter called "unactions" :)) and use their
# discriminator to remove the real actions
for unaction in self.actions:
+ # Special case subscriber actions.
+ if is_subscriber(*unaction):
+ factory = real_subscriber_factory(*unaction)
+ action = subscribers.get(factory)
+ if action is None:
+ continue
+ self.remove_action(action)
+ del subscribers[factory]
+
+ # Generic from here
discriminator = unaction[0]
if discriminator is None:
- # XXX apply special majyck for subscribers here
continue
action = unique.get(discriminator)
if action is None:
@@ -45,13 +89,16 @@
# configured in the first place. Ignore.
continue
- # An action with the same discriminator has been found.
- # We can't remove it because we mustn't change the length
- # of the actions list (because includeOverrides relies on
- # this not to change and we could easily be included via
- # includeOverrides).
- i = self.context.actions.index(action)
- self.context.actions[i] = (None, None)
+ self.remove_action(action)
+ del unique[discriminator]
- # Action has been replaced, no longer need to remember.
- del unique[discriminator]
+ def remove_action(self, action):
+ # We can't actually remove actions because we mustn't change
+ # the length of the actions list. The main reason is that
+ # includeOverrides relies on the length of the action list
+ # (and we could easily be included via includeOverrides and
+ # therefore run into this problem). So let's simply replace
+ # actions with a null value. Actions whose callable is None
+ # won't be executed.
+ i = self.context.actions.index(action)
+ self.context.actions[i] = (None, None)
Added: z3c.unconfigure/trunk/src/z3c/unconfigure/testfixtures/handlers.py
===================================================================
--- z3c.unconfigure/trunk/src/z3c/unconfigure/testfixtures/handlers.py (rev 0)
+++ z3c.unconfigure/trunk/src/z3c/unconfigure/testfixtures/handlers.py 2008-08-06 15:30:29 UTC (rev 89442)
@@ -0,0 +1,21 @@
+from zope.component import adapter
+
+class Event(object):
+ pass
+
+ at adapter(Event)
+def regular(event):
+ print "Regular subscriber"
+
+ at adapter(Event)
+def trusted(event):
+ print "Trusted subscriber"
+
+ at adapter(Event)
+def located(event):
+ print "Located subscriber"
+
+ at adapter(Event)
+def locatedtrusted(event):
+ print "Located trusted subscriber"
+
Property changes on: z3c.unconfigure/trunk/src/z3c/unconfigure/testfixtures/handlers.py
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: z3c.unconfigure/trunk/src/z3c/unconfigure/tests.txt
===================================================================
--- z3c.unconfigure/trunk/src/z3c/unconfigure/tests.txt 2008-08-06 13:39:44 UTC (rev 89441)
+++ z3c.unconfigure/trunk/src/z3c/unconfigure/tests.txt 2008-08-06 15:30:29 UTC (rev 89442)
@@ -44,3 +44,45 @@
Goodbye World!
This is the last directive
I can has hamburger?
+
+
+Unconfiguring event handlers
+----------------------------
+
+This package also supports unconfiguring event handlers.
+
+ >>> import zope.component.eventtesting
+ >>> zope.component.eventtesting.setUp()
+
+Consider a bunch of event handlers configured in various ways:
+
+ >>> zcml("""
+ ... <configure xmlns="http://namespaces.zope.org/zope">
+ ... <include package="zope.component" file="meta.zcml" />
+ ...
+ ... <subscriber handler=".handlers.regular" />
+ ... <subscriber handler=".handlers.trusted" trusted="yes" />
+ ... <subscriber handler=".handlers.located" locate="yes" />
+ ... <subscriber handler=".handlers.locatedtrusted"
+ ... trusted="yes" locate="yes" />
+ ...
+ ... <unconfigure>
+ ... <subscriber handler=".handlers.regular" />
+ ... <subscriber handler=".handlers.trusted" trusted="yes" />
+ ... <subscriber handler=".handlers.located" locate="yes" />
+ ... <subscriber handler=".handlers.locatedtrusted"
+ ... trusted="yes" locate="yes" />
+ ... </unconfigure>
+ ... </configure>
+ ... """)
+
+Since we've unconfigured the handlers, we expect that nothing will
+happen when we send the event:
+
+ >>> from zope.event import notify
+ >>> from z3c.unconfigure.testfixtures.handlers import Event
+ >>> notify(Event())
+
+ >>> import zope.testing.cleanup
+ >>> zope.testing.cleanup.cleanUp()
+
More information about the Checkins
mailing list