[Zope3-dev] Missing ObjectContentModifiedEvent

Jim Fulton jim at zope.com
Thu May 26 12:05:11 EDT 2005


This proposal is way too unpythonic IMO.

Application code shouldn't have to go through this much
machinery just to make changes.

I don't mind if some application does something like this,
but I wouldn't want to make this a standard mode of operation
for Zope 3.

If a goal is to avoid reindexing values that haven't changed,
then I would say that indexes should remember old values and
only reindex if the value hasn't changed.  This would be an
optimization and thus optional.

Jim

Uwe Oestermeier wrote:
> Dieter Maurer wrote:
> As soon as you index the content, you will be interested
> to distinguish between a modification in the primary
> content and some meta data (as it has big repercussions
> on the speed of the reindexing).
> 
> I agree, but perhaps we can find a compromise that fits
> all needs. I propose to use pluggable modification utilities.
> 
> The container related events are already fired by only two
> functions (setitem and uncontained). If we introduce a third
> one for object modification (e.g. update or modify and an
> additional annotate if needed), we can replace these
> functions with callable utilities, which are responsible for
> performing the changes and  firing the events.
> It's then up these components which events are
> actually used.
> 
> Direct calls of ObjectModifiedEvents can then be marked as
> deprecated to ensure that all applications will use
> these pluggable modifiers.
> 
> Regards,
> Uwe
> 
> The following code should make clear what I mean:
> 
> #! python
> 
> import doctest, unittest, zope
> from zope.app import zapi
> from zope.interface import Interface, implements
> from zope.app.event.objectevent import ObjectModifiedEvent
> from zope.app.event.interfaces import IObjectModifiedEvent
> 
> class IPluggableModifier(Interface) :
>     """
>     A pluggable modifier can be used to replace the
>     existing modification mechanism in  Zope.
>     It should be used in all places where other systems
>     are notified about changes.
>         
>     The implementation must ensure that
>     at least one IObjectModifiedEvent is fired
>     if an object's state has been changed.
>     """
>        
>     def __call__(self, obj, interface, **kw) :
>         """
>         Performs the update and fires an IObjectModifiedEvent.
>         
>         It's up to the plugin which specialization of
>         IObjectModifiedEvent is actually used.
>         
>         Returns the modified object or None if the object
>         could not be modified.
>         """
>         
> class DefaultModifier(object) :
>     """
>     Implements a default behavior that mimics Zope3's current
>     modification event handling.
>         
>     Setup :
>         
>         >>> from zope.component import provideUtility
>         >>> provideUtility(DefaultModifier(), IPluggableModifier)
>         >>> events = []
>         >>> zope.event.subscribers.append(events.append)
>         >>> class Sample(object) : pass
>         
>     Usage :
>     
>         >>> modify = zapi.getUtility(IPluggableModifier)
>         >>> sample = Sample()
>         >>> result = modify(sample, None, title='Test', 
> description='Example')
>         >>> result == sample
>         True
>         >>> IObjectModifiedEvent.providedBy(events[0])
>         True
>         >>> sample.title
>         'Test'
>         >>> sample.description
>         'Example'
>         
>         
>     """
>     implements(IPluggableModifier)
>     
>     def __call__(self, obj, interface, **kw) :
>         """ Modifies an object and fires an IObjectModifiedEvent. """
>         
>         if interface is not None :
>             obj = interface(obj)
>         for key, value in kw.items() :
>             setattr(obj, key, value)
>         zope.event.notify(ObjectModifiedEvent(obj))
>         return obj
> 
> 
> class ValueChangedEvent(object) :
>     """
>     A modification event that keeps additional information about
>     the used interface, the old and new values.
>     """
>     
>     def __init__(self, object, interface, key, old_value, new_value) :
>         self.object = object
>         self.interface = interface
>         self.key = key
>         self.old_value = old_value
>         self.new_value = new_value
>     
> class BetterModifier(object) :
>     """
>     Implements a modification behavior that fires more
>     informative events for more efficient versioning
>     and reindexing.
> 
>     Setup :
>         
>         >>> from zope.component import provideUtility
>         >>> provideUtility(BetterModifier(), IPluggableModifier)
>         >>> events = []
>         >>> zope.event.subscribers.append(events.append)
>         >>> class Sample(object) : pass
>         
>     Usage :
>     
>         >>> modify = zapi.getUtility(IPluggableModifier)
>         >>> sample = Sample()
>         >>> result = modify(sample, None, title='Test', 
> description='Example')
>         >>> result == sample
>         True
>         >>> sample.title
>         'Test'
>         >>> sample.description
>         'Example'
>         >>> for x in events : print x.__class__.__name__
>         ValueChangedEvent
>         ValueChangedEvent
>         ObjectModifiedEvent
> 
>     """
>     implements(IPluggableModifier)
>         
>     undefined = object()
>     
>     def __call__(self, obj, interface, **kw) :
>         """ Modifies an object and fires an IObjectModifiedEvent. """
>         
>         if interface is not None :
>             obj = interface(obj)
>         for key, value in kw.items() :
>             old = getattr(obj, key, self.undefined)
>             if old != value :
>                 setattr(obj, key, value)
>                 event = ValueChangedEvent(obj, interface, key, old, value)
>                 zope.event.notify(event)
>         zope.event.notify(ObjectModifiedEvent(obj))
>         return obj
>     
> 
> from doctest import DocTestSuite
> 
> def test_suite():
>     return unittest.TestSuite((
>         DocTestSuite(),
>         ))
> 
> if __name__ == '__main__':
>     unittest.main(defaultTest='test_suite')
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Zope3-dev mailing list
> Zope3-dev at zope.org
> Unsub: http://mail.zope.org/mailman/options/zope3-dev/jim%40zope.com
> 


-- 
Jim Fulton           mailto:jim at zope.com       Python Powered!
CTO                  (540) 361-1714            http://www.python.org
Zope Corporation     http://www.zope.com       http://www.zope.org


More information about the Zope3-dev mailing list