server/hook.py
branchstable
changeset 5093 8d073d2e089d
parent 5072 072ae171aeb0
child 5116 a2ce436e00ad
equal deleted inserted replaced
5092:e126becc1263 5093:8d073d2e089d
    46 
    46 
    47 from logilab.common.decorators import classproperty
    47 from logilab.common.decorators import classproperty
    48 from logilab.common.deprecation import deprecated
    48 from logilab.common.deprecation import deprecated
    49 from logilab.common.logging_ext import set_log_methods
    49 from logilab.common.logging_ext import set_log_methods
    50 
    50 
       
    51 from cubicweb import RegistryNotFound
    51 from cubicweb.cwvreg import CWRegistry, VRegistry
    52 from cubicweb.cwvreg import CWRegistry, VRegistry
    52 from cubicweb.selectors import (objectify_selector, lltrace, ExpectedValueSelector,
    53 from cubicweb.selectors import (objectify_selector, lltrace, ExpectedValueSelector,
    53                                 implements)
    54                                 implements)
    54 from cubicweb.appobject import AppObject
    55 from cubicweb.appobject import AppObject
    55 from cubicweb.server.session import security_enabled
    56 from cubicweb.server.session import security_enabled
    64                     'session_open', 'session_close'))
    65                     'session_open', 'session_close'))
    65 ALL_HOOKS = ENTITIES_HOOKS | RELATIONS_HOOKS | SYSTEM_HOOKS
    66 ALL_HOOKS = ENTITIES_HOOKS | RELATIONS_HOOKS | SYSTEM_HOOKS
    66 
    67 
    67 
    68 
    68 class HooksRegistry(CWRegistry):
    69 class HooksRegistry(CWRegistry):
       
    70     def initialization_completed(self):
       
    71         for appobjects in self.values():
       
    72             for cls in appobjects:
       
    73                 if not cls.enabled:
       
    74                     warn('[3.6] %s: enabled is deprecated' % cls)
       
    75                     self.unregister(cls)
    69 
    76 
    70     def register(self, obj, **kwargs):
    77     def register(self, obj, **kwargs):
    71         try:
    78         try:
    72             iter(obj.events)
    79             iter(obj.events)
    73         except AttributeError:
    80         except AttributeError:
    94                                key=lambda x: x.order)
   101                                key=lambda x: x.order)
    95                 with security_enabled(session, write=False):
   102                 with security_enabled(session, write=False):
    96                     for hook in hooks:
   103                     for hook in hooks:
    97                         hook()
   104                         hook()
    98 
   105 
    99 VRegistry.REGISTRY_FACTORY['hooks'] = HooksRegistry
   106 class HooksManager(object):
       
   107     def __init__(self, vreg):
       
   108         self.vreg = vreg
       
   109 
       
   110     def call_hooks(self, event, session=None, **kwargs):
       
   111         try:
       
   112             self.vreg['%s_hooks' % event].call_hooks(event, session, **kwargs)
       
   113         except RegistryNotFound:
       
   114             pass # no hooks for this event
       
   115 
       
   116 
       
   117 for event in ALL_HOOKS:
       
   118     VRegistry.REGISTRY_FACTORY['%s_hooks' % event] = HooksRegistry
   100 
   119 
   101 _MARKER = object()
   120 _MARKER = object()
   102 def entity_oldnewvalue(entity, attr):
   121 def entity_oldnewvalue(entity, attr):
   103     """returns the couple (old attr value, new attr value)
   122     """returns the couple (old attr value, new attr value)
   104     NOTE: will only work in a before_update_entity hook
   123     NOTE: will only work in a before_update_entity hook
   111         entity[attr] = newvalue
   130         entity[attr] = newvalue
   112     return oldvalue, newvalue
   131     return oldvalue, newvalue
   113 
   132 
   114 
   133 
   115 # some hook specific selectors #################################################
   134 # some hook specific selectors #################################################
   116 
       
   117 @objectify_selector
       
   118 @lltrace
       
   119 def _bw_is_enabled(cls, req, **kwargs):
       
   120     if cls.enabled:
       
   121         return 1
       
   122     warn('[3.6] %s: enabled is deprecated' % cls)
       
   123     return 0
       
   124 
       
   125 @objectify_selector
       
   126 @lltrace
       
   127 def match_event(cls, req, **kwargs):
       
   128     if kwargs.get('event') in cls.events:
       
   129         return 1
       
   130     return 0
       
   131 
   135 
   132 @objectify_selector
   136 @objectify_selector
   133 @lltrace
   137 @lltrace
   134 def enabled_category(cls, req, **kwargs):
   138 def enabled_category(cls, req, **kwargs):
   135     if req is None:
   139     if req is None:
   188         for rel_set in self.expected:
   192         for rel_set in self.expected:
   189             if kwargs.get('rtype') in rel_set:
   193             if kwargs.get('rtype') in rel_set:
   190                 return 1
   194                 return 1
   191         return 0
   195         return 0
   192 
   196 
       
   197 
   193 # base class for hook ##########################################################
   198 # base class for hook ##########################################################
   194 
   199 
   195 class Hook(AppObject):
   200 class Hook(AppObject):
   196     __registry__ = 'hooks'
   201     __select__ = enabled_category()
   197     __select__ = match_event() & enabled_category() & _bw_is_enabled()
       
   198     # set this in derivated classes
   202     # set this in derivated classes
   199     events = None
   203     events = None
   200     category = None
   204     category = None
   201     order = 0
   205     order = 0
   202     # XXX deprecated
   206     # XXX deprecated
   203     enabled = True
   207     enabled = True
       
   208 
       
   209     @classproperty
       
   210     def __registries__(self):
       
   211         return ['%s_hooks' % ev for ev in self.events]
   204 
   212 
   205     @classproperty
   213     @classproperty
   206     def __regid__(cls):
   214     def __regid__(cls):
   207         warn('[3.6] %s.%s: please specify an id for your hook'
   215         warn('[3.6] %s.%s: please specify an id for your hook'
   208              % (cls.__module__, cls.__name__), DeprecationWarning)
   216              % (cls.__module__, cls.__name__), DeprecationWarning)