server/hooksmanager.py
branchtls-sprint
changeset 1802 d628defebc17
parent 730 9062cdc140a9
child 1977 606923dff11b
equal deleted inserted replaced
1801:672acc730ce5 1802:d628defebc17
    26 :copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
    26 :copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
    27 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
    27 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
    28 """
    28 """
    29 __docformat__ = "restructuredtext en"
    29 __docformat__ = "restructuredtext en"
    30 
    30 
    31 ENTITIES_HOOKS = ('before_add_entity',    'after_add_entity', 
    31 ENTITIES_HOOKS = ('before_add_entity',    'after_add_entity',
    32                   'before_update_entity', 'after_update_entity',
    32                   'before_update_entity', 'after_update_entity',
    33                   'before_delete_entity', 'after_delete_entity')
    33                   'before_delete_entity', 'after_delete_entity')
    34 RELATIONS_HOOKS = ('before_add_relation',   'after_add_relation' ,
    34 RELATIONS_HOOKS = ('before_add_relation',   'after_add_relation' ,
    35                    'before_delete_relation','after_delete_relation')
    35                    'before_delete_relation','after_delete_relation')
    36 SYSTEM_HOOKS = ('server_startup', 'server_shutdown',
    36 SYSTEM_HOOKS = ('server_startup', 'server_shutdown',
    40 
    40 
    41 class HooksManager(object):
    41 class HooksManager(object):
    42     """handle hooks registration and calls
    42     """handle hooks registration and calls
    43     """
    43     """
    44     verification_hooks_activated = True
    44     verification_hooks_activated = True
    45     
    45 
    46     def __init__(self, schema):
    46     def __init__(self, schema):
    47         self.set_schema(schema)
    47         self.set_schema(schema)
    48 
    48 
    49     def set_schema(self, schema):
    49     def set_schema(self, schema):
    50         self._hooks = {}
    50         self._hooks = {}
    51         self.schema = schema
    51         self.schema = schema
    52         self._init_hooks(schema)
    52         self._init_hooks(schema)
    53         
    53 
    54     def register_hooks(self, hooks):
    54     def register_hooks(self, hooks):
    55         """register a dictionary of hooks :
    55         """register a dictionary of hooks :
    56         
    56 
    57              {'event': {'entity or relation type': [callbacks list]}}
    57              {'event': {'entity or relation type': [callbacks list]}}
    58         """
    58         """
    59         for event, subevents in hooks.items():
    59         for event, subevents in hooks.items():
    60             for subevent, callbacks in subevents.items():
    60             for subevent, callbacks in subevents.items():
    61                 for callback in callbacks:
    61                 for callback in callbacks:
    62                     self.register_hook(callback, event, subevent)
    62                     self.register_hook(callback, event, subevent)
    63                     
    63 
    64     def register_hook(self, function, event, etype=''):
    64     def register_hook(self, function, event, etype=''):
    65         """register a function to call when <event> occurs
    65         """register a function to call when <event> occurs
    66         
    66 
    67          <etype> is an entity/relation type or an empty string.
    67          <etype> is an entity/relation type or an empty string.
    68          If etype is the empty string, the function will be called at each
    68          If etype is the empty string, the function will be called at each
    69          event, else the function will be called only when event occurs on an
    69          event, else the function will be called only when event occurs on an
    70          entity/relation of the given type.
    70          entity/relation of the given type.
    71         """
    71         """
    74         etype = etype or ''
    74         etype = etype or ''
    75         try:
    75         try:
    76             self._hooks[event][etype].append(function)
    76             self._hooks[event][etype].append(function)
    77             self.debug('registered hook %s on %s (%s)', event, etype or 'any',
    77             self.debug('registered hook %s on %s (%s)', event, etype or 'any',
    78                        function.func_name)
    78                        function.func_name)
    79             
    79 
    80         except KeyError:
    80         except KeyError:
    81             self.error('can\'t register hook %s on %s (%s)',
    81             self.error('can\'t register hook %s on %s (%s)',
    82                        event, etype or 'any', function.func_name)
    82                        event, etype or 'any', function.func_name)
    83             
    83 
    84     def unregister_hook(self, function, event, etype=''):
    84     def unregister_hook(self, function, event, etype=''):
    85         """register a function to call when <event> occurs
    85         """register a function to call when <event> occurs
    86         
    86 
    87         <etype> is an entity/relation type or an empty string.
    87         <etype> is an entity/relation type or an empty string.
    88         If etype is the empty string, the function will be called at each
    88         If etype is the empty string, the function will be called at each
    89         event, else the function will be called only when event occurs on an
    89         event, else the function will be called only when event occurs on an
    90         entity/relation of the given type.
    90         entity/relation of the given type.
    91         """
    91         """
   107             hook(*args, **kwargs)
   107             hook(*args, **kwargs)
   108         if __type:
   108         if __type:
   109             for hook in self._hooks[__event][__type]:
   109             for hook in self._hooks[__event][__type]:
   110                 #print '[%s]'%__type, hook.__name__
   110                 #print '[%s]'%__type, hook.__name__
   111                 hook(*args, **kwargs)
   111                 hook(*args, **kwargs)
   112     
   112 
   113     def _init_hooks(self, schema):
   113     def _init_hooks(self, schema):
   114         """initialize the hooks map"""
   114         """initialize the hooks map"""
   115         for hook_event in ENTITIES_HOOKS:
   115         for hook_event in ENTITIES_HOOKS:
   116             self._hooks[hook_event] = {'': []}
   116             self._hooks[hook_event] = {'': []}
   117             for etype in schema.entities():
   117             for etype in schema.entities():
   162         self.unregister_hook(cstrcheck_after_add_relation, 'after_add_relation', '')
   162         self.unregister_hook(cstrcheck_after_add_relation, 'after_add_relation', '')
   163         self.unregister_hook(uniquecstrcheck_before_modification, 'before_add_entity', '')
   163         self.unregister_hook(uniquecstrcheck_before_modification, 'before_add_entity', '')
   164         self.unregister_hook(uniquecstrcheck_before_modification, 'before_update_entity', '')
   164         self.unregister_hook(uniquecstrcheck_before_modification, 'before_update_entity', '')
   165 #         self.unregister_hook(tidy_html_fields('before_add_entity'), 'before_add_entity', '')
   165 #         self.unregister_hook(tidy_html_fields('before_add_entity'), 'before_add_entity', '')
   166 #         self.unregister_hook(tidy_html_fields('before_update_entity'), 'before_update_entity', '')
   166 #         self.unregister_hook(tidy_html_fields('before_update_entity'), 'before_update_entity', '')
   167         
   167 
   168     def reactivate_verification_hooks(self):
   168     def reactivate_verification_hooks(self):
   169         from cubicweb.server.hooks import (cardinalitycheck_after_add_entity,
   169         from cubicweb.server.hooks import (cardinalitycheck_after_add_entity,
   170                                         cardinalitycheck_before_del_relation,
   170                                         cardinalitycheck_before_del_relation,
   171                                         cstrcheck_after_add_relation,
   171                                         cstrcheck_after_add_relation,
   172                                         uniquecstrcheck_before_modification)
   172                                         uniquecstrcheck_before_modification)
   177         self.register_hook(cstrcheck_after_add_relation, 'after_add_relation', '')
   177         self.register_hook(cstrcheck_after_add_relation, 'after_add_relation', '')
   178         self.register_hook(uniquecstrcheck_before_modification, 'before_add_entity', '')
   178         self.register_hook(uniquecstrcheck_before_modification, 'before_add_entity', '')
   179         self.register_hook(uniquecstrcheck_before_modification, 'before_update_entity', '')
   179         self.register_hook(uniquecstrcheck_before_modification, 'before_update_entity', '')
   180 #         self.register_hook(tidy_html_fields('before_add_entity'), 'before_add_entity', '')
   180 #         self.register_hook(tidy_html_fields('before_add_entity'), 'before_add_entity', '')
   181 #         self.register_hook(tidy_html_fields('before_update_entity'), 'before_update_entity', '')
   181 #         self.register_hook(tidy_html_fields('before_update_entity'), 'before_update_entity', '')
   182             
   182 
   183 from cubicweb.selectors import yes
   183 from cubicweb.selectors import yes
   184 from cubicweb.appobject import AppObject
   184 from cubicweb.appobject import AppObject
   185 
   185 
   186 class autoid(type):
   186 class autoid(type):
   187     """metaclass to create an unique 'id' attribute on the class using it"""
   187     """metaclass to create an unique 'id' attribute on the class using it"""
   197     __select__ = yes()
   197     __select__ = yes()
   198     # set this in derivated classes
   198     # set this in derivated classes
   199     events = None
   199     events = None
   200     accepts = None
   200     accepts = None
   201     enabled = True
   201     enabled = True
   202     
   202 
   203     def __init__(self, event=None):
   203     def __init__(self, event=None):
   204         super(Hook, self).__init__()
   204         super(Hook, self).__init__()
   205         self.event = event
   205         self.event = event
   206         
   206 
   207     @classmethod
   207     @classmethod
   208     def registered(cls, vreg):
   208     def registered(cls, vreg):
   209         super(Hook, cls).registered(vreg)
   209         super(Hook, cls).registered(vreg)
   210         return cls()
   210         return cls()
   211     
   211 
   212     @classmethod
   212     @classmethod
   213     def register_to(cls):
   213     def register_to(cls):
   214         if not cls.enabled:
   214         if not cls.enabled:
   215             cls.warning('%s hook has been disabled', cls)
   215             cls.warning('%s hook has been disabled', cls)
   216             return
   216             return
   230                     for eetype in eschema.specialized_by():
   230                     for eetype in eschema.specialized_by():
   231                         if (event, eetype) in done:
   231                         if (event, eetype) in done:
   232                             continue
   232                             continue
   233                         yield event, str(eetype)
   233                         yield event, str(eetype)
   234                         done.add((event, eetype))
   234                         done.add((event, eetype))
   235                         
   235 
   236 
   236 
   237     def make_callback(self, event):
   237     def make_callback(self, event):
   238         if len(self.events) == 1:
   238         if len(self.events) == 1:
   239             return self.call
   239             return self.call
   240         return self.__class__(event=event).call
   240         return self.__class__(event=event).call
   241 
   241 
   242     def call(self):
   242     def call(self):
   243         raise NotImplementedError
   243         raise NotImplementedError
   244     
   244 
   245 class SystemHook(Hook):
   245 class SystemHook(Hook):
   246     accepts = ('',)
   246     accepts = ('',)
   247 
   247 
   248 from logging import getLogger
   248 from logging import getLogger
   249 from cubicweb import set_log_methods
   249 from cubicweb import set_log_methods