Package Products :: Package ZenHub :: Module zodb
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenHub.zodb

  1  ############################################################################## 
  2  #  
  3  # Copyright (C) Zenoss, Inc. 2007, all rights reserved. 
  4  #  
  5  # This content is made available according to terms specified in 
  6  # License.zenoss under the directory where your Zenoss product is installed. 
  7  #  
  8  ############################################################################## 
  9   
 10   
 11  import logging 
 12  log = logging.getLogger('zen.ZenHub') 
 13   
 14  from zope.interface import implements 
 15  from zope.interface.advice import addClassAdvisor 
 16  from zope.component import provideHandler 
 17  from zope.component.interfaces import ObjectEvent 
 18  from Products.ZenHub.interfaces import IUpdateEvent, IDeletionEvent 
 19   
 20   
21 -class InvalidationEvent(ObjectEvent):
22 - def __init__(self, object, oid):
23 super(InvalidationEvent, self).__init__(object) 24 self.oid = oid
25 26
27 -class UpdateEvent(InvalidationEvent):
28 implements(IUpdateEvent)
29 30
31 -class DeletionEvent(InvalidationEvent):
32 implements(IDeletionEvent)
33 34
35 -def _listener_decorator_factory(eventtype):
36 """ 37 Given a particular event interface, returns a decorator factory that may be 38 used to create decorators for methods causing those methods, when bound, to 39 be registered as object event subscribers. 40 41 @param eventtype: The event interface to which the subscribers should 42 listen. 43 """ 44 def factory(*types): 45 """ 46 The eventtype-specific decorator factory. Calling this factory both 47 produces a decorator and wraps the __init__ of the class of the 48 decorated method with a function that registers the handlers. 49 """ 50 # Create a mutable to store the handler name between the call to 51 # decorator and the call to advisor (simple assignment won't work for 52 # scope reasons) 53 _f = {} 54 55 def decorator(f): 56 """ 57 The decorator. All it does is print a log message, then call the 58 original function. 59 """ 60 def inner(self, obj, event): 61 # Log that we've called this listener 62 fname = '.'.join((self.__class__.__name__, f.__name__)) 63 log.debug('%s is interested in %r for %r' % (fname, event, obj)) 64 65 # Call the original function 66 return f(self, obj, event)
67 68 # Push the name of the function outside the decorator scope so the 69 # class advisor has access when it needs to register handlers. 70 _f[f.__name__] = 1 71 72 # Return the closure to replace the original function. 73 return inner 74 75 def advisor(cls): 76 """ 77 A class advisor that is called after the class is created. We use 78 this to wrap __init__ in a function that registers any handlers 79 created via this factory, which are stored on the class. 80 """ 81 # Set one flag per fname on the class so we don't double-register 82 # when we override in a subclass (once for super, once for sub) 83 fname = _f.keys()[0] 84 cls.__registered = getattr(cls, '__registered', {}) 85 86 # Check our flag 87 if fname not in cls.__registered or not issubclass(cls, tuple(cls.__registered[fname])): 88 # Decorator for __init__ 89 def registerHandlers(f): 90 def __init__(self, *args, **kwargs): 91 # Call the original constructor; we'll register handlers 92 # afterwards 93 f(self, *args, **kwargs) 94 handler = getattr(self, fname) 95 for t in types: 96 # Register the handler. Here's where we use 97 # eventtype, which was passed in to the outermost 98 # function in this behemoth. 99 provideHandler(handler, (t, eventtype)) 100 101 # Return the closure to replace the decorated method 102 return __init__ 103 104 # Decorate __init__ so it will register the handlers on 105 # instantiation 106 cls.__init__ = registerHandlers(cls.__init__) 107 # Set the flag for this fname 108 cls.__registered.setdefault(fname, []).append(cls) 109 110 111 # Return the class, which will replace the original class. 112 return cls 113 114 # Add the advisor to the class. 115 addClassAdvisor(advisor) 116 117 # Return the decorator so we get the log message when called 118 return decorator 119 120 return factory 121 122 123 # Create two decorator factories for the two kinds of events. 124 onUpdate = _listener_decorator_factory(IUpdateEvent) 125 onDelete = _listener_decorator_factory(IDeletionEvent) 126